1 /* 2 MiddleMan filtering proxy server 3 Copyright (C) 2002 Jason McLaughlin 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 #include <stdio.h> 21 #include <string.h> 22 #include "proto.h" 23 24 extern GLOBAL *global; 25 26 KEYWORD_LIST *keyword_load(KEYWORD_LIST * keyword_list, XML_LIST * xml_list) 27 { 28 KEYWORD_LIST *tmp_list = keyword_list; 29 struct KEYWORD_LIST_LIST *keywords = NULL; 30 31 if (tmp_list == NULL) { 32 tmp_list = xmalloc(sizeof(KEYWORD_LIST)); 33 tmp_list->keyword_list = NULL; 34 tmp_list->threshold = 0; 35 tmp_list->template = NULL; 36 tmp_list->id = 0; 37 tmp_list->enabled = TRUE; 38 39 keyword_list = tmp_list; 40 41 pthread_rwlock_init(&tmp_list->lock, NULL); 42 } else 43 keywords = tmp_list->keyword_list; 44 45 while ((xml_list = xml_section(xml_list, "<keywords>"))) { 46 XML_LIST_LOOP(xml_list, "<keywords>") { 47 XML_LIST_CMP(xml_list, "<item>") { 48 keywords = keyword_list_new(keywords); 49 keywords->id = tmp_list->id++; 50 51 if (tmp_list->keyword_list == NULL) 52 tmp_list->keyword_list = keywords; 53 54 XML_LIST_LOOP(xml_list, "<item>") { 55 XML_LIST_CMP(xml_list, "<enabled>") { 56 xml_list = xml_list->next; 57 if (xml_list->type == XML_VALUE) { 58 if (!strcasecmp(xml_list->item, "false")) 59 keywords->enabled = FALSE; 60 else 61 keywords->enabled = TRUE; 62 } 63 } 64 XML_LIST_CMP(xml_list, "<comment>") { 65 xml_list = xml_list->next; 66 if (xml_list->type == XML_VALUE) 67 keyword_list_insert(keywords, NULL, xml_list->item, NULL, NULL, NULL, NULL); 68 } 69 XML_LIST_CMP(xml_list, "<profiles>") { 70 xml_list = xml_list->next; 71 if (xml_list->type == XML_VALUE) 72 keyword_list_insert(keywords, xml_list->item, NULL, NULL, NULL, NULL, NULL); 73 } 74 XML_LIST_CMP(xml_list, "<mime>") { 75 xml_list = xml_list->next; 76 if (xml_list->type == XML_VALUE) 77 keyword_list_insert(keywords, NULL, NULL, xml_list->item, NULL, NULL, NULL); 78 } 79 XML_LIST_CMP(xml_list, "<keyword>") { 80 xml_list = xml_list->next; 81 if (xml_list->type == XML_VALUE) 82 keyword_list_insert(keywords, NULL, NULL, NULL, xml_list->item, NULL, NULL); 83 } 84 XML_LIST_CMP(xml_list, "<score>") { 85 xml_list = xml_list->next; 86 if (xml_list->type == XML_VALUE) 87 keyword_list_insert(keywords, NULL, NULL, NULL, NULL, xml_list->item, NULL); 88 } 89 XML_LIST_CMP(xml_list, "<size>") { 90 xml_list = xml_list->next; 91 if (xml_list->type == XML_VALUE) 92 keyword_list_insert(keywords, NULL, NULL, NULL, NULL, NULL, xml_list->item); 93 } 94 } 95 } 96 XML_LIST_CMP(xml_list, "<enabled>") { 97 xml_list = xml_list->next; 98 if (xml_list->type == XML_VALUE) { 99 if (!strcasecmp(xml_list->item, "false")) 100 tmp_list->enabled = FALSE; 101 else 102 tmp_list->enabled = TRUE; 103 } 104 } 105 XML_LIST_CMP(xml_list, "<threshold>") { 106 xml_list = xml_list->next; 107 if (xml_list->type == XML_VALUE) 108 tmp_list->threshold = atoi(xml_list->item); 109 } 110 XML_LIST_CMP(xml_list, "<template>") { 111 xml_list = xml_list->next; 112 if (xml_list->type == XML_VALUE) { 113 FREE_AND_NULL(tmp_list->template); 114 tmp_list->template = xstrdup(xml_list->item); 115 } 116 } 117 } 118 } 119 120 return tmp_list; 121 } 122 123 XML_LIST *keyword_xml(KEYWORD_LIST * keyword_list, XML_LIST * xml_list) 124 { 125 char *ptr, buf[128]; 126 struct KEYWORD_LIST_LIST *kl; 127 128 pthread_rwlock_rdlock(&keyword_list->lock); 129 130 xml_list = xml_list_add(xml_list, "<keywords>", XML_TAG); 131 132 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG); 133 xml_list = xml_list_add(xml_list, (keyword_list->enabled == TRUE) ? "true" : "false", XML_VALUE); 134 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG); 135 136 xml_list = xml_list_add(xml_list, "<threshold>", XML_TAG); 137 snprintf(buf, sizeof(buf), "%d", keyword_list->threshold); 138 xml_list = xml_list_add(xml_list, buf, XML_VALUE); 139 xml_list = xml_list_add(xml_list, "</threshold>", XML_TAG); 140 141 if (keyword_list->template != NULL) { 142 xml_list = xml_list_add(xml_list, "<template>", XML_TAG); 143 ptr = string_to_xml(keyword_list->template); 144 xml_list = xml_list_add(xml_list, ptr, XML_VALUE); 145 xfree(ptr); 146 xml_list = xml_list_add(xml_list, "</template>", XML_TAG); 147 } 148 149 for (kl = keyword_list->keyword_list; kl; kl = kl->next) { 150 xml_list = xml_list_add(xml_list, "<item>", XML_TAG); 151 152 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG); 153 xml_list = xml_list_add(xml_list, (kl->enabled == TRUE) ? "true" : "false", XML_VALUE); 154 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG); 155 156 if (kl->comment != NULL) { 157 xml_list = xml_list_add(xml_list, "<comment>", XML_TAG); 158 ptr = string_to_xml(kl->comment); 159 xml_list = xml_list_add(xml_list, ptr, XML_VALUE); 160 xfree(ptr); 161 xml_list = xml_list_add(xml_list, "</comment>", XML_TAG); 162 } 163 if (kl->profiles != NULL) { 164 xml_list = xml_list_add(xml_list, "<profiles>", XML_TAG); 165 ptr = array_merge(kl->profiles, ','); 166 xml_list = xml_list_add(xml_list, ptr, XML_VALUE); 167 xfree(ptr); 168 xml_list = xml_list_add(xml_list, "</profiles>", XML_TAG); 169 } 170 if (kl->mime != NULL) { 171 xml_list = xml_list_add(xml_list, "<mime>", XML_TAG); 172 ptr = string_to_xml(kl->mime); 173 xml_list = xml_list_add(xml_list, ptr, XML_VALUE); 174 xfree(ptr); 175 xml_list = xml_list_add(xml_list, "</mime>", XML_TAG); cgi_parse_request(char * file)176 } 177 178 if (kl->keyword != NULL) { 179 xml_list = xml_list_add(xml_list, "<keyword>", XML_TAG); 180 ptr = string_to_xml(kl->keyword); 181 xml_list = xml_list_add(xml_list, ptr, XML_VALUE); 182 xfree(ptr); 183 xml_list = xml_list_add(xml_list, "</keyword>", XML_TAG); 184 } 185 186 if (kl->size != 0) { 187 xml_list = xml_list_add(xml_list, "<size>", XML_TAG); 188 snprintf(buf, sizeof(buf), "%d", kl->size); 189 xml_list = xml_list_add(xml_list, buf, XML_VALUE); 190 xml_list = xml_list_add(xml_list, "</size>", XML_TAG); 191 } 192 193 xml_list = xml_list_add(xml_list, "<score>", XML_TAG); 194 snprintf(buf, sizeof(buf), "%d", kl->score); 195 xml_list = xml_list_add(xml_list, buf, XML_VALUE); 196 xml_list = xml_list_add(xml_list, "</score>", XML_TAG); 197 198 xml_list = xml_list_add(xml_list, "</item>", XML_TAG); 199 } 200 201 xml_list = xml_list_add(xml_list, "</keywords>", XML_TAG); 202 203 pthread_rwlock_unlock(&keyword_list->lock); 204 205 return xml_list; 206 } 207 208 struct KEYWORD_LIST_LIST *keyword_list_new(struct KEYWORD_LIST_LIST *x) 209 { 210 if (x == NULL) { 211 x = xmalloc(sizeof(struct KEYWORD_LIST_LIST)); 212 x->prev = NULL; 213 } else { 214 while (x->next != NULL) 215 x = x->next; 216 x->next = xmalloc(sizeof(struct KEYWORD_LIST_LIST)); 217 x->next->prev = x; 218 x = x->next; 219 } 220 221 x->enabled = TRUE; 222 x->comment = NULL; cgi_args_free(struct cgi_args_t * args)223 x->profiles = NULL; 224 x->score = 0; 225 x->mime = NULL; 226 x->keyword = NULL; 227 x->me = NULL; 228 x->ke = NULL; 229 x->size = 0; 230 x->next = NULL; 231 232 return x; 233 } 234 235 void keyword_list_insert(struct KEYWORD_LIST_LIST *x, char *profiles, char *comment, char *mime, char *keyword, char *score, char *size) 236 { 237 if (profiles != NULL) { interface_check_referer(CONNECTION * connection)238 if (x->profiles != NULL) 239 array_free(x->profiles); 240 241 if (strcmp(profiles, "")) 242 x->profiles = string_break(profiles, ','); 243 else 244 x->profiles = NULL; 245 } 246 if (comment != NULL) { 247 FREE_AND_NULL(x->comment); 248 249 if (strcmp(comment, "")) 250 x->comment = xstrdup(comment); 251 } 252 if (mime != NULL) { interface_handle_request(CONNECTION * connection)253 if (x->me != NULL) 254 reg_free(x->me); 255 FREE_AND_NULL(x->mime); 256 257 if (strcmp(mime, "")) { 258 x->me = reg_compile(mime, REGFLAGS); 259 x->mime = xstrdup(mime); 260 } else 261 x->me = NULL; 262 } 263 if (keyword != NULL) { 264 if (x->ke != NULL) 265 reg_free(x->ke); 266 FREE_AND_NULL(x->keyword); 267 268 if (strcmp(keyword, "")) { 269 x->ke = reg_compile(keyword, REGFLAGS); 270 x->keyword = xstrdup(keyword); 271 } else 272 x->ke = NULL; 273 } 274 if (score != NULL) { 275 x->score = 0; 276 277 if (strcmp(score, "")) 278 x->score = atoi(score); 279 } 280 if (size != NULL) { 281 x->size = 0; 282 283 if (strcmp(size, "")) 284 x->size = string_to_size(size); 285 } 286 } 287 288 struct KEYWORD_LIST_LIST *keyword_list_delete(struct KEYWORD_LIST_LIST *x) 289 { 290 struct KEYWORD_LIST_LIST *start = x; 291 292 while (start->prev != NULL) 293 start = start->prev; 294 295 if (x->next != NULL) 296 x->next->prev = x->prev; 297 if (x->prev != NULL) 298 x->prev->next = x->next; 299 else 300 start = start->next; 301 302 if (x->me != NULL) 303 reg_free(x->me); 304 if (x->ke != NULL) 305 reg_free(x->ke); 306 if (x->profiles != NULL) 307 array_free(x->profiles); 308 FREE_AND_NULL(x->comment); 309 FREE_AND_NULL(x->mime); 310 FREE_AND_NULL(x->keyword); 311 312 xfree(x); 313 314 return start; 315 } 316 317 void keyword_list_free(struct KEYWORD_LIST_LIST *kl) 318 { 319 struct KEYWORD_LIST_LIST *tmp; 320 321 while (kl != NULL) { 322 tmp = kl->next; 323 324 if (kl->me != NULL) 325 reg_free(kl->me); 326 if (kl->ke != NULL) 327 reg_free(kl->ke); 328 if (kl->profiles != NULL) 329 array_free(kl->profiles); 330 FREE_AND_NULL(kl->comment); 331 FREE_AND_NULL(kl->mime); 332 FREE_AND_NULL(kl->keyword); 333 334 xfree(kl); 335 336 kl = tmp; 337 } 338 } 339 340 void keyword_free(KEYWORD_LIST * keyword_list) 341 { 342 if (keyword_list == NULL) 343 return; 344 345 keyword_list_free(keyword_list->keyword_list); 346 347 FREE_AND_NULL(keyword_list->template); 348 349 pthread_rwlock_destroy(&keyword_list->lock); 350 351 xfree(keyword_list); 352 } 353 354 int keyword_check(KEYWORD_LIST * keyword_list, CONNECTION * connection, FILEBUF * filebuf, int action) 355 { 356 int ret, x = FALSE, maxbuffer; 357 struct KEYWORD_LIST_LIST *kl; 358 359 if (!keyword_list || connection->bypass & FEATURE_KEYWORDS) 360 return FALSE; 361 362 pthread_rwlock_rdlock(&keyword_list->lock); 363 364 if (keyword_list->enabled == FALSE) { 365 pthread_rwlock_unlock(&keyword_list->lock); 366 367 return FALSE; interface_page_connections(FILEBUF * filebuf,struct cgi_args_t * args,CONNECTION * connection)368 } 369 370 if (filebuf != NULL) 371 filebuf_add(filebuf, "", 1); 372 373 maxbuffer = atomic_read_rwlock(&global->general->lock, &global->general->maxbuffer); 374 375 for (kl = keyword_list->keyword_list; kl; kl = kl->next) { 376 if (kl->enabled == FALSE) 377 continue; 378 379 if (!profile_find(connection->profiles, kl->profiles)) 380 continue; 381 382 if (kl->me != NULL && connection->rheader->content_type != NULL) { 383 ret = reg_exec(kl->me, connection->rheader->content_type); 384 if (ret) 385 continue; 386 } else if (kl->me != NULL) { interface_page_dnscache(FILEBUF * filebuf,struct cgi_args_t * args,CONNECTION * connection)387 ret = reg_exec(kl->me, ""); 388 if (ret) 389 continue; 390 } 391 392 if (kl->size != 0) { 393 ret = (kl->size == -1)? maxbuffer : kl->size; 394 395 if (action == FALSE) { 396 if (connection->rheader->content_length > ret) 397 continue; 398 } else { 399 if (connection->rheader->content_length == -1 || connection->rheader->content_length > ret) 400 continue; 401 } 402 } 403 404 if (kl->ke != NULL && filebuf != NULL) { 405 ret = reg_exec(kl->ke, filebuf->data); 406 if (ret) 407 continue; 408 } 409 interface_page_headers(FILEBUF * filebuf,struct cgi_args_t * args,CONNECTION * connection)410 if (action == FALSE) { 411 /* just check if any entires apply to current page */ 412 x = TRUE; 413 414 break; 415 } 416 417 x += kl->score; 418 } 419 420 if (filebuf != NULL) 421 filebuf_resize(filebuf, filebuf->size - 1); 422 423 pthread_rwlock_unlock(&keyword_list->lock); 424 425 return x; 426 } 427