Imported Upstream version 2.7
[ossec-hids.git] / src / os_regex / os_match_compile.c
1 /*   $OSSEC, os_match_compile.c, v0.1, 2006/04/17, Daniel B. Cid$   */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  */
11
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <ctype.h>
17
18 #include "os_regex.h"
19 #include "os_regex_internal.h"
20
21 /* Prototype fo the _OsMatch */
22 int _OS_Match(char *pattern, char *str, int str_len, int size);
23 int _os_strncmp(char *pattern, char *str, int str_len, int size);
24 int _os_strcmp_last(char *pattern, char *str, int str_len, int size);
25 int _os_strcmp(char *pattern, char *str, int str_len, int size);
26 int _os_strmatch(char *pattern, char *str, int str_len, int size);
27 int _os_strstr(char *pattern, char *str, int str_len, int size);
28
29
30 /** int OSMatch_Compile(char *pattern, OSMatch *reg, int flags) v0.1
31  * Compile a pattern to be used later.
32  * Allowed flags are:
33  *      - OS_CASE_SENSITIVE
34  * Returns 1 on success or 0 on error.
35  * The error code is set on reg->error.
36  */
37 int OSMatch_Compile(char *pattern, OSMatch *reg, int flags)
38 {
39     int usstrstr = 0;
40     int i = 0;
41     int count = 0;
42     int end_of_string = 0;
43
44     char *pt;
45     char *new_str;
46     char *new_str_free = NULL;
47
48
49     /* Checking for references not initialized */
50     if(reg == NULL)
51     {
52         return(0);
53     }
54
55
56     /* Initializing OSRegex structure */
57     reg->error = 0;
58     reg->patterns = NULL;
59     reg->size = NULL;
60
61
62     /* The pattern can't be null */
63     if(pattern == NULL)
64     {
65         reg->error = OS_REGEX_PATTERN_NULL;
66         goto compile_error;
67     }
68
69
70     /* Maximum size of the pattern */
71     if(strlen(pattern) > OS_PATTERN_MAXSIZE)
72     {
73         reg->error = OS_REGEX_MAXSIZE;
74         goto compile_error;
75     }
76
77
78     /* Duping the pattern for our internal work */
79     new_str = strdup(pattern);
80     if(!new_str)
81     {
82         reg->error = OS_REGEX_OUTOFMEMORY;
83         goto compile_error;
84     }
85     new_str_free = new_str;
86     pt = new_str;
87
88
89
90     /* Getting the number of sub patterns */
91     while(*pt != '\0')
92     {
93         /* The pattern must be always lower case if
94          * case sensitive is set
95          */
96         if(!(flags & OS_CASE_SENSITIVE))
97         {
98             *pt = charmap[(uchar)*pt];
99         }
100
101         /* Number of sub patterns */
102         if(*pt == OR)
103         {
104             count++;
105         }
106         else if(*pt == -29)
107         {
108             usstrstr = 1;
109         }
110         pt++;
111     }
112
113
114     /* For the last pattern */
115     count++;
116     reg->patterns = calloc(count +1, sizeof(char *));
117     reg->size = calloc(count +1, sizeof(int));
118     reg->match_fp = calloc(count +1, sizeof(void *));
119
120
121     /* Memory allocation error check */
122     if(!reg->patterns || !reg->size || !reg->match_fp)
123     {
124         reg->error = OS_REGEX_OUTOFMEMORY;
125         goto compile_error;
126     }
127
128
129     /* Initializing each sub pattern */
130     for(i = 0; i<=count; i++)
131     {
132         reg->patterns[i] = NULL;
133         reg->match_fp[i] = NULL;
134         reg->size[i] = 0;
135     }
136     i = 0;
137
138
139     /* Reassigning pt to the beginning of the string */
140     pt = new_str;
141
142
143     /* Getting the sub patterns */
144     do
145     {
146         if((*pt == OR) || (*pt == '\0'))
147         {
148             if(*pt == '\0')
149             {
150                 end_of_string = 1;
151             }
152
153             *pt = '\0';
154
155             /* Dupping the string */
156             if(*new_str == BEGINREGEX)
157                 reg->patterns[i] = strdup(new_str +1);
158             else
159                 reg->patterns[i] = strdup(new_str);
160
161             /* Memory error */
162             if(!reg->patterns[i])
163             {
164                 reg->error = OS_REGEX_OUTOFMEMORY;
165                 goto compile_error;
166             }
167
168
169             /* If the string has ^ and $ */
170             if((*new_str == BEGINREGEX) && (*(pt -1) == ENDREGEX))
171             {
172                 reg->match_fp[i] = _os_strcmp;
173                 reg->size[i] = strlen(reg->patterns[i]) -1;
174                 reg->patterns[i][reg->size[i]] = '\0';
175             }
176             else if(strlen(new_str) == 0)
177             {
178                 reg->match_fp[i] = _os_strmatch;
179                 reg->size[i] = 0;
180             }
181
182             /* String only has $ */
183             else if(*(pt -1) == ENDREGEX)
184             {
185                 reg->match_fp[i] = _os_strcmp_last;
186                 reg->size[i] = strlen(reg->patterns[i]) -1;
187                 reg->patterns[i][reg->size[i]] = '\0';
188             }
189
190             /* If string starts with ^, use strncmp */
191             else if(*new_str == BEGINREGEX)
192             {
193                 reg->match_fp[i] = _os_strncmp;
194                 reg->size[i] = strlen(reg->patterns[i]);
195             }
196
197             else if(usstrstr == 1)
198             {
199                 reg->match_fp[i] = _os_strstr;
200                 reg->size[i] = strlen(reg->patterns[i]);
201             }
202
203             else
204             {
205                 reg->match_fp[i] = _OS_Match;
206                 reg->size[i] = strlen(reg->patterns[i]);
207             }
208
209             if(end_of_string)
210             {
211                 break;
212             }
213
214             new_str = ++pt;
215             i++;
216             continue;
217         }
218         pt++;
219
220     }while(!end_of_string);
221
222
223     /* Success return */
224     free(new_str_free);
225     return(1);
226
227
228     /* Error handling */
229     compile_error:
230
231     if(new_str_free)
232     {
233         free(new_str_free);
234     }
235
236     OSMatch_FreePattern(reg);
237
238     return(0);
239 }
240
241
242 /* EOF */