1 /* $Id: nodetree.c,v 1.11 2011/08/28 12:25:20 sbajic Exp $ */
2 
3 /*
4  DSPAM
5  COPYRIGHT (C) 2002-2012 DSPAM PROJECT
6 
7  This program is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Affero General Public License as
9  published by the Free Software Foundation, either version 3 of the
10  License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU Affero General Public License for more details.
16 
17  You should have received a copy of the GNU Affero General Public License
18  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #ifndef _WIN32
25 #include <pwd.h>
26 #endif
27 
28 #include "nodetree.h"
29 #include "util.h"
30 #include "error.h"
31 #include "libdspam_objects.h"
32 #include "language.h"
33 
34 /* nt_node_create (used internally) to allocate space for a new node */
nt_node_create(void * data)35 struct nt_node * nt_node_create (void *data) {
36   struct nt_node *node;
37   if ((node = (struct nt_node *) malloc (sizeof (struct nt_node))) == 0)
38   {
39     LOG (LOG_CRIT, ERR_MEM_ALLOC);
40     exit (1);
41   }
42   node->ptr = data;
43   node->next = (struct nt_node *) NULL;
44   return (node);
45 }
46 
47 /* nt_create allocates space for and initializes a nodetree */
48 struct nt *
nt_create(int nodetype)49 nt_create (int nodetype)
50 {
51   struct nt *nt = (struct nt *) malloc (sizeof (struct nt));
52   if (nt == NULL)
53   {
54     LOG (LOG_CRIT, ERR_MEM_ALLOC);
55     return NULL;
56   }
57   nt->first = (struct nt_node *) NULL;
58   nt->insert = (struct nt_node *) NULL;
59   nt->items = 0;
60   nt->nodetype = nodetype;
61   return (nt);
62 }
63 
64 /* nt_destroy methodically destroys a nodetree, freeing resources */
65 void
nt_destroy(struct nt * nt)66 nt_destroy (struct nt *nt)
67 {
68   struct nt_node *cur, *next;
69   int i;
70   if (!nt)
71     return;
72 
73   cur = nt->first;
74   for (i = 0; i < nt->items; i++)
75   {
76     next = cur->next;
77     if (nt->nodetype != NT_INDEX)
78       free (cur->ptr);
79     free (cur);
80     cur = next;
81   }
82   free (nt);
83 }
84 
85 /* nt_add adds an item to the nodetree */
86 struct nt_node *
nt_add(struct nt * nt,void * data)87 nt_add (struct nt *nt, void *data)
88 {
89   struct nt_node *prev;
90   struct nt_c c;
91   struct nt_node *node = c_nt_first (nt, &c);
92   void *vptr;
93 
94   if (nt->insert) {
95     prev = nt->insert;
96   } else {
97     prev = 0;
98     while (node)
99     {
100       prev = node;
101       node = node->next;
102     }
103   }
104   nt->items++;
105 
106   if (nt->nodetype == NT_CHAR)
107   {
108     long size = strlen ((char *) data) + 1;
109     /* vptr is compared with  'From' and 'X-DSPAM-'even if data is shorter; but a larger buffer is allocated to prevent a comparison against garbage */
110     vptr = malloc (size < 16 ? 16 : size);
111     if (vptr == NULL)
112     {
113       LOG (LOG_CRIT, ERR_MEM_ALLOC);
114       return NULL;
115     }
116     strlcpy (vptr, data, size);
117   }
118   else
119   {
120     vptr = data;
121   }
122 
123   if (prev)
124   {
125     node = nt_node_create (vptr);
126     prev->next = node;
127     nt->insert = node;
128     return (node);
129   }
130   else
131   {
132     node = nt_node_create (vptr);
133     nt->first = node;
134     nt->insert = node;
135     return (node);
136   }
137 }
138 
139 /* c_nt_next returns the next item in a nodetree */
140 struct nt_node *
c_nt_next(struct nt * nt,struct nt_c * c)141 c_nt_next (struct nt *nt, struct nt_c *c)
142 {
143   struct nt_node *node = c->iter_index;
144   if (node)
145   {
146     c->iter_index = node->next;
147     return (node->next);
148   }
149   else
150   {
151     if (nt->items > 0)
152     {
153       c->iter_index = nt->first;
154       return nt->first;
155     }
156   }
157 
158   return ((struct nt_node *) NULL);
159 }
160 
161 /* nt_first returns the first item in a nodetree */
162 struct nt_node *
c_nt_first(struct nt * nt,struct nt_c * c)163 c_nt_first (struct nt *nt, struct nt_c *c)
164 {
165   c->iter_index = nt->first;
166   return (nt->first);
167 }
168