Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

fo_arcview.c

Go to the documentation of this file.
00001 
00007 /* {{{ Initial comment */
00008 /*
00009  * $LastChangedDate$
00010  * $LastChangedRevision$
00011  * $LastChangedBy$
00012  *
00013  */
00014 /* }}} */
00015 
00016 /* {{{ Includes */
00017 #include "config.h"
00018 #include "defines.h"
00019 
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <ctype.h>
00023 #include <dlfcn.h>
00024 #include <errno.h>
00025 
00026 #include <sys/types.h>
00027 #include <dirent.h>
00028 
00029 #include <locale.h>
00030 
00031 #include <sys/stat.h>
00032 #include <fcntl.h>
00033 
00034 #include <sys/mman.h>
00035 
00036 #include <gdome.h>
00037 
00038 #include "readline.h"
00039 #include "hashlib.h"
00040 #include "utils.h"
00041 #include "configparser.h"
00042 #include "cfcgi.h"
00043 #include "template.h"
00044 #include "charconvert.h"
00045 #include "clientlib.h"
00046 #include "fo_arcview.h"
00047 /* }}} */
00048 
00049 /* {{{ Dummy function, for ignoring unknown directives */
00050 #ifndef DOXYGEN
00051 int ignre(t_configfile *cf,u_char **args,int argnum) {
00052   return 0;
00053 }
00054 #endif
00055 /* }}} */
00056 
00057 /* {{{ get_month_name */
00065 size_t get_month_name(int month,u_char **name) {
00066   struct tm tm;
00067   t_name_value *v = cfg_get_value(&fo_default_conf,"DateLocale");
00068   if(!v) return 0;
00069 
00070   *name = fo_alloc(NULL,BUFSIZ,1,FO_ALLOC_MALLOC);
00071 
00072   memset(&tm,0,sizeof(tm));
00073   tm.tm_mon = month-1;
00074 
00075   setlocale(LC_TIME,v->values[0]);
00076   return strftime(*name,BUFSIZ,"%B",&tm);
00077 }
00078 /* }}} */
00079 
00080 /* {{{ is_numeric */
00086 int is_numeric(register const u_char *ptr) {
00087   for(;*ptr;ptr++) {
00088     if(!isdigit(*ptr)) return 0;
00089   }
00090 
00091   return 1;
00092 }
00093 /* }}} */
00094 
00095 /* {{{ nummeric comparison of array elements */
00096 #ifndef DOXYGEN
00097 int array_numeric_compare(const void *elem1,const void *elem2) {
00098   int elem1_i = *((int *)elem1);
00099   int elem2_i = *((int *)elem2);
00100 
00101   if(elem1_i < elem2_i)  return -1;
00102   if(elem1_i == elem2_i) return  0;
00103   if(elem1_i > elem2_i)  return  1;
00104 
00105   /* eh? */
00106   return 0;
00107 }
00108 #endif
00109 /* }}} */
00110 
00111 /* {{{ read_dir_content */
00117 t_array *read_dir_content(const u_char *dir) {
00118   DIR *d_dir;
00119   struct dirent *ent;
00120   t_array *ary = fo_alloc(NULL,1,sizeof(*ary),FO_ALLOC_MALLOC);
00121   int num;
00122 
00123   array_init(ary,sizeof(num),NULL);
00124 
00125   if((d_dir = opendir(dir)) == NULL) {
00126     return NULL;
00127   }
00128 
00129   while((ent = readdir(d_dir)) != NULL) {
00130     if(*ent->d_name == '.') continue;
00131     num = atoi(ent->d_name);
00132 
00133     if(num) array_push(ary,&num);
00134   }
00135 
00136   closedir(d_dir);
00137 
00138   array_sort(ary,array_numeric_compare);
00139   return ary;
00140 }
00141 /* }}} */
00142 
00143 /* {{{ get_next_token */
00153 u_char *get_next_token(register u_char *ptr,const u_char *base,size_t len,const u_char *token,size_t tlen) {
00154   for(;ptr < base+len;ptr++) {
00155     if(*ptr == *token) {
00156       if(cf_strncmp(ptr,token,tlen) == 0) return ptr;
00157     }
00158   }
00159 
00160   return NULL;
00161 }
00162 /* }}} */
00163 
00164 /* {{{ get_id */
00171 u_int64_t get_id(u_char *ptr,const u_char *base,size_t len) {
00172   if(!(ptr = get_next_token(ptr,base,len,(const u_char *)"id=",3))) return 0;
00173   return strtoull(ptr+5,NULL,10);
00174 }
00175 /* }}} */
00176 
00177 /* {{{ generate_thread_output */
00190 void generate_thread_output(t_arc_message *msg,t_string *threads,t_string *threadlist,t_cf_template *pt_tpl,t_cf_template *tl_tpl,t_cf_template *ud_tpl,t_name_value *cs,int admin,int show_invisible) {
00191   size_t i;
00192   t_arc_message *child;
00193   u_char buff[256];
00194   size_t len;
00195   t_string *str = fo_alloc(NULL,1,sizeof(*str),FO_ALLOC_CALLOC);
00196   t_mod_api msg_to_html = cf_get_mod_api_ent("msg_to_html");
00197   void *ptr = fo_alloc(NULL,1,sizeof(const u_char *) + 2 * sizeof(t_string *),FO_ALLOC_MALLOC);
00198   int printed = 0;
00199 
00200   /* first: set threadlist variables */
00201   len = snprintf(buff,256,"#%llu",msg->mid);
00202   cf_set_variable(tl_tpl,cs,"mid",buff,len,1);
00203   cf_set_variable(tl_tpl,cs,"subject",msg->subject.content,msg->subject.len,1);
00204   if(msg->category.len) cf_set_variable(tl_tpl,cs,"category",msg->category.content,msg->category.len,1);
00205   else tpl_cf_freevar(tl_tpl,"category");
00206 
00207   /* parse threadlist and append output to threadlist content */
00208   tpl_cf_parse_to_mem(tl_tpl);
00209   str_chars_append(threadlist,tl_tpl->parsed.content,tl_tpl->parsed.len);
00210 
00211   tl_tpl->parsed.len = 0;
00212 
00213   /* after that: set per thread variables */
00214   cf_set_variable(pt_tpl,cs,"mid",buff,len,1);
00215   cf_set_variable(pt_tpl,cs,"subject",msg->subject.content,msg->subject.len,1);
00216   cf_set_variable(pt_tpl,cs,"author",msg->author.content,msg->author.len,1);
00217 
00218   /* category */
00219   if(msg->category.len) cf_set_variable(pt_tpl,cs,"category",msg->category.content,msg->category.len,1);
00220   else                  tpl_cf_freevar(pt_tpl,"category");
00221   /* email */
00222   if(msg->email.len)    cf_set_variable(pt_tpl,cs,"email",msg->email.content,msg->email.len,1);
00223   else                  tpl_cf_freevar(pt_tpl,"email");
00224   /* homepage url */
00225   if(msg->hp.len)       cf_set_variable(pt_tpl,cs,"link",msg->hp.content,msg->hp.len,1);
00226   else                  tpl_cf_freevar(pt_tpl,"link");
00227   /* image url */
00228   if(msg->img.len)      cf_set_variable(pt_tpl,cs,"image",msg->img.content,msg->img.len,1);
00229   else                  tpl_cf_freevar(pt_tpl,"image");
00230 
00231   /* set message... */
00232   memcpy(ptr,&(msg->content.content),sizeof(const u_char *));
00233   memcpy(ptr+sizeof(const u_char *),&str,sizeof(t_string *));
00234   memset(ptr+sizeof(const u_char *)+sizeof(t_string *),0,sizeof(t_string *));
00235 
00236   msg_to_html(ptr);
00237 
00238   tpl_cf_setvar(pt_tpl,"message",str->content,str->len,0);
00239   str_cleanup(str);
00240   free(str);
00241 
00242   tpl_cf_parse_to_mem(pt_tpl);
00243   str_chars_append(threads,pt_tpl->parsed.content,pt_tpl->parsed.len);
00244   pt_tpl->parsed.len = 0;
00245 
00246   if(msg->childs.elements) {
00247     str_chars_append(threadlist,"<ul>",4);
00248 
00249     for(i=0;i<msg->childs.elements;i++) {
00250       child = array_element_at(&msg->childs,i);
00251       if(child->invisible == 1 && (admin == 0 || show_invisible == 0)) continue;
00252 
00253       printed = 1;
00254 
00255       tpl_cf_parse_to_mem(ud_tpl);
00256       str_chars_append(threads,ud_tpl->parsed.content,ud_tpl->parsed.len);
00257       ud_tpl->parsed.len = 0;
00258 
00259       str_chars_append(threadlist,"<li>",4);
00260       generate_thread_output(child,threads,threadlist,pt_tpl,tl_tpl,ud_tpl,cs,admin,show_invisible);
00261       str_chars_append(threadlist,"</li>",5);
00262     }
00263 
00264     if(printed) str_chars_append(threadlist,"</ul>",5);
00265     else {
00266       threadlist->len -= 4;
00267       *(threadlist->content + threadlist->len) = '\0';
00268     }
00269   }
00270 }
00271 /* }}} */
00272 
00273 /* {{{ print_thread_structure */
00282 void print_thread_structure(t_arc_thread *thr,const u_char *year,const u_char *month,int admin,int show_invisible) {
00283   t_name_value *main_tpl_cfg       = cfg_get_value(&fo_arcview_conf,"ThreadTemplate");
00284   t_name_value *threadlist_tpl_cfg = cfg_get_value(&fo_arcview_conf,"ThreadListTemplate");
00285   t_name_value *per_thread_tpl_cfg = cfg_get_value(&fo_arcview_conf,"PerThreadTemplate");
00286   t_name_value *up_down_tpl_cfg    = cfg_get_value(&fo_arcview_conf,"UpDownTemplate");
00287 
00288   t_name_value *cs = cfg_get_value(&fo_default_conf,"ExternCharset");
00289 
00290   u_char main_tpl_name[256],threadlist_tpl_name[256],per_thread_tpl_name[256],up_down_tpl_name[256];
00291   t_cf_template main_tpl,threadlist_tpl,per_thread_tpl,up_down_tpl;
00292 
00293   u_char *tmp;
00294   int len;
00295 
00296   t_string threadlist,threads;
00297 
00298   /* Buarghs. Four templates. This is fucking bad. */
00299   generate_tpl_name(main_tpl_name,256,main_tpl_cfg);
00300   generate_tpl_name(threadlist_tpl_name,256,threadlist_tpl_cfg);
00301   generate_tpl_name(per_thread_tpl_name,256,per_thread_tpl_cfg);
00302   generate_tpl_name(up_down_tpl_name,256,up_down_tpl_cfg);
00303 
00304   if(tpl_cf_init(&main_tpl,main_tpl_name) != 0
00305     || tpl_cf_init(&threadlist_tpl,threadlist_tpl_name) != 0
00306     || tpl_cf_init(&per_thread_tpl,per_thread_tpl_name) != 0
00307     || tpl_cf_init(&up_down_tpl,up_down_tpl_name) != 0) {
00308     str_error_message("E_TPL_NOT_FOUND",NULL,15);
00309     return;
00310   }
00311 
00312   len = get_month_name(atoi(month),&tmp);
00313 
00314   tpl_cf_setvar(&main_tpl,"month",tmp,len,1);
00315   tpl_cf_setvar(&main_tpl,"year",year,strlen(year),0);
00316   cf_set_variable(&main_tpl,cs,"subject",thr->msgs->subject.content,thr->msgs->subject.len,1);
00317   tpl_cf_setvar(&main_tpl,"charset",cs->values[0],strlen(cs->values[0]),0);
00318 
00319   free(tmp);
00320 
00321   str_init(&threads);
00322   str_init(&threadlist);
00323 
00324   generate_thread_output(thr->msgs,&threads,&threadlist,&per_thread_tpl,&threadlist_tpl,&up_down_tpl,cs,admin,show_invisible);
00325 
00326   tpl_cf_setvar(&main_tpl,"threads",threads.content,threads.len,0);
00327   tpl_cf_setvar(&main_tpl,"threadlist",threadlist.content,threadlist.len,0);
00328 
00329   tpl_cf_parse(&main_tpl);
00330 
00331   tpl_cf_finish(&main_tpl);
00332   tpl_cf_finish(&threadlist_tpl);
00333   tpl_cf_finish(&per_thread_tpl);
00334   tpl_cf_finish(&up_down_tpl);
00335 }
00336 /* }}} */
00337 
00338 /* {{{ node_compare */
00339 #ifndef DOXYGEN
00340 int node_compare(t_cf_tree_dataset *a,t_cf_tree_dataset *b) {
00341   if(*((u_int64_t *)a->key) < *((u_int64_t *)b->key)) return -1;
00342   if(*((u_int64_t *)a->key) > *((u_int64_t *)b->key)) return 1;
00343 
00344   return 0;
00345 }
00346 #endif
00347 /* }}} */
00348 
00349 /* {{{ set_nodevalue_to_str */
00355 void set_nodevalue_to_str(GdomeNode *n,t_string *str) {
00356   GdomeException exc;
00357   GdomeNode *x   = gdome_n_firstChild(n,&exc);
00358   GdomeDOMString *y;
00359 
00360   str_init(str);
00361 
00362   if(x) {
00363     y = gdome_n_nodeValue(x,&exc);
00364 
00365     if(y) {
00366       str_char_set(str,y->str,strlen(y->str));
00367 
00368       gdome_n_unref(x,&exc);
00369       gdome_str_unref(y);
00370       return;
00371     }
00372     else {
00373       y = gdome_n_nodeValue(n,&exc);
00374 
00375       if(y) {
00376         str_char_set(str,y->str,strlen(y->str));
00377 
00378         gdome_n_unref(x,&exc);
00379         gdome_str_unref(y);
00380         return;
00381       }
00382     }
00383 
00384     gdome_n_unref(x,&exc);
00385   }
00386 }
00387 /* }}} */
00388 
00389 /* {{{ handle_header */
00395 void handle_header(t_arc_message *p,GdomeNode *n) {
00396   GdomeException     exc;
00397   GdomeNodeList     *nl       = gdome_n_childNodes(n,&exc);
00398   GdomeNode         *author   = gdome_nl_item(nl,0,&exc);
00399   GdomeNode         *category = gdome_nl_item(nl,1,&exc);
00400   GdomeNode         *subject  = gdome_nl_item(nl,2,&exc);
00401   GdomeNode         *date     = gdome_nl_item(nl,3,&exc);
00402   GdomeDOMString    *ls_str   = gdome_str_mkref("longSec");
00403   GdomeNamedNodeMap *atts     = gdome_n_attributes(date,&exc);
00404   GdomeNode         *longSec  = gdome_nnm_getNamedItem(atts,ls_str,&exc);
00405   GdomeDOMString    *ls_val   = gdome_n_nodeValue(longSec,&exc);
00406 
00407   GdomeNodeList     *a_nl     = gdome_n_childNodes(author,&exc);
00408   GdomeNode         *a_name   = gdome_nl_item(a_nl,0,&exc);
00409   GdomeNode         *a_email  = gdome_nl_item(a_nl,1,&exc);
00410   GdomeNode         *a_hp     = gdome_nl_item(a_nl,2,&exc);
00411   GdomeNode         *a_img    = gdome_nl_item(a_nl,3,&exc);
00412 
00413   p->date          = strtol(ls_val->str,NULL,10);
00414 
00415   set_nodevalue_to_str(a_name,&p->author);
00416   set_nodevalue_to_str(subject,&p->subject);
00417   set_nodevalue_to_str(category,&p->category);
00418   set_nodevalue_to_str(a_email,&p->email);
00419   set_nodevalue_to_str(a_hp,&p->hp);
00420   set_nodevalue_to_str(a_img,&p->img);
00421 
00422   gdome_str_unref(ls_val);
00423   gdome_n_unref(a_name,&exc);
00424   gdome_n_unref(a_email,&exc);
00425   gdome_n_unref(a_hp,&exc);
00426   gdome_n_unref(a_img,&exc);
00427   gdome_n_unref(longSec,&exc);
00428   gdome_nl_unref(a_nl,&exc);
00429   gdome_str_unref(ls_str);
00430   gdome_nnm_unref(atts,&exc);
00431   gdome_n_unref(author,&exc);
00432   gdome_n_unref(category,&exc);
00433   gdome_n_unref(subject,&exc);
00434   gdome_n_unref(date,&exc);
00435   gdome_nl_unref(nl,&exc);
00436 }
00437 /* }}} */
00438 
00439 /* {{{ sort_compare */
00440 #ifndef DOXYGEN
00441 int sort_compare(const void *a,const void *b) {
00442   if(((t_arc_message *)a)->mid > ((t_arc_message *)b)->mid) return 1;
00443   if(((t_arc_message *)a)->mid < ((t_arc_message *)b)->mid) return -1;
00444 
00445   return 0;
00446 }
00447 #endif
00448 /* }}} */
00449 
00450 /* {{{ make_thread_tree */
00458 void make_thread_tree(t_arc_thread *thread,t_arc_message *msg,GdomeNode *posting,t_cf_tree *tree) {
00459   GdomeException e;
00460   GdomeNodeList     *childs    = gdome_n_childNodes(posting,&e);
00461   GdomeNamedNodeMap *atts      = gdome_n_attributes(posting,&e);
00462   GdomeDOMString    *str_id    = gdome_str_mkref("id");
00463   GdomeDOMString    *str_invi  = gdome_str_mkref("invisible");
00464   GdomeNode         *invi      = gdome_nnm_getNamedItem(atts,str_invi,&e);
00465   GdomeNode         *id        = gdome_nnm_getNamedItem(atts,str_id,&e);
00466   GdomeNode         *fcnt      = NULL;
00467   GdomeDOMString    *tmp       = NULL;
00468   GdomeNode *element;
00469   GdomeDOMString *name;
00470   t_arc_message m;
00471 
00472   t_cf_tree_dataset d,*rs;
00473   size_t len,i;
00474 
00475   thread->msg_len++;
00476 
00477 
00478   if(id) {
00479     GdomeDOMString *tmp = gdome_n_nodeValue(id,&e);
00480     msg->mid            = strtoull(tmp->str+1,NULL,10);
00481 
00482     gdome_str_unref(tmp);
00483   }
00484   else {
00485     fprintf(stderr,"thread %llu: no id found\n",thread->tid);
00486     str_error_message("E_ARCHIVE_ERROR",NULL,15);
00487     exit(0);
00488   }
00489 
00490   if(invi) {
00491     GdomeDOMString *tmp = gdome_n_nodeValue(invi,&e);
00492     msg->invisible     = atoi(tmp->str);
00493 
00494     gdome_str_unref(tmp);
00495   }
00496   else {
00497     msg->invisible     = 0;
00498   }
00499 
00500   tmp   = NULL;
00501   d.key = &msg->mid;
00502   rs    = (t_cf_tree_dataset *)cf_tree_find(tree,tree->root,&d);
00503 
00504   if(rs) {
00505     fcnt         = (GdomeNode *)rs->data;
00506     GdomeNode *n = gdome_n_firstChild(fcnt,&e);
00507     tmp          = gdome_n_nodeValue(n,&e);
00508     gdome_n_unref(n,&e);
00509   }
00510   else {
00511     fprintf(stderr,"thread %llu: no posting content found\n",thread->tid);
00512     str_error_message("E_ARCHIVE_ERROR",NULL,15);
00513     exit(0);
00514   }
00515 
00516   if(tmp) {
00517     str_init(&msg->content);
00518     str_char_set(&msg->content,tmp->str,gdome_str_length(tmp));
00519     gdome_str_unref(tmp);
00520   }
00521   else {
00522     fprintf(stderr,"thread %llu: could not get posting content\n",thread->tid);
00523     str_error_message("E_ARCHIVE_ERROR",NULL,15);
00524     exit(0);
00525   }
00526 
00527   for(i=0,len=gdome_nl_length(childs,&e);i<len;i++) {
00528     element = gdome_nl_item(childs,i,&e);
00529     name    = gdome_n_nodeName(element,&e);
00530 
00531     if(cf_strcmp(name->str,"Header") == 0) {
00532       handle_header(msg,element);
00533     }
00534     else if(cf_strcmp(name->str,"Message") == 0) {
00535       memset(&m,0,sizeof(m));
00536 
00537       if(msg->childs.element_size == 0) {
00538         /* \todo cleanup routine for child postings array */
00539         array_init(&msg->childs,sizeof(m),NULL);
00540       }
00541 
00542       make_thread_tree(thread,&m,element,tree);
00543 
00544       array_push(&msg->childs,&m);
00545     }
00546 
00547     gdome_str_unref(name);
00548     gdome_n_unref(element,&e);
00549   }
00550 
00551   gdome_nl_unref(childs,&e);
00552   gdome_nnm_unref(atts,&e);
00553   gdome_str_unref(str_id);
00554   gdome_str_unref(str_invi);
00555   gdome_n_unref(invi,&e);
00556   gdome_n_unref(id,&e);
00557 
00558   /* ok, this level of postings has been created. Go and sort (if necessary) */
00559   if(msg->childs.elements > 1) {
00560     array_sort(&msg->childs,sort_compare);
00561   }
00562 }
00563 /* }}} */
00564 
00565 /* {{{ create_thread_structure */
00571 void create_thread_structure(GdomeDocument *doc,t_arc_thread *thr) {
00572   size_t i,len;
00573   t_cf_tree tree;
00574   GdomeException e;
00575   GdomeDOMString *msgcnt_str = gdome_str_mkref("MessageContent");
00576   GdomeNodeList *message_content = gdome_doc_getElementsByTagName(doc,msgcnt_str,&e);
00577   GdomeNodeList *messages;
00578   GdomeNode *n,*msg;
00579   GdomeNamedNodeMap *atts;
00580   GdomeDOMString *mid_str = gdome_str_mkref("mid"),*mid_v;
00581   GdomeDOMString *message_str = gdome_str_mkref("Message");
00582   GdomeNode *mid_n;
00583   t_cf_tree_dataset d;
00584 
00585   memset(thr,0,sizeof(*thr));
00586 
00587   cf_tree_init(&tree,node_compare,NULL);
00588 
00589   /*
00590    * first we put every MessageContent node into a tree. This is necessary
00591    * because the MessageContent nodes are childs of the ContentList node.
00592    * And the ContentList node is the last child of the Thread node...
00593    */
00594    for(i=0,len=gdome_nl_length(message_content,&e);i<len;i++) {
00595 
00596      n      = gdome_nl_item(message_content,i,&e);
00597      atts   = gdome_n_attributes(n,&e);
00598      mid_n  = gdome_nnm_getNamedItem(atts,mid_str,&e);
00599      mid_v  = gdome_n_nodeValue(mid_n,&e);
00600 
00601      d.data = n;
00602      d.key  = fo_alloc(NULL,1,sizeof(u_int64_t),FO_ALLOC_MALLOC);
00603      *((u_int64_t *)d.key) = strtoull(mid_v->str+1,NULL,10);
00604 
00605      cf_tree_insert(&tree,NULL,&d);
00606 
00607      gdome_str_unref(mid_v);
00608      gdome_n_unref(mid_n,&e);
00609      gdome_nnm_unref(atts,&e);
00610    }
00611 
00612    gdome_nl_unref(message_content,&e);
00613    gdome_str_unref(msgcnt_str);
00614    gdome_str_unref(mid_str);
00615 
00616    /*
00617     * ok... now we have fast access to the node values. The
00618     * next thing we have to do is creating an internal structure
00619     * from the XML. Trivial recursive algorithm -- if there weren't
00620     * the need of sorting. So we cannot use the standard (flat) data
00621     * types, we have to use a datatype which is not flat and therefore
00622     * possible to sort (has to be recursive, too)
00623     *
00624     * Ah. Nice idea: we can sort them in make_thread_tree(). A little
00625     * array_qsort() before every return would probably work very well
00626     */
00627     messages = gdome_doc_getElementsByTagName(doc,message_str,&e);
00628     msg      = gdome_nl_item(messages,0,&e);
00629 
00630     thr->msgs = fo_alloc(NULL,1,sizeof(*thr->msgs),FO_ALLOC_CALLOC);
00631     make_thread_tree(thr,thr->msgs,msg,&tree);
00632 
00633     gdome_n_unref(msg,&e);
00634     gdome_nl_unref(messages,&e);
00635     gdome_str_unref(message_str);
00636 
00637 }
00638 /* }}} */
00639 
00640 /* {{{ show_thread */
00647 void show_thread(const u_char *year,const u_char *month,const u_char *tid) {
00648   t_name_value *apath = cfg_get_value(&fo_default_conf,"ArchivePath");
00649   struct stat st;
00650   t_string path;
00651   t_arc_thread thr;
00652   t_mod_api is_admin = cf_get_mod_api_ent("is_admin");
00653   u_char *uname = cf_hash_get(GlobalValues,"UserName",8);
00654   int admin = uname ? (int)is_admin(uname) : 0;
00655   int show_invisible = cf_hash_get(GlobalValues,"ShowInvisible",13) != NULL;
00656 
00657   GdomeException e;
00658   GdomeDocument *doc;
00659   GdomeDOMImplementation *impl;
00660 
00661   /* no further headers (at the moment) */
00662   fwrite("\015\012",1,2,stdout);
00663 
00664   memset(&thr,0,sizeof(thr));
00665 
00666   /* generate file name */
00667   str_init(&path);
00668   str_chars_append(&path,apath->values[0],strlen(apath->values[0]));
00669   str_char_append(&path,'/');
00670   str_chars_append(&path,year,strlen(year));
00671   str_char_append(&path,'/');
00672   str_chars_append(&path,month,strlen(month));
00673   if(*tid == 't') str_char_append(&path,'/');
00674   else            str_chars_append(&path,"/t",2);
00675   str_chars_append(&path,tid,strlen(tid));
00676   str_chars_append(&path,".xml",4);
00677 
00678   if(stat(path.content,&st) == -1) {
00679     str_error_message("E_ARCHIVE_THREADNOTPRESENT",NULL,26);
00680     return;
00681   }
00682 
00683   impl = gdome_di_mkref();
00684   if((doc = gdome_di_createDocFromURI(impl,path.content,GDOME_LOAD_PARSING,&e)) == NULL) {
00685     str_error_message("E_ARCHIVE_THREADNOTPRESENT",NULL,26);
00686     gdome_di_unref(impl,&e);
00687     return;
00688   }
00689 
00690   create_thread_structure(doc,&thr);
00691 
00692   gdome_doc_unref(doc,&e);
00693   gdome_di_unref(impl,&e);
00694 
00695   if(thr.msgs->invisible == 0 || (admin == 1 && show_invisible == 1)) {
00696     print_thread_structure(&thr,year,month,admin,show_invisible);
00697   }
00698   else {
00699     str_error_message("E_FO_404",NULL,8);
00700   }
00701 }
00702 /* }}} */
00703 
00704 /* {{{ show_month_content */
00710 void show_month_content(const u_char *year,const u_char *month) {
00711   t_name_value *v      = cfg_get_value(&fo_default_conf,"ArchivePath");
00712   t_name_value *cs     = cfg_get_value(&fo_default_conf,"ExternCharset");
00713   t_name_value *m_tp   = cfg_get_value(&fo_arcview_conf,"MonthsTemplate");
00714   t_name_value *tl_tp  = cfg_get_value(&fo_arcview_conf,"ThreadListMonthTemplate");
00715   t_string path;
00716   struct stat st;
00717   u_char *ptr,*file,*tmp1,*tmp2;
00718   int fd;
00719   u_int64_t tid;
00720   time_t date;
00721   int len;
00722 
00723   t_cf_template m_tpl,tl_tpl;
00724   u_char mt_name[256],tl_name[256],buff[256];
00725 
00726   /* no additional headers */
00727   fwrite("\015\012",1,2,stdout);
00728 
00729 
00730   /* generate path to index file */
00731   str_init(&path);
00732 
00733   str_chars_append(&path,v->values[0],strlen(v->values[0]));
00734   str_char_append(&path,'/');
00735   str_chars_append(&path,year,strlen(year));
00736   str_char_append(&path,'/');
00737   str_chars_append(&path,month,strlen(month));
00738   str_chars_append(&path,"/index.xml",10);
00739 
00740   if(stat(path.content,&st) == -1) {
00741     perror("stat");
00742     str_error_message("E_ARCHIVE_MONTHNOTPRESENT",NULL,25);
00743     return;
00744   }
00745 
00746 
00747   /* get templates */
00748   generate_tpl_name(mt_name,256,m_tp);
00749   generate_tpl_name(tl_name,256,tl_tp);
00750 
00751   if(tpl_cf_init(&m_tpl,mt_name) != 0 || tpl_cf_init(&tl_tpl,tl_name) != 0) {
00752     str_error_message("E_CONFIG_ERR",NULL,12);
00753     return;
00754   }
00755 
00756 
00757   /* open file for mmap */
00758   if((fd = open(path.content,O_RDONLY)) == -1) {
00759     perror("open");
00760     str_error_message("E_ARCHIVE_MONTHNOTPRESENT",NULL,25);
00761     return;
00762   }
00763 
00764   if((caddr_t)(file = ptr = mmap(0,st.st_size,PROT_READ,MAP_FILE|MAP_SHARED,fd,0)) == (caddr_t)-1) {
00765     perror("mmap");
00766     str_error_message("E_ARCHIVE_MONTHNOTPRESENT",NULL,25);
00767     return;
00768   }
00769 
00770   for(;ptr < file + st.st_size;ptr++) {
00771     if(!(ptr = get_next_token(ptr,file,st.st_size,"<Thread",7))) break;
00772     tid = get_id(ptr,file,st.st_size);
00773     len = snprintf(buff,256,"%llu",tid);
00774     cf_set_variable(&tl_tpl,cs,"link",buff,len,1);
00775 
00776     if(!(ptr = get_next_token(ptr,file,st.st_size,"<Message",8))) break;
00777 
00778     /* we need: date, category, tid, subject, author */
00779     for(++ptr;ptr < file + st.st_size;ptr++) {
00780       if(*ptr == '<') {
00781         if(cf_strncmp(ptr,"<Name>",6) == 0) {
00782           tmp2 = get_next_token(ptr,file,st.st_size,"</Name>",7);
00783           tmp1 = strndup(ptr+6,tmp2-ptr-6);
00784           cf_set_variable(&tl_tpl,cs,"author",tmp1,tmp2-ptr-6,1);
00785           free(tmp1);
00786         }
00787         else if(cf_strncmp(ptr,"<Category",9) == 0) {
00788           if(cf_strncmp(ptr,"<Category/>",11) == 0) {
00789             tpl_cf_freevar(&tl_tpl,"cat");
00790           }
00791           else {
00792             tmp2 = get_next_token(ptr,file,st.st_size,"</Category>",11);
00793             tmp1 = strndup(ptr+10,tmp2-ptr-10);
00794             cf_set_variable(&tl_tpl,cs,"cat",tmp1,tmp2-ptr-10,1);
00795             free(tmp1);
00796           }
00797         }
00798         else if(cf_strncmp(ptr,"<Subject>",9) == 0) {
00799           tmp2 = get_next_token(ptr,file,st.st_size,"</Subject>",10);
00800           tmp1 = strndup(ptr+9,tmp2-ptr-9);
00801           cf_set_variable(&tl_tpl,cs,"subject",tmp1,tmp2-ptr-9,1);
00802           free(tmp1);
00803         }
00804         else if(cf_strncmp(ptr,"<Date",5) == 0) {
00805           ptr += 15;
00806           date = strtol(ptr,NULL,10);
00807           tmp1 = get_time(&fo_arcview_conf,"DateFormatList",&len,&date);
00808           cf_set_variable(&tl_tpl,cs,"date",tmp1,len,1);
00809           free(tmp1);
00810         }
00811         /* baba, finished */
00812         else if(cf_strncmp(ptr,"<Message",8) == 0 || cf_strncmp(ptr,"</Message>",10) == 0) break;
00813       }
00814     }
00815 
00816     tpl_cf_parse_to_mem(&tl_tpl);
00817   }
00818 
00819   munmap(file,st.st_size);
00820 
00821   len = get_month_name(atoi(month),&tmp1);
00822   cf_set_variable(&m_tpl,cs,"month",tmp1,len,1);
00823   cf_set_variable(&m_tpl,cs,"year",year,strlen(year),1);
00824 
00825   tpl_cf_setvar(&m_tpl,"charset",cs->values[0],strlen(cs->values[0]),0);
00826   tpl_cf_setvar(&m_tpl,"threads",tl_tpl.parsed.content,tl_tpl.parsed.len,0);
00827   tpl_cf_parse(&m_tpl);
00828 
00829   tpl_cf_finish(&tl_tpl);
00830   tpl_cf_finish(&m_tpl);
00831 }
00832 /* }}} */
00833 
00834 /* {{{ show_year_content */
00839 void show_year_content(const u_char *year) {
00840   t_name_value *v   = cfg_get_value(&fo_default_conf,"ArchivePath");
00841   t_name_value *mt  = cfg_get_value(&fo_arcview_conf,"MonthsTemplate");
00842   t_name_value *mlt = cfg_get_value(&fo_arcview_conf,"MonthsListTemplate");
00843   t_name_value *cs  = cfg_get_value(&fo_default_conf,"ExternCharset");
00844 
00845   t_cf_template mt_tpl,mlt_tpl;
00846 
00847   t_array *months;
00848   size_t len,i;
00849   int month;
00850 
00851   u_char mt_name[256],mlt_name[256],path[256],buff[10],*name;
00852 
00853   struct stat st;
00854 
00855   fwrite("\015\012",1,2,stdout);
00856 
00857   if(!v || !mt || !mlt) {
00858     str_error_message("E_CONFIG_ERR",NULL,12);
00859     return;
00860   }
00861 
00862   snprintf(path,256,"%s/%s",v->values[0],year);
00863   if(stat(path,&st) == -1) {
00864     perror("stat");
00865     str_error_message("E_ARCHIVE_YEARNOTPRESENT",NULL,24);
00866     return;
00867   }
00868 
00869   generate_tpl_name(mt_name,256,mt);
00870   generate_tpl_name(mlt_name,256,mlt);
00871 
00872   if(tpl_cf_init(&mt_tpl,mt_name) != 0 || tpl_cf_init(&mlt_tpl,mlt_name) != 0) {
00873     str_error_message("E_CONFIG_ERR",NULL,12);
00874     return;
00875   }
00876 
00877   months = read_dir_content(path);
00878 
00879   for(i=0;i<months->elements;i++) {
00880     month = *((int *)array_element_at(months,i));
00881     len = snprintf(buff,10,"%d",month);
00882 
00883     tpl_cf_setvar(&mlt_tpl,"month",buff,len,0);
00884 
00885     if((len = get_month_name(month,&name)) != 0) {
00886       tpl_cf_setvar(&mlt_tpl,"name",name,len,1);
00887       free(name);
00888     }
00889 
00890     tpl_cf_parse_to_mem(&mlt_tpl);
00891   }
00892 
00893   tpl_cf_setvar(&mt_tpl,"charset",cs->values[0],strlen(cs->values[0]),0);
00894   tpl_cf_setvar(&mt_tpl,"months",mlt_tpl.parsed.content,mlt_tpl.parsed.len,0);
00895   tpl_cf_parse(&mt_tpl);
00896 
00897   tpl_cf_finish(&mlt_tpl);
00898   tpl_cf_finish(&mt_tpl);
00899 }
00900 /* }}} */
00901 
00902 /* {{{ show_year_list */
00906 void show_year_list(void) {
00907   t_name_value *ap = cfg_get_value(&fo_default_conf,"ArchivePath");
00908   t_array *ary = read_dir_content(ap->values[0]);
00909 
00910   t_name_value *yt  = cfg_get_value(&fo_arcview_conf,"YearsTemplate");
00911   t_name_value *ylt = cfg_get_value(&fo_arcview_conf,"YearListTemplate");
00912 
00913   t_cf_template years,year;
00914   u_char buff[10],yt_name[256],ylt_name[256];
00915 
00916   unsigned int i,y;
00917 
00918   fwrite("\015\012",1,2,stdout);
00919 
00920   if(!ap || !yt || !ylt) {
00921     str_error_message("E_CONFIG_ERR",NULL,12);
00922     return;
00923   }
00924 
00925   generate_tpl_name(yt_name,256,yt);
00926   generate_tpl_name(ylt_name,256,ylt);
00927 
00928   if(tpl_cf_init(&years,yt_name) != 0 || tpl_cf_init(&year,ylt_name) != 0) {
00929     str_error_message("E_CONFIG_ERR",NULL,12);
00930     return;
00931   }
00932 
00933   for(i=0;i<ary->elements;i++) {
00934     y = *((int *)array_element_at(ary,i));
00935     y = snprintf(buff,10,"%d",y);
00936 
00937     tpl_cf_setvar(&year,"year",buff,y,0);
00938     tpl_cf_parse_to_mem(&year);
00939   }
00940 
00941   tpl_cf_setvar(&years,"years",year.parsed.content,year.parsed.len,0);
00942   tpl_cf_parse(&years);
00943 
00944   tpl_cf_finish(&year);
00945   tpl_cf_finish(&years);
00946 
00947   array_destroy(ary);
00948 }
00949 /* }}} */
00950 
00951 
00952 /* {{{ main */
00960 int main(int argc,char *argv[],char *env[]) {
00961   static const u_char *wanted[] = {
00962     "fo_default", "fo_arcview"
00963   };
00964 
00965   u_int32_t pieces;
00966   int ret;
00967   u_char  *ucfg;
00968   t_array *cfgfiles = get_conf_file(wanted,2);
00969   t_configfile conf,dconf,uconf;
00970   t_name_value *cs = NULL;
00971   u_char *UserName;
00972   u_char *fname;
00973   u_char **path_infos;
00974   t_cf_hash *head = cf_cgi_new();
00975   size_t len;
00976 
00977   if(!cfgfiles) {
00978     return EXIT_FAILURE;
00979   }
00980 
00981   init_modules();
00982 
00983   ret  = FLT_OK;
00984 
00985   fname = *((u_char **)array_element_at(cfgfiles,0));
00986   cfg_init_file(&dconf,fname);
00987   free(fname);
00988 
00989   fname = *((u_char **)array_element_at(cfgfiles,1));
00990   cfg_init_file(&conf,fname);
00991   free(fname);
00992 
00993   cfg_register_options(&dconf,default_options);
00994   cfg_register_options(&conf,fo_arcview_options);
00995 
00996   if(read_config(&dconf,NULL) != 0 || read_config(&conf,NULL) != 0) {
00997     fprintf(stderr,"config file error!\n");
00998 
00999     cfg_cleanup_file(&conf);
01000     cfg_cleanup_file(&dconf);
01001 
01002     return EXIT_FAILURE;
01003   }
01004 
01005   /* first action: authorization modules */
01006   if(Modules[AUTH_HANDLER].elements) {
01007     size_t i;
01008     t_filter_begin exec;
01009     t_handler_config *handler;
01010 
01011     ret = FLT_DECLINE;
01012 
01013     for(i=0;i<Modules[AUTH_HANDLER].elements && ret == FLT_DECLINE;i++) {
01014       handler = array_element_at(&Modules[AUTH_HANDLER],i);
01015 
01016       exec = (t_filter_begin)handler->func;
01017       ret = exec(head,&fo_default_conf,&fo_view_conf);
01018     }
01019   }
01020 
01021   if((UserName = cf_hash_get(GlobalValues,"UserName",8)) != NULL) {
01022     /* get user config */
01023     ucfg = get_uconf_name(UserName);
01024     if(ucfg) {
01025       free(conf.filename);
01026       conf.filename = ucfg;
01027 
01028       if(read_config(&conf,ignre) != 0) {
01029         fprintf(stderr,"config file error!\n");
01030 
01031         cfg_cleanup_file(&conf);
01032         cfg_cleanup_file(&dconf);
01033         cfg_cleanup_file(&uconf);
01034 
01035         return EXIT_FAILURE;
01036       }
01037     }
01038   }
01039 
01040   /* first state: let the begin-filters run! :-) */
01041   if(ret != FLT_EXIT && Modules[INIT_HANDLER].elements) {
01042     size_t i;
01043     t_handler_config *handler;
01044     t_filter_begin exec;
01045 
01046     for(i=0;i<Modules[INIT_HANDLER].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
01047       handler = array_element_at(&Modules[INIT_HANDLER],i);
01048       exec    = (t_filter_begin)handler->func;
01049       ret     = exec(head,&fo_default_conf,&fo_view_conf);
01050     }
01051   }
01052 
01053   cs = cfg_get_value(&fo_default_conf,"ExternCharset");
01054 
01055   if(ret != FLT_EXIT) {
01056     printf("Content-Type: text/html; charset=%s\015\012",cs?cs->values[0]?cs->values[0]:(u_char *)"UTF-8":(u_char *)"UTF-8");
01057 
01058 
01059     /* ok, let's check whats going on... parse PATH_INFO */
01060     pieces = path_info_parsed(&path_infos);
01061 
01062     /* {{{ we do not want bad values */
01063     /* bad, ugly ass! don't fool me! */
01064     for(len=0;len<pieces;len++) {
01065       /* we accept an trailing t for the tid */
01066       if(len == 3 && *path_infos[len] == 't') {
01067         if(!is_numeric(path_infos[len]+1)) {
01068           /* destroy everything */
01069           for(len=0;len<pieces;len++) {
01070             free(path_infos[len]);
01071           }
01072 
01073           free(path_infos);
01074           pieces = 0;
01075           break;
01076         }
01077       }
01078       else {
01079         if(!is_numeric(path_infos[len])) {
01080           /* destroy everything */
01081           for(len=0;len<pieces;len++) {
01082             free(path_infos[len]);
01083           }
01084 
01085           free(path_infos);
01086           pieces = 0;
01087           break;
01088         }
01089       }
01090     }
01091     /* }}} */
01092 
01093     switch(pieces) {
01094       /* year given */
01095       case 1:
01096         show_year_content(path_infos[0]);
01097         break;
01098       /* and month given */
01099       case 2:
01100         show_month_content(path_infos[0],path_infos[1]);
01101         break;
01102       /* and tid given */
01103       case 3:
01104         show_thread(path_infos[0],path_infos[1],path_infos[2]);
01105         break;
01106 
01107       /* show list of years due to an input error or nothing given */
01108       default:
01109         show_year_list();
01110     }
01111   }
01112 
01113   return EXIT_SUCCESS;
01114 }
01115 /* }}} */
01116 
01117 /* eof */

Generated on Sun Apr 25 16:37:39 2004 for Classic Forum by doxygen 1.3.5