/* Copyright (C) 2000-2006 Lavtech.com corp. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "udm_config.h" #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_LOCALE_H #include #endif #ifdef HAVE_GETOPT_H #include #endif #include "udmsearch.h" #include "udm_xmalloc.h" /* This should be last include */ #ifdef DMALLOC #include "dmalloc.h" #endif #ifdef WIN32 #include "udm_winutils.h" #endif #define POWERED_LOGO "
 Powered by mnoGoSearch - free web search engine software
\n" #define UDM_HTTPD_CGI 1 #define UDM_HTTPD_DAEMON 2 /******************** Misc functions *********************************/ static void ParseQStringUnescaped(UDM_VARLIST *vars, const char *qstring) { char *tok, *lt, *qs; if ((qs= (char*)UdmStrdup(qstring))) { UdmSGMLUnescape(qs); tok = udm_strtok_r(qs, "&", <); while(tok) { char *arg= strchr(tok,'='); if(arg) *arg++='\0'; UdmVarListAddStr(vars,tok,arg?arg:""); tok= udm_strtok_r(NULL, "&", <); } UdmFree(qs); } } static int UdmVarListReplaceOrDelInt(UDM_VARLIST *V, const char *name, int i) { return i ? UdmVarListReplaceInt(V, name, i) : UdmVarListDel(V, name); } static char * BuildPageURL(UDM_VARLIST * vars, char **dst) { size_t i, nargs= 0, dstlen= 0; char *end; for(i= 0; i < vars->nvars; i++) dstlen+= 7 + strlen(vars->Var[i].name) + strlen(vars->Var[i].val); if (!(*dst= (char*)UdmRealloc(*dst, 3*dstlen))) return NULL; end = *dst; for(i=0; i < vars->nvars; i++) { strcpy(end, nargs ? "&" : "?"); end += nargs ? 5 : 1; strcpy(end,vars->Var[i].name); end= end + strlen(end); strcpy(end++,"="); strcpy(end,vars->Var[i].val); UdmURLCanonizePath(end, 3*strlen(vars->Var[i].val) + 1,vars->Var[i].val); end= end + strlen(end); nargs++; } return NULL; } /*****************************************************************/ static char *UdmConfDir(void) { #ifdef WIN32 return WinUdmConfDir(); #else char* result; result = (char *)UdmStrdup(UDM_CONF_DIR); return result; #endif } #ifndef WIN32 #include static int UdmLoadGroups (UDM_ENV *E) { struct group *grp; size_t cnt = 0; char name[32]; char **p; const char *user = UdmVarListFindStr(&E->Vars, "REMOTE_USER", NULL); if (! user) return(UDM_OK); setgrent(); while ((grp = getgrent())) { for (p = grp->gr_mem; *p; p++) { if (! strcmp(user, *p)) { udm_snprintf(name, sizeof(name), "REMOTE_GROUP%d", cnt); UdmVarListAddStr(&E->Vars, name, grp->gr_name); cnt++; break; } } } getgrent(); return(UDM_OK); } #endif /************************************************************/ static int StoreDocCGI(UDM_AGENT *Agent, UDM_ENV *Env, UDM_VARLIST *tmpl, int httpd) { UDM_DOCUMENT *Doc; UDM_RESULT *Res; UDM_HTMLTOK tag; char *HDoc= NULL; char *HEnd= NULL; char *last= NULL; char ch; const char *content_type, *charset, *htok, *qstring; UDM_CHARSET *cs; #ifdef USE_PARSER UDM_PARSER *Parser; #endif Doc=UdmDocInit(NULL); Res=UdmResultInit(NULL); UdmPrepare(Agent,Res); UdmVarListReplaceStr(&Doc->Sections, "URL", UdmVarListFindStr(&Env->Vars, "URL", "0")); UdmVarListReplaceStr(&Doc->Sections, "dbnum", UdmVarListFindStr(&Env->Vars, "dbnum", "0")); if ((qstring= UdmVarListFindStr(&Env->Vars, "ENV.QUERY_STRING", NULL))) { /* Remove dbnum from query string */ if (!strncmp(qstring, "dbnum=", 6)) { char tmp[256]; for (qstring+= 6 ; (qstring[0] >= '0' && qstring[0] <= '9') || qstring[0]=='&' ; qstring++); udm_snprintf(tmp, sizeof(tmp), "%s", qstring); UdmVarListReplaceStr(&Doc->Sections, "ENV.QUERY_STRING", tmp); UdmVarListReplaceStr(&Env->Vars, "ENV.QUERY_STRING", tmp); } else { UdmVarListReplaceStr(&Doc->Sections, "ENV.QUERY_STRING", UdmVarListFindStr(&Env->Vars, "ENV.QUERY_STRING", NULL)); } } UdmURLAction(Agent, Doc, UDM_URL_ACTION_GET_CACHED_COPY); UdmVarListReplaceLst(&Env->Vars, &Doc->Sections, NULL, "*"); charset = UdmVarListFindStr(&Env->Vars,"Charset","iso-8859-1"); cs = UdmGetCharSet(charset); if (httpd & UDM_HTTPD_DAEMON) printf("HTTP/1.0 200 OK\r\n"); printf("Content-type: text/html; charset=%s\r\n\r\n", charset); /* Now start displaying template*/ UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, tmpl, "storedoc_top"); /* UnStore Doc, Highlight and Display */ content_type = UdmVarListFindStr(&Env->Vars, "Content-Type", "text/html"); #ifdef USE_PARSER if ((Parser= UdmParserFind(&Env->Parsers, content_type))) { content_type = Parser->to_mime ? Parser->to_mime : "text/html"; } #endif if(!Doc->Buf.content)goto fin; HEnd=HDoc = (char*)UdmMalloc(UDM_MAXDOCSIZE + 32); *HEnd='\0'; if (strncasecmp(content_type, "text/plain", 10) == 0) { sprintf(HEnd, "
\n");
    HEnd += strlen(HEnd);
  }

  UdmHTMLTOKInit(&tag);
  for(htok= UdmHTMLToken(Doc->Buf.content, (const char **)&last, &tag) ; htok ;)
  {
    char *tmp;
    switch(tag.type) {
    case UDM_HTML_COM:
    case UDM_HTML_TAG:
      memcpy(HEnd,htok,(size_t)(last-htok));
      HEnd+= last-htok;
      HEnd[0]= '\0';
      UdmHTMLParseTag(&tag,Doc);
      break;
    case UDM_HTML_TXT:
      ch= *last;
      *last= '\0';
      if (tag.title || tag.script || tag.comment || tag.style)
      {
        if ((tmp= UdmHlConvert(NULL, htok, cs, cs)))
        {
          memcpy(HEnd, tmp, strlen(tmp) + 1);
          UdmFree(tmp);
        }
      }
      else
      {
        if ((tmp= UdmHlConvert(&Res->WWList, htok, cs, cs)))
        {
          memcpy(HEnd, tmp, strlen(tmp) + 1);
          UdmFree(tmp);
        }
      }
      HEnd=UDM_STREND(HEnd);
      *last = ch;
      break;
    }
    htok = UdmHTMLToken(NULL, (const char **)&last, &tag);
  }

  if (strncasecmp(content_type, "text/plain", 10) == 0)
  {
    sprintf(HEnd, "
\n"); HEnd+= strlen(HEnd); } UdmVarListAddStr(&Env->Vars, "document", HDoc); UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, tmpl, "storedoc"); fin: UdmResultFree(Res); UdmDocFree(Doc); UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, tmpl, "storedoc_bottom"); UdmVarListFree(tmpl); UdmAgentFree(Agent); UdmEnvFree(Env); UDM_FREE(HDoc); return(0); } /************************************************************/ /* We need to initialize WSA to process possible includes in template. */ static void UdmWSAStartup(void) { #ifdef WIN32 WSADATA wsaData; if(WSAStartup(0x101,&wsaData)!=0) { fprintf(stderr,"WSAStartup() error %d\n",WSAGetLastError); exit(1); } #endif } static void UdmWSACleanup(void) { #ifdef WIN32 WSACleanup(); #endif } /************************************************************/ #if defined(HAVE_PTHREAD) && !defined(WIN32) static int UdmThreadCreate(void **thd, void *(*start_routine)(void *), void *arg) { return pthread_create((pthread_t*) thd, NULL, start_routine, arg); } static int UdmThreadJoin(void *thd) { return pthread_join((pthread_t) thd, NULL); } #endif static int UdmHTTPHeadersSend(int httpd, const char *content_type, const char *bcs) { if (httpd & UDM_HTTPD_DAEMON) printf("HTTP/1.0 200 OK\r\n"); if (httpd && strcasecmp(content_type, "none")) { if (bcs) printf("Content-type: %s; charset=%s\r\n\r\n", content_type, bcs); else printf("Content-Type: %s\r\n\r\n", content_type); } return UDM_OK; } static void usage(void) { } typedef struct udm_self_template_query_st { char template_name[1024]; char self[1024]; char query_string[1024]; } UDM_SELF_TEMPLATE_QUERY; static int UdmDetectSelfTemplateQueryCGI(UDM_ENV *Env, UDM_SELF_TEMPLATE_QUERY *q, int argc, char **argv) { char *env; /* Detect self */ if((env= getenv("UDMSEARCH_SELF")) || (env= getenv("REQUEST_URI"))) { /* Use Apache's REQUEST_URI, which is not in CGI standard */ char *end; udm_snprintf(q->self, sizeof(q->self), "%s", env); if ((end= strchr(q->self,'?'))) end[0]='\0'; } else if ((env= getenv("SCRIPT_NAME"))) { /* Use standard CGI variables if not under Apache */ const char *path_info= getenv("PATH_INFO"); udm_snprintf(q->self, sizeof(q->self),"%s%s", env, path_info ? path_info:""); } else { udm_snprintf(q->self, sizeof(q->self), "search.cgi"); } /* Detect template name */ if((env= getenv("UDMSEARCH_TEMPLATE"))) { char ename[1024]; strncpy(ename,env,sizeof(ename)-1); ename[sizeof(ename)]='\0'; UdmUnescapeCGIQuery(q->template_name, ename); } else if(getenv("REDIRECT_STATUS") && (env= getenv("PATH_TRANSLATED"))) { /* Check Apache internal redirect */ /* via "AddHandler" and "Action" */ udm_snprintf(q->template_name, sizeof(q->template_name), "%s", env); } else if ((env= getenv("PATH_INFO")) && env[0]) { /* http://localhost/cgi-bin/search.cgi/path/to/search.htm */ char name[128], *conf_dir; strncpy(name,env,sizeof(name)-1); name[sizeof(name)-1]='\0'; if (UDMSLASH !='/') { char *s; for (s=name; s[0]; s++) if (s[0]=='\\')s[0]='/'; } conf_dir= ((env= getenv("UDM_CONF_DIR")) || (env= getenv("UDM_ETC_DIR"))) ? (char *)UdmStrdup(env) : UdmConfDir(); /* Take from the config directory */ udm_snprintf(q->template_name, sizeof(q->template_name)-5, "%s%s%s", conf_dir,UDMSLASHSTR,name); UDM_FREE(conf_dir); } else { /* CGI executed without Apache internal redirect */ /* or started from command line */ char *end, *conf_dir; size_t length; conf_dir= ((env= getenv("UDM_CONF_DIR")) || (env= getenv("UDM_ETC_DIR"))) ? (char *)UdmStrdup(env) : UdmConfDir(); /* Take from the config directory */ length= udm_snprintf(q->template_name, sizeof(q->template_name)-5, "%s%s%s", conf_dir,UDMSLASHSTR, (end= strrchr(q->self,'/')) ? (end+1) : (q->self)); end= q->template_name + length; if ( length > 3 && (!strcmp(end-4,".exe") || !strcmp(end-4,".cgi"))) end-=4; strcpy(end,".htm"); UDM_FREE(conf_dir); } if((env= getenv("QUERY_STRING"))) { udm_snprintf(q->query_string, sizeof(q->query_string), "%s", env); } else if(argv[0]) { udm_snprintf(q->query_string, sizeof(q->query_string), "q=%s", argv[0]); UdmVarListReplaceStr(&Env->Vars, "ENV.QUERY_STRING", q->query_string); } else { udm_snprintf(q->query_string, sizeof(q->query_string), "q="); } return UDM_OK; } static int UdmDetectSelfTemplateQueryDaemon(UDM_ENV *Env, UDM_SELF_TEMPLATE_QUERY *q, FILE *stream) { char str[1024]; while (fgets(str, sizeof(str), stream)) { UdmRTrim(str, "\r\n"); if (!strncmp(str, "GET ", 4)) { char *method, *uri, *lt; if ((method= udm_strtok_r(str, " ", <)) && (uri= udm_strtok_r(NULL, " ", <))) { char *conf_dir, *query_string= strchr(uri, '?'); if (query_string) { *query_string= '\0'; query_string++; udm_snprintf(q->query_string, sizeof(q->query_string), "%s", query_string); } conf_dir= UdmConfDir(); udm_snprintf(q->template_name, sizeof(q->template_name)-5, "%s%s%s", conf_dir, UDMSLASHSTR, uri); udm_snprintf(q->self, sizeof(q->self), "%s", uri); UDM_FREE(conf_dir); } } if (!strcmp(str,"")) break; } return UDM_OK; } int main(int argc, char ** argv) { const char *env, *bcharset, *lcharset; char search_time[100]= ""; char *nav= NULL, *url= NULL; char *searchwords= NULL, *storedstr= NULL; int page_size, page_number, res, ch, httpd= 0; size_t i, swlen= 0, nav_len, storedlen, catcolumns= 0; ssize_t page1,page2,npages,ppp=10; UDM_ENV *Env; UDM_AGENT *Agent; UDM_RESULT *Res; UDM_VARLIST query_vars; UDM_VARLIST tmpl; UDM_SELF_TEMPLATE_QUERY q; q.template_name[0]= 0; q.self[0]= 0; q.query_string[0]= 0; while ((ch= getopt(argc, argv, "xh?")) != -1) { switch (ch) { case 'x': httpd|= UDM_HTTPD_DAEMON; break; case '?': case 'h': default: usage(); exit(0); } } argc-= optind; argv+= optind; UdmWSAStartup(); /* Output Content-type if under HTTPD Some servers do not pass QUERY_STRING if the query was empty, so check REQUEST_METHOD too to be safe */ httpd|= getenv("QUERY_STRING") || getenv("REQUEST_METHOD") ? UDM_HTTPD_CGI : 0; #if ( (defined WIN32) && (defined _DEBUG) ) if(httpd) { WIN32_IIS_DEBUG_MSG DebugBreak(); } #endif UdmInit(); Env=UdmEnvInit(NULL); #if defined(HAVE_PTHREAD) && !defined(WIN32) UdmInitMutexes(); UdmSetLockProc(Env, UdmLockProc); Env->ThreadCreate= UdmThreadCreate; Env->ThreadJoin= UdmThreadJoin; #endif UdmVarListInit(&tmpl); UdmVarListInit(&query_vars); Agent = UdmAgentInit(NULL, Env, 0); UdmVarListAddEnviron(&Env->Vars,"ENV"); UdmVarListReplaceStr(&Env->Vars, "version", VERSION); if (httpd & UDM_HTTPD_DAEMON) UdmDetectSelfTemplateQueryDaemon(Env, &q, stdin); else UdmDetectSelfTemplateQueryCGI(Env, &q, argc, argv); /* Hack for Russian Apache from apache.lexa.ru QUERY_STRING is already converted to server character set. We must print original query string instead however. Under usual apache we'll use QUERY_STRING. Note that query_vars list will contain not unescaped values, so we don't have to escape them when displaying */ env= getenv("CHARSET_SAVED_QUERY_STRING"); ParseQStringUnescaped(&query_vars, env ? env : q.query_string); /* Unescape and save variables from QUERY_STRING */ /* Env->Vars will have unescaped values however */ UdmParseQueryString(Agent, &Env->Vars, q.query_string); #ifndef WIN32 env= getenv("REMOTE_USER"); if (env) { UdmVarListAddStr(&Env->Vars, "REMOTE_USER", env); UdmLoadGroups(Env); } #endif if((res=UdmTemplateLoad(Agent, q.template_name, &tmpl))) { UdmHTTPHeadersSend(httpd, "text/plain", NULL); printf("%s\n",Env->errstr); UdmVarListFree(&tmpl); UdmVarListFree(&query_vars); UdmEnvFree(Env); UdmAgentFree(Agent); return(0); } #ifdef HAVE_LOCALE_H if ((env= UdmVarListFindStr(&Env->Vars, "Locale", NULL))) setlocale(LC_ALL, env); #endif #ifdef HAVE_SETVBUF { /* Set stdout buffer size. It allows to avoid re-rendering in the browser. After setting StdoutBufferSize to a reasonably big value, search.cgi will send whole output at once in the end, rather than gradually. */ size_t bsz= (size_t) UdmVarListFindInt(&Env->Vars, "StdoutBufferSize", 0); if (bsz > 0) setvbuf(stdout, NULL, _IOFBF, bsz); } #endif UdmTemplatePrint(Agent, NULL, NULL, 0, &Env->Vars, &tmpl, "variables"); UdmSetLogLevel(NULL, UdmVarListFindInt(&Env->Vars, "LogLevel", 0)); UdmOpenLog("search.cgi", Env, !strcasecmp(UdmVarListFindStr(&Env->Vars, "Log2stderr", (!httpd) ? "yes" : "no"), "yes")); UdmLog(Agent,UDM_LOG_ERROR, "search.cgi started with '%s'", q.template_name); /* This is for query tracking */ UdmVarListReplaceStr(&Env->Vars, "tmplt", q.template_name); UdmVarListAddStr(&Env->Vars,"QUERY_STRING", q.query_string); UdmVarListAddStr(&Env->Vars,"self", q.self); bcharset= UdmVarListFindStr(&Env->Vars,"BrowserCharset","iso-8859-1"); Env->bcs= UdmGetCharSet(bcharset); lcharset= UdmVarListFindStr(&Env->Vars,"LocalCharset","iso-8859-1"); Env->lcs= UdmGetCharSet(lcharset); ppp= UdmVarListFindInt(&Env->Vars,"PagesPerScreen",10); if (! Env->bcs) { UdmHTTPHeadersSend(httpd, "text/plain", NULL); printf("Unknown BrowserCharset '%s' in template '%s'\n", bcharset, q.template_name); exit(0); } if(! Env->lcs) { UdmHTTPHeadersSend(httpd, "text/plain", NULL); printf("Unknown LocalCharset '%s' in template '%s'\n", lcharset, q.template_name); exit(0); } if (UdmVarListFindInt(&Env->Vars, "cc", 0)) { UdmVarListFree(&query_vars); return StoreDocCGI(Agent, Env, &tmpl, httpd); } UdmHTTPHeadersSend(httpd, UdmVarListFindStr(&Env->Vars, "ResultContentType", "text/html"), bcharset); /* These parameters taken from "variable section of template"*/ res= UdmVarListFindInt(&Env->Vars,"np",0)*UdmVarListFindInt(&Env->Vars,"ps",10); UdmVarListAddInt(&Env->Vars,"pn",res); if(NULL==(Res=UdmFind(Agent))) { UdmVarListAddStr(&Env->Vars,"E",UdmEnvErrMsg(Agent->Conf)); UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "top"); UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "error"); if (Res != NULL) goto freeres; goto end; } UdmVarListAddInt(&Env->Vars,"first",(int)Res->first); UdmVarListAddInt(&Env->Vars,"last",(int)Res->last); UdmVarListAddInt(&Env->Vars,"total",(int)Res->total_found); sprintf(search_time,"%.3f",((double)Res->work_time)/1000); UdmVarListAddStr(&Env->Vars,"SearchTime",search_time); UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "top"); #ifdef TRIAL_VER fprintf(stdout,"%s",POWERED_LOGO); #endif if(!Res->WWList.nwords) { UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "noquery"); goto freeres; } if(!Res->num_rows) { UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "notfound"); goto freeres; } page_size = UdmVarListFindInt(&Agent->Conf->Vars,"ps",10); page_number = UdmVarListFindInt(&Agent->Conf->Vars,"np",0); for (i = 0; i < Res->WWList.nwords; i++) swlen += (8 * Res->WWList.Word[i].len) + 2; if ((searchwords= UdmXmalloc(swlen)) != NULL) { int z=0; for (i= 0; i < Res->WWList.nwords; i++) { if (Res->WWList.Word[i].count > 0) { sprintf(UDM_STREND(searchwords), (z)?"+%s":"%s", Res->WWList.Word[i].word); z++; } } } storedstr= UdmRealloc(storedstr, storedlen = 1024 + 10 * swlen); npages= (Res->total_found/(page_size?page_size:10)) + ((Res->total_found % (page_size?page_size:10) != 0 ) ? 1 : 0); page1= page_number-ppp/2; page2= page_number+ppp/2; if(page1<0) { page2-=page1; page1=0; } else if(page2>npages) { page1-=(page2-npages); page2=npages; } if(page1 < 0) page1=0; if( page2 > npages) page2=npages; nav = (char *)UdmRealloc(nav, nav_len = (size_t)(page2 - page1 + 2) * (1024 + 1024)); /* !!! 1024 - limit for navbar0/navbar1 template size */ nav[0] = '\0'; /* build NL NB NR */ for(i = (size_t)page1; i < (size_t)page2; i++) { UdmVarListReplaceOrDelInt(&query_vars,"np",(int)i); BuildPageURL(&query_vars, &url); UdmVarListReplaceStr(&Env->Vars,"NH",url); UdmVarListReplaceInt(&Env->Vars,"NP",(int)(i+1)); UdmTemplatePrint(Agent, NULL, UDM_STREND(nav), nav_len - (nav - UDM_STREND(nav)), &Env->Vars, &tmpl, (i == (size_t)page_number)?"navbar0":"navbar1"); } UdmVarListAddStr(&Env->Vars,"NB",nav); UdmVarListReplaceOrDelInt(&query_vars,"np",page_number-1); BuildPageURL(&query_vars, &url); UdmVarListReplaceStr(&Env->Vars,"NH",url); if(Res->first==1) /* First page */ { UdmTemplatePrint(Agent, NULL, nav, nav_len, &Env->Vars, &tmpl, "navleft_nop"); UdmVarListReplaceStr(&Env->Vars,"NL",nav); } else { UdmTemplatePrint(Agent, NULL, nav, nav_len, &Env->Vars, &tmpl, "navleft"); UdmVarListReplaceStr(&Env->Vars,"NL",nav); } UdmVarListReplaceOrDelInt(&query_vars,"np",page_number+1); BuildPageURL(&query_vars, &url); UdmVarListReplaceStr(&Env->Vars,"NH",url); UdmVarListReplaceOrDelInt(&query_vars, "np", 0); UdmVarListDel(&query_vars, "s"); BuildPageURL(&query_vars, &url); UdmVarListReplaceStr(&Env->Vars, "FirstPage", url); if(Res->last>=Res->total_found) /* Last page */ { UdmTemplatePrint(Agent, NULL, nav, nav_len, &Env->Vars, &tmpl, "navright_nop"); UdmVarListReplaceStr(&Env->Vars,"NR",nav); } else { UdmTemplatePrint(Agent, NULL, nav, nav_len, &Env->Vars, &tmpl, "navright"); UdmVarListReplaceStr(&Env->Vars,"NR",nav); } UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars,&tmpl, "restop"); for(i=0;inum_rows;i++) { UDM_DOCUMENT *Doc=&Res->Doc[i]; UDM_CATEGORY C; const char *stored_href; size_t sc; UDM_VARLIST Merge; int dbnum= UdmVarListFindInt(&Doc->Sections, "dbnum", 0); bzero((void*)&C, sizeof(C)); strcpy(C.addr,UdmVarListFindStr(&Doc->Sections,"Category","")); if(catcolumns && !UdmCatAction(Agent, &C, UDM_CAT_ACTION_PATH)) { char *catpath; size_t c, l = 0; for(c = 0; c < C.ncategories; c++) l+= 32 + strlen(C.Category[c].path) + strlen(C.Category[c].name); if (l > 0 && (catpath= (char*)UdmMalloc(l))) { *catpath = '\0'; for(c = 0; c < C.ncategories; c++) sprintf(catpath+strlen(catpath)," > %s ", C.Category[c].path,C.Category[c].name); UdmVarListReplaceStr(&Env->Vars,"DY",catpath); UDM_FREE(catpath); } } UDM_FREE(C.Category); stored_href= UdmVarListFindStr(&Doc->Sections, "stored_href", NULL); if ((!(stored_href= UdmVarListFindStr(&Doc->Sections, "stored_href", NULL)) || !stored_href[0]) && UdmVarListFindStr(&Doc->Sections, "CachedCopy", NULL)) { const char *u= UdmVarListFindStr(&Doc->Sections, "URL", ""); char *eu= (char*)UdmMalloc(strlen(u)*10 + 30); UdmEscapeURL(eu, u); if (dbnum) { udm_snprintf(storedstr, storedlen, "?cc=1&dbnum=%d&URL=%s&q=%s&wm=%s", dbnum, eu, searchwords, UdmVarListFindStr(&Env->Vars, "wm", "wrd")); } else { udm_snprintf(storedstr, storedlen, "?cc=1&URL=%s&q=%s&wm=%s", eu, searchwords, UdmVarListFindStr(&Env->Vars, "wm", "wrd")); } UdmFree(eu); UdmVarListReplaceStr(&Doc->Sections, "stored_href", storedstr); } else { /* add dbnum to stored_href returned from searchd */ if (stored_href && dbnum) { char tmp[256]; udm_snprintf(tmp, sizeof(tmp), "?dbnum=%d&%s", dbnum, stored_href + 1); UdmVarListReplaceStr(&Doc->Sections, "stored_href", tmp); } } if ( (sc = UdmVarListFindInt(&Env->Vars, "site", 0)) == 0) { UdmVarListReplaceOrDelInt(&query_vars,"np", 0); UdmVarListReplaceInt(&query_vars, "site", UdmVarListFindInt(&Doc->Sections, "Site_id", 0)); BuildPageURL(&query_vars, &url); UdmVarListReplaceStr(&Env->Vars, "sitelimit_href", url); } UdmVarListInit(&Merge); UdmVarListMerge(&Merge, &Env->Vars, &Doc->Sections); UdmTemplatePrint(Agent, stdout, NULL, 0, &Merge, &tmpl, "res"); UdmVarListFree(&Merge); } UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "resbot"); UDM_FREE(searchwords); UDM_FREE(storedstr); freeres: UdmResultFree(Res); end: UdmTemplatePrint(Agent, stdout, NULL, 0, &Env->Vars, &tmpl, "bottom"); UdmVarListFree(&tmpl); UdmVarListFree(&query_vars); UdmEnvFree(Env); UdmAgentFree(Agent); UDM_FREE(url); UDM_FREE(nav); if (httpd) fflush(NULL); else fclose(stdout); UdmWSACleanup(); return UDM_OK; }