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

fo_view.c

Go to the documentation of this file.
00001 
00007 /* {{{ Initial comment */
00008 /*
00009  * $LastChangedDate: 2004-04-01 18:34:17 +0200 (Thu, 01 Apr 2004) $
00010  * $LastChangedRevision: 50 $
00011  * $LastChangedBy: ckruse $
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 <dlfcn.h>
00023 #include <errno.h>
00024 
00025 #include <sys/types.h>
00026 
00027 /* socket includes */
00028 #include <sys/socket.h>
00029 #include <netdb.h>
00030 #include <unistd.h>
00031 #include <sys/un.h>
00032 
00033 #ifdef CF_SHARED_MEM
00034 #include <sys/ipc.h>
00035 #include <sys/shm.h>
00036 #endif
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 "clientlib.h"
00045 #include "fo_view.h"
00046 /* }}} */
00047 
00051 int ignre(t_configfile *cf,u_char **args,int argnum) {
00052   return 0;
00053 }
00054 
00055 /* {{{ print_thread_structure
00056  * Returns: nothing
00057  * Parameters:
00058  *   - t_cl_thread *thr  the thread structure
00059  *
00060  * this function prints a thread list
00061  *
00062  */
00063 void print_thread_structure(t_cl_thread *thread,t_cf_hash *head) {
00064   t_message *msg;
00065   int level = 0,len = 0;
00066   u_char *date,*link;
00067   int printed = 0,rc = 0;
00068   t_name_value *cs = cfg_get_value(&fo_default_conf,"ExternCharset");
00069   int ShowInvisible = cf_hash_get(GlobalValues,"ShowInvisible",13) == NULL ? 0 : 1;
00070 
00071   for(msg=thread->messages;msg;msg=msg->next) {
00072     if((msg->may_show && msg->invisible == 0) || ShowInvisible == 1) {
00073       rc = handle_thread_list_posting(msg,head,thread->tid,0);
00074       if(ShowInvisible == 0 && ((rc != FLT_DECLINE && rc != FLT_OK) || msg->may_show == 0)) continue;
00075 
00076       printed = 1;
00077 
00078       date = get_time(&fo_view_conf,"DateFormatThreadList",&len,&msg->date);
00079       link = get_link(thread->tid,msg->mid);
00080 
00081       cf_set_variable(&msg->tpl,cs,"author",msg->author,strlen(msg->author),1);
00082       cf_set_variable(&msg->tpl,cs,"title",msg->subject,strlen(msg->subject),1);
00083 
00084       if(msg->category) {
00085         cf_set_variable(&msg->tpl,cs,"category",msg->category,strlen(msg->category),1);
00086       }
00087 
00088       if(date) {
00089         cf_set_variable(&msg->tpl,cs,"time",date,len,1);
00090         free(date);
00091       }
00092 
00093       if(link) {
00094         cf_set_variable(&msg->tpl,cs,"link",link,strlen(link),1);
00095         free(link);
00096       }
00097 
00098       if(msg->level < level) {
00099         for(;level>msg->level;level--) {
00100           printf("</ul></li>");
00101         }
00102       }
00103 
00104       level = msg->level;
00105 
00106       if(msg->next && has_answers(msg)) { /* this message has at least one answer */
00107         printf("<li>");
00108         tpl_cf_parse(&msg->tpl);
00109         printf("<ul>");
00110 
00111         level++;
00112       }
00113       else {
00114         printf("<li>");
00115         tpl_cf_parse(&msg->tpl);
00116         printf("</li>");
00117       }
00118     }
00119   }
00120 
00121   for(;level>0;level--) {
00122     printf("</ul></li>");
00123   }
00124 
00125   if(printed) {
00126     printf("\n<li>&nbsp;</li>\n");
00127   }
00128 }
00129 /* }}} */
00130 
00131 
00132 /* {{{ send_posting
00133  * Returns: nothing
00134  * Parameters:
00135  *   - int sock                 the socket handle
00136  *   - unsigned long long tid   the thread-id
00137  *   - unsigned long long mid   the message-id
00138  *
00139  * this function sends a posting to an user
00140  *
00141  */
00142 #ifndef CF_SHARED_MEM
00143 void send_posting(t_cf_hash *head,int sock,u_int64_t tid,u_int64_t mid) {
00144 #else
00145 void send_posting(t_cf_hash *head,void *shm_ptr,u_int64_t tid,u_int64_t mid) {
00146 #endif
00147   t_cl_thread thread;
00148   #ifndef CF_SHARED_MEM
00149   rline_t tsd;
00150   #endif
00151   t_name_value *fo_thread_tpl  = cfg_get_value(&fo_view_conf,"TemplateForumThread");
00152   t_name_value *fo_posting_tpl = cfg_get_value(&fo_view_conf,"TemplatePosting");
00153   t_cf_template tpl;
00154   u_char fo_thread_tplname[256],fo_posting_tplname[256];
00155   size_t len;
00156   char buff[128];
00157   int del = cf_hash_get(GlobalValues,"ShowInvisible",13) == NULL ? CF_KILL_DELETED : CF_KEEP_DELETED;
00158 
00159   #ifndef CF_SHARED_MEM
00160   memset(&tsd,0,sizeof(tsd));
00161   #endif
00162 
00163   if(!fo_thread_tpl || !fo_posting_tpl) {
00164     str_error_message("E_TPL_NOT_FOUND",NULL,15);
00165     return;
00166   }
00167 
00168   generate_tpl_name(fo_thread_tplname,256,fo_thread_tpl);
00169   generate_tpl_name(fo_posting_tplname,256,fo_posting_tpl);
00170 
00171   if(tpl_cf_init(&tpl,fo_posting_tplname) != 0) {
00172     str_error_message("E_TPL_NOT_FOUND",NULL,15);
00173     return;
00174   }
00175 
00176   #ifndef CF_SHARED_MEM
00177   if(cf_get_message_through_sock(sock,&tsd,&thread,fo_thread_tplname,tid,mid,del) == -1) {
00178   #else
00179   if(cf_get_message_through_shm(shm_ptr,&thread,fo_thread_tplname,tid,mid,del) == -1) {
00180   #endif
00181     str_error_message(ErrorString,NULL,strlen(ErrorString));
00182     return;
00183   }
00184 
00185   len = snprintf(buff,128,"%d",thread.msg_len);
00186   tpl_cf_setvar(&thread.messages->tpl,"msgnum",buff,len,0);
00187 
00188   len = snprintf(buff,128,"%d",thread.msg_len-1);
00189   tpl_cf_setvar(&thread.messages->tpl,"answers",buff,len,0);
00190 
00191   if(handle_posting_filters(head,&thread,&tpl) != FLT_EXIT) {
00192     tpl_cf_parse(&tpl);
00193   }
00194 
00195   tpl_cf_finish(&tpl);
00196 
00197   cleanup_struct(&thread);
00198 }
00199 /* }}} */
00200 
00201 /* {{{ send_threadlist
00202  * Returns: nothing
00203  * Parameters:
00204  *   - int sock         the socket
00205  *   - t_cf_hash *head  the list of the cgi lib
00206  *
00207  * this function sends a threadlist to an user
00208  *
00209  */
00210 #ifndef CF_SHARED_MEM
00211 void send_threadlist(int sock,t_cf_hash *head) {
00212 #else
00213 void send_threadlist(void *shm_ptr,t_cf_hash *head) {
00214 #endif
00215   int ret,len;
00216   #ifndef CF_SHARED_MEM
00217   rline_t tsd;
00218   u_char *line,*tmp;
00219   #else
00220   void *ptr,*ptr1;
00221   #endif
00222 
00223   t_name_value *fo_begin_tpl  = cfg_get_value(&fo_view_conf,"TemplateForumBegin");
00224   t_name_value *fo_end_tpl    = cfg_get_value(&fo_view_conf,"TemplateForumEnd");
00225   t_name_value *fo_thread_tpl = cfg_get_value(&fo_view_conf,"TemplateForumThread");
00226   t_name_value *cs            = cfg_get_value(&fo_default_conf,"ExternCharset");
00227   t_cf_template tpl_begin,tpl_end;
00228   u_char fo_begin_tplname[256],fo_end_tplname[256],fo_thread_tplname[256],buff[128],*ltime;
00229   time_t tm;
00230   t_cl_thread thread;
00231   size_t i;
00232   t_handler_config *handler;
00233   t_filter_init_view fkt;
00234   int del = cf_hash_get(GlobalValues,"ShowInvisible",13) == NULL ? CF_KILL_DELETED : CF_KEEP_DELETED;
00235 
00236   /* initialization work */
00237 
00238   #ifndef CF_SHARED_MEM
00239   memset(&tsd,0,sizeof(tsd));
00240   #endif
00241 
00242   if(!fo_begin_tpl || !fo_end_tpl || !fo_thread_tpl) {
00243     str_error_message("E_TPL_NOT_FOUND",NULL,15);
00244     return;
00245   }
00246 
00247   generate_tpl_name(fo_begin_tplname,256,fo_begin_tpl);
00248   generate_tpl_name(fo_end_tplname,256,fo_end_tpl);
00249   generate_tpl_name(fo_thread_tplname,256,fo_thread_tpl);
00250 
00251   /*
00252    * if not in shm mode, request the threadlist from
00253    * the forum server. If in shm mode, request the
00254    * shm pointer
00255    */
00256 
00257   #ifndef CF_SHARED_MEM
00258   len = snprintf(buff,128,"GET THREADLIST invisible=%d\n",del);
00259   writen(sock,buff,len);
00260   line = readline(sock,&tsd);
00261   #else
00262   ptr = shm_ptr;
00263   ptr1 = ptr + sizeof(time_t);
00264   #endif
00265 
00266   /*
00267    * Check if request was ok. If not, send error message.
00268    */
00269   #ifndef CF_SHARED_MEM
00270   if(!line || cf_strcmp(line,"200 Ok\n")) {
00271     if(line) {
00272       ret = snprintf(buff,128,"E_FO_%d",atoi(line));
00273       str_error_message(buff,NULL,ret);
00274       free(line);
00275     }
00276     else {
00277       str_error_message("E_NO_THREADLIST",NULL,15);
00278     }
00279   }
00280   #else
00281   if(!ptr) {
00282     str_error_message("E_NO_CONN",NULL,9,strerror(errno));
00283   }
00284   #endif
00285 
00286   /*
00287    * Request of shm segment/threadlist wen't through,
00288    * go on with work
00289    */
00290   else {
00291     tm    = time(NULL);
00292     ltime = get_time(&fo_view_conf,"DateFormatLoadTime",&len,&tm);
00293 
00294     if(tpl_cf_init(&tpl_begin,fo_begin_tplname) != 0) {
00295       str_error_message("E_TPL_NOT_FOUND",NULL,15);
00296       return;
00297     }
00298     if(tpl_cf_init(&tpl_end,fo_end_tplname) != 0) {
00299       str_error_message("E_TPL_NOT_FOUND",NULL,15);
00300       return;
00301     }
00302 
00303     tpl_cf_setvar(&tpl_begin,"charset",cs->values[0],strlen(cs->values[0]),0);
00304 
00305     /* run some plugins */
00306     if(Modules[VIEW_INIT_HANDLER].elements) {
00307       for(i=0;i<Modules[VIEW_INIT_HANDLER].elements;i++) {
00308         handler = array_element_at(&Modules[VIEW_INIT_HANDLER],i);
00309         fkt     = (t_filter_init_view)handler->func;
00310         fkt(head,&fo_default_conf,&fo_view_conf,&tpl_begin,&tpl_end);
00311       }
00312     }
00313 
00314     #ifndef CF_SHARED_MEM
00315     free(line);
00316     #endif
00317 
00318     thread.tid      = 0;
00319     thread.messages = NULL;
00320     thread.last     = NULL;
00321     thread.msg_len  = 0;
00322 
00323     if(ltime) {
00324       cf_set_variable(&tpl_begin,cs,"LOAD_TIME",ltime,len,1);
00325       free(ltime);
00326     }
00327 
00328     tpl_cf_parse(&tpl_begin);
00329     tpl_cf_finish(&tpl_begin);
00330 
00331     #ifndef CF_SHARED_MEM
00332     while(cf_get_next_thread_through_sock(sock,&tsd,&thread,fo_thread_tplname) == 0) {
00333     #else
00334     while((ptr1 = cf_get_next_thread_through_shm(ptr1,&thread,fo_thread_tplname)) != NULL) {
00335     #endif
00336       if((thread.messages->invisible == 0 && thread.messages->may_show) || del == CF_KEEP_DELETED) {
00337         tpl_cf_setvar(&thread.messages->tpl,"start","1",1,0);
00338 
00339         len = snprintf(buff,128,"%d",thread.msg_len);
00340         tpl_cf_setvar(&thread.messages->tpl,"msgnum",buff,len,0);
00341 
00342         len = snprintf(buff,128,"%d",thread.msg_len-1);
00343         tpl_cf_setvar(&thread.messages->tpl,"answers",buff,len,0);
00344 
00345         ret = handle_thread(&thread,head,0);
00346         if(ret == FLT_OK || ret == FLT_DECLINE || del == CF_KEEP_DELETED) print_thread_structure(&thread,head);
00347 
00348         cleanup_struct(&thread);
00349       }
00350     }
00351 
00352     #ifndef CF_SHARED_MEM
00353     if(*ErrorString) {
00354       str_error_message(ErrorString,NULL,strlen(ErrorString));
00355       return;
00356     }
00357     #else
00358     if(ptr1 == NULL && *ErrorString) {
00359       str_error_message(ErrorString,NULL,strlen(ErrorString));
00360       return;
00361     }
00362     #endif
00363 
00364     tpl_cf_parse(&tpl_end);
00365     tpl_cf_finish(&tpl_end);
00366   }
00367 }
00368 /* }}} */
00369 
00377 int main(int argc,char *argv[],char *env[]) {
00378   #ifndef CF_SHARED_MEM
00379   int sock;
00380   #else
00381   void *sock;
00382   #endif
00383 
00384   static const u_char *wanted[] = {
00385     "fo_default", "fo_view"
00386   };
00387 
00388   int ret;
00389   u_char  *ucfg,*m  = NULL,*t = NULL;
00390   t_array *cfgfiles = get_conf_file(wanted,2);
00391   t_cf_hash *head = cf_cgi_new();
00392   t_configfile conf,dconf,uconf;
00393   t_name_value *cs = NULL;
00394   u_char *UserName;
00395   u_char *fname;
00396 
00397   if(!cfgfiles) {
00398     return EXIT_FAILURE;
00399   }
00400 
00401   init_modules();
00402 
00403   #ifndef CF_SHARED_MEM
00404   sock = 0;
00405   #else
00406   sock = NULL;
00407   #endif
00408 
00409   ret  = FLT_OK;
00410 
00411   fname = *((u_char **)array_element_at(cfgfiles,0));
00412   cfg_init_file(&dconf,fname);
00413   free(fname);
00414 
00415   fname = *((u_char **)array_element_at(cfgfiles,1));
00416   cfg_init_file(&conf,fname);
00417   free(fname);
00418 
00419   cfg_register_options(&dconf,default_options);
00420   cfg_register_options(&conf,fo_view_options);
00421 
00422   if(read_config(&dconf,NULL) != 0 || read_config(&conf,NULL) != 0) {
00423     fprintf(stderr,"config file error!\n");
00424 
00425     cfg_cleanup_file(&conf);
00426     cfg_cleanup_file(&dconf);
00427 
00428     return EXIT_FAILURE;
00429   }
00430 
00431   /* first action: authorization modules */
00432   if(Modules[AUTH_HANDLER].elements) {
00433     size_t i;
00434     t_filter_begin exec;
00435     t_handler_config *handler;
00436 
00437     ret = FLT_DECLINE;
00438 
00439     for(i=0;i<Modules[AUTH_HANDLER].elements && ret == FLT_DECLINE;i++) {
00440       handler = array_element_at(&Modules[AUTH_HANDLER],i);
00441 
00442       exec = (t_filter_begin)handler->func;
00443       ret = exec(head,&fo_default_conf,&fo_view_conf);
00444     }
00445   }
00446 
00447   if((UserName = cf_hash_get(GlobalValues,"UserName",8)) != NULL) {
00448     /* get user config */
00449     ucfg = get_uconf_name(UserName);
00450     if(ucfg) {
00451       free(conf.filename);
00452       conf.filename = ucfg;
00453 
00454       if(read_config(&conf,ignre) != 0) {
00455         fprintf(stderr,"config file error!\n");
00456 
00457         cfg_cleanup_file(&conf);
00458         cfg_cleanup_file(&dconf);
00459         cfg_cleanup_file(&uconf);
00460 
00461         return EXIT_FAILURE;
00462       }
00463     }
00464   }
00465 
00466   /* first state: let the begin-filters run! :-) */
00467   if(ret != FLT_EXIT && Modules[INIT_HANDLER].elements) {
00468     size_t i;
00469     t_handler_config *handler;
00470     t_filter_begin exec;
00471 
00472     for(i=0;i<Modules[INIT_HANDLER].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
00473       handler = array_element_at(&Modules[INIT_HANDLER],i);
00474       exec    = (t_filter_begin)handler->func;
00475       ret     = exec(head,&fo_default_conf,&fo_view_conf);
00476     }
00477   }
00478 
00479   cs = cfg_get_value(&fo_default_conf,"ExternCharset");
00480 
00481   if(ret != FLT_EXIT) {
00482     /* now, we need a socket connection */
00483     // main source
00484 
00485     #ifndef CF_SHARED_MEM
00486     if((sock = set_us_up_the_socket()) <= 0) {
00487       printf("Content-Type: text/html; charset=%s\015\012\015\012",cs?cs->values[0]?cs->values[0]:(u_char *)"UTF-8":(u_char *)"UTF-8");
00488       str_error_message("E_NO_SOCK",NULL,9,strerror(errno));
00489       exit(0);
00490     }
00491     #else
00492     if((sock = get_shm_ptr()) == NULL) {
00493       printf("Content-Type: text/html; charset=%s\015\012\015\012",cs?cs->values[0]?cs->values[0]:(u_char *)"UTF-8":(u_char *)"UTF-8");
00494       str_error_message("E_NO_CONN",NULL,9,strerror(errno));
00495       exit(0);
00496     }
00497     #endif
00498 
00499     if(Modules[CONNECT_INIT_HANDLER].elements) {
00500       size_t i;
00501       t_filter_connect exec;
00502       t_handler_config *handler;
00503 
00504       for(i=0;i<Modules[CONNECT_INIT_HANDLER].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
00505         handler = array_element_at(&Modules[CONNECT_INIT_HANDLER],i);
00506         exec    = (t_filter_connect)handler->func;
00507         ret     = exec(head,&fo_default_conf,&fo_view_conf,(int)sock);
00508       }
00509     }
00510 
00511     if(ret != FLT_EXIT) {
00512       printf("Content-Type: text/html; charset=%s\015\012\015\012",cs?cs->values[0]?cs->values[0]:(u_char *)"UTF-8":(u_char *)"UTF-8");
00513       /* after that, look for m= and t= */
00514       if(head) {
00515         t = cf_cgi_get(head,"t");
00516         m = cf_cgi_get(head,"m");
00517       }
00518 
00519       if(t && m) {
00520         send_posting(head,sock,strtoull(t,NULL,10),strtoull(m,NULL,10));
00521       }
00522       else {
00523         send_threadlist(sock,head);
00524       }
00525     }
00526 
00527     #ifndef CF_SHARED_MEM
00528     writen(sock,"QUIT\n",5);
00529     close(sock);
00530     #endif
00531   }
00532 
00533   /* cleanup source */
00534   cfg_cleanup(&fo_default_conf);
00535   cfg_cleanup_file(&dconf);
00536   cfg_cleanup(&fo_view_conf);
00537   cfg_cleanup_file(&conf);
00538 
00539   array_destroy(cfgfiles);
00540   free(cfgfiles);
00541 
00542   cleanup_modules(Modules);
00543 
00544   if(head) {
00545     cf_hash_destroy(head);
00546   }
00547 
00548   #ifdef CF_SHARED_MEM
00549   if(sock) shmdt((void *)sock);
00550   #endif
00551 
00552   return EXIT_SUCCESS;
00553 }
00554 
00555 /* eof */

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