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

clientlib.c

Go to the documentation of this file.
00001 
00010 /* {{{ Initial comments */
00011 /*
00012  * $LastChangedDate: 2004-04-15 14:41:57 +0200 (Thu, 15 Apr 2004) $
00013  * $LastChangedRevision: 53 $
00014  * $LastChangedBy: ckruse $
00015  *
00016  */
00017 /* }}} */
00018 
00019 /* {{{ Includes */
00020 #include "config.h"
00021 #include "defines.h"
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <stdarg.h>
00028 #include <fcntl.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <sys/uio.h>
00032 #include <sys/un.h>
00033 #include <sys/socket.h>
00034 #include <dlfcn.h>
00035 #include <locale.h>
00036 
00037 #include <pthread.h>
00038 
00039 #include <pwd.h>
00040 
00041 #ifdef CF_SHARED_MEM
00042 #include <sys/ipc.h>
00043 #include <sys/shm.h>
00044 #include <sys/sem.h>
00045 #endif
00046 
00047 #ifdef CF_SHARED_MEM
00048 #include "semaphores.h"
00049 #endif
00050 
00051 #include "hashlib.h"
00052 #include "utils.h"
00053 #include "configparser.h"
00054 #include "template.h"
00055 #include "readline.h"
00056 #include "charconvert.h"
00057 #include "clientlib.h"
00058 /* }}} */
00059 
00060 /* user authentification */
00061 t_cf_hash *GlobalValues = NULL;
00062 
00063 t_cf_hash *APIEntries = NULL;
00064 
00065 /* error string */
00066 u_char ErrorString[50];
00067 
00068 #ifdef CF_SHARED_MEM
00069 /* {{{ Shared memory functions */
00070 
00071 static int   shm_id        = -1;   
00072 static void *shm_ptr       = NULL; 
00073 static int   shm_lock_sem  = -1;   
00075 void *reget_shm_ptr() {
00076   t_name_value *shm  = cfg_get_value(&fo_default_conf,"SharedMemIds");
00077   unsigned short val;
00078 
00079   if(shm_ptr) {
00080     shmdt(shm_ptr);
00081     shm_ptr = NULL;
00082   }
00083 
00084   if(cf_sem_getval(shm_lock_sem,0,1,&val) == 0) {
00085     if((shm_id = shmget(atoi(shm->values[val]),0,0)) == -1) {
00086       return NULL;
00087     }
00088 
00089     /*
00090      * we don't have and don't *need* write-permissions.
00091      * So set SHM_RDONLY in the shmat-flag.
00092      */
00093     if((shm_ptr = shmat(shm_id,0,SHM_RDONLY)) == (void *)-1) {
00094       return NULL;
00095     }
00096   }
00097 
00098   return shm_ptr;
00099 }
00100 
00101 void *get_shm_ptr() {
00102   t_name_value *shm  = cfg_get_value(&fo_default_conf,"SharedMemIds");
00103   unsigned short val;
00104 
00105   if(shm_lock_sem == -1) {
00106     /* create a new segment */
00107     if((shm_lock_sem = semget(atoi(shm->values[2]),0,0)) == -1) {
00108       return NULL;
00109     }
00110   }
00111 
00112   if(cf_sem_getval(shm_lock_sem,0,1,&val) == 0) {
00113     val = val == 1 ? 0 : 1;
00114 
00115     if(shm_id == -1) {
00116       if((shm_id = shmget(atoi(shm->values[val]),0,0)) == -1) {
00117         return NULL;
00118       }
00119     }
00120 
00121     if(shm_ptr == NULL) {
00122       /*
00123        * we don't have and don't *need* write-permissions.
00124        * So set SHM_RDONLY in the shmat-flag.
00125        */
00126       if((shm_ptr = shmat(shm_id,0,SHM_RDONLY)) == (void *)-1) {
00127         return NULL;
00128       }
00129     }
00130   }
00131 
00132   return shm_ptr;
00133 }
00134 
00135 /* }}} */
00136 #endif
00137 
00138 /* {{{ get_uconf_name
00139  * Returns: u_char *    the userconfig filename or NULL
00140  * Parameters:
00141  *
00142  * this function searches for a user configuration
00143  *
00144  */
00145 u_char *get_uconf_name(const u_char *uname) {
00146   u_char *path,*name;
00147   u_char *ptr;
00148   struct stat sb;
00149   t_name_value *confpath = cfg_get_value(&fo_default_conf,"ConfigDirectory");
00150 
00151   if(!uname) return NULL;
00152 
00153   name = strdup(uname);
00154   if(!name) return NULL;
00155 
00156   for(ptr = name;*ptr;ptr++) {
00157     if(isupper(*ptr)) {
00158       *ptr = tolower(*ptr);
00159     }
00160   }
00161 
00162   path = fo_alloc(NULL,strlen(confpath->values[0]) + strlen(name) + 12,1,FO_ALLOC_MALLOC);
00163 
00164   sprintf(path,"%s%c/%c/%c/%s.conf",confpath->values[0],name[0],name[1],name[2],name);
00165 
00166   if(stat(path,&sb) == -1) {
00167     free(path);
00168     free(name);
00169     fprintf(stderr,"user config file '%s' not found!\n",path);
00170     return NULL;
00171   }
00172 
00173   free(name);
00174 
00175   return path;
00176 }
00177 /* }}} */
00178 
00179 /* {{{ set_us_up_the_socket
00180  * Returns: int   the socket
00181  * Parameters:
00182  *
00183  * this functions sets up the socket
00184  *
00185  */
00186 int set_us_up_the_socket(void) {
00187   int sock;
00188   struct sockaddr_un addr;
00189   t_name_value *sockpath = cfg_get_value(&fo_default_conf,"SocketName");
00190 
00191   if(sockpath) {
00192     memset(&addr,0,sizeof(addr));
00193     addr.sun_family = AF_LOCAL;
00194     (void)strncpy(addr.sun_path,sockpath->values[0],103);
00195 
00196     if((sock = socket(AF_LOCAL,SOCK_STREAM,0)) == -1) {
00197       strcpy(ErrorString,"E_NO_SOCK");
00198       return -1;
00199     }
00200 
00201     if((connect(sock,(struct sockaddr *)&addr,sizeof(addr))) != 0) {
00202       strcpy(ErrorString,"E_NO_CONN");
00203       return -1;
00204     }
00205 
00206     return sock;
00207   }
00208 
00209   strcpy(ErrorString,"E_CONFIG_ERR");
00210   return -1;
00211 }
00212 /* }}} */
00213 
00214 /* {{{ generate_tpl_name
00215  * Returns: nothing
00216  * Parameters:
00217  *   - u_char msg[256]    the buffer to sprint into
00218  *   - t_name_value *v   the configfile
00219  *
00220  * this function spits out an error message
00221  *
00222  */
00223 void generate_tpl_name(u_char buff[],int len,t_name_value *v) {
00224   t_name_value *vn = cfg_get_value(&fo_default_conf,"TemplateMode");
00225 
00226   if(vn) {
00227     snprintf(buff,len,v->values[0],"tpl_",vn->values[0]);
00228   }
00229   else {
00230     snprintf(buff,len,v->values[0],"","");
00231   }
00232 }
00233 /* }}} */
00234 
00235 /* {{{ cf_set_variable */
00236 void cf_set_variable(t_cf_template *tpl,t_name_value *cs,u_char *vname,const u_char *val,size_t len,int html) {
00237   u_char *tmp;
00238   size_t len1;
00239 
00240   if(cs) {
00241     if(cf_strcmp(cs->values[0],"UTF-8")) {
00242       if(html) {
00243         tmp = htmlentities_charset_convert(val,"UTF-8",cs->values[0],&len1,0);
00244         html = 0;
00245       }
00246       else {
00247         tmp = charset_convert(val,len,"UTF-8",cs->values[0],&len1);
00248       }
00249 
00250       if(!tmp) { /* This should only happen if we use charset_convert() -- and we should not use it. */
00251         tpl_cf_setvar(tpl,vname,val,len,html);
00252       }
00253       else {
00254         tpl_cf_setvar(tpl,vname,tmp,len1,html);
00255         free(tmp);
00256       }
00257     }
00258     /* ExternCharset is also UTF-8 */
00259     else {
00260       tpl_cf_setvar(tpl,vname,val,len,html);
00261     }
00262   }
00263   else {
00264     tpl_cf_setvar(tpl,vname,val,len,html);
00265   }
00266 
00267 }
00268 /* }}} */
00269 
00270 /* {{{ str_error_message
00271  * Returns: nothing
00272  * Parameters:
00273  *   - const u_char *msg the errorcode
00274  *
00275  * this function spits out an error message
00276  *
00277  */
00278 void str_error_message(const u_char *err,FILE *out,int rd, ...) {
00279   t_name_value *v  = cfg_get_value(&fo_default_conf,"ErrorTemplate");
00280   t_name_value *v1 = cfg_get_value(&fo_default_conf,"ErrorMessages");
00281   t_name_value *cs = cfg_get_value(&fo_default_conf,"ExternCharset");
00282   t_cf_template tpl;
00283   u_char tplname[256];
00284   va_list ap;
00285 
00286   FILE *fd;
00287   u_char *buff = NULL;
00288   u_char *fmt  = NULL;
00289   register u_char *ptr;
00290   t_string msg;
00291   int found = 0;
00292   size_t size,chars;
00293   u_char ibuff[50];
00294 
00295   int ivar;
00296   u_char *svar;
00297 
00298   if(v && v1) {
00299     fd = fopen(v1->values[0],"r");
00300 
00301     if(fd) {
00302       generate_tpl_name(tplname,256,v);
00303 
00304       tpl_cf_init(&tpl,tplname);
00305 
00306       if(tpl.tpl) {
00307         while((chars = getline((char **)&buff,&size,fd)) != 0) {
00308           if(cf_strncmp(buff,err,rd) == 0) {
00309             /* cf_set_variable(&tpl,cs,"error",buff+rd+1,chars-rd-1,1); */
00310             str_init(&msg);
00311             fmt = strndup(buff+rd+2,chars-rd-3);
00312             va_start(ap,rd);
00313 
00314             for(ptr=fmt;*ptr;ptr++) {
00315               if(*ptr == '%') {
00316                 ptr++;
00317 
00318                 switch(*ptr) {
00319                   case '%':
00320                     str_char_append(&msg,*ptr);
00321                     break;
00322 
00323                   case 's':
00324                     svar = va_arg(ap,u_char *);
00325                     str_chars_append(&msg,svar,strlen(svar));
00326                     break;
00327 
00328                   case 'd':
00329                     ivar = va_arg(ap,int);
00330                     size = snprintf(ibuff,50,"%d",ivar);
00331                     str_chars_append(&msg,ibuff,50);
00332                     break;
00333 
00334                   default:
00335                     str_char_append(&msg,*ptr);
00336                     break;
00337                 }
00338               }
00339               else {
00340                 str_char_append(&msg,*ptr);
00341               }
00342             }
00343 
00344             va_end(ap);
00345             free(fmt);
00346 
00347             cf_set_variable(&tpl,cs,"error",msg.content,msg.len,1);
00348 
00349             str_cleanup(&msg);
00350             found = 1;
00351             break;
00352           }
00353         }
00354 
00355         fclose(fd);
00356 
00357         if(found == 0) {
00358           found = snprintf(buff,2048,"Message not found: %s\n",err);
00359           tpl_cf_setvar(&tpl,"error",buff,found,1);
00360         }
00361 
00362         if(out) {
00363           tpl_cf_parse_to_mem(&tpl);
00364           fwrite(tpl.parsed.content,1,tpl.parsed.len,out);
00365         }
00366         else {
00367           tpl_cf_parse(&tpl);
00368         }
00369 
00370         tpl_cf_finish(&tpl);
00371       }
00372       else {
00373         printf("Sorry, could not find template file. I got error %s\n",err);
00374       }
00375     }
00376     else {
00377       printf("Sorry, could not find error messages. I got error %s\n",err);
00378     }
00379   }
00380   else {
00381     printf("Sorry, but I could not find my templates.\nI got error %s\n",err);
00382   }
00383 
00384   if(size) free(buff);
00385 }
00386 /* }}} */
00387 
00388 /* {{{ get_error_message */
00389 u_char *get_error_message(const u_char *err,int rd,size_t *len, ...) {
00390   t_name_value *v1 = cfg_get_value(&fo_default_conf,"ErrorMessages");
00391   FILE *fd;
00392   u_char *buff = NULL;
00393   size_t size = 0,chars;
00394   t_string msg;
00395   u_char *fmt = NULL,*svar;
00396   register u_char *ptr;
00397   va_list ap;
00398   int ivar;
00399   u_char ibuff[50];
00400 
00401   if(v1) {
00402     fd = fopen(v1->values[0],"r");
00403 
00404     if(fd) {
00405       while((chars = getline((char **)&buff,&size,fd)) != 0) {
00406         if(cf_strncmp(buff,err,rd) == 0) {
00407         str_init(&msg);
00408         fmt = strndup(buff+rd+1,chars-rd-1);
00409         va_start(ap,len);
00410 
00411         for(ptr=fmt;*ptr;ptr++) {
00412           if(*ptr == '%') {
00413             ptr++;
00414 
00415             switch(*ptr) {
00416               case '%':
00417                 str_char_append(&msg,*ptr);
00418                   break;
00419 
00420                 case 's':
00421                   svar = va_arg(ap,u_char *);
00422                   str_chars_append(&msg,svar,strlen(svar));
00423                   break;
00424 
00425                 case 'd':
00426                   ivar = va_arg(ap,int);
00427                   size = snprintf(ibuff,50,"%d",ivar);
00428                   str_chars_append(&msg,ibuff,50);
00429                   break;
00430 
00431                 default:
00432                   str_char_append(&msg,*ptr);
00433                   break;
00434               }
00435             }
00436             else {
00437               str_char_append(&msg,*ptr);
00438             }
00439           }
00440 
00441           va_end(ap);
00442           free(fmt);
00443           free(buff);
00444 
00445           fclose(fd);
00446           return msg.content;
00447         }
00448       }
00449 
00450       fclose(fd);
00451     }
00452     else {
00453       return NULL;
00454     }
00455   }
00456   else {
00457     return NULL;
00458   }
00459 
00460   if(buff && size) free(buff);
00461   return NULL;
00462 }
00463 /* }}} */
00464 
00465 /* {{{ delete_subtree
00466  * Returns:            the next message
00467  * Parameters:
00468  *   - t_message *msg  the message structure
00469  *
00470  * This function deletes a posting subtree
00471  *
00472  */
00473 t_message *delete_subtree(t_message *msg) {
00474   int lvl = msg->level;
00475 
00476   for(msg=msg->next;msg && msg->level > lvl;msg=msg->next) {
00477     msg->may_show = 0;
00478   }
00479 
00480   return msg;
00481 }
00482 /* }}} */
00483 
00484 /* {{{ cleanup_struct
00485  * Returns: nothing
00486  * Parameters:
00487  *   - t_cl_thread *thr   the thread structure
00488  *
00489  * this function frees reserved memory and closes templates
00490  *
00491  */
00492 void cleanup_struct(t_cl_thread *thr) {
00493   t_message *msg = thr->messages,*last = thr->messages;
00494 
00495   for(;msg;msg=last) {
00496     last = msg->next;
00497 
00498     #ifndef CF_SHARED_MEM
00499     free(msg->author);
00500     free(msg->subject);
00501 
00502     if(msg->category) {
00503       free(msg->category);
00504     }
00505 
00506     if(msg->content) {
00507       free(msg->content);
00508     }
00509 
00510     if(msg->email) {
00511       free(msg->email);
00512     }
00513 
00514     if(msg->hp) {
00515       free(msg->hp);
00516     }
00517 
00518     if(msg->img) {
00519       free(msg->img);
00520     }
00521     #endif
00522 
00523     tpl_cf_finish(&msg->tpl);
00524 
00525     free(msg);
00526   }
00527 
00528 }
00529 /* }}} */
00530 
00531 /* {{{ get_link
00532  * Returns: u_char *    NULL or a string
00533  * Parameters:
00534  *   - u_int64_t tid  the thread id
00535  *   - u_int64_t mid  the message id
00536  *
00537  * this function creates the URL string
00538  *
00539  */
00540 u_char *get_link(u_int64_t tid,u_int64_t mid) {
00541   t_name_value *vs = cfg_get_value(&fo_default_conf,cf_hash_get(GlobalValues,"UserName",8) ? "UBaseURL" : "BaseURL");
00542   u_char *buff = NULL;
00543   size_t len;
00544 
00545   if(vs) {
00546     len = 50 + strlen(vs->values[0]);
00547     buff = fo_alloc(NULL,len,1,FO_ALLOC_MALLOC);
00548     snprintf(buff,len,"%s?t=%lld&m=%lld",vs->values[0],tid,mid);
00549   }
00550 
00551   return buff;
00552 }
00553 /* }}} */
00554 
00555 /* {{{ has_answers
00556  * Returns: int         returns a true value if the msg has anwers, a false value if it has no answers
00557  * Parameters:
00558  *   - t_messages *msg  a pointer to the message
00559  *
00560  * as the name says: it checks, if the message has an answer
00561  *
00562  */
00563 int has_answers(t_message *msg) {
00564   int lvl = msg->level;
00565   int ShowInvisible = cf_hash_get(GlobalValues,"ShowInvisible",13) == NULL ? 0 : 1;
00566 
00567   if(msg->next) {
00568     if((msg->next->may_show && msg->invisible == 0) || ShowInvisible == 1) {
00569       if(msg->next->level > msg->level) {
00570         return 1;
00571       }
00572       return 0;
00573     }
00574     else {
00575       for(msg=msg->next;msg && (msg->may_show == 0 || msg->invisible == 1) && ShowInvisible == 0;msg=msg->next);
00576 
00577       if(!msg) {
00578         return 0;
00579       }
00580       else {
00581         if(msg->level > lvl) {
00582           return 1;
00583         }
00584 
00585         return 0;
00586       }
00587     }
00588   }
00589   else {
00590     return 0;
00591   }
00592 }
00593 /* }}} */
00594 
00595 /* {{{ handle_thread_list_posting
00596  * Returns: int                 returns the return value of the last filter
00597  * Parameters:
00598  *   - t_message *m             a pointer to the message
00599  *   - t_cf_hash *head          a pointer to the cgi variable list
00600  *   - unsigned long long tid   the thread id
00601  *   - int mode                 the mode; 0 if in threadlist, 1 if in posting
00602  *
00603  * handles VIEW_LIST_HANDLER filters
00604  *
00605  */
00606 int handle_thread_list_posting(t_message *p,t_cf_hash *head,u_int64_t tid,int mode) {
00607   int ret = FLT_OK;
00608   t_handler_config *handler;
00609   size_t i;
00610   t_filter_list_posting fkt;
00611 
00612   if(Modules[VIEW_LIST_HANDLER].elements) {
00613     for(i=0;i<Modules[VIEW_LIST_HANDLER].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
00614       handler = array_element_at(&Modules[VIEW_LIST_HANDLER],i);
00615       fkt     = (t_filter_list_posting)handler->func;
00616       ret     = fkt(head,&fo_default_conf,&fo_view_conf,p,tid,mode);
00617     }
00618   }
00619 
00620   return ret;
00621 }
00622 /* }}} */
00623 
00624 /* {{{ handle_thread
00625  * Returns: int
00626  * Parameters:
00627  *   - t_cl_thread *thr  the thread structure
00628  *
00629  * this function handles a completely read thread
00630  *
00631  */
00632 int handle_thread(t_cl_thread *thr,t_cf_hash *head,int mode) {
00633   int    ret = FLT_OK;
00634   t_handler_config *handler;
00635   size_t i;
00636   t_filter_list fkt;
00637 
00638   if(Modules[VIEW_HANDLER].elements) {
00639     for(i=0;i<Modules[VIEW_HANDLER].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
00640       handler = array_element_at(&Modules[VIEW_HANDLER],i);
00641       fkt     = (t_filter_list)handler->func;
00642       ret     = fkt(head,&fo_default_conf,&fo_view_conf,thr,mode);
00643     }
00644   }
00645 
00646   return ret;
00647 }
00648 /* }}} */
00649 
00650 /* {{{ handle_posting_filters */
00651 int handle_posting_filters(t_cf_hash *head,t_cl_thread *thr,t_cf_template *tpl) {
00652   int ret = FLT_OK;
00653   t_handler_config *handler;
00654   size_t i;
00655   t_filter_posting fkt;
00656 
00657   if(Modules[POSTING_HANDLER].elements) {
00658     for(i=0;i<Modules[POSTING_HANDLER].elements && (ret == FLT_OK || ret == FLT_DECLINE);i++) {
00659       handler = array_element_at(&Modules[POSTING_HANDLER],i);
00660       fkt     = (t_filter_posting)handler->func;
00661       ret     = fkt(head,&fo_default_conf,&fo_view_conf,thr,tpl);
00662     }
00663   }
00664 
00665   return ret;
00666 }
00667 /* }}} */
00668 
00669 /* {{{ get_time
00670  * Returns: u_char *         a pointer or NULL
00671  * Parameters:
00672  *   - const u_char *symbol the date symbol
00673  *   - int *len            the len pointer
00674  *
00675  * this function creates a date string
00676  *
00677  */
00678 u_char *get_time(t_configuration *cfg,const u_char *symbol,int *len,time_t *date) {
00679   t_name_value *symb = cfg_get_value(cfg,symbol);
00680   t_name_value *loc  = cfg_get_value(&fo_default_conf,"DateLocale");
00681   u_char *buff;
00682   int ln = 0;
00683   struct tm *tptr;
00684 
00685   if(!symb || !loc) {
00686     return NULL;
00687   }
00688 
00689   if(!setlocale(LC_TIME,loc->values[0])) {
00690     return NULL;
00691   }
00692 
00693   ln = strlen(symb->values[0]) + 50;
00694   buff = fo_alloc(NULL,ln,1,FO_ALLOC_MALLOC);
00695   if(!buff) return NULL;
00696 
00697   tptr  = localtime(date);
00698 
00699   *len = strftime(buff,(size_t)ln,symb->values[0],tptr);
00700 
00701   return buff;
00702 }
00703 /* }}} */
00704 
00705 /* {{{ get_next_thread_through_sock */
00706 int cf_get_next_thread_through_sock(int sock,rline_t *tsd,t_cl_thread *thr,const u_char *tplname) {
00707   u_char *line,*chtmp;
00708   int shallRun = 1;
00709   t_message *x;
00710   int ok = 0;
00711 
00712   memset(thr,0,sizeof(*thr));
00713 
00714   /* now lets read the threadlist */
00715   while(shallRun) {
00716     line = readline(sock,tsd);
00717 
00718     if(line) {
00719       line[tsd->rl_len-1] = '\0';
00720 
00721       if(*line == '\0') {
00722         shallRun = 0;
00723       }
00724       else if(cf_strncmp(line,"THREAD t",8) == 0) {
00725         chtmp = strstr(line,"m");
00726 
00727         thr->messages           = fo_alloc(NULL,1,sizeof(t_message),FO_ALLOC_CALLOC);
00728         thr->last               = thr->messages;
00729         thr->last->mid          = strtoull(&line[chtmp-line+1],NULL,10);
00730         thr->messages->may_show = 1;
00731         thr->msg_len            = 1;
00732         thr->tid                = strtoull(line+8,NULL,10);
00733 
00734         if(tplname) {
00735           tpl_cf_init(&thr->last->tpl,tplname);
00736           tpl_cf_setvar(&thr->last->tpl,"start","1",1,0);
00737         }
00738       }
00739       else if(cf_strncmp(line,"MSG m",5) == 0) {
00740         x = thr->last;
00741 
00742         if(thr->last) {
00743           thr->last->next = fo_alloc(NULL,1,sizeof(t_message),FO_ALLOC_CALLOC);
00744           thr->last->next->prev = thr->last;
00745           thr->last       = thr->last->next;
00746         }
00747         else {
00748           thr->messages = fo_alloc(NULL,1,sizeof(t_message),FO_ALLOC_CALLOC);
00749           thr->last     = thr->messages;
00750         }
00751 
00752         thr->last->mid      = strtoull(&line[5],NULL,10);
00753         thr->last->may_show = 1;
00754 
00755         thr->msg_len++;
00756 
00757         if(tplname) {
00758           tpl_cf_init(&thr->last->tpl,tplname);
00759         }
00760       }
00761       else if(cf_strncmp(line,"Author:",7) == 0) {
00762         thr->last->author = strdup(&line[7]);
00763       }
00764       else if(cf_strncmp(line,"Visible:",8) == 0) {
00765         thr->last->invisible = line[8] == '0';
00766       }
00767       else if(cf_strncmp(line,"Subject:",8) == 0) {
00768         thr->last->subject = strdup(&line[8]);
00769       }
00770       else if(cf_strncmp(line,"Category:",9) == 0) {
00771         thr->last->category = strdup(&line[9]);
00772       }
00773       else if(cf_strncmp(line,"Date:",5) == 0) {
00774         thr->last->date = strtoul(&line[5],NULL,10);
00775       }
00776       else if(cf_strncmp(line,"Level:",6) == 0) {
00777         thr->last->level = atoi(&line[6]);
00778       }
00779       else if(cf_strncmp(line,"Content:",8) == 0) {
00780         thr->last->content = strdup(&line[8]);
00781       }
00782       else if(cf_strncmp(line,"Homepage:",9) == 0) {
00783         thr->last->hp = strdup(&line[9]);
00784       }
00785       else if(cf_strncmp(line,"Image:",6) == 0) {
00786         thr->last->img = strdup(&line[6]);
00787       }
00788       else if(cf_strncmp(line,"EMail:",6) == 0) {
00789         thr->last->email = strdup(&line[6]);
00790       }
00791       else if(cf_strncmp(line,"END",3) == 0) {
00792         shallRun = 0;
00793         ok = 1;
00794       }
00795 
00796       free(line);
00797     }
00798     else {
00799       shallRun = 0; /* connection broke */
00800       strcpy(ErrorString,"E_COMMUNICATE");
00801     }
00802   }
00803 
00804   if(ok) return 0;
00805   return -1;
00806 }
00807 
00808 #ifdef CF_SHARED_MEM
00809 void *cf_get_next_thread_through_shm(void *shm_ptr,t_cl_thread *thr,const u_char *tplname) {
00810   register void *ptr = shm_ptr;
00811   u_int32_t post;
00812   struct shmid_ds shm_buf;
00813   void *ptr1 = get_shm_ptr();
00814   size_t len;
00815   u_char buff[128];
00816 
00817   memset(thr,0,sizeof(*thr));
00818 
00819   if(shmctl(shm_id,IPC_STAT,&shm_buf) != 0) {
00820     strcpy(ErrorString,"E_CONFIG_ERR");
00821     return NULL;
00822   }
00823 
00824   /* Uh, oh, we are at the end of the segment */
00825   if(ptr >= ptr1 + shm_buf.shm_segsz) return NULL;
00826 
00827   /* thread id */
00828   thr->tid = *((u_int64_t *)ptr);
00829   ptr += sizeof(u_int64_t);
00830 
00831   /* message id */
00832   thr->msg_len = *((int32_t *)ptr);
00833   ptr += sizeof(int32_t);
00834 
00835   for(post = 0;post < thr->msg_len;post++) {
00836     if(thr->last == NULL) {
00837       thr->messages = thr->last = fo_alloc(NULL,1,sizeof(t_message),FO_ALLOC_CALLOC);
00838     }
00839     else {
00840       thr->last->next = fo_alloc(NULL,1,sizeof(t_message),FO_ALLOC_CALLOC);
00841       thr->last->next->prev = thr->last;
00842       thr->last       = thr->last->next;
00843     }
00844 
00845     if(tplname) tpl_cf_init(&thr->last->tpl,tplname);
00846 
00847     /* message id */
00848     thr->last->mid = *((u_int64_t *)ptr);
00849     ptr += sizeof(u_int64_t);
00850 
00851     /* length of subject */
00852     thr->last->subject_len = *((u_int32_t *)ptr) - 1;
00853     ptr += sizeof(u_int32_t);
00854 
00855     /* subject */
00856     thr->last->subject = ptr;
00857     ptr += thr->last->subject_len + 1;
00858 
00859     /* length of category */
00860     thr->last->category_len = *((u_int32_t *)ptr) - 1;
00861     ptr += sizeof(u_int32_t);
00862 
00863     /* category */
00864     if(thr->last->category_len) {
00865       thr->last->category = ptr;
00866       ptr += thr->last->category_len + 1;
00867     }
00868 
00869     /* content length */
00870     thr->last->content_len = *((u_int32_t *)ptr) - 1;
00871     ptr += sizeof(u_int32_t);
00872 
00873     /* content */
00874     thr->last->content = ptr;
00875     ptr += thr->last->content_len + 1;
00876 
00877     /* date */
00878     thr->last->date = *((time_t *)ptr);
00879     ptr += sizeof(time_t);
00880 
00881     /* level */
00882     thr->last->level = *((u_int16_t *)ptr);
00883     ptr += sizeof(u_int16_t);
00884 
00885     /* invisible */
00886     thr->last->invisible = *((u_int16_t *)ptr);
00887     thr->last->may_show  = 1;
00888     ptr += sizeof(u_int16_t);
00889 
00890     /* author length */
00891     thr->last->author_len = *((u_int32_t *)ptr) - 1;
00892     ptr += sizeof(u_int32_t);
00893 
00894     /* author */
00895     thr->last->author = ptr;
00896     ptr += thr->last->author_len + 1;
00897 
00898     /* email length */
00899     thr->last->email_len = *((u_int32_t *)ptr);
00900     ptr += sizeof(u_int32_t);
00901 
00902     /* email */
00903     if(thr->last->email_len) {
00904       thr->last->email = ptr;
00905       ptr += thr->last->email_len;
00906     }
00907 
00908     /* homepage length */
00909     thr->last->hp_len = *((u_int32_t *)ptr);
00910     ptr += sizeof(u_int32_t);
00911 
00912     /* homepage */
00913     if(thr->last->hp_len) {
00914       thr->last->hp = ptr;
00915       ptr += thr->last->hp_len;
00916     }
00917 
00918     /* image length */
00919     thr->last->img_len = *((u_int32_t *)ptr);
00920     ptr += sizeof(u_int32_t);
00921 
00922     /* image */
00923     if(thr->last->img_len) {
00924       thr->last->img = ptr;
00925       ptr += thr->last->img_len;
00926     }
00927   }
00928 
00929   if(tplname) {
00930     if(thr->messages) {
00931       tpl_cf_setvar(&thr->messages->tpl,"start","1",1,0);
00932 
00933       len = snprintf(buff,128,"%d",thr->msg_len);
00934       tpl_cf_setvar(&thr->messages->tpl,"msgnum",buff,len,0);
00935 
00936       len = snprintf(buff,128,"%d",thr->msg_len-1);
00937       tpl_cf_setvar(&thr->messages->tpl,"answers",buff,len,0);
00938     }
00939   }
00940 
00941   return ptr;
00942 }
00943 #endif
00944 /* }}} */
00945 
00946 /* {{{ get_message */
00947 int cf_get_message_through_sock(int sock,rline_t *tsd,t_cl_thread *thr,const u_char *tplname,u_int64_t tid,u_int64_t mid,int del) {
00948   int len;
00949   u_char buff[128],*line;
00950   t_message *msg;
00951 
00952   memset(thr,0,sizeof(*thr));
00953 
00954   len  = snprintf(buff,128,"GET POSTING t%lld m%lld invisible=%d\n",tid,mid,del);
00955   writen(sock,buff,len);
00956 
00957   line = readline(sock,tsd);
00958 
00959   if(line && cf_strncmp(line,"200 Ok",6) == 0) {
00960     free(line);
00961 
00962     thr->tid      = tid;
00963     thr->messages = NULL;
00964     thr->last     = NULL;
00965 
00966     if(cf_get_next_thread_through_sock(sock,tsd,thr,tplname) < 0 && *ErrorString) {
00967       strcpy(ErrorString,"E_COMMUNICATION");
00968       return -1;
00969     }
00970     else {
00971       /* set thread message pointer to the right message */
00972       if(mid == 0) {
00973         thr->threadmsg = thr->messages;
00974       }
00975       else {
00976         for(msg = thr->messages;msg;msg=msg->next) {
00977           if(msg->mid == mid) {
00978             thr->threadmsg = msg;
00979             break;
00980           }
00981         }
00982       }
00983     }
00984   }
00985   else {
00986     /* bye, bye */
00987     if(line) {
00988       len = snprintf(ErrorString,50,"E_FO_%d",atoi(line));
00989       free(line);
00990     }
00991     else {
00992       strcpy(ErrorString,"E_COMMUNICATION");
00993     }
00994 
00995     return -1;
00996   }
00997 
00998   return 0;
00999 }
01000 
01001 #ifdef CF_SHARED_MEM
01002 int cf_get_message_through_shm(void *shm_ptr,t_cl_thread *thr,const u_char *tplname,u_int64_t tid,u_int64_t mid,int del) {
01003   struct shmid_ds shm_buf;
01004   register void *ptr1;
01005   u_int64_t val = 0;
01006   size_t posts,post;
01007   t_message *msg;
01008 
01009   if(shmctl(shm_id,IPC_STAT,&shm_buf) != 0) {
01010     strcpy(ErrorString,"E_CONFIG_ERR");
01011     return -1;
01012   }
01013 
01014   /*
01015    *
01016    * CAUTION! Deep magic begins here! Do not edit if you don't know
01017    * what you are doing
01018    *
01019    */
01020 
01021   for(ptr1=shm_ptr+sizeof(time_t);ptr1 < shm_ptr+shm_buf.shm_segsz;) {
01022     /* first: tid */
01023     val   = *((u_int64_t *)ptr1);
01024 
01025     if(val == tid) break;
01026 
01027     ptr1 += sizeof(u_int64_t);
01028 
01029     /* after that: number of postings */
01030     posts = *((int32_t *)ptr1);
01031     ptr1 += sizeof(int32_t);
01032 
01033     for(post = 0;post < posts;post++) {
01034       /* then: message id */
01035       ptr1 += sizeof(u_int64_t);
01036 
01037       /* then: length of the subject + subject */
01038       val = *((u_int32_t *)ptr1);
01039       ptr1 += sizeof(u_int32_t) + val;
01040 
01041       /* length of the category + category */
01042       val = *((u_int32_t *)ptr1);
01043       ptr1 += sizeof(u_int32_t);
01044       if(val) ptr1 += val;
01045 
01046       /* length of the content + content */
01047       val = *((u_int32_t *)ptr1);
01048       ptr1 += sizeof(u_int32_t) + val;
01049 
01050       /* date, level, invisible */
01051       ptr1 += sizeof(time_t) + sizeof(u_int16_t) + sizeof(u_int16_t);
01052 
01053       /* user name length + user name */
01054       val = *((u_int32_t *)ptr1);
01055       ptr1 += sizeof(u_int32_t) + val;
01056 
01057       /* email length + email */
01058       val = *((u_int32_t *)ptr1);
01059       ptr1 += sizeof(u_int32_t);
01060       if(val) ptr1 += val;
01061 
01062       /* homepage length + homepage */
01063       val = *((u_int32_t *)ptr1);
01064       ptr1 += sizeof(u_int32_t);
01065       if(val) ptr1 += val;
01066 
01067       /* image length + image */
01068       val = *((u_int32_t *)ptr1);
01069       ptr1 += sizeof(u_int32_t);
01070       if(val) ptr1 += val;
01071     }
01072   }
01073 
01074   /*
01075    *
01076    * Phew, deep magic ended
01077    *
01078    */
01079 
01080   if(ptr1 >= shm_ptr + shm_buf.shm_segsz) {
01081     strcpy(ErrorString,"E_FO_404");
01082     return -1;
01083   }
01084 
01085   if((ptr1 = cf_get_next_thread_through_shm(ptr1,thr,tplname)) == NULL) {
01086     return -1;
01087   }
01088 
01089   if(mid == 0) {
01090     thr->threadmsg = thr->messages;
01091   }
01092   else {
01093     for(msg=thr->messages;msg;msg=msg->next) {
01094       if(msg->mid == mid) {
01095         thr->threadmsg = msg;
01096         break;
01097       }
01098     }
01099   }
01100 
01101   if(!thr->threadmsg) {
01102     strcpy(ErrorString,"E_FO_404");
01103     return -1;
01104   }
01105 
01106   if((thr->messages->invisible == 1 || thr->threadmsg->invisible == 1) && del == CF_KILL_DELETED) {
01107     strcpy(ErrorString,"E_FO_404");
01108     return -1;
01109   }
01110 
01111   return 0;
01112 }
01113 #endif
01114 /* }}} */
01115 
01116 /* {{{ cf_register_mod_api_ent */
01117 int cf_register_mod_api_ent(const u_char *mod_name,const u_char *unique_identifier,t_mod_api func) {
01118   size_t len2 = strlen(unique_identifier);
01119   t_mod_api_ent *ent;
01120 
01121   if((ent = cf_hash_get(APIEntries,(u_char *)unique_identifier,len2)) != NULL) {
01122     if(cf_strcmp(ent->mod_name,mod_name)) {
01123       return -1;
01124     }
01125 
01126     ent->function          = func;
01127   }
01128   else {
01129     ent                    = fo_alloc(NULL,1,sizeof(*ent),FO_ALLOC_MALLOC);
01130     ent->mod_name          = strdup(mod_name);
01131     ent->unique_identifier = strdup(unique_identifier);
01132     ent->function          = func;
01133 
01134     cf_hash_set(APIEntries,(u_char *)unique_identifier,len2,ent,sizeof(*ent));
01135 
01136     free(ent);
01137   }
01138 
01139   return 0;
01140 }
01141 /* }}} */
01142 
01143 /* {{{ cf_unregister_mod_api_ent */
01144 int cf_unregister_mod_api_ent(const u_char *unid) {
01145   size_t len1 = strlen(unid);
01146   t_mod_api_ent *ent;
01147 
01148   if((ent = cf_hash_get(APIEntries,(u_char *)unid,len1)) == NULL) {
01149     return -1;
01150   }
01151 
01152   cf_hash_entry_delete(APIEntries,(u_char *)unid,len1);
01153   return 0;
01154 }
01155 /* }}} */
01156 
01157 /* {{{ cf_get_mod_api_ent */
01158 t_mod_api cf_get_mod_api_ent(const u_char *unid) {
01159   t_mod_api_ent *ent;
01160   size_t len1 = strlen(unid);
01161 
01162   if((ent = cf_hash_get(APIEntries,(u_char *)unid,len1)) == NULL) {
01163     return NULL;
01164   }
01165 
01166   return ent->function;
01167 }
01168 /* }}} */
01169 
01170 /* {{{ destroy_entry */
01175 void destroy_entry(void *elem) {
01176   t_mod_api_ent *a = (t_mod_api_ent *)elem;
01177   free(a->mod_name);
01178   free(a->unique_identifier);
01179 }
01180 /* }}} */
01181 
01182 /* {{{ cf_init */
01186 void cf_init(void) {
01187   GlobalValues = cf_hash_new(NULL);
01188   APIEntries = cf_hash_new(destroy_entry);
01189   memset(ErrorString,0,sizeof(ErrorString));
01190 }
01191 /* }}} */
01192 
01193 /* {{{ cf_fini */
01197 void cf_fini(void) {
01198   cf_hash_destroy(GlobalValues);
01199   cf_hash_destroy(APIEntries);
01200 }
01201 /* }}} */
01202 
01203 /* eof */

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