00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00050 #ifndef DOXYGEN
00051 int ignre(t_configfile *cf,u_char **args,int argnum) {
00052 return 0;
00053 }
00054 #endif
00055
00056
00057
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
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
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
00106 return 0;
00107 }
00108 #endif
00109
00110
00111
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00559 if(msg->childs.elements > 1) {
00560 array_sort(&msg->childs,sort_compare);
00561 }
00562 }
00563
00564
00565
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
00591
00592
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
00618
00619
00620
00621
00622
00623
00624
00625
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
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
00662 fwrite("\015\012",1,2,stdout);
00663
00664 memset(&thr,0,sizeof(thr));
00665
00666
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
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
00727 fwrite("\015\012",1,2,stdout);
00728
00729
00730
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
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
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
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
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
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
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
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
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
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
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
01060 pieces = path_info_parsed(&path_infos);
01061
01062
01063
01064 for(len=0;len<pieces;len++) {
01065
01066 if(len == 3 && *path_infos[len] == 't') {
01067 if(!is_numeric(path_infos[len]+1)) {
01068
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
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
01095 case 1:
01096 show_year_content(path_infos[0]);
01097 break;
01098
01099 case 2:
01100 show_month_content(path_infos[0],path_infos[1]);
01101 break;
01102
01103 case 3:
01104 show_thread(path_infos[0],path_infos[1],path_infos[2]);
01105 break;
01106
01107
01108 default:
01109 show_year_list();
01110 }
01111 }
01112
01113 return EXIT_SUCCESS;
01114 }
01115
01116
01117