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 <dlfcn.h>
00023 #include <errno.h>
00024
00025 #include <sys/types.h>
00026
00027
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
00056
00057
00058
00059
00060
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)) {
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> </li>\n");
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
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
00202
00203
00204
00205
00206
00207
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
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
00253
00254
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
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
00288
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
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
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
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
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
00483
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
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
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