1 /*
2 AWFFull - A Webalizer Fork, Full o' features
3
4 hashtab.c
5 The various hashing functions for 'fast' access to data
6
7 Copyright (C) 1997-2001 Bradford L. Barrett (brad@mrunix.net)
8 Copyright (C) 2006 by Alexander Lazic (al-awffull@none.at)
9 Copyright (C) 2006, 2007, 2008 by Stephen McInerney (spm@stedee.id.au)
10 Copyright (C) 2006 by John Heaton (john@manchester.ac.uk)
11 Copyright (C) 2007 by Benoît Dejean (benoit@placenet.org)
12
13 This file is part of AWFFull.
14
15 AWFFull is free software: you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19
20 AWFFull is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with AWFFull. If not, see <http://www.gnu.org/licenses/>.
27
28 This software uses the gd graphics library, which is copyright by
29 Quest Protein Database Center, Cold Spring Harbor Labs. Please
30 see the documentation supplied with the library for additional
31 information and license terms, or visit www.boutell.com/gd/ for the
32 most recent version of the library and supporting documentation.
33
34 */
35
36 /*********************************************/
37 /* STANDARD INCLUDES */
38 /*********************************************/
39
40 #include "awffull.h" /* main header */
41
42 /* internal function prototypes */
43
44 HNODEPTR new_hnode(char *); /* new host node */
45 UNODEPTR new_unode(char *); /* new url node */
46 RNODEPTR new_rnode(char *); /* new referrer node */
47 ANODEPTR new_anode(char *); /* new user agent node */
48 SNODEPTR new_snode(char *); /* new search string.. */
49 INODEPTR new_inode(char *); /* new ident node */
50 ENODEPTR new_enode(char *, char *); /* new errorpage node */
51
52 void update_entry(char *); /* update entry/exit */
53 void update_exit(char *, bool); /* page totals */
54
55 unsigned long hash(char *); /* hash function */
56
57 static void del_htab(NODEPTR * htab, const char *htab_name, size_t size, void (*free_node) (NODEPTR));
58
59 /* local data */
60
61 HNODEPTR sm_htab[MAXHASH]; /* hash tables */
62 HNODEPTR sd_htab[MAXHASH];
63 UNODEPTR um_htab[MAXHASH]; /* for hits, sites, */
64 RNODEPTR rm_htab[MAXHASH]; /* referrers and agents... */
65 ANODEPTR am_htab[MAXHASH];
66 SNODEPTR sr_htab[MAXHASH]; /* search string table */
67 INODEPTR im_htab[MAXHASH]; /* ident table (username) */
68 ENODEPTR ep_htab[MAXHASH]; /* errorpage table */
69
70 SEGNODEPTR seg_ref_htab[MAXHASH]; /* Segment on Referrers. */
71
72 /* Arrays of Constant Node Information for generic Node Creation
73 * Also see the "#define NODE_H..." 's in hashtab.h for numerical ordering */
74 static unsigned int nodemax[] = { MAXHOST, MAXURL, MAXREF, MAXAGENT, MAXSRCHH, MAXIDENT, MAXURL, MAXHOST + MAXAGENT };
75 static char node_c[] = { 'h', 'u', 'r', 'a', 's', 'i', 'e', 'g' };
76 static unsigned int nodesizes[] =
77 { sizeof(struct hnode), sizeof(struct unode), sizeof(struct rnode), sizeof(struct anode), sizeof(struct snode), sizeof(struct inode), sizeof(struct enode),
78 sizeof(struct seg_node)
79 };
80
81
82 /************************************************************************
83 * DEL_HTABS - clear out our hash tables *
84 * *
85 * Clear out our various hash tables here, *
86 * by calling the appropriate del_* function for each *
87 ************************************************************************/
88 void
del_htabs()89 del_htabs()
90 {
91 del_hlist(sd_htab);
92 del_ulist(um_htab);
93 del_hlist(sm_htab);
94 del_rlist(rm_htab);
95 del_alist(am_htab);
96 del_slist(sr_htab);
97 del_ilist(im_htab);
98 del_elist(ep_htab);
99 }
100
101
102 /************************************************************************
103 * check_hashstr_size *
104 * *
105 * Check and, if necessary!, reset the incoming string size. *
106 * Based off the maxsize for various strings from nodemax[] *
107 * *
108 * Arguments: *
109 * char *str: The string to check. eg The URL, Hostname etc *
110 * int nodetype: The type of node. See hashtab.h for details *
111 * *
112 * Returns: *
113 * The new or existing length of the string *
114 ************************************************************************/
115 static int
check_hashstr_size(char * str,int nodetype)116 check_hashstr_size(char *str, int nodetype)
117 {
118 size_t len;
119
120 len = strlen(str) + 1;
121 if (len >= nodemax[nodetype]) {
122 ERRVPRINT(VERBOSE1, "[new_%cnode] %s (%d)\n", node_c[nodetype], _("Warning: String exceeds storage size"), (int) len);
123 VPRINT(VERBOSE3, "STR: %s", str);
124 str[nodemax[nodetype]] = 0;
125 len = nodemax[nodetype];
126 VPRINT(VERBOSE3, " --> %d %s\n", len, str);
127 }
128 return (len);
129 }
130
131
132 /************************************************************************
133 * new_node *
134 * *
135 * Generic creator of all Chained-Hash-Table Nodes. *
136 * *
137 * Arguments: *
138 * char *str: The key to use. eg The URL, Hostname etc *
139 * int nodetype: The type of node. See hashtab.h for details *
140 * *
141 * Returns: *
142 * a pointer to the newly created (calloc'd) structure *
143 ************************************************************************/
144 static void *
new_node(char * str,int nodetype,size_t len)145 new_node(char *str, int nodetype, size_t len)
146 {
147 void *newptr, *string_offsetptr;
148 HNODEPTR hptr;
149 UNODEPTR uptr;
150 RNODEPTR rptr;
151 ANODEPTR aptr;
152 SNODEPTR sptr;
153 INODEPTR iptr;
154
155 // ENODEPTR eptr;
156 SEGNODEPTR gptr;
157
158 // if (nodetype == NODE_SEG) {
159 // ERRVPRINT(0, "\nNODE: %d --> %s\n", nodetype, str);
160 // }
161 newptr = xmalloc(nodesizes[nodetype] + (len * sizeof(char)));
162
163 switch (nodetype) {
164 case NODE_H:
165 hptr = newptr;
166 string_offsetptr = hptr->string;
167 break;
168 case NODE_U:
169 uptr = newptr;
170 string_offsetptr = uptr->string;
171 break;
172 case NODE_R:
173 rptr = newptr;
174 string_offsetptr = rptr->string;
175 break;
176 case NODE_A:
177 aptr = newptr;
178 string_offsetptr = aptr->string;
179 break;
180 case NODE_S:
181 sptr = newptr;
182 string_offsetptr = sptr->string;
183 break;
184 case NODE_I:
185 iptr = newptr;
186 string_offsetptr = iptr->string;
187 break;
188 case NODE_SEG:
189 gptr = newptr;
190 string_offsetptr = gptr->string;
191 break;
192 default:
193 exit(1); /* FIXME! */
194 }
195
196 memcpy(string_offsetptr, str, len);
197 // if (nodetype == NODE_SEG) {
198 // ERRVPRINT(0, "SEG: %s --> %s\n", str, gptr->string);
199 // }
200
201 return newptr;
202 }
203
204
205 /************************************************************************
206 * put_hnode *
207 * *
208 * insert/update host node *
209 * *
210 * Arguments: *
211 * char *str: Hostname *
212 * int type: obj type *
213 * unsigned long count: hit count *
214 * unsigned long file: File flag *
215 * unsigned long long xfer: xfer size *
216 * unsigned long *ctr: counter *
217 * unsigned long visit: visits *
218 * unsigned long page: pages *
219 * unsigned long tstamp: timestamp *
220 * char *url: Current URL *
221 * char *lasturl: lasturl *
222 * HNODEPTR * htab: Host Hash Table *
223 * bool lasturl_is_entry: TRUE if the last URL is an entry page. *
224 * Only used for creating a new node from *
225 * preserve/restore *
226 * bool isapage: Is a Page Y/N *
227 * bool *isnewsite *
228 * *
229 * --------------------------------------------------------------- *
230 * if visit > 0; then this is a "load" event from preserve.c *
231 * OR is a CreateGroup event from output.c *
232 * *
233 * Returns: *
234 * 0 on Success, 1 on Failure *
235 ************************************************************************/
236 int
put_hnode(char * str,int type,unsigned long count,unsigned long file,unsigned long long xfer,unsigned long * ctr,unsigned long visit,unsigned long page,unsigned long tstamp,char * url,char * lasturl,HNODEPTR * htab,bool lasturl_is_entry,bool isapage,bool * isnewsite)237 put_hnode(char *str,
238 int type,
239 unsigned long count,
240 unsigned long file,
241 unsigned long long xfer,
242 unsigned long *ctr,
243 unsigned long visit, unsigned long page, unsigned long tstamp, char *url, char *lasturl, HNODEPTR * htab, bool lasturl_is_entry, bool isapage, bool * isnewsite)
244 {
245 HNODEPTR cptr, nptr = NULL, prev_cptr = NULL;
246 size_t len;
247
248 len = check_hashstr_size(str, NODE_H);
249 cptr = htab[hash(str)];
250 while (cptr != NULL) {
251 if (strncmp(cptr->string, str, MAXHOST) == 0) {
252 if ((type == cptr->flag) || ((type != OBJ_GRP) && (cptr->flag != OBJ_GRP))) {
253 /* found... bump counters */
254 cptr->count += count;
255 cptr->files += file;
256 cptr->xfer += xfer;
257 cptr->pages += page;
258 if (type == OBJ_GRP) {
259 /* Updating a group */
260 cptr->visit += visit;
261 } else if (isapage) {
262 if ((tstamp - cptr->tstamp) >= g_settings.settings.visit_timeout) {
263 /* Is a new Visit */
264 cptr->visit++;
265 /* ONLY! Update entry/exit if working with Monthly table */
266 if (htab == sm_htab) {
267 update_exit(cptr->lasturl, cptr->lasturl_is_entry);
268 update_entry(url);
269 cptr->lasturl_is_entry = true;
270 cptr->lasturl = find_url(url);
271 }
272 } else { /* Still in same visit */
273 if (htab == sm_htab) {
274 cptr->lasturl_is_entry = false;
275 cptr->lasturl = find_url(url);
276 }
277 }
278 /* Either way, update the last timestamp for this visit - we have a page! */
279 cptr->tstamp = tstamp;
280 }
281 return 0;
282 }
283 }
284 prev_cptr = cptr;
285 cptr = cptr->next;
286 }
287 /* Failed to Hash, or doesn't already exist */
288 if ((nptr = new_node(str, NODE_H, len)) != NULL) {
289 nptr->flag = type;
290 nptr->count = count;
291 nptr->files = file;
292 nptr->xfer = xfer;
293 nptr->pages = page;
294 nptr->next = NULL;
295 nptr->lasturl = blank_str;
296 nptr->lasturl_is_entry = lasturl_is_entry;
297 if (prev_cptr != NULL) {
298 prev_cptr->next = nptr;
299 } else {
300 htab[hash(str)] = nptr;
301 }
302 if (type != OBJ_GRP) {
303 (*ctr)++;
304 if (!*isnewsite) {
305 *isnewsite = true;
306 }
307 }
308 if (visit) {
309 nptr->visit = visit;
310 if (type != OBJ_GRP) {
311 nptr->lasturl = find_url(lasturl);
312 nptr->tstamp = tstamp;
313 }
314 return 0;
315 } else {
316 if (isapage) {
317 /* ONLY! Update entry/exit if working with Monthly table */
318 if (htab == sm_htab) {
319 update_entry(url);
320 nptr->lasturl = find_url(url);
321 nptr->lasturl_is_entry = true;
322 }
323 nptr->tstamp = tstamp;
324 nptr->visit = 1;
325 }
326 }
327 }
328 return nptr == NULL;
329 }
330
331
332 /*********************************************/
333 /* PUT_UNODE - insert/update URL node */
334 /*********************************************/
335 int
put_unode(char * str,int type,unsigned long count,unsigned long long xfer,unsigned long * ctr,unsigned long entry_page_ctr,unsigned long exit_page_ctr,unsigned long single_access,int resp_code,UNODEPTR * htab)336 put_unode(char *str, /* Hostname */
337 int type, /* obj type */
338 unsigned long count, /* hit count */
339 unsigned long long xfer, /* xfer size */
340 unsigned long *ctr, /* counter */
341 unsigned long entry_page_ctr, /* Entry Page Counter */
342 unsigned long exit_page_ctr, /* Exit Page Counter */
343 unsigned long single_access, /* Single Access Counter */
344 int resp_code, UNODEPTR * htab)
345 {
346 UNODEPTR cptr, nptr = NULL, prev_cptr = NULL;
347 size_t len;
348
349 /* Ignore "Empty/Null" URL's */
350 if (str[0] == '-') {
351 return 0;
352 }
353
354 len = check_hashstr_size(str, NODE_U);
355 cptr = htab[hash(str)];
356 while (cptr != NULL) {
357 if (strcmp(cptr->string, str) == 0) {
358 if ((type == cptr->flag) || ((type != OBJ_GRP) && (cptr->flag != OBJ_GRP))) {
359 /* found... bump counters */
360 if (resp_code == RC_PARTIALCONTENT) {
361 cptr->pcount += count;
362 cptr->pxfer += xfer;
363 g_counters.month.partial_hit += count;
364 g_counters.month.partial_vol += xfer;
365 } else {
366 cptr->count += count;
367 cptr->xfer += xfer;
368 }
369 return 0;
370 }
371 }
372 prev_cptr = cptr;
373 cptr = cptr->next;
374 }
375 /* Failed to Hash, or doesn't already exist */
376 if ((nptr = new_node(str, NODE_U, len)) != NULL) {
377 nptr->flag = type;
378 if (resp_code == RC_PARTIALCONTENT) {
379 nptr->count = 0;
380 nptr->xfer = 0;
381 nptr->pcount = count;
382 nptr->pxfer = xfer;
383 g_counters.month.partial_hit += count;
384 g_counters.month.partial_vol += xfer;
385 } else {
386 nptr->count = count;
387 nptr->xfer = xfer;
388 nptr->pcount = 0;
389 nptr->pxfer = 0;
390 }
391 nptr->next = NULL;
392 nptr->entry = entry_page_ctr;
393 nptr->exit = exit_page_ctr;
394 nptr->single_access = single_access;
395 if (prev_cptr != NULL) {
396 prev_cptr->next = nptr;
397 } else {
398 htab[hash(str)] = nptr;
399 }
400 if (type != OBJ_GRP) {
401 (*ctr)++;
402 }
403 }
404 return nptr == NULL;
405 }
406
407
408 /*********************************************/
409 /* PUT_RNODE - insert/update referrer node */
410 /*********************************************/
411 int
put_rnode(char * str,int type,unsigned long count,unsigned long * ctr,RNODEPTR * htab)412 put_rnode(char *str, int type, unsigned long count, unsigned long *ctr, RNODEPTR * htab)
413 {
414 RNODEPTR cptr, nptr = NULL, prev_cptr = NULL;
415 size_t len;
416
417 /* Ignore "Empty/Null" URL's */
418 if (str[0] == '-' && str[1] == '\0') {
419 strcpy(str, "- (Direct Request)");
420 }
421
422 len = check_hashstr_size(str, NODE_R);
423 cptr = htab[hash(str)];
424 while (cptr != NULL) {
425 if (strcmp(cptr->string, str) == 0) {
426 if ((type == cptr->flag) || ((type != OBJ_GRP) && (cptr->flag != OBJ_GRP))) {
427 /* found... bump counter */
428 cptr->count += count;
429 return 0;
430 }
431 }
432 prev_cptr = cptr;
433 cptr = cptr->next;
434 }
435 if ((nptr = new_node(str, NODE_R, len)) != NULL) {
436 nptr->flag = type;
437 nptr->count = count;
438 nptr->next = NULL;
439 if (prev_cptr != NULL) {
440 prev_cptr->next = nptr;
441 } else {
442 htab[hash(str)] = nptr;
443 }
444 if (type != OBJ_GRP) {
445 (*ctr)++;
446 }
447 }
448 return nptr == NULL;
449 }
450
451
452 /*********************************************/
453 /* PUT_ANODE - insert/update user agent node */
454 /*********************************************/
455 int
put_anode(char * str,int type,unsigned long count,unsigned long * ctr,ANODEPTR * htab)456 put_anode(char *str, int type, unsigned long count, unsigned long *ctr, ANODEPTR * htab)
457 {
458 ANODEPTR cptr, nptr = NULL, prev_cptr = NULL;
459 size_t len;
460
461 /* skip bad user agents */
462 if (str[0] == '-') {
463 return 0;
464 }
465
466 len = check_hashstr_size(str, NODE_A);
467 cptr = htab[hash(str)];
468 while (cptr != NULL) {
469 if (strcmp(cptr->string, str) == 0) {
470 if ((type == cptr->flag) || ((type != OBJ_GRP) && (cptr->flag != OBJ_GRP))) {
471 /* found... bump counter */
472 cptr->count += count;
473 return 0;
474 }
475 }
476 prev_cptr = cptr;
477 cptr = cptr->next;
478 }
479 if ((nptr = new_node(str, NODE_A, len)) != NULL) {
480 nptr->flag = type;
481 nptr->count = count;
482 nptr->next = NULL;
483 if (prev_cptr != NULL) {
484 prev_cptr->next = nptr;
485 } else {
486 htab[hash(str)] = nptr;
487 }
488 if (type != OBJ_GRP) {
489 (*ctr)++;
490 }
491 }
492 return nptr == NULL;
493 }
494
495
496 /*********************************************/
497 /* PUT_SNODE - insert/update search str node */
498 /*********************************************/
499 int
put_snode(char * str,unsigned long count,SNODEPTR * htab)500 put_snode(char *str, unsigned long count, SNODEPTR * htab)
501 {
502 SNODEPTR cptr, nptr = NULL, prev_cptr = NULL;
503 size_t len;
504
505 /* skip bad search strs */
506 if (str[0] == '\0' || str[0] == ' ') {
507 return 0;
508 }
509
510 len = check_hashstr_size(str, NODE_S);
511 cptr = htab[hash(str)];
512 while (cptr != NULL) {
513 if (strcmp(cptr->string, str) == 0) {
514 /* found... bump counter */
515 cptr->count += count;
516 return 0;
517 }
518 prev_cptr = cptr;
519 cptr = cptr->next;
520 }
521 if ((nptr = new_node(str, NODE_S, len)) != NULL) {
522 nptr->count = count;
523 nptr->next = NULL;
524 if (prev_cptr != NULL) {
525 prev_cptr->next = nptr;
526 } else {
527 htab[hash(str)] = nptr;
528 }
529 }
530 return nptr == NULL;
531 }
532
533
534 /*********************************************/
535 /* PUT_INODE - insert/update ident node */
536 /*********************************************/
537 int
put_inode(char * str,int type,unsigned long count,unsigned long file,unsigned long long xfer,unsigned long * ctr,unsigned long visit,unsigned long tstamp,INODEPTR * htab,bool isapage)538 put_inode(char *str, /* ident str */
539 int type, /* obj type */
540 unsigned long count, /* hit count */
541 unsigned long file, /* File flag */
542 unsigned long long xfer, /* xfer size */
543 unsigned long *ctr, /* counter */
544 unsigned long visit, /* visits */
545 unsigned long tstamp, /* timestamp */
546 INODEPTR * htab, bool isapage)
547 { /* hashtable */
548 INODEPTR cptr, nptr = NULL, prev_cptr = NULL;
549 size_t len;
550
551 /* skip if no username */
552 if ((str[0] == '-') || (str[0] == '\0')) {
553 return 0;
554 }
555
556 len = check_hashstr_size(str, NODE_I);
557 cptr = htab[hash(str)];
558 while (cptr != NULL) {
559 if (strcmp(cptr->string, str) == 0) {
560 if ((type == cptr->flag) || ((type != OBJ_GRP) && (cptr->flag != OBJ_GRP))) {
561 /* found... bump counter */
562 cptr->count += count;
563 cptr->files += file;
564 cptr->xfer += xfer;
565 if (type == OBJ_GRP) {
566 /* Updating a group */
567 cptr->visit += visit;
568 } else if (isapage) {
569 if ((tstamp - cptr->tstamp) >= g_settings.settings.visit_timeout) {
570 /* Is a new Visit */
571 cptr->visit++;
572 }
573 /* Either way, update the last timestamp for this visit - we have a page! */
574 cptr->tstamp = tstamp;
575 }
576 return 0;
577 }
578 }
579 prev_cptr = cptr;
580 cptr = cptr->next;
581 }
582 if ((nptr = new_node(str, NODE_I, len)) != NULL) {
583 nptr->flag = type;
584 nptr->count = count;
585 nptr->files = file;
586 nptr->xfer = xfer;
587 nptr->next = NULL;
588 if (prev_cptr != NULL) {
589 prev_cptr->next = nptr;
590 } else {
591 htab[hash(str)] = nptr;
592 }
593 if (type != OBJ_GRP) {
594 (*ctr)++;
595 }
596 if (visit) {
597 nptr->visit = visit;
598 if (type != OBJ_GRP) {
599 /* Don't update timestamp for groups */
600 nptr->tstamp = tstamp;
601 }
602 return 0;
603 } else {
604 if (isapage) {
605 nptr->tstamp = tstamp;
606 nptr->visit = 1;
607 }
608 }
609 }
610 return nptr == NULL;
611 }
612
613
614 /*********************************************/
615 /* NEW_ENODE - create errorpage node */
616 /*********************************************/
617
618 ENODEPTR
new_enode(char * url,char * refer)619 new_enode(char *url, /* url str */
620 char *refer)
621 { /* my referer */
622 ENODEPTR newptr;
623 char *url_ptr, *ref_ptr, *key_ptr;
624 size_t len_url = strlen(url);
625 size_t len_ref = strlen(refer);
626
627 if (len_url >= MAXURL) {
628 ERRVPRINT(VERBOSE1, "[new_enode] %s (%d)\n", _("Warning: String exceeds storage size"), (int) len_url);
629 ERRVPRINT(VERBOSE3, " --> %s\n", url);
630 url[MAXURL - 1] = 0;
631 len_url = MAXURL - 1;
632 }
633
634 url_ptr = XMALLOC(char, len_url + 1);
635
636 memcpy(url_ptr, url, len_url);
637
638 if (len_ref >= MAXURL) {
639 ERRVPRINT(VERBOSE1, "[new_enode:referer] %s (%d)\n", _("Warning: String exceeds storage size"), (int) len_ref);
640 ERRVPRINT(VERBOSE3, " --> %s\n", refer);
641 refer[MAXURL - 1] = 0;
642 len_ref = MAXURL - 1;
643 }
644
645 ref_ptr = XMALLOC(char, len_ref + 1);
646
647 memcpy(ref_ptr, refer, len_ref);
648
649 /* Hash key can be sized MAXURL x 2 */
650 key_ptr = XMALLOC(char, len_url + len_ref + 1);
651
652 memcpy(key_ptr, url, len_url);
653 strncat(key_ptr, refer, len_ref);
654
655 newptr = XMALLOC(struct enode, 1);
656
657 newptr->error_request = key_ptr;
658 newptr->url = url_ptr;
659 newptr->referer = ref_ptr;
660 newptr->count = 1;
661 newptr->next = NULL;
662 return newptr;
663 }
664
665 /*********************************************/
666 /* PUT_ENODE - insert/update error node */
667 /*********************************************/
668 int
put_enode(char * url,char * refer,int type,unsigned long count,unsigned long * ctr,ENODEPTR * htab)669 put_enode(char *url, /* url str */
670 char *refer, /* my referer */
671 int type, /* obj type */
672 unsigned long count, /* hit count */
673 unsigned long *ctr, /* counter */
674 ENODEPTR * htab)
675 { /* hashtable */
676 ENODEPTR cptr, nptr;
677 char *key_ptr;
678 size_t len_url = strlen(url);
679 size_t len_ref = strlen(refer);
680 unsigned long hash_val;
681
682 key_ptr = XMALLOC(char, len_url + len_ref + 1);
683
684 memcpy(key_ptr, url, len_url);
685 strncat(key_ptr, refer, len_ref);
686
687 hash_val = hash(key_ptr);
688 /* check if hashed */
689 if ((cptr = htab[hash_val]) == NULL) {
690 /* not hashed */
691 if ((nptr = new_enode(url, refer)) != NULL) {
692 nptr->next = NULL;
693 htab[hash_val] = nptr;
694 (*ctr)++;
695 nptr->count = count;
696 XFREE(key_ptr);
697 return 0;
698 }
699 } else {
700 /* hashed */
701 while (cptr != NULL) {
702 if (strcmp(cptr->error_request, key_ptr) == 0) {
703 /* found... bump counter */
704 cptr->count += count;
705 XFREE(key_ptr);
706 return 0;
707 }
708 cptr = cptr->next;
709 }
710 /* not found... */
711 if ((nptr = new_enode(url, refer)) != NULL) {
712 nptr->next = htab[hash_val];
713 htab[hash_val] = nptr;
714 (*ctr)++;
715 }
716 }
717
718 XFREE(key_ptr);
719 return nptr == NULL;
720 }
721
722
723 /*********************************************/
724 /* PUT_SEGNODE - insert/update segmenting ID node */
725 /*********************************************/
726 unsigned long
put_segnode(char * str,unsigned long new_tstamp,SEGNODEPTR * htab)727 put_segnode(char *str, unsigned long new_tstamp, SEGNODEPTR * htab)
728 {
729 SEGNODEPTR cptr, nptr = NULL, prev_cptr = NULL;
730 unsigned long old_tstamp = 0;
731 size_t len;
732
733 len = check_hashstr_size(str, NODE_SEG);
734 cptr = htab[hash(str)];
735 while (cptr != NULL) {
736 if (strcmp(cptr->string, str) == 0) {
737 /* found */
738 old_tstamp = cptr->tstamp;
739 cptr->tstamp = new_tstamp;
740 return (old_tstamp);
741 }
742 prev_cptr = cptr;
743 cptr = cptr->next;
744 }
745 if ((nptr = new_node(str, NODE_SEG, len)) != NULL) {
746 nptr->next = NULL;
747 old_tstamp = new_tstamp;
748 nptr->tstamp = new_tstamp;
749 if (prev_cptr != NULL) {
750 prev_cptr->next = nptr;
751 } else {
752 htab[hash(str)] = nptr;
753 }
754 // ERRVPRINT(0, "Leaving\n");
755 }
756 return (old_tstamp);
757 }
758
759
760 /* Return the timestamp when found */
761 unsigned long
get_segnode(char * str,SEGNODEPTR * htab)762 get_segnode(char *str, SEGNODEPTR * htab)
763 {
764 SEGNODEPTR cptr;
765
766 check_hashstr_size(str, NODE_SEG);
767 cptr = htab[hash(str)];
768 while (cptr != NULL) {
769 if (strcmp(cptr->string, str) == 0) {
770 /* found */
771 return (cptr->tstamp);
772 }
773 cptr = cptr->next;
774 }
775 return (0);
776 }
777
778
779 /* Return 1 on success */
780 int
remove_segnode(char * str,SEGNODEPTR * htab)781 remove_segnode(char *str, SEGNODEPTR * htab)
782 {
783 SEGNODEPTR cptr, prev_cptr = NULL, next_cptr = NULL;
784
785 check_hashstr_size(str, NODE_SEG);
786 cptr = htab[hash(str)];
787 while (cptr != NULL) {
788 if (strcmp(cptr->string, str) == 0) {
789 /* found */
790 next_cptr = cptr->next;
791 free(cptr);
792 if (prev_cptr == NULL) {
793 htab[hash(str)] = NULL;
794 } else {
795 prev_cptr->next = next_cptr;
796 }
797 return (1);
798 }
799 prev_cptr = cptr;
800 cptr = cptr->next;
801 }
802 return (0);
803 }
804
805
806 /* Remove all old visits from a given segmenting hash table. */
807 void
segment_htab_cleanup(SEGNODEPTR * htab)808 segment_htab_cleanup(SEGNODEPTR * htab)
809 {
810 SEGNODEPTR cptr, prev_cptr, next_cptr;
811 unsigned int i;
812
813 for (i = 0; i < MAXHASH; i++) {
814 cptr = htab[i];
815 prev_cptr = NULL;
816 next_cptr = NULL;
817 while (cptr != NULL) {
818 if ((cur_tstamp - cptr->tstamp) >= g_settings.settings.visit_timeout) {
819 /* Is now an "old" Visit? Throw away. */
820 next_cptr = cptr->next;
821 free(cptr);
822 if (prev_cptr == NULL) {
823 htab[i] = NULL;
824 } else {
825 prev_cptr->next = next_cptr;
826 }
827 break;
828 }
829 prev_cptr = cptr;
830 cptr = cptr->next;
831 }
832 }
833 }
834
835
836 /*********************************************/
837 /* HASH - return hash value for string */
838 /*********************************************/
839 unsigned long
hash(char * str)840 hash(char *str)
841 {
842 unsigned long hashval = MAXHASH;
843
844 while (*str != '\0') {
845 hashval = (hashval << 5) + hashval + *str;
846 str++;
847 }
848 return hashval % MAXHASH;
849 }
850
851
852 /*********************************************/
853 /* FIND_URL - Find URL in hash table */
854 /*********************************************/
855 char *
find_url(char * str)856 find_url(char *str)
857 {
858 UNODEPTR cptr;
859
860 if ((cptr = um_htab[hash(str)]) != NULL) {
861 while (cptr != NULL) {
862 if (strcmp(cptr->string, str) == 0)
863 return cptr->string;
864 cptr = cptr->next;
865 }
866 }
867 return blank_str; /* shouldn't get here */
868 }
869
870
871 /*********************************************/
872 /* UPDATE_ENTRY - update entry page total */
873 /*********************************************/
874 void
update_entry(char * str)875 update_entry(char *str)
876 {
877 UNODEPTR uptr;
878
879 if (str == NULL)
880 return;
881 if ((uptr = um_htab[hash(str)]) == NULL)
882 return;
883 else {
884 while (uptr != NULL) {
885 if (strcmp(uptr->string, str) == 0) {
886 if (uptr->flag != OBJ_GRP) {
887 uptr->entry++;
888 return;
889 }
890 }
891 uptr = uptr->next;
892 }
893 }
894 }
895
896
897 /*********************************************/
898 /* UPDATE_EXIT - update exit page total */
899 /*********************************************/
900 void
update_exit(char * str,bool is_single_access)901 update_exit(char *str, bool is_single_access)
902 {
903 UNODEPTR uptr;
904
905 if (str == NULL)
906 return;
907 if ((uptr = um_htab[hash(str)]) == NULL)
908 return;
909 else {
910 while (uptr != NULL) {
911 if (strcmp(uptr->string, str) == 0) {
912 if (uptr->flag != OBJ_GRP) {
913 uptr->exit++;
914 if (is_single_access) {
915 uptr->single_access++;
916 }
917 return;
918 }
919 }
920 uptr = uptr->next;
921 }
922 }
923 }
924
925
926 /*********************************************/
927 /* MONTH_UPDATE_EXIT - eom exit page update */
928 /*********************************************/
929 void
month_update_exit(unsigned long tstamp)930 month_update_exit(unsigned long tstamp)
931 {
932 HNODEPTR nptr;
933 int i;
934
935 for (i = 0; i < MAXHASH; i++) {
936 nptr = sm_htab[i];
937 while (nptr != NULL) {
938 if (nptr->flag != OBJ_GRP) {
939 if ((tstamp - nptr->tstamp) >= g_settings.settings.visit_timeout) {
940 /* End of month, update all "still open" sessions; and count as closed sessions that would be expired */
941 update_exit(nptr->lasturl, nptr->lasturl_is_entry);
942 }
943 }
944 nptr = nptr->next;
945 }
946 }
947 }
948
949
950 /*********************************************/
951 /* TOT_VISIT - calculate total visits */
952 /*********************************************/
953 unsigned long
tot_visit(HNODEPTR * list)954 tot_visit(HNODEPTR * list)
955 {
956 HNODEPTR hptr;
957 unsigned long tot = 0;
958 int i;
959
960 for (i = 0; i < MAXHASH; i++) {
961 hptr = list[i];
962 while (hptr != NULL) {
963 if (hptr->flag != OBJ_GRP) {
964 tot += hptr->visit;
965 }
966 hptr = hptr->next;
967 }
968 }
969 return tot;
970 }
971
972
973 /* DEL_HLIST - delete host hash table */
974 void
del_hlist(HNODEPTR * htab)975 del_hlist(HNODEPTR * htab)
976 {
977 del_htab((NODEPTR *) htab, "hlist", MAXHASH, (void (*)(NODEPTR)) free);
978 }
979
980 /* DEL_ULIST - delete URL hash table */
981 void
del_ulist(UNODEPTR * htab)982 del_ulist(UNODEPTR * htab)
983 {
984 del_htab((NODEPTR *) htab, "ulist", MAXHASH, (void (*)(NODEPTR)) free);
985 }
986
987 /* DEL_RLIST - delete referrer hash table */
988 void
del_rlist(RNODEPTR * htab)989 del_rlist(RNODEPTR * htab)
990 {
991 del_htab((NODEPTR *) htab, "rlist", MAXHASH, (void (*)(NODEPTR)) free);
992 }
993
994 /* DEL_ALIST - delete user agent hash table */
995 void
del_alist(ANODEPTR * htab)996 del_alist(ANODEPTR * htab)
997 {
998 del_htab((NODEPTR *) htab, "alist", MAXHASH, (void (*)(NODEPTR)) free);
999 }
1000
1001 /* DEL_SLIST - delete search str hash table */
1002 void
del_slist(SNODEPTR * htab)1003 del_slist(SNODEPTR * htab)
1004 {
1005 del_htab((NODEPTR *) htab, "slist", MAXHASH, (void (*)(NODEPTR)) free);
1006 }
1007
1008 /* DEL_ILIST - delete ident hash table */
1009 void
del_ilist(INODEPTR * htab)1010 del_ilist(INODEPTR * htab)
1011 {
1012 del_htab((NODEPTR *) htab, "ilist", MAXHASH, (void (*)(NODEPTR)) free);
1013 }
1014
1015 /* DEL_ELIST - delete errorpage hash table */
1016 void
free_ENODEPTR(ENODEPTR ptr)1017 free_ENODEPTR(ENODEPTR ptr)
1018 {
1019 XFREE(ptr->error_request);
1020 XFREE(ptr->referer);
1021 XFREE(ptr->url);
1022 XFREE(ptr);
1023 }
1024
1025 void
del_elist(ENODEPTR * htab)1026 del_elist(ENODEPTR * htab)
1027 {
1028 del_htab((NODEPTR *) htab, "elist", MAXHASH, (void (*)(NODEPTR)) free_ENODEPTR);
1029 }
1030
1031
1032 /*********************************************
1033 * del_htab - Generic delete all hash table entries
1034 *********************************************/
1035 void
del_htab(NODEPTR * htab,const char * htab_name,size_t size,void (* free_node)(NODEPTR))1036 del_htab(NODEPTR * htab, const char *htab_name, size_t size, void (*free_node) (NODEPTR))
1037 {
1038 unsigned long long count = 0;
1039 unsigned long long maxdeep = 1;
1040 unsigned long long deep = 0;
1041 size_t i;
1042
1043 for (i = 0; i != size; ++i) {
1044 if (htab[i]) {
1045 NODEPTR node = htab[i];
1046
1047 deep = 1;
1048 while (node) {
1049 NODEPTR next = node->next;
1050
1051 free_node(node);
1052 node = next;
1053 count++;
1054 deep++;
1055 }
1056 if (deep > maxdeep) {
1057 maxdeep = deep;
1058 }
1059 htab[i] = NULL;
1060 }
1061 }
1062 if (count == 0) {
1063 maxdeep = 0;
1064 }
1065 VPRINT(VERBOSE2, "htab#%s freed %7llu nodes; Max Depth: %llu\n", htab_name, count, maxdeep);
1066 }
1067
1068 /************************************************************************
1069 ************************************************************************
1070 * END OF FILE *
1071 ************************************************************************/
1072