00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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
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
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
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
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
00304
00305
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
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