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

flt_visited.c

Go to the documentation of this file.
00001 
00009 /* {{{ Initial comments */
00010 /*
00011  * $LastChangedDate: 2004-04-01 18:34:17 +0200 (Thu, 01 Apr 2004) $
00012  * $LastChangedRevision: 50 $
00013  * $LastChangedBy: ckruse $
00014  *
00015  */
00016 /* }}} */
00017 
00018 /* {{{ Includes */
00019 #include "config.h"
00020 #include "defines.h"
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <time.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 
00029 #include "readline.h"
00030 #include "hashlib.h"
00031 #include "utils.h"
00032 #include "configparser.h"
00033 #include "cfcgi.h"
00034 #include "template.h"
00035 #include "clientlib.h"
00036 /* }}} */
00037 
00038 struct {
00039   int   HighlightVisitedPostings;
00040   u_char *VisitedPostingsColorF;
00041   u_char *VisitedPostingsColorB;
00042   u_char *VisitedFile;
00043   t_cf_tree tree;
00044 } Cfg = { 0, NULL, NULL, NULL, { NULL, NULL, NULL } };
00045 
00046 int flt_visited_compare(t_cf_tree_dataset *a,t_cf_tree_dataset *b) {
00047   if(*((u_int64_t *)a->key) < *((u_int64_t *)b->key)) return -1;
00048   if(*((u_int64_t *)a->key) > *((u_int64_t *)b->key)) return 1;
00049 
00050   return 0;
00051 }
00052 
00053 void flt_visited_create_tree() {
00054   if(Cfg.tree.root == NULL) {
00055     FILE *fd;
00056     struct stat st;
00057     u_int64_t *field;
00058     u_int32_t i,nmem = 0;
00059 
00060     t_cf_tree_dataset data;
00061     data.data = NULL;
00062 
00063     if(stat(Cfg.VisitedFile,&st) == 0) {
00064       nmem  = st.st_size / sizeof(*field);
00065       field = fo_alloc(NULL,nmem,sizeof(*field),FO_ALLOC_MALLOC);
00066 
00067       if((fd = fopen(Cfg.VisitedFile,"r")) == NULL) {
00068         free(field);
00069         return;
00070       }
00071 
00072       fread(field,sizeof(*field),st.st_size / sizeof(*field),fd);
00073       fclose(fd);
00074 
00075       cf_tree_init(&Cfg.tree,flt_visited_compare,NULL);
00076       for(i=0;i<nmem;i++) {
00077         data.key = memdup(&field[i],sizeof(*field));
00078         cf_tree_insert(&Cfg.tree,NULL,&data);
00079       }
00080 
00081       free(field);
00082     }
00083     else {
00084       if((fd = fopen(Cfg.VisitedFile,"w")) != NULL) {
00085         fclose(fd);
00086       }
00087     }
00088   }
00089 }
00090 
00091 /* module api function, checks if message has been visited */
00092 void *flt_visited_is_visited(void *vmid) {
00093   u_int64_t *mid = (u_int64_t *)vmid;
00094   t_cf_tree_dataset data;
00095 
00096   data.data = NULL;
00097 
00098   if(Cfg.VisitedFile) {
00099     flt_visited_create_tree();
00100 
00101     data.key = mid;
00102     if(cf_tree_find(&Cfg.tree,Cfg.tree.root,&data)) {
00103       return (void *)mid;
00104     }
00105   }
00106 
00107   return NULL;
00108 }
00109 
00110 /* module api function, mark a posting visited */
00111 void *flt_visited_mark_visited(void *vmid) {
00112   u_int64_t *mid = (u_int64_t *)vmid;
00113   t_cf_tree_dataset data;
00114   FILE *fd;
00115 
00116   data.data = NULL;
00117 
00118   if(Cfg.VisitedFile) {
00119     flt_visited_create_tree();
00120 
00121     data.key = memdup(mid,sizeof(*mid));
00122     if(cf_tree_find(&Cfg.tree,Cfg.tree.root,&data) == NULL) {
00123       if((fd = fopen(Cfg.VisitedFile,"a")) != NULL) {
00124         cf_tree_insert(&Cfg.tree,NULL,&data);
00125         fwrite(mid,sizeof(*mid),1,fd);
00126         fclose(fd);
00127 
00128         return vmid;
00129       }
00130     }
00131 
00132     free(data.key);
00133   }
00134 
00135   return NULL;
00136 }
00137 
00138 /*
00139  * Returns: int   one of the FLT_* values
00140  * Parameters:
00141  *   - t_cf_hash *head          a pointer to the cgi paramter list
00142  *   - t_configuration *dc      a pointer to the default configuration
00143  *   - t_configuration *vc      a pointer to the fo_view configuration
00144  *   - t_configuration *uc      a pointer to the user config
00145  *
00146  * This function is the api function for the "mark visited messages" plugin. It is a
00147  * t_filter_begin function
00148  *
00149  */
00150 int execute_filter(t_cf_hash *head,t_configuration *dc,t_configuration *vc,int sock) {
00151   u_char *uname = cf_hash_get(GlobalValues,"UserName",8);
00152   t_cf_tree_dataset data = { NULL, NULL };
00153   u_char *cmid;
00154   u_char *ctid;
00155   u_int64_t mid,tid;
00156   FILE *fd;
00157   int ret;
00158   rline_t tsd;
00159   t_message *msg;
00160   t_cl_thread thread;
00161 
00162   if(uname && Cfg.VisitedFile) {
00163     /* register module api */
00164     cf_register_mod_api_ent("flt_visited","is_visited",flt_visited_is_visited);
00165     cf_register_mod_api_ent("flt_visited","mark_visited",flt_visited_mark_visited);
00166 
00167     if(head && Cfg.HighlightVisitedPostings) {
00168       cmid = cf_cgi_get(head,"m");
00169       ctid  = cf_cgi_get(head,"mv");
00170 
00171       /* we shall mark a whole thread visited */
00172       if(ctid) {
00173         tid = strtoull(ctid,NULL,10);
00174         memset(&tsd,0,sizeof(tsd));
00175         memset(&thread,0,sizeof(thread));
00176 
00177         if(tid) {
00178           #ifdef CF_SHARED_MEM
00179           ret = cf_get_message_through_shm((void *)sock,&thread,NULL,tid,0,CF_KILL_DELETED);
00180           #else
00181           ret = cf_get_message_through_sock(sock,&tsd,&thread,NULL,tid,0,CF_KILL_DELETED);
00182           #endif
00183 
00184           if(ret == -1) {
00185             return FLT_DECLINE;
00186           }
00187 
00188           if((fd = fopen(Cfg.VisitedFile,"a")) == NULL) {
00189             return FLT_DECLINE;
00190           }
00191 
00192           for(msg=thread.messages;msg;msg=msg->next) {
00193             data.key = memdup(&msg->mid,sizeof(msg->mid));
00194 
00195             if(!cf_tree_find(&Cfg.tree,Cfg.tree.root,&data)) {
00196               fwrite(&msg->mid,sizeof(msg->mid),1,fd);
00197               cf_tree_insert(&Cfg.tree,NULL,&data);
00198             }
00199           }
00200 
00201           cleanup_struct(&thread);
00202           fclose(fd);
00203         }
00204       }
00205 
00206       /* we shall only mark a message visited */
00207       else if(cmid) {
00208         mid = strtoull(cmid,NULL,10);
00209 
00210         if(mid) {
00211           flt_visited_create_tree();
00212 
00213           data.key = memdup(&mid,sizeof(mid));
00214 
00215           if(!cf_tree_find(&Cfg.tree,Cfg.tree.root,&data)) {
00216             cf_tree_insert(&Cfg.tree,NULL,&data);
00217             fd = fopen(Cfg.VisitedFile,"a");
00218             if(fd) {
00219               fwrite(&mid,sizeof(mid),1,fd);
00220               fclose(fd);
00221             }
00222           }
00223           else {
00224             free(data.key);
00225           }
00226         }
00227       }
00228 
00229       return FLT_OK;
00230     }
00231   }
00232 
00233   return FLT_DECLINE;
00234 }
00235 
00236 int set_col(t_cf_hash *head,t_configuration *dc,t_configuration *vc,t_cf_template *begin,t_cf_template *end) {
00237   if(Cfg.VisitedPostingsColorF || Cfg.VisitedPostingsColorB) {
00238     tpl_cf_setvar(begin,"visitedcol","1",1,0);
00239 
00240     if(Cfg.VisitedPostingsColorF && *Cfg.VisitedPostingsColorF) {
00241       tpl_cf_setvar(begin,"visitedcolfg",Cfg.VisitedPostingsColorF,strlen(Cfg.VisitedPostingsColorF),0);
00242     }
00243     if(Cfg.VisitedPostingsColorB && *Cfg.VisitedPostingsColorB) {
00244       tpl_cf_setvar(begin,"visitedcolbg",Cfg.VisitedPostingsColorB,strlen(Cfg.VisitedPostingsColorB),0);
00245     }
00246   }
00247 
00248   return FLT_OK;
00249 }
00250 
00251 int posting_handler(t_cf_hash *head,t_configuration *dc,t_configuration *vc,t_cl_thread *thread,t_cf_template *tpl) {
00252   return set_col(head,dc,vc,tpl,NULL);
00253 }
00254 
00255 int mark_visited(t_cf_hash *head,t_configuration *dc,t_configuration *vc,t_message *msg,unsigned long long tid,int mode) {
00256   u_char *uname = cf_hash_get(GlobalValues,"UserName",8);
00257   t_cf_tree_dataset data;
00258 
00259   data.data = NULL;
00260 
00261   if(uname && Cfg.VisitedFile && Cfg.HighlightVisitedPostings) {
00262     flt_visited_create_tree();
00263 
00264     data.key = memdup(&msg->mid,sizeof(msg->mid));
00265     if(cf_tree_find(&Cfg.tree,Cfg.tree.root,&data)) {
00266       tpl_cf_setvar(&msg->tpl,"visited","1",1,0);
00267     }
00268 
00269     return FLT_OK;
00270   }
00271 
00272   return FLT_DECLINE;
00273 }
00274 
00275 int flt_visit_handle_command(t_configfile *cf,t_conf_opt *opt,u_char **args,int argnum) {
00276   if(cf_strcmp(opt->name,"HighlightVisitedPostings") == 0) {
00277     Cfg.HighlightVisitedPostings = !cf_strcmp(args[0],"yes");
00278   }
00279   else if(cf_strcmp(opt->name,"VisitedPostingsColors") == 0) {
00280     if(Cfg.VisitedPostingsColorF) free(Cfg.VisitedPostingsColorF);
00281     if(Cfg.VisitedPostingsColorB) free(Cfg.VisitedPostingsColorB);
00282     Cfg.VisitedPostingsColorF = strdup(args[0]);
00283     Cfg.VisitedPostingsColorB = strdup(args[1]);
00284   }
00285   else if(cf_strcmp(opt->name,"VisitedFile") == 0) {
00286     if(Cfg.VisitedFile) free(Cfg.VisitedFile);
00287     Cfg.VisitedFile = strdup(args[0]);
00288   }
00289 
00290   return 0;
00291 }
00292 
00293 int flt_visited_validate(t_cf_hash *head,t_configuration *dc,t_configuration *vc,time_t last_modified,int sock) {
00294   struct stat st;
00295 
00296   if(Cfg.VisitedFile) {
00297     if(stat(Cfg.VisitedFile,&st) == -1) return FLT_DECLINE;
00298     if(st.st_mtime > last_modified) return FLT_EXIT;
00299   }
00300 
00301   return FLT_OK;
00302 }
00303 
00304 time_t flt_visited_lm(t_cf_hash *head,t_configuration *dc,t_configuration *vc,int sock) {
00305   struct stat st;
00306 
00307   if(Cfg.VisitedFile) {
00308     if(stat(Cfg.VisitedFile,&st) == -1) return -1;
00309     return st.st_mtime;
00310   }
00311 
00312 
00313   return -1;
00314 }
00315 
00316 void flt_visited_cleanup(void) {
00317   if(Cfg.VisitedPostingsColorF) free(Cfg.VisitedPostingsColorF);
00318   if(Cfg.VisitedPostingsColorB) free(Cfg.VisitedPostingsColorB);
00319   if(Cfg.VisitedFile)      free(Cfg.VisitedFile);
00320 
00321   cf_tree_destroy(&Cfg.tree);
00322 }
00323 
00324 t_conf_opt flt_visited_config[] = {
00325   { "HighlightVisitedPostings", flt_visit_handle_command, NULL },
00326   { "VisitedPostingsColors",    flt_visit_handle_command, NULL },
00327   { "VisitedFile",              flt_visit_handle_command, NULL },
00328   { NULL, NULL, NULL }
00329 };
00330 
00331 t_handler_config flt_visited_handlers[] = {
00332   { CONNECT_INIT_HANDLER, execute_filter  },
00333   { VIEW_INIT_HANDLER,    set_col         },
00334   { POSTING_HANDLER,      posting_handler },
00335   { VIEW_LIST_HANDLER,    mark_visited    },
00336   { 0, NULL }
00337 };
00338 
00339 t_module_config flt_visited = {
00340   flt_visited_config,
00341   flt_visited_handlers,
00342   flt_visited_validate,
00343   flt_visited_lm,
00344   NULL,
00345   flt_visited_cleanup
00346 };
00347 
00348 
00349 /* eof */

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