#pragma implementation #include #include #include "parsers.h" PUBLIC VIEWITEMS_S::VIEWITEMS_S() : vip(vip_default) { } PUBLIC VIEWITEMS_S::VIEWITEMS_S(VIEWITEMS_PARSER &_vip) : vip(_vip) { } PUBLIC VIEWITEMS* VIEWITEMS_S::getitem(int no) const { return (VIEWITEMS*)ARRAY::getitem(no); } PUBLIC VIEWITEM *VIEWITEMS_S::locate (const char *key) { VIEWITEM *ret = NULL; for (int i=0; ret == NULL && ilocate (key); } return ret; } /* Locate all configuration lines with the keyword key tb will receive all the values. */ PUBLIC int VIEWITEMS_S::locate_all (const char *key, SSTRING_IDXS &tb) { int ret = 0; int lenkey = strlen(key); reset_iter(); VIEWITEM *it; while ((it=getnext())!=NULL){ const char *s = it->line.get(); s = str_skip(s); if (strncmp(s,key,lenkey) && isspace(s[lenkey])){ s = str_skip(s+lenkey); char word[200]; str_copyword(word,s,sizeof(word)-1); tb.add (new SSTRING_IDX(word,ret)); ret++; } } return ret; } /* Reset the iterator for the getnext() function */ PUBLIC void VIEWITEMS_S::reset_iter() { nofile = 0; positer = 0; } PUBLIC VIEWITEM *VIEWITEMS_S::getnext() { VIEWITEM *ret = NULL; VIEWITEMS *its = getitem(nofile); if (its != NULL){ if (positer == its->getnb()){ positer=0; nofile++; ret = getnext(); }else{ ret = its->getitem(positer); positer++; } } return ret; } PUBLIC int VIEWITEMS_S::write (CONFIG_FILE &conf) const { int ret = getitem(0)->write (conf,NULL); for (int i=1; iget(); CONFIG_FILE f_path (path,help_nil,CONFIGF_OPTIONAL); VIEWITEMS *items = getitem(i); ret |= items->write (f_path,NULL); } return ret; } /* Return the value of a "keyword value" line */ const char *viewsub_getval (VIEWITEM *it) { const char *s = it->line.get(); s = str_skip(s); s = str_skipword(s); s = str_skip(s); return s; } /* Extract the path of all include files in one configuration file Return the number found. This function is generally overriden since the syntax to describe include file may vary. Further, the way to locate the file later may depend on another directive (serverroot in apache). */ PROTECTED VIRTUAL int VIEWITEMS_S::getincludes ( VIEWITEMS *items, SSTRINGS &tb) { return 0; } /* Read the configuration file and the include files as well */ PUBLIC int VIEWITEMS_S::read ( CONFIG_FILE &conf, bool extract) // Extract the include file from the archive { int ret = -1; remove_all(); includes.remove_all(); VIEWITEMS *its = new VIEWITEMS(vip); add (its); if (its->read (conf) != -1){ int no = 0; while (no < getnb()){ VIEWITEMS *items = getitem(no++); SSTRINGS tb; int nb = getincludes (items,tb); // Locate all include files // in this file for (int i=0; iget(); includes.add (new SSTRING(incl)); VIEWITEMS *subs = new VIEWITEMS(vip); add (subs); CONFIG_FILE f_path (incl,help_nil,CONFIGF_OPTIONAL); if (extract) f_path.extract(); subs->read (f_path); } } ret = 0; } return ret; } /* Find all sections of a given type. Return the number of section found */ PUBLIC int VIEWITEMS_S::locatesection ( const char *keyword, // virtualhost, directory, file, ... SSTRING_IDXS &tb) // Will contain all section names { int ret = 0; int lenkey = strlen(keyword); reset_iter(); VIEWITEM *it; while ((it=getnext())!=NULL){ const char *s = it->line.get(); s = str_skip(s); if (s[0] == '<'){ s = str_skip(s+1); if (strncmp(s,keyword,lenkey)==0 && isspace(s[lenkey])){ s = str_skip(s+lenkey); char tmp[strlen(s)+1]; strcpy (tmp,s); char *pt = strchr(tmp,'>'); if (pt != NULL) *pt = '\0'; strip_end (tmp); tb.add (new SSTRING_IDX(tmp,ret)); ret++; } } } return ret; } PUBLIC VIEWITEMS_SUB::VIEWITEMS_SUB(VIEWITEMS_S &_itemss) : itemss (_itemss) { } PUBLIC VIRTUAL VIEWITEMS_SUB::~VIEWITEMS_SUB() { } PUBLIC void VIEWITEMS_SUB::remove_del (VIEWITEM *it) { // Not sure from which VIEWITEMS this VIEWITEM belongs // We try them all. for (int i=0; iremove_del (it); } } PUBLIC VIEWITEMS_RANGE::VIEWITEMS_RANGE(VIEWITEMS_S &_itemss) : VIEWITEMS_SUB (_itemss) { resetview(); } PUBLIC void VIEWITEMS_RANGE::resetview() { items = NULL; start = -1; end = -1; } PUBLIC void VIEWITEMS_RANGE::delall() { if (items != NULL){ for (int i=start; i<=end; i++) items->remove_del (start); } } /* Locate a cpnfiguration line starting with key within the sub range. Return NULL if not found. */ PUBLIC VIEWITEM *VIEWITEMS_RANGE::locate (const char *key) const { return items->locate (key,start,end); } /* Add an item at the end of the range */ PUBLIC void VIEWITEMS_RANGE::add (VIEWITEM *it) { items->insert (end,it); end++; } PUBLIC VIEW_SECTION::VIEW_SECTION(const char *keyword, VIEWITEMS_S &_itemss) : VIEWITEMS_RANGE(_itemss) { key.setfrom (keyword); } /* Delimit the section within a ... Assume that a section cannot span multiple files. */ PRIVATE int VIEW_SECTION::setview (const char *value, int index) { const char *keyword = key.get(); resetview(); int ret = -1; int lenkey = strlen(keyword); int lenval = value != NULL ? strlen(value) : 0; itemss.reset_iter(); VIEWITEM *it; while ((it=itemss.getnext())!=NULL){ const char *s = it->line.get(); s = str_skip(s); if (s[0] == '<'){ s = str_skip(s+1); if (strncmp(s,keyword,lenkey)==0 && isspace(s[lenkey])){ if (index == 0){ ret = 0; }else if (value != NULL){ s = str_skip(s+lenkey); if (strncmp(s,value,lenval)==0 && (isspace(s[lenval]) || s[lenval] == '>')){ ret = 0; } } if (ret == 0){ items = itemss.getitem(itemss.nofile); start = itemss.positer-1; }else{ index--; } }else if (s[0] == '/' && start != -1){ s++; if (strncmp(s,keyword,lenkey)==0 && (isspace(s[lenkey]) || s[lenkey] == '>')){ end = itemss.positer-1; break; } } } } // fprintf (stderr,"setview :%s: :%s: %d %d\n",keyword,value,start,end); return ret; } /* Delimit the section within a ... Assume that a section cannot span multiple files. Use the value to locate the section. */ PUBLIC int VIEW_SECTION::setview (const char *value) { return setview (value,-1); } /* Delimit the section within a ... Assume that a section cannot span multiple files. Use the index to locate the section. You generally use this version (of setview) when there are multiple instance of a pair. */ PUBLIC int VIEW_SECTION::setview (int index) { return setview (NULL,index); } PUBLIC void VIEW_SECTION::updatehead(const char *val) { VIEWITEM *it = NULL; if (items == NULL){ // Ok, the section did not exist, we create it // We place it at the end of the main file items = itemss.getitem(0); it = new VIEWITEM(""); start = items->getnb(); items->add (it); VIEWITEM *end_it = new VIEWITEM(""); end_it->line.setfromf ("",key.get()); end = items->getnb(); items->add (end_it); }else{ it = items->getitem(start); } it->line.setfromf("<%s %s>",key.get(),val); } PUBLIC VIEW_MAIN::VIEW_MAIN(VIEWITEMS_S &_itemss) : VIEWITEMS_SUB (_itemss) { /* #Specification: httpd.conf / global stuff New global configuration lines are always placed in the main httpd.conf file (not an include), at the start of the file. At some point, we may introduce policies if some standard emerge to organise httpd.conf include files. */ } PUBLIC int VIEW_MAIN::locate_all (const char *key, VIEWITEMS &its) const { int ret = 0; its.neverdelete(); int lenkey = strlen(key); itemss.reset_iter(); VIEWITEM *it; int secnest = 0; // Nesting in various ... sections while ((it=itemss.getnext())!=NULL){ const char *s = it->line.get(); s = str_skip(s); if (s[0] == '<'){ if (s[1] == '/'){ secnest--; }else{ secnest++; } }else if (secnest == 0){ if (strncmp(s,key,lenkey)==0 && isspace(s[lenkey])){ its.add (it); ret++; } } } return ret; } PUBLIC int VIEW_MAIN::locate_all (const char *key, SSTRING_IDXS &tb) const { VIEWITEMS its; int ret = locate_all (key,its); for (int i=0; i 0) ret = its.getitem(0); return ret; } PUBLIC void VIEW_MAIN::add (VIEWITEM *it) { VIEWITEMS *first = itemss.getitem(0); if (first != NULL) first->insert(0,it); } PUBLIC VIEW_AREA::VIEW_AREA(const char *_keyword, VIEWITEMS_SUB &_sub) : sub(_sub) { keyword.setfrom (_keyword); insert_pos = 0; #if 0 for (int i=0; i