/*
* private.h
*
* Copyright (C) 2003 - 2008 Bojan Smojver, Rexursive
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
#ifndef __RXV_SPIN_PRIVATE__
#define __RXV_SPIN_PRIVATE__
#include
#include
#ifdef HAVE_APR_H
#include
#endif
#ifdef HAVE_APR_VERSION_H
#include
#endif
#ifdef HAVE_APR_GENERAL_H
#include
#endif
#ifdef HAVE_APR_LIB_H
#include
#endif
#ifdef HAVE_APR_THREAD_MUTEX_H
#include
#endif
#ifdef HAVE_APR_FILE_IO_H
#include
#endif
#ifdef HAVE_APR_PORTABLE_H
#include
#endif
#ifdef HAVE_APR_RING_H
#include
#endif
#ifdef HAVE_APR_MMAP_H
#include
#endif
#ifdef HAVE_APU_VERSION_H
#include
#endif
#ifdef HAVE_APR_MD5_H
#include
#endif
#ifdef HAVE_APR_RESLIST_H
#include
#endif
#ifdef HAVE_APREQ_MODULE_APACHE2_H
#include
#endif
#ifdef HAVE_AP_MPM_H
#include
#endif
#ifdef HAVE_LIBXML_XMLREADER_H
#include
#endif
#ifdef HAVE_LIBXML_XMLWRITER_H
#include
#endif
#if defined (HAVE_LIBPQ) && defined (HAVE_LIBPQ_FE_H)
#include
#endif
#if defined (HAVE_LIBMYSQLCLIENT_R) && defined (HAVE_MYSQL_H)
#include
#endif
#if defined (HAVE_LIBSQLITE) && defined (HAVE_SQLITE_H)
#include
#endif
#if defined (HAVE_LIBSQLITE3) && defined (HAVE_SQLITE3_H)
#include
#endif
/*
* Type definitions
*/
typedef struct rxv_spin_pool rxv_spin_pool_t;
typedef struct rxv_spin_iter rxv_spin_iter_t;
typedef struct rxv_spin_node rxv_spin_node_t;
typedef struct rxv_spin_txt rxv_spin_txt_t;
typedef struct rxv_spin_ref rxv_spin_ref_t;
typedef struct rxv_spin_for rxv_spin_for_t;
typedef struct rxv_spin_if rxv_spin_if_t;
typedef struct rxv_spin_reg rxv_spin_reg_t;
typedef struct rxv_spin_lit rxv_spin_lit_t;
typedef struct rxv_spin_num rxv_spin_num_t;
typedef struct rxv_spin_extra rxv_spin_extra_t;
typedef struct rxv_spin_config rxv_spin_config_t;
typedef struct rxv_spin_conncf rxv_spin_conncf_t;
typedef struct rxv_spin_reqcf rxv_spin_reqcf_t;
typedef struct rxv_spin_fltcf rxv_spin_fltcf_t;
typedef struct rxv_spin_private rxv_spin_private_t;
/*
* Generic true and false
*/
typedef enum{
RXV_SPIN_FALSE,
RXV_SPIN_TRUE
} rxv_spin_bool_e;
/*
* Data and context structures
*/
/*
* Data: representation of all data placed in context, be that singles (nul
* terminated, counted strings) or rows (hash table of column names pointing
* to arrays of data).
*/
#define RXV_SPIN_ROWS (~(apr_size_t)0)
struct rxv_spin_data{
apr_size_t size; /* data size: length of single, ~0 otherwise */
union{
char *data; /* single data */
apr_hash_t *cols; /* columns of rows type */
};
};
struct rxv_spin_iter{
int index; /* current position */
int size; /* number of elements in each array */
rxv_spin_data_t *rows; /* data */
};
struct rxv_spin_curs{
rxv_spin_iter_t *iter; /* rows iterator */
apr_array_header_t *data; /* array of data */
};
struct rxv_spin_ctx{
rxv_spin_data_t *data; /* application prepared data */
request_rec *r; /* raw Apache request */
apreq_handle_t *req; /* parsed request */
rxv_spin_private_t *priv; /* process private data */
rxv_spin_config_t *conf; /* module configration */
rxv_spin_reqcf_t *rcnf; /* request configuration */
rxv_spin_db_t *store; /* store database connection */
char *sesfn; /* session store file name */
rxv_spin_bool_e sdirty:1; /* session store dirty */
rxv_spin_bool_e adirty:1; /* application store dirty */
rxv_spin_bool_e havest:1; /* we have the store */
rxv_spin_bool_e dbstor:1; /* store has database backend */
rxv_spin_bool_e closed:1; /* store still closed */
rxv_spin_bool_e killed:1; /* session was killed */
apr_hash_t *app; /* application store */
apr_hash_t *ses; /* session store */
apr_time_t ptime; /* time configuration was last parsed */
const char *sstore; /* select timestamp and data from store */
const char *ustore; /* update timestamp and data in store */
const char *istore; /* insert timestamp and data into store */
const char *ustamp; /* update timestamp in store */
const char *remove; /* delete session in store */
void *extra; /* extra data placed in context by API user */
};
/*
* Database structures
*/
struct rxv_spin_pool{
APR_RING_ENTRY(rxv_spin_pool) link; /* LRU: ring link */
apr_pool_t *pool; /* connection pool specific pool */
char *cinfo; /* type:connect string */
char *parms; /* connect string */
const apr_dbd_driver_t *driver; /* APR Util database driver */
rxv_spin_private_t *priv; /* thread private data */
apr_time_t atime; /* time connection was last accessed */
#if APR_HAS_THREADS
union{
apr_reslist_t *list; /* connection resource list */
#endif
rxv_spin_db_t *conn; /* single connection (no threads) */
#if APR_HAS_THREADS
};
#endif
};
struct rxv_spin_db{
apr_pool_t *pool; /* connection specific pool */
rxv_spin_pool_t *cp; /* connection pool for this handle */
apr_dbd_t *handle; /* APR Util database handle */
apr_hash_t *stmts; /* prepared statements */
};
struct rxv_spin_db_txn{
apr_pool_t *pool; /* transaction specific pool */
rxv_spin_db_t *db; /* database assiciated with this transaction */
apr_dbd_transaction_t *txn; /* APR Util transaction */
};
/*
* Statement/node types
*/
typedef enum{
RXV_SPIN_UDF,
RXV_SPIN_TXT,
RXV_SPIN_REF,
RXV_SPIN_FOR,
RXV_SPIN_IF,
RXV_SPIN_REG,
RXV_SPIN_LIT,
RXV_SPIN_NUM
} rxv_spin_node_e;
/*
* Reference types
*/
typedef enum{
RXV_SPIN_REF_REG,
RXV_SPIN_REF_SIZ,
RXV_SPIN_REF_IND
} rxv_spin_ref_e;
/*
* Conditional types: #if (guaranteed to be 0) and #unless (guaranteed to be 1)
*/
typedef enum{
RXV_SPIN_IF_IF,
RXV_SPIN_IF_UNLESS
} rxv_spin_if_e;
/*
* Comparison operators
*/
typedef enum{
RXV_SPIN_OP_NONE,
RXV_SPIN_OP_MATCH,
RXV_SPIN_OP_EQ_LIT,
RXV_SPIN_OP_EQ_NUM,
RXV_SPIN_OP_EQ_REF,
RXV_SPIN_OP_MODULO
} rxv_spin_op_e;
/*
* Maximum nesting depth of the #if/#unless and #for
*/
#define RXV_SPIN_MAX_DEPTH 32
/*
* Maximum/minimum size of scan buffer
*/
#define RXV_SPIN_SCAN_MIN APR_BUCKET_BUFF_SIZE
#define RXV_SPIN_SCAN_MAX (RXV_SPIN_SCAN_MIN*8)
/*
* Maximum number of buckets to hold before we flush
*/
#define RXV_SPIN_FLUSH_COUNT 64
/*
* Data structures for Abstract Syntax Tree
*/
struct rxv_spin_node{
rxv_spin_node_e type:3;
rxv_spin_node_t *next;
};
struct rxv_spin_txt{
rxv_spin_node_t node;
apr_bucket *bucket; /* ready to use/copy bucket */
rxv_spin_bool_e used:1; /* have we used this bucket already */
};
struct rxv_spin_ref{
rxv_spin_node_t node;
char *name; /* last chunk of the full name */
rxv_spin_ref_t *ref; /* enclosing reference */
rxv_spin_data_t *data; /* data currently associated with this reference */
apr_size_t *ip; /* pointer to actual index of data */
apr_size_t index; /* index of data in a loop */
apr_size_t fixed; /* fixed index of data */
rxv_spin_ref_e type:2; /* type of reference: regular, size or index */
};
struct rxv_spin_for{
rxv_spin_node_t node;
rxv_spin_ref_t *ref; /* what to loop around */
rxv_spin_node_t *stmt; /* what to replicate each time */
};
struct rxv_spin_if{
rxv_spin_node_t node;
rxv_spin_if_e type:1; /* is this actually the unless, not if */
rxv_spin_op_e oper:3; /* what operator is used */
rxv_spin_ref_t *ref; /* the reference we're checking, on the left */
union{
ap_regex_t *reg; /* regular expression to match */
rxv_spin_ref_t *rfr; /* the reference to match, on the right */
char *lit; /* literal string */
struct{
unsigned long num; /* number to the right of the operator */
unsigned long res; /* result of the modulo comparison, right of == */
};
};
rxv_spin_node_t *pos; /* statement if ref is not null */
rxv_spin_node_t *neg; /* statement if ref is null */
};
struct rxv_spin_reg{
rxv_spin_node_t node;
ap_regex_t reg;
};
struct rxv_spin_lit{
rxv_spin_node_t node;
char *lit;
};
struct rxv_spin_num{
rxv_spin_node_t node;
unsigned long num;
};
/*
* Data structures for the scanner
*/
struct rxv_spin_extra{
apr_pool_t *pool; /* regular pool for all memory allocations */
apr_off_t offset; /* from beginning of brigade */
apr_off_t pos; /* good chunk from beginning of brigade */
apr_off_t row; /* current row of the template */
apr_off_t col; /* current column of the template */
rxv_spin_node_t *root; /* root of the abstract syntax tree */
rxv_spin_node_t **tail; /* tails of node lists on the stack */
rxv_spin_for_t **loop; /* nesting loops */
unsigned char *nest; /* nesting type stack, #if or #for */
apr_size_t *boff; /* branch offset, RXV_SPIN_MAX_DEPTH for #else */
int depth; /* current nesting depth */
int ldepth; /* current loop nesting depth */
apr_size_t count; /* number of parsed TXT/REF tokens */
char *error; /* descriptive error */
apr_bucket_brigade *input; /* what we're scanning */
apr_bucket_brigade *split; /* split brigade that needs saving */
apr_bucket_brigade *output; /* where the result goes */
apr_bucket_brigade *metabb; /* metadata bucket brigade to send out */
apr_bucket_brigade *text; /* brigade of text nodes */
apr_bucket *eof; /* brigade sentinel seen */
apr_bucket *eos; /* EOS bucket seen */
apr_bucket *scan; /* first bucket we're scanning */
apr_size_t soff; /* offset from start of the scan bucket */
apr_off_t erow; /* scan row where the error occurred */
apr_off_t ecol; /* scan column where the error occurred */
char *buf; /* flex buffer */
apr_size_t blen; /* flex buffer length */
apr_size_t bpos; /* where are we within the buffer now */
void *scanner; /* the scanner */
rxv_spin_ctx_t *ctx; /* the context - data, parameters etc. */
ap_filter_t *f; /* our filter, if any */
};
/* Function declarations */
apr_status_t rxv_spin_build(rxv_spin_extra_t *extra);
apr_status_t rxv_spin_render(rxv_spin_node_t *node,rxv_spin_extra_t *extra);
/* Missing parser and scanner stuff */
#define YYSTYPE rxv_spin_node_t*
#define YY_EXTRA_TYPE rxv_spin_extra_t*
int rxv_spin_yyparse(void *YYPARSE_PARAM);
void rxv_spin_yyerror(char *s);
int rxv_spin_yylex(rxv_spin_node_t **yyval_param,void *yyscanner);
/*
* Module configuration
*/
typedef enum{
RXV_SPIN_APPLICATION_SET=0x0001,
RXV_SPIN_APPINIT_SET =0x0002,
RXV_SPIN_APPFIXUP_SET =0x0004,
RXV_SPIN_APPENTRY_SET =0x0008,
RXV_SPIN_CFGFN_SET =0x0010,
RXV_SPIN_STORE_SET =0x0020,
RXV_SPIN_STORETBL_SET =0x0040,
RXV_SPIN_CKNAME_SET =0x0080,
RXV_SPIN_CKPATH_SET =0x0100,
RXV_SPIN_CKDOMAIN_SET =0x0200,
RXV_SPIN_TIMEOUT_SET =0x0400,
RXV_SPIN_CONNPOOL_SET =0x0800
} rxv_spin_cfg_e;
struct rxv_spin_config{
char *application; /* path to the application shared library */
char *appinit; /* application init function name */
char *appfixup; /* application fixup function name */
char *appentry; /* application entry function name */
char *cfgfn; /* configuration file filename */
char *driver; /* store connect driver */
char *store; /* store connect string */
char *appfn; /* application store file name */
char *storetbl; /* store table name */
char *ckname; /* name of the cookie for session tracking */
char *ckpath; /* path of the cookie for session tracking */
char *ckdomain; /* domain of the cookie for session tracking */
apr_time_t timeout; /* session timeout */
rxv_spin_bool_e connpool:1; /* enable connection pooling */
rxv_spin_cfg_e set:12; /* what options were actually set */
};
/*
* Request configuration
*/
struct rxv_spin_reqcf{
char *sesid; /* session id */
rxv_spin_ctx_t *ctx; /* context passed from fixup to handler */
apr_dso_handle_sym_t fix; /* fixup function handle */
apr_dso_handle_sym_t svc; /* service function handle */
rxv_spin_bool_e valid:1; /* session is valid: value 1, otherwise 0 */
};
/*
* Filter configuration
*/
struct rxv_spin_fltcf{
rxv_spin_extra_t *extra;
};
/*
* Private process data
*/
struct rxv_spin_private{
apr_pool_t *pool; /* process specific pool */
apr_hash_t *dso; /* cache of DSOs so we don't keep opening */
apr_hash_t *conns; /* hash table of connection pools */
int count; /* maximum number of connections in each pool */
APR_RING_HEAD(rxv_spin_pool_list,rxv_spin_pool) list; /* LRU: pool list */
#if APR_HAS_THREADS
apr_thread_mutex_t *mutex; /* global thread mutex */
#endif
};
#if APR_HAS_THREADS
#define rxv_spin_lock(p) \
do { \
if((p)->mutex) apr_thread_mutex_lock((p)->mutex); \
} while(0)
#define rxv_spin_trylock(p,rv) \
do { \
if((p)->mutex) (rv)=apr_thread_mutex_trylock((p)->mutex); \
else (rv)=APR_SUCCESS; \
} while(0)
#define rxv_spin_unlock(p) \
do { \
if((p)->mutex) apr_thread_mutex_unlock((p)->mutex); \
} while(0)
#else
#define rxv_spin_lock(p)
#define rxv_spin_trylock(p,rv)
#define rxv_spin_unlock(p)
#endif
/*
* Crypto lengths
*/
#define RXV_SPIN_SALT_MIN 30
#define RXV_SPIN_SALT_MAX 64
/*
* Missing from APR 1.2.x
*/
#ifndef APR_INT64_MIN
#ifdef INT64_MIN
#define APR_INT64_MIN INT64_MIN
#else
#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1)
#endif
#endif
#endif