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

flt_cftp.c

Go to the documentation of this file.
00001 
00008 /* {{{ Initial comments */
00009 /*
00010  * $LastChangedDate: 2004-01-08 14:20:45 +0100 (Thu, 08 Jan 2004) $
00011  * $LastChangedRevision: 32 $
00012  * $LastChangedBy: ckruse $
00013  *
00014  */
00015 /* }}} */
00016 
00017 /* {{{ Includes */
00018 #include "config.h"
00019 #include "defines.h"
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <time.h>
00026 
00027 #include <pthread.h>
00028 
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 
00032 #include "cf_pthread.h"
00033 
00034 #include "hashlib.h"
00035 #include "utils.h"
00036 #include "configparser.h"
00037 #include "readline.h"
00038 #include "fo_server.h"
00039 #include "serverlib.h"
00040 /* }}} */
00041 
00042 int flt_cftp_handler(int sockfd,const u_char **tokens,int tnum,rline_t *tsd) {
00043   t_name_value *sort_t_v = cfg_get_value(&fo_server_conf,"SortThreads");
00044   t_name_value *sort_m_v = cfg_get_value(&fo_server_conf,"SortMessages");
00045 
00046   int sort_m = atoi(sort_m_v->values[0]);
00047   int sort_t = atoi(sort_t_v->values[0]);
00048 
00049   if(cf_strcmp(tokens[0],"GET") == 0) {
00050     if(tnum >= 2) {
00051       cf_log(LOG_DBG,__FILE__,__LINE__,"%s %s\n",tokens[0],tokens[1]);
00052 
00053       /* {{{ GET THREADLIST */
00054       if(cf_strcmp(tokens[1],"THREADLIST") == 0) {
00055         CF_RW_RD(&head.lock);
00056 
00057         if(tnum == 3 && cf_strcmp(tokens[2],"invisible=1") == 0) {
00058           writen(sockfd,head.cache_invisible.content,head.cache_invisible.len);
00059         }
00060         else {
00061           writen(sockfd,head.cache_visible.content,head.cache_visible.len);
00062         }
00063 
00064         CF_RW_UN(&head.lock);
00065       }
00066       /* }}} */
00067 
00068       /* {{{ GET POSTING */
00069       else if(cf_strcmp(tokens[1],"POSTING") == 0) {
00070         if(tnum < 4) {
00071           writen(sockfd,"501 Thread id or message id missing\n",36);
00072         }
00073         else if(tnum > 5) {
00074           writen(sockfd,"500 Syntax error\n",17);
00075         }
00076         else {
00077           u_int64_t tid = strtoull(tokens[2]+1,NULL,10);
00078           u_int64_t mid = strtoull(tokens[3]+1,NULL,10);
00079 
00080           cf_send_posting(sockfd,tid,mid,tnum == 5 && cf_strcmp(tokens[4],"invisible=1") == 0);
00081         }
00082       }
00083       /* }}} */
00084 
00085       /* {{{ GET LASTMODIFIED */
00086       else if(cf_strcmp(tokens[1],"LASTMODIFIED") == 0) {
00087         u_char buff[50];
00088         int l;
00089 
00090         CF_RW_RD(&head.lock);
00091 
00092         if(tnum == 3 && *tokens[2] == '1') {
00093           l = snprintf(buff,50,"%ld\n",head.date_invisible);
00094         }
00095         else {
00096           l = snprintf(buff,50,"%ld\n",head.date_visible);
00097         }
00098 
00099         CF_RW_UN(&head.lock);
00100 
00101         writen(sockfd,buff,l);
00102       }
00103       /* }}} */
00104 
00105       /* {{{ GET MIDLIST */
00106       else if(cf_strcmp(tokens[1],"MIDLIST") == 0) {
00107         t_string str;
00108         t_thread *t,*t1;
00109         t_posting *p;
00110         char buff[256];
00111         size_t len;
00112 
00113         str_init(&str);
00114         str_chars_append(&str,"200 List Follows\n",17);
00115 
00116         CF_RW_RD(&head.lock);
00117         t = head.thread;
00118         CF_RW_UN(&head.lock);
00119 
00120         for(;t;t=t1) {
00121           CF_RW_RD(&t->lock);
00122 
00123           for(p=t->postings;p;p=p->next) {
00124             len = snprintf(buff,256,"m%lld\n",p->mid);
00125             str_chars_append(&str,buff,len);
00126           }
00127 
00128           t1 = t->next;
00129           CF_RW_UN(&t->lock);
00130         }
00131 
00132         str_char_append(&str,'\n');
00133 
00134         writen(sockfd,str.content,str.len);
00135         str_cleanup(&str);
00136       }
00137       /* }}} */
00138 
00139       else {
00140         return FLT_DECLINE;
00141       }
00142     }
00143   }
00144   else if(cf_strcmp(tokens[0],"STAT") == 0) {
00145     if(tnum != 4) return FLT_DECLINE;
00146 
00147     /* {{{ STAT THREAD */
00148     if(cf_strcmp(tokens[1],"THREAD") == 0) {
00149       u_int64_t tid = strtoull(tokens[2]+1,NULL,10);
00150 
00151       if(cf_get_thread(tid)) {
00152         writen(sockfd,"200 Exists\n",11);
00153       }
00154       else {
00155         writen(sockfd,"404 Thread not found\n",21);
00156       }
00157     }
00158     /* }}} */
00159 
00160     /* {{{ STAT POST */
00161     else if(cf_strcmp(tokens[1],"POST") == 0) {
00162       u_int64_t tid,mid;
00163       t_thread *t;
00164 
00165       tid = strtoull(tokens[2]+1,NULL,10);
00166       mid = strtoull(tokens[3]+1,NULL,10);
00167 
00168       if((t = cf_get_thread(tid)) != NULL) {
00169         if(cf_get_posting(t,mid)) writen(sockfd,"200 Posting exists\n",19);
00170         else writen(sockfd,"404 Posting not found\n",22);
00171       }
00172       else writen(sockfd,"404 Thread not found\n",21);
00173     }
00174     /* }}} */
00175 
00176     else {
00177       return FLT_DECLINE;
00178     }
00179 
00180   }
00181   else if(cf_strcmp(tokens[0],"POST") == 0) {
00182     if(tnum < 2) return FLT_DECLINE;
00183 
00184     /* {{{ POST ANSWER */
00185     if(cf_strcmp(tokens[1],"ANSWER") == 0) {
00186       t_posting *p = fo_alloc(NULL,1,sizeof(t_posting),FO_ALLOC_CALLOC),*p1,*p2;
00187       t_thread *t;
00188       u_int64_t tid,mid;
00189       int err = 0;
00190 
00191       if(tnum != 4) {
00192         writen(sockfd,"500 Sorry\n",10);
00193         cf_log(LOG_ERR,__FILE__,__LINE__,"Bad request\n");
00194       }
00195       else {
00196         tid = strtoull(tokens[2]+2,NULL,10);
00197         mid = strtoull(tokens[3]+2,NULL,10);
00198 
00199         t  = cf_get_thread(tid);
00200 
00201         if(!t) {
00202           writen(sockfd,"404 Thread Not Found\n",21);
00203           cf_log(LOG_ERR,__FILE__,__LINE__,"Thread not found\n");
00204           err = 1;
00205         }
00206         else {
00207           p1 = cf_get_posting(t,mid);
00208           if(!p1 || p1->invisible == 1) {
00209             writen(sockfd,"404 Posting Not Found\n",22);
00210             cf_log(LOG_ERR,__FILE__,__LINE__,"Posting not found\n");
00211             err = 1;
00212           }
00213           else {
00214             if(cf_read_posting(p,sockfd,tsd)) {
00215               CF_RW_WR(&t->lock);
00216 
00217               for(p2=t->postings;p2;p2=p2->next) {
00218                 if(p2->unid && p->unid && cf_strcmp(p2->unid,p->unid) == 0) {
00219                   writen(sockfd,"502 Unid already got\n",21);
00220                   cf_log(LOG_ERR,__FILE__,__LINE__,"Unid already got\n");
00221                   err = 1;
00222                   break;
00223                 }
00224               }
00225 
00226               if(err == 0) {
00227                 p->level     = p1->level + 1;
00228                 p->invisible = 0;
00229                 t->newest    = p;
00230                 t->posts    += 1;
00231 
00232                 if(sort_m == 2 || p1->next == NULL) {
00233                   p->next       = p1->next;
00234                   p1->next      = p;
00235                   p->prev       = p1;
00236 
00237                   if(p->next) p->next->prev = p;
00238                   else        t->last = p;
00239                 }
00240                 else {
00241                   for(p1=p1->next;p1->next && p1->level == p->level;p1=p1->next);
00242                   p->next       = p1->next;
00243                   p1->next      = p;
00244                   p->prev       = p1;
00245 
00246                   if(p->next) p->next->prev = p;
00247                   else        t->last       = p;
00248                 }
00249 
00250                 writen(sockfd,"200 Ok\n",7);
00251 
00252                 CF_RW_UN(&t->lock);
00253                 cf_generate_cache(NULL);
00254               }
00255               else {
00256                 CF_RW_UN(&t->lock);
00257 
00258                 if(p->unid)       free(p->unid);
00259                 if(p->category)   free(p->subject);
00260                 if(p->category)   free(p->category);
00261                 if(p->content)    free(p->content);
00262                 if(p->user.name)  free(p->user.name);
00263                 if(p->user.email) free(p->user.email);
00264                 if(p->user.hp)    free(p->user.hp);
00265                 if(p->user.img)   free(p->user.img);
00266                 if(p->user.ip)    free(p->user.ip);
00267                 free(p);
00268               }
00269             }
00270             else {
00271               if(p->unid)       free(p->unid);
00272               if(p->subject)    free(p->subject);
00273               if(p->category)   free(p->category);
00274               if(p->content)    free(p->content);
00275               if(p->user.name)  free(p->user.name);
00276               if(p->user.email) free(p->user.email);
00277               if(p->user.hp)    free(p->user.hp);
00278               if(p->user.img)   free(p->user.img);
00279               if(p->user.ip)    free(p->user.ip);
00280 
00281               free(p);
00282             }
00283           }
00284         }
00285       }
00286     }
00287     /* }}} */
00288 
00289     /* {{{ POST THREAD */
00290     else if(cf_strcmp(tokens[1],"THREAD") == 0) {
00291       t_posting *p = fo_alloc(NULL,1,sizeof(t_posting),FO_ALLOC_CALLOC);
00292       t_thread  *t = fo_alloc(NULL,1,sizeof(t_thread),FO_ALLOC_CALLOC),*t1;
00293       int err = 0;
00294 
00295       if(cf_read_posting(p,sockfd,tsd)) {
00296         CF_RW_RD(&head.lock);
00297         if(sort_t == 2) t1 = head.thread;
00298         else            t1 = head.last;
00299         CF_RW_UN(&head.lock);
00300 
00301         if(t1) {
00302           /*
00303            * we only need to check the unid of the first posting in the last thread, because the user
00304            * tried to create a new thread and the first message of the thread before has to have the
00305            * same unid if this is a double posting created by pressing SUBMIT two times.
00306            */
00307           CF_RW_WR(&t1->lock);
00308 
00309           if(t1->postings->unid && cf_strcmp(t1->postings->unid,p->unid) == 0) {
00310             writen(sockfd,"502 Unid already got\n",21);
00311             cf_log(LOG_ERR,__FILE__,__LINE__,"Unid already got\n");
00312             err = 1;
00313             CF_RW_UN(&t1->lock);
00314           }
00315         }
00316 
00317         if(err == 0) {
00318           u_char buff[50];
00319 
00320           CF_RW_WR(&head.lock);
00321 
00322           snprintf(buff,50,"t%lld",head.tid+1);
00323           cf_rwlock_init(buff,&t->lock);
00324 
00325           t->postings  = p;
00326           t->last      = p;
00327           t->newest    = p;
00328           t->tid       = ++head.tid;
00329           t->posts     = 1;
00330 
00331           head.fresh   = 0;
00332 
00333           if(t1) {
00334             if(sort_t == 1) {
00335               t1->next    = t;
00336               t->prev     = t1;
00337             }
00338             else {
00339               t->next       = head.thread;
00340               head.thread   = t;
00341               t->next->prev = t;
00342             }
00343 
00344             CF_RW_UN(&t1->lock);
00345           }
00346           else {
00347             head.thread = t;
00348           }
00349 
00350           CF_RW_UN(&head.lock);
00351 
00352           cf_register_thread(t);
00353 
00354           writen(sockfd,"200 Ok\n",7);
00355 
00356           cf_generate_cache(NULL);
00357         }
00358         else {
00359           if(p->unid)       free(p->unid);
00360           if(p->subject)    free(p->subject);
00361           if(p->category)   free(p->category);
00362           if(p->content)    free(p->content);
00363           if(p->user.name)  free(p->user.name);
00364           if(p->user.email) free(p->user.email);
00365           if(p->user.hp)    free(p->user.hp);
00366           if(p->user.img)   free(p->user.img);
00367           if(p->user.ip)    free(p->user.ip);
00368 
00369           free(p);
00370           free(t);
00371         }
00372       }
00373       else {
00374         if(p->unid)       free(p->unid);
00375         if(p->subject)    free(p->subject);
00376         if(p->category)   free(p->category);
00377         if(p->content)    free(p->content);
00378         if(p->user.name)  free(p->user.name);
00379         if(p->user.email) free(p->user.email);
00380         if(p->user.hp)    free(p->user.hp);
00381         if(p->user.img)   free(p->user.img);
00382         if(p->user.ip)    free(p->user.ip);
00383 
00384         free(p);
00385         free(t);
00386       }
00387     }
00388     /* }}} */
00389   }
00390   else if(cf_strcmp(tokens[0],"PING") == 0) {
00391     writen(sockfd,"200 PONG!\n",10);
00392   }
00393   else {
00394     /* hu? how could this happen? */
00395     return FLT_DECLINE;
00396   }
00397 
00398   return FLT_OK;
00399 }
00400 
00401 int flt_cftp_register_handlers(int sock) {
00402   cf_register_protocol_handler("GET",flt_cftp_handler);
00403   cf_register_protocol_handler("POST",flt_cftp_handler);
00404   cf_register_protocol_handler("PING",flt_cftp_handler);
00405   cf_register_protocol_handler("STAT",flt_cftp_handler);
00406 
00407   return FLT_OK;
00408 }
00409 
00410 t_conf_opt flt_cftp_config[] = {
00411   { NULL, NULL, NULL }
00412 };
00413 
00414 t_handler_config flt_cftp_handlers[] = {
00415   { INIT_HANDLER,            flt_cftp_register_handlers   },
00416   { 0, NULL }
00417 };
00418 
00419 t_module_config flt_cftp = {
00420   flt_cftp_config,
00421   flt_cftp_handlers,
00422   NULL,
00423   NULL,
00424   NULL,
00425   NULL
00426 };
00427 
00428 /* eof */

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