/* * 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