/** * store.c * * Copyright (C) 2003, 2004 Bojan Smojver, Rexursive * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licence as published by the Free * Software Foundation; either version 2 of the Licence, 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 General Public Licence for * more details. * * You should have received a copy of the GNU General Public Licence along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as two special exceptions, Bojan Smojver, Rexursive, gives * permission to: * * 1. Link, both statically and dynamically, the code of this program with * Apache HTTP Server, Apache Portable Runtime and Apache Portable Runtime * Utility Library from Apache Software Foundation (or with modified versions * of the above, that use the same licence - Apache Software Licence 1.1, 2.0 * or any later version), and distribute linked combinations including the * program and the above software from Apache Software Foundation. You must * obey the GNU General Public Licence in all respects for all of the code * used other than Apache HTTP Server, Apache Portable Runtime and Apache * Portable Runtime Utility Library. * * 2. Dynamically link any shared library with this program at run-time, * through the interface of SpinApplication/SpinAppEntry or LoadModule * run-time configuration directives of Apache HTTP Server, as provided by * this program or Apache HTTP Server itself, regardless of licensing terms of * those shared libraries. You must obey the GNU General Public Licence in all * respects for all of the code used other than that of those shared * libraries. * * If you modify this file, you may extend these exceptions to your version of * the file, but you are not obligated to do so. If you do not wish to do so, * delete one or both of these exception statements from your version. * */ #include "private.h" /* * Application and session API functions */ static rxv_spin_data_t *sdbm_store(rxv_spin_context_t *ctx,apr_sdbm_t **db, const char *fn,const char *cf, const char *skey,rxv_spin_data_t *sval); static apr_status_t xmlctx_clean(void *data){ xmlFreeParserCtxt((xmlParserCtxt *)data); return APR_SUCCESS; } static apr_status_t xmldoc_clean(void *data){ xmlFreeDoc((xmlDoc *)data); return APR_SUCCESS; } static void parse_config(rxv_spin_context_t *ctx){ xmlParserCtxt *ctxt; xmlDoc *doc; rxv_spin_guts_t *guts=(rxv_spin_guts_t *)ctx->guts; if(!(ctxt=xmlNewParserCtxt())) return; apr_pool_cleanup_register(ctx->pool,ctxt,xmlctx_clean,apr_pool_cleanup_null); if((doc=xmlCtxtReadFile(ctxt,guts->cfgfn,NULL,XML_PARSE_DTDVALID))){ xmlNode *root,*node,*text; xmlAttr *attr; char *key; rxv_spin_data_t *val; apr_pool_cleanup_register(ctx->pool,doc,xmldoc_clean,apr_pool_cleanup_null); if(!(val=apr_pcalloc(ctx->pool,sizeof(*val)))) return; val->type=RXV_SPIN_DATA_SGL; root=xmlDocGetRootElement(doc); for(node=root->children;node;node=node->next){ if(xmlStrEqual(node->name,(xmlChar*)"prop") && (text=node->children) && xmlStrEqual(text->name,(xmlChar*)"text") && text->content && (attr=node->properties) && xmlStrEqual(attr->name,(xmlChar*)"name") && attr->children){ key=(char*)attr->children->content; val->data=(char*)text->content; val->size=xmlStrlen(text->content); sdbm_store(ctx,&guts->app,guts->appfn,NULL,key,val); } } } } static apr_status_t sdbm_open(rxv_spin_context_t *ctx,apr_sdbm_t **db, const char *fn,const char *cf){ if(!*db){ /* maybe we need to parse the configuration file */ if(cf){ apr_status_t status; apr_finfo_t *spg,*scf; rxv_spin_guts_t *guts=(rxv_spin_guts_t *)ctx->guts; spg=apr_palloc(ctx->pool,sizeof(*spg)); scf=apr_palloc(ctx->pool,sizeof(*scf)); if(!(spg && scf)) return APR_ENOMEM; /* page file status first - this file may not exist */ status=apr_stat(spg,guts->pagfn,APR_FINFO_MTIME,ctx->pool); if(status!=APR_SUCCESS || (status==APR_SUCCESS && apr_stat(scf,cf,APR_FINFO_MTIME,ctx->pool)==APR_SUCCESS && scf->mtime >= spg->mtime)) parse_config(ctx); } return apr_sdbm_open(db,fn,APR_WRITE|APR_CREATE|APR_SHARELOCK, APR_UREAD|APR_UWRITE,ctx->pool); } return APR_SUCCESS; } static rxv_spin_data_t *sdbm_fetch(rxv_spin_context_t *ctx,apr_sdbm_t **db, const char *fn,const char *cf, const char *skey){ apr_sdbm_datum_t *key,*val; rxv_spin_data_t *sval; key=apr_palloc(ctx->pool,sizeof(*key)); val=apr_palloc(ctx->pool,sizeof(*val)); if(!(key && val)) return NULL; if(sdbm_open(ctx,db,fn,cf)!=APR_SUCCESS) return NULL; key->dptr=(char*)skey; key->dsize=strlen(skey); if(apr_sdbm_fetch(*db,val,*key)==APR_SUCCESS && (sval=apr_pcalloc(ctx->pool,sizeof(*sval)))){ if(!(sval->data=apr_pstrmemdup(ctx->pool,val->dptr,val->dsize))) return NULL; sval->type=RXV_SPIN_DATA_SGL; sval->size=val->dsize; return sval; } return NULL; } static rxv_spin_data_t *sdbm_store(rxv_spin_context_t *ctx,apr_sdbm_t **db, const char *fn,const char *cf, const char *skey,rxv_spin_data_t *sval){ apr_sdbm_datum_t *key,*val; if(sval->type!=RXV_SPIN_DATA_SGL) return NULL; key=apr_palloc(ctx->pool,sizeof(*key)); val=apr_palloc(ctx->pool,sizeof(*val)); if(!(key && val)) return NULL; if(sdbm_open(ctx,db,fn,cf)!=APR_SUCCESS) return NULL; key->dptr=(char*)skey; key->dsize=strlen(skey); val->dptr=sval->data; val->dsize=sval->size; if(apr_sdbm_store(*db,*key,*val,APR_SDBM_REPLACE)==APR_SUCCESS) return sval; return NULL; } static apr_status_t sdbm_delete(rxv_spin_context_t *ctx,apr_sdbm_t **db, const char *fn,const char *cf, const char *skey){ apr_sdbm_datum_t *key; apr_status_t status; key=apr_palloc(ctx->pool,sizeof(*key)); if(!key) return APR_ENOMEM; if((status=sdbm_open(ctx,db,fn,cf))!=APR_SUCCESS) return status; key->dptr=(char*)skey; key->dsize=strlen(skey); return apr_sdbm_delete(*db,*key); } /* application get/set/del */ rxv_spin_data_t *rxv_spin_app_get(rxv_spin_context_t *ctx,const char *key){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts) && guts->appfn && key) return sdbm_fetch(ctx,&guts->app,guts->appfn,guts->cfgfn,key); return NULL; } rxv_spin_data_t *rxv_spin_app_set(rxv_spin_context_t *ctx, const char *key,rxv_spin_data_t *val){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts) && guts->appfn && key && val) return sdbm_store(ctx,&guts->app,guts->appfn,guts->cfgfn,key,val); return NULL; } apr_status_t rxv_spin_app_del(rxv_spin_context_t *ctx,const char *key){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts) && guts->appfn && key) return sdbm_delete(ctx,&guts->app,guts->appfn,guts->cfgfn,key); return APR_EGENERAL; } /* session get/set/del */ rxv_spin_data_t *rxv_spin_ses_get(rxv_spin_context_t *ctx,const char *key){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts) && guts->sesfn && key) return sdbm_fetch(ctx,&guts->ses,guts->sesfn,NULL,key); return NULL; } rxv_spin_data_t *rxv_spin_ses_set(rxv_spin_context_t *ctx, const char *key,rxv_spin_data_t *val){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts) && guts->sesfn && key && val) return sdbm_store(ctx,&guts->ses,guts->sesfn,NULL,key,val); return NULL; } apr_status_t rxv_spin_ses_del(rxv_spin_context_t *ctx,const char *key){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts) && guts->sesfn && key) return sdbm_delete(ctx,&guts->ses,guts->sesfn,NULL,key); return APR_EGENERAL; } /* session id and validity */ char *rxv_spin_ses_idget(rxv_spin_context_t *ctx){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts)) return guts->sesid; return NULL; } int rxv_spin_ses_valid(rxv_spin_context_t *ctx){ rxv_spin_guts_t *guts; if(ctx && (guts=ctx->guts)) return guts->valid; return 0; }