bf1c951f76b2e85f6e3bb56aed4752f10f2a5073
[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 /** int OSMatch_Compile(char *pattern, OSMatch *reg, int flags) v0.1
22  * Compile a pattern to be used later.
23  * Allowed flags are:
24  *      - OS_CASE_SENSITIVE
25  * Returns 1 on success or 0 on error.
26  * The error code is set on reg->error.
27  */
28 int OSMatch_Compile(const char *pattern, OSMatch *reg, int flags)
29 {
30     int usstrstr = 0;
31     size_t i = 0;
32     size_t count = 0;
33     int end_of_string = 0;
34
35     char *pt;
36     char *new_str;
37     char *new_str_free = NULL;
38
39
40     /* Checking for references not initialized */
41     if(reg == NULL)
42     {
43         return(0);
44     }
45
46
47     /* Initializing OSRegex structure */
48     reg->error = 0;
49     reg->patterns = NULL;
50     reg->size = NULL;
51     reg->match_fp = NULL;
52
53
54     /* The pattern can't be null */
55     if(pattern == NULL)
56     {
57         reg->error = OS_REGEX_PATTERN_NULL;
58         goto compile_error;
59     }
60
61
62     /* Maximum size of the pattern */
63     if(strlen(pattern) > OS_PATTERN_MAXSIZE)
64     {
65         reg->error = OS_REGEX_MAXSIZE;
66         goto compile_error;
67     }
68
69
70     /* Duping the pattern for our internal work */
71     new_str = strdup(pattern);
72     if(!new_str)
73     {
74         reg->error = OS_REGEX_OUTOFMEMORY;
75         goto compile_error;
76     }
77     new_str_free = new_str;
78     pt = new_str;
79
80
81
82     /* Getting the number of sub patterns */
83     while(*pt != '\0')
84     {
85         /* The pattern must be always lower case if
86          * case sensitive is set
87          */
88         if(!(flags & OS_CASE_SENSITIVE))
89         {
90             *pt = (char) charmap[(uchar)*pt];
91         }
92
93         /* Number of sub patterns */
94         if(*pt == OR)
95         {
96             count++;
97         }
98         else if(*pt == -29)
99         {
100             usstrstr = 1;
101         }
102         pt++;
103     }
104
105
106     /* For the last pattern */
107     count++;
108     reg->patterns = (char **) calloc(count +1, sizeof(char *));
109     reg->size = (size_t *) calloc(count +1, sizeof(size_t));
110     reg->match_fp = (int (**)(const char *, const char *, size_t, size_t)) calloc(count +1, sizeof(void *));
111
112
113     /* Memory allocation error check */
114     if(!reg->patterns || !reg->size || !reg->match_fp)
115     {
116         reg->error = OS_REGEX_OUTOFMEMORY;
117         goto compile_error;
118     }
119
120
121     /* Initializing each sub pattern */
122     for(i = 0; i<=count; i++)
123     {
124         reg->patterns[i] = NULL;
125         reg->match_fp[i] = NULL;
126         reg->size[i] = 0;
127     }
128     i = 0;
129
130
131     /* Reassigning pt to the beginning of the string */
132     pt = new_str;
133
134
135     /* Getting the sub patterns */
136     do
137     {
138         if((*pt == OR) || (*pt == '\0'))
139         {
140             if(*pt == '\0')
141             {
142                 end_of_string = 1;
143             }
144
145             *pt = '\0';
146
147             /* Dupping the string */
148             if(*new_str == BEGINREGEX)
149                 reg->patterns[i] = strdup(new_str +1);
150             else
151                 reg->patterns[i] = strdup(new_str);
152
153             /* Memory error */
154             if(!reg->patterns[i])
155             {
156                 reg->error = OS_REGEX_OUTOFMEMORY;
157                 goto compile_error;
158             }
159
160
161             /* If the string has ^ and $ */
162             if((*new_str == BEGINREGEX) && (*(pt -1) == ENDREGEX))
163             {
164                 reg->match_fp[i] = _os_strcmp;
165                 reg->size[i] = strlen(reg->patterns[i]) -1;
166                 reg->patterns[i][reg->size[i]] = '\0';
167             }
168             else if(strlen(new_str) == 0)
169             {
170                 reg->match_fp[i] = _os_strmatch;
171                 reg->size[i] = 0;
172             }
173
174             /* String only has $ */
175             else if(*(pt -1) == ENDREGEX)
176             {
177                 reg->match_fp[i] = _os_strcmp_last;
178                 reg->size[i] = strlen(reg->patterns[i]) -1;
179                 reg->patterns[i][reg->size[i]] = '\0';
180             }
181
182             /* If string starts with ^, use strncmp */
183             else if(*new_str == BEGINREGEX)
184             {
185                 reg->match_fp[i] = _os_strncmp;
186                 reg->size[i] = strlen(reg->patterns[i]);
187             }
188
189             else if(usstrstr == 1)
190             {
191                 reg->match_fp[i] = _os_strstr;
192                 reg->size[i] = strlen(reg->patterns[i]);
193             }
194
195             else
196             {
197                 reg->match_fp[i] = _OS_Match;
198                 reg->size[i] = strlen(reg->patterns[i]);
199             }
200
201             if(end_of_string)
202             {
203                 break;
204             }
205
206             new_str = ++pt;
207             i++;
208             continue;
209         }
210         pt++;
211
212     }while(!end_of_string);
213
214
215     /* Success return */
216     free(new_str_free);
217     return(1);
218
219
220     /* Error handling */
221     compile_error:
222
223     if(new_str_free)
224     {
225         free(new_str_free);
226     }
227
228     OSMatch_FreePattern(reg);
229
230     return(0);
231 }
232
233
234 /* EOF */