00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020 #include "defines.h"
00021
00022 #include <pthread.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <stdio.h>
00026 #include <time.h>
00027 #include <pthread.h>
00028
00029 #include <gdome.h>
00030
00031 #include "cf_pthread.h"
00032
00033 #include "hashlib.h"
00034 #include "utils.h"
00035 #include "configparser.h"
00036 #include "readline.h"
00037 #include "fo_server.h"
00038 #include "initfinish.h"
00039 #include "charconvert.h"
00040 #include "xml_handling.h"
00041 #include "serverlib.h"
00042
00043
00044
00046 typedef struct s_h_p {
00047 t_posting *node;
00048 long len;
00049 struct s_h_p *childs;
00050 } t_h_p;
00051
00052
00059 t_posting *hirarchy_them(t_h_p *parent,t_posting *pst) {
00060 t_posting *p;
00061 int lvl;
00062
00063 p = pst;
00064 lvl = p->level;
00065
00066 while(p) {
00067 if(p->level == lvl) {
00068 parent->childs = fo_alloc(parent->childs,parent->len+1, sizeof(t_h_p),FO_ALLOC_REALLOC);
00069 memset(&parent->childs[parent->len],0,sizeof(t_h_p));
00070
00071 parent->childs[parent->len++].node = p;
00072 p = p->next;
00073 }
00074 else if(p->level > lvl) {
00075 p = hirarchy_them(&parent->childs[parent->len-1],p);
00076 }
00077 else {
00078 return p;
00079 }
00080 }
00081
00082 return NULL;
00083 }
00084
00085
00086
00093 void quicksort_posts(t_h_p *list,long low,long high) {
00094 long i = low,j = high;
00095 t_h_p *pivot,tmp;
00096
00097 pivot = &list[(low+high)/2];
00098
00099 do {
00100 while(i<high && list[i].node->date < pivot->node->date) i++;
00101 while(j>low && list[j].node->date > pivot->node->date) j--;
00102
00103 if(i <= j) {
00104 tmp = list[i];
00105 list[i] = list[j];
00106 list[j] = tmp;
00107 i++; j--;
00108 }
00109 } while(i <= j);
00110
00111 if(low<j) quicksort_posts(list,low,j);
00112 if(i<high) quicksort_posts(list,i,high);
00113 }
00114
00115
00116
00121 void sort_them(t_h_p *node) {
00122 long i;
00123
00124 if(node->len) {
00125 quicksort_posts(node->childs,0,node->len-1);
00126
00127 for(i=0;i<node->len;i++) {
00128 sort_them(&node->childs[i]);
00129 }
00130 }
00131
00132 }
00133
00134
00135
00140 void free_structs(t_h_p *node) {
00141 long i;
00142
00143 if(node->len) {
00144 for(i=0;i<node->len;i++) {
00145 free_structs(&node->childs[i]);
00146 }
00147
00148 free(node->childs);
00149 }
00150 }
00151
00152
00153
00160 t_posting *serialize_them(t_h_p *node,int sort) {
00161 long i;
00162 t_posting *p;
00163
00164 if(sort == 1) {
00165 if(node->len) {
00166 node->node->next = node->childs[0].node;
00167
00168 for(i=0;i<node->len;i++) {
00169 if(node->childs[i].len) {
00170 p = serialize_them(&node->childs[i],sort);
00171
00172 if(i < node->len-1) {
00173 p->next = node->childs[i+1].node;
00174 }
00175 else {
00176 p->next = NULL;
00177 return p;
00178 }
00179 }
00180 else {
00181 if(i < node->len-1) {
00182 node->childs[i].node->next = node->childs[i+1].node;
00183 }
00184 else {
00185 node->childs[i].node->next = NULL;
00186 return node->childs[i].node;
00187 }
00188 }
00189 }
00190 }
00191 else {
00192 node->node->next = NULL;
00193 return node->node;
00194 }
00195 }
00196 else {
00197 if(node->len) {
00198 node->node->next = node->childs[node->len-1].node;
00199
00200 for(i=node->len-1;i>=0;i--) {
00201 if(node->childs[i].len) {
00202 p = serialize_them(&node->childs[i],sort);
00203
00204 if(i > 0) {
00205 p->next = node->childs[i-1].node;
00206 }
00207 else {
00208 p->next = NULL;
00209 return p;
00210 }
00211 }
00212 else {
00213 if(i > 0) {
00214 node->childs[i].node->next = node->childs[i-1].node;
00215 }
00216 else {
00217 node->childs[i].node->next = NULL;
00218 return node->childs[i].node;
00219 }
00220 }
00221 }
00222 }
00223 else {
00224 node->node->next = NULL;
00225 return node->node;
00226 }
00227 }
00228
00229 return NULL;
00230 }
00231
00232
00233
00239 void sort_postings(t_posting *posts,int sort) {
00240 t_h_p *first = fo_alloc(NULL,1,sizeof(t_h_p),FO_ALLOC_CALLOC);
00241
00242 if(posts->next) {
00243 first->node = posts;
00244 hirarchy_them(first,posts);
00245
00246 }
00247 else {
00248 free(first);
00249 return;
00250 }
00251
00252 sort_them(first);
00253 serialize_them(first,sort);
00254
00255 free_structs(first);
00256 free(first);
00257 }
00258
00259
00260
00267 void quicksort_threads(t_thread **list,long low,long high) {
00268 long i = low,j = high;
00269 t_thread *pivot,*tmp;
00270
00271 pivot = list[(low+high)/2];
00272
00273 do {
00274 while(i<high && list[i]->postings->date < pivot->postings->date) i++;
00275 while(j>low && list[j]->postings->date > pivot->postings->date) j--;
00276
00277 if(i <= j) {
00278 tmp = list[i];
00279 list[i] = list[j];
00280 list[j] = tmp;
00281 i++; j--;
00282 }
00283 } while(i <= j);
00284
00285 if(low<j) quicksort_threads(list,low,j);
00286 if(i<high) quicksort_threads(list,i,high);
00287 }
00288
00289
00290
00295 void sort_threadlist(t_head *head) {
00296 t_name_value *sort_thr_v = cfg_get_value(&fo_server_conf,"SortThreads");
00297 t_name_value *sort_msg_v = cfg_get_value(&fo_server_conf,"SortMessages");
00298 int threadnum = 0,reser = 0,i,sort_thr,sort_msg;
00299 t_thread **list = NULL,*tmp;
00300 t_posting *p,*p1;
00301
00302 sort_thr = atoi(sort_thr_v->values[0]);
00303 sort_msg = atoi(sort_msg_v->values[0]);
00304
00305 for(tmp=head->thread;tmp;tmp=tmp->next,threadnum++) {
00306 if(threadnum >= reser) {
00307 reser += 5;
00308 list = fo_alloc(list,reser,sizeof(t_thread *),FO_ALLOC_REALLOC);
00309 }
00310
00311 list[threadnum] = tmp;
00312 }
00313
00314 quicksort_threads(list,0,threadnum-1);
00315
00316 if(sort_thr == 1) {
00317 for(i=0;i<threadnum;i++) {
00318 sort_postings(list[i]->postings,sort_msg);
00319
00320
00321 for(p=list[i]->postings,p1=NULL;p;p=p->next) {
00322 p->prev = p1;
00323 p1 = p;
00324 }
00325
00326 if(i < threadnum-1) {
00327 list[i]->next = list[i+1];
00328 if(i==0) list[i]->prev = NULL;
00329 else list[i]->prev = list[i-1];
00330 }
00331 else {
00332 list[i]->next = NULL;
00333 if(i==0) list[i]->prev = NULL;
00334 else list[i]->prev = list[i-1];
00335 }
00336 }
00337 }
00338 else {
00339 for(i=threadnum-1;i>=0;i--) {
00340 sort_postings(list[i]->postings,sort_msg);
00341
00342 if(i > 0) {
00343 list[i]->next = list[i-1];
00344 if(i<threadnum-1) list[i]->prev = list[i+1];
00345 else list[i]->prev = NULL;
00346 }
00347 else {
00348 list[i]->next = NULL;
00349 if(i<threadnum-1) list[i]->prev = list[i+1];
00350 else list[i]->prev = NULL;
00351 }
00352 }
00353
00354 head->thread = list[threadnum-1];
00355 }
00356
00357 free(list);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 void make_forumtree(t_configuration *cfg,t_head *head) {
00371 int i = 0,len = 0,len1 = 0;
00372 u_char *fname = fo_alloc(NULL,MAXLINE,1,FO_ALLOC_MALLOC);
00373 u_char *tmp = fo_alloc(NULL,MAXLINE,1,FO_ALLOC_MALLOC);
00374 GdomeException exc;
00375 GdomeDocument *doc;
00376 GdomeElement *el;
00377 GdomeNodeList *nl;
00378 t_name_value *msgpath = cfg_get_value(cfg,"MessagePath");
00379 GdomeDOMImplementation *impl = gdome_di_mkref();
00380 GdomeDOMString *thread_str = gdome_str_mkref("Thread");
00381 GdomeDOMString *tmpstr,*tmpstr1;
00382 u_char buff[50];
00383
00384 (void)strcpy(fname,msgpath->values[0]);
00385 (void)strcpy(tmp,msgpath->values[0]);
00386 if(fname[strlen(fname)-1] != '/') {
00387 (void)strcat(fname,"/");
00388 (void)strcat(tmp,"/");
00389 }
00390
00391 (void)strcat(fname,"forum.xml");
00392
00393 len1 = strlen(tmp);
00394 doc = gdome_di_createDocFromURI(impl,fname,GDOME_LOAD_PARSING,&exc);
00395
00396 if(!doc) {
00397 cf_log(LOG_ERR,__FILE__,__LINE__,"coult not load file %s!\n",fname);
00398 exit(-1);
00399 }
00400
00401 el = gdome_doc_documentElement(doc,&exc);
00402 nl = gdome_doc_getElementsByTagName(doc,thread_str,&exc);
00403
00404
00405 tmpstr = gdome_str_mkref("lastMessage");
00406 tmpstr1 = gdome_el_getAttribute(el,tmpstr,&exc);
00407 head->mid = strtoull(tmpstr1->str+1,NULL,10);
00408 gdome_str_unref(tmpstr1);
00409 gdome_str_unref(tmpstr);
00410
00411 tmpstr = gdome_str_mkref("lastThread");
00412 tmpstr1 = gdome_el_getAttribute(el,tmpstr,&exc);
00413 head->tid = strtoull(tmpstr1->str+1,NULL,10);
00414 gdome_str_unref(tmpstr);
00415 gdome_str_unref(tmpstr1);
00416 gdome_el_unref(el,&exc);
00417
00418 len = gdome_nl_length(nl,&exc);
00419
00420 for(i=0;i<len;i++) {
00421 GdomeDocument *tmpdoc;
00422 GdomeNodeList *nl_threads,*nl_msgcnt;
00423 GdomeNode *nl_thread,*nl_message;
00424 t_thread *thread = fo_alloc(NULL,1,sizeof(t_thread),FO_ALLOC_CALLOC);
00425 GdomeNode *thread_el = gdome_nl_item(nl,i,&exc);
00426 GdomeNamedNodeMap *atts = gdome_n_attributes(thread_el,&exc);
00427 GdomeDOMString *id_str = gdome_str_mkref("id");
00428 GdomeDOMString *msgcnt_str = gdome_str_mkref("MessageContent");
00429 GdomeNode *id_n = gdome_nnm_getNamedItem(atts,id_str,&exc);
00430 GdomeDOMString *id = gdome_n_nodeValue(id_n,&exc);
00431 GdomeNode *posting = gdome_n_firstChild(thread_el,&exc);
00432
00433 (void)strcpy(&tmp[len1],id->str);
00434 strcat(tmp,".xml");
00435 tmpdoc = gdome_di_createDocFromURI(impl,tmp,GDOME_LOAD_PARSING,&exc);
00436
00437 nl_threads = gdome_doc_getElementsByTagName(tmpdoc,thread_str,&exc);
00438 nl_thread = gdome_nl_item(nl_threads,0,&exc);
00439 nl_message = gdome_n_firstChild(nl_thread,&exc);
00440
00441 nl_msgcnt = gdome_doc_getElementsByTagName(tmpdoc,msgcnt_str,&exc);
00442
00443 thread->tid = strtoull(&id->str[1],NULL,10);
00444 thread->next = head->thread;
00445 thread->postings = fo_alloc(NULL,1,sizeof(t_posting),FO_ALLOC_CALLOC);
00446 thread->last = thread->postings;
00447 if(head->thread) head->thread->prev = thread;
00448 head->thread = thread;
00449
00450
00451 cf_register_thread(thread);
00452
00453
00454 snprintf(buff,50,"t%lld",thread->tid);
00455 cf_rwlock_init(buff,&thread->lock);
00456
00457 make_thread_tree(nl_message,posting,nl_msgcnt,thread,thread->postings,0,0);
00458
00459 gdome_nl_unref(nl_msgcnt,&exc);
00460 gdome_nl_unref(nl_threads,&exc);
00461 gdome_n_unref(nl_thread,&exc);
00462 gdome_n_unref(nl_message,&exc);
00463 gdome_di_freeDoc(impl,tmpdoc,&exc);
00464
00465 gdome_str_unref(msgcnt_str);
00466 gdome_str_unref(id);
00467 gdome_str_unref(id_str);
00468 gdome_n_unref(id_n,&exc);
00469 gdome_n_unref(thread_el,&exc);
00470 gdome_n_unref(posting,&exc);
00471 gdome_nnm_unref(atts,&exc);
00472 }
00473
00474 gdome_nl_unref(nl,&exc);
00475 gdome_di_freeDoc(impl,doc,&exc);
00476 gdome_di_unref(impl,&exc);
00477
00478 free(tmp);
00479 free(fname);
00480
00481 if(head->thread) {
00482 t_thread *thread;
00483
00484 sort_threadlist(head);
00485
00486 for(thread=head->thread;thread->next;thread=thread->next);
00487 head->last = thread;
00488 }
00489 }
00490
00491
00492
00499 GdomeNode *get_posting_content(GdomeNodeList *contents,unsigned long long mid) {
00500 GdomeException exc;
00501 int len = gdome_nl_length(contents,&exc);
00502 int i;
00503
00504 for(i=0;i<len;i++) {
00505 GdomeNode *n = gdome_nl_item(contents,i,&exc);
00506 GdomeDOMString *str_mid = gdome_str_mkref("mid");
00507 GdomeNamedNodeMap *atts = gdome_n_attributes(n,&exc);
00508 GdomeNode *nmid = gdome_nnm_getNamedItem(atts,str_mid,&exc);
00509
00510 if(!nmid) {
00511 cf_log(LOG_ERR,__FILE__,__LINE__,"Could not get mid in message m%lld\n",mid);
00512 }
00513 else {
00514 GdomeDOMString *val = gdome_n_nodeValue(nmid,&exc);
00515
00516 if(val) {
00517 unsigned long long m = strtoull(val->str+1,NULL,10);
00518
00519 if(m == mid) {
00520 gdome_str_unref(val);
00521
00522 gdome_nnm_unref(atts,&exc);
00523 gdome_n_unref(nmid,&exc);
00524 gdome_str_unref(str_mid);
00525
00526 return n;
00527 }
00528
00529 gdome_str_unref(val);
00530 }
00531
00532 gdome_n_unref(nmid,&exc);
00533 }
00534
00535
00536 gdome_nnm_unref(atts,&exc);
00537 gdome_n_unref(n,&exc);
00538 gdome_str_unref(str_mid);
00539 }
00540
00541 return NULL;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 void make_thread_tree(GdomeNode *posting_newdoc, GdomeNode *posting_index, GdomeNodeList *contents, t_thread *thread, t_posting *post, int level,int pos) {
00559 int i,len,z;
00560 GdomeException exc;
00561 GdomeNodeList *childs_nd = gdome_n_childNodes(posting_newdoc,&exc);
00562 GdomeNodeList *childs_in = gdome_n_childNodes(posting_index,&exc);
00563 GdomeNamedNodeMap *atts = gdome_n_attributes(posting_newdoc,&exc);
00564 GdomeNamedNodeMap *atts_ind = gdome_n_attributes(posting_index,&exc);
00565 GdomeDOMString *str_id = gdome_str_mkref("id");
00566 GdomeDOMString *str_ip = gdome_str_mkref("ip");
00567 GdomeDOMString *str_invi = gdome_str_mkref("invisible");
00568 GdomeDOMString *str_unid = gdome_str_mkref("unid");
00569 GdomeNode *invi = gdome_nnm_getNamedItem(atts,str_invi,&exc);
00570 GdomeNode *id = gdome_nnm_getNamedItem(atts,str_id,&exc);
00571 GdomeNode *ip = gdome_nnm_getNamedItem(atts,str_ip,&exc);
00572 GdomeNode *unid = gdome_nnm_getNamedItem(atts_ind,str_unid,&exc);
00573 GdomeNode *fcnt = NULL;
00574 GdomeDOMString *tmp = NULL;
00575
00576 post->level = level;
00577 thread->posts += 1;
00578
00579 if(id) {
00580 GdomeDOMString *tmp = gdome_n_nodeValue(id,&exc);
00581 post->mid = strtoull(&tmp->str[1],NULL,10);
00582
00583 gdome_str_unref(tmp);
00584 }
00585 else {
00586 cf_log(LOG_ERR,__FILE__,__LINE__,"could not get posting id for thread t%lld, posting %d!\n",thread->tid,pos);
00587 exit(0);
00588 }
00589
00590 if(unid) {
00591 GdomeDOMString *tmp = gdome_n_nodeValue(unid,&exc);
00592 post->unid = strdup(tmp->str);
00593 post->unid_len = strlen(post->unid);
00594 gdome_str_unref(tmp);
00595 }
00596 else {
00597 cf_log(LOG_ERR,__FILE__,__LINE__,"could not get unique id for thread t%lld, posting m%lld!\n",thread->tid,post->mid);
00598 }
00599
00600 gdome_nnm_unref(atts_ind,&exc);
00601 gdome_str_unref(str_unid);
00602 gdome_n_unref(unid,&exc);
00603
00604
00605 if(ip) {
00606 GdomeDOMString *tmp = gdome_n_nodeValue(ip,&exc);
00607 post->user.ip = strdup(tmp->str);
00608 post->user.ip_len = strlen(post->user.ip);
00609
00610 gdome_str_unref(tmp);
00611 }
00612 else {
00613 cf_log(LOG_ERR,__FILE__,__LINE__,"could not get user ip for thread t%lld, posting m%lld!\n",thread->tid,post->mid);
00614 exit(0);
00615 }
00616
00617 if(invi) {
00618 GdomeDOMString *tmp = gdome_n_nodeValue(invi,&exc);
00619 post->invisible = atoi(tmp->str);
00620
00621 gdome_str_unref(tmp);
00622 }
00623 else {
00624 post->invisible = 0;
00625 }
00626
00627 fcnt = get_posting_content(contents,post->mid);
00628 if(fcnt) {
00629 GdomeNode *n = gdome_n_firstChild(fcnt,&exc);
00630 tmp = gdome_n_nodeValue(n,&exc);
00631 gdome_n_unref(n,&exc);
00632 }
00633 else {
00634 cf_log(LOG_ERR,__FILE__,__LINE__,"error: could not get content for thread t%lld, message m%lld\n",thread->tid,post->mid);
00635 exit(0);
00636 }
00637
00638 if(tmp) {
00639 post->content = strdup(tmp->str);
00640 post->content_len = strlen(post->content);
00641 gdome_str_unref(tmp);
00642 }
00643 else {
00644 cf_log(LOG_ERR,__FILE__,__LINE__,"could not get posting content for thread t%lld, message m%lld\n",thread->tid,post->mid);
00645 exit(0);
00646 }
00647
00648 len = gdome_nl_length(childs_nd,&exc);
00649
00650 for(z=0,i=0;i<len;i++) {
00651 GdomeNode *element_nd = gdome_nl_item(childs_nd,i,&exc);
00652 GdomeNode *element_in = gdome_nl_item(childs_in,i,&exc);
00653 GdomeDOMString *name_nd = gdome_n_nodeName(element_nd,&exc);
00654
00655 if(cf_strcmp(name_nd->str,"Header") == 0) {
00656 handle_header(post,element_nd,thread->tid);
00657
00658 if(!thread->newest || post->date > thread->newest->date) thread->newest = post;
00659 if(!thread->oldest || post->date < thread->oldest->date) thread->oldest = post;
00660 }
00661 else if(cf_strcmp(name_nd->str,"Message") == 0) {
00662 t_posting *p = fo_alloc(NULL,1,sizeof(t_posting),FO_ALLOC_CALLOC);
00663 z++;
00664
00665 if(thread->last != NULL) {
00666 thread->last->next = p;
00667 }
00668
00669 p->prev = thread->last;
00670 thread->last = p;
00671
00672 make_thread_tree(element_nd,element_in,contents,thread,p,level+1,z+pos);
00673 }
00674
00675 gdome_str_unref(name_nd);
00676 gdome_n_unref(element_nd,&exc);
00677 gdome_n_unref(element_in,&exc);
00678 }
00679
00680 if(fcnt) {
00681 gdome_n_unref(fcnt,&exc);
00682 }
00683
00684 gdome_n_unref(invi,&exc);
00685 gdome_str_unref(str_ip);
00686 gdome_n_unref(ip,&exc);
00687 gdome_nnm_unref(atts,&exc);
00688 gdome_str_unref(str_id);
00689 gdome_str_unref(str_invi);
00690 gdome_n_unref(id,&exc);
00691 gdome_nl_unref(childs_nd,&exc);
00692 gdome_nl_unref(childs_in,&exc);
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 void handle_header(t_posting *p,GdomeNode *n,u_int64_t tid) {
00706 GdomeException exc;
00707 GdomeNodeList *nl = gdome_n_childNodes(n,&exc);
00708 GdomeNode *author = gdome_nl_item(nl,0,&exc);
00709 GdomeNode *category = gdome_nl_item(nl,1,&exc);
00710 GdomeNode *subject = gdome_nl_item(nl,2,&exc);
00711 GdomeNode *date = gdome_nl_item(nl,3,&exc);
00712 GdomeDOMString *ls_str = gdome_str_mkref("longSec");
00713 GdomeNamedNodeMap *atts = gdome_n_attributes(date,&exc);
00714 GdomeNode *longSec = gdome_nnm_getNamedItem(atts,ls_str,&exc);
00715 GdomeDOMString *ls_val = gdome_n_nodeValue(longSec,&exc);
00716
00717 GdomeNodeList *a_nl = gdome_n_childNodes(author,&exc);
00718 GdomeNode *a_name = gdome_nl_item(a_nl,0,&exc);
00719 GdomeNode *a_email = gdome_nl_item(a_nl,1,&exc);
00720 GdomeNode *a_hp = gdome_nl_item(a_nl,2,&exc);
00721 GdomeNode *a_img = gdome_nl_item(a_nl,3,&exc);
00722
00723 p->date = strtol(ls_val->str,NULL,10);
00724
00725 p->user.name = get_node_value(a_name);
00726 p->user.name_len = strlen(p->user.name);
00727 p->subject = get_node_value(subject);
00728 p->subject_len = strlen(p->subject);
00729 p->category = get_node_value(category);
00730 if(p->category) p->category_len = strlen(p->category);
00731 p->user.email = get_node_value(a_email);
00732 if(p->user.email) p->user.email_len = strlen(p->user.email);
00733 p->user.hp = get_node_value(a_hp);
00734 if(p->user.hp) p->user.hp_len = strlen(p->user.hp);
00735 p->user.img = get_node_value(a_img);
00736 if(p->user.img) p->user.img_len = strlen(p->user.img);
00737
00738 if(!p->subject) {
00739 cf_log(LOG_ERR,__FILE__,__LINE__,"no subject in thread t%lld, message m%lld\n",tid,p->mid);
00740 exit(0);
00741 }
00742
00743 gdome_str_unref(ls_val);
00744 gdome_n_unref(a_name,&exc);
00745 gdome_n_unref(a_email,&exc);
00746 gdome_n_unref(a_hp,&exc);
00747 gdome_n_unref(a_img,&exc);
00748 gdome_n_unref(longSec,&exc);
00749 gdome_nl_unref(a_nl,&exc);
00750 gdome_str_unref(ls_str);
00751 gdome_nnm_unref(atts,&exc);
00752 gdome_n_unref(author,&exc);
00753 gdome_n_unref(category,&exc);
00754 gdome_n_unref(subject,&exc);
00755 gdome_n_unref(date,&exc);
00756 gdome_nl_unref(nl,&exc);
00757 }
00758
00759
00760
00761 void cleanup_forumtree() {
00762 t_thread *t,*t1;
00763 t_posting *p,*p1;
00764
00765 for(t=head.thread;t;t=t1) {
00766 for(p=t->postings;p;p=p1) {
00767 free(p->user.name);
00768 free(p->subject);
00769 free(p->unid);
00770 free(p->user.ip);
00771 free(p->content);
00772
00773 if(p->category) free(p->category);
00774 if(p->user.email) free(p->user.email);
00775 if(p->user.hp) free(p->user.hp);
00776 if(p->user.img) free(p->user.img);
00777
00778 p1 = p->next;
00779 free(p);
00780 }
00781
00782 cf_rwlock_destroy(&t->lock);
00783
00784 t1 = t->next;
00785 free(t);
00786 }
00787
00788 str_cleanup(&head.cache_invisible);
00789 str_cleanup(&head.cache_visible);
00790 }
00791
00792
00793