1 /* -*-pgsql-c-*- */
2 /*
3  * $Header$
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL
6  * written by Tatsuo Ishii
7  *
8  * Copyright (c) 2003-2016	PgPool Global Development Group
9  *
10  * Permission to use, copy, modify, and distribute this software and
11  * its documentation for any purpose and without fee is hereby
12  * granted, provided that the above copyright notice appear in all
13  * copies and that both that copyright notice and this permission
14  * notice appear in supporting documentation, and that the name of the
15  * author not be used in advertising or publicity pertaining to
16  * distribution of the software without specific, written prior
17  * permission. The author makes no representations about the
18  * suitability of this software for any purpose.  It is provided "as
19  * is" without express or implied warranty.
20  *
21  */
22 
23 /*
24  * This module handles regular expressio arrary.
25  */
26 #include <string.h>
27 
28 #include "pool.h"
29 #include "pool_config.h"
30 #include "utils/regex_array.h"
31 #ifndef POOL_PRIVATE
32 #include "utils/elog.h"
33 #include "utils/palloc.h"
34 #else
35 #include "utils/fe_ports.h"
36 #endif
37 
38 /*
39  * Create RegArray object
40  */
41 RegArray *
create_regex_array(void)42 create_regex_array(void)
43 {
44 	RegArray   *ar;
45 
46 	ar = palloc(sizeof(RegArray));
47 	ar->pos = 0;
48 	ar->size = AR_ALLOC_UNIT;
49 	ar->regex = (regex_t **) palloc(sizeof(regex_t *) * ar->size);
50 
51 	return ar;
52 }
53 
54 /*
55  * Add an regular expression pattern
56  */
57 int
add_regex_array(RegArray * ar,char * pattern)58 add_regex_array(RegArray * ar, char *pattern)
59 {
60 	int			regex_flags;
61 	regex_t    *regex;
62 	char	   *pat;
63 	int			len;
64 
65 	if (ar == NULL)
66 	{
67 		ereport(WARNING,
68 				(errmsg("failed to add regex pattern, regex array is NULL")));
69 
70 		return -1;
71 	}
72 
73 	if (pattern == NULL)
74 	{
75 		ereport(WARNING,
76 				(errmsg("failed to add regex pattern, regex pattern is NULL")));
77 		return -1;
78 	}
79 
80 	len = strlen(pattern);
81 
82 	/* Force case insensitive pattern matching */
83 	regex_flags = REG_NOSUB;
84 	regex_flags |= REG_ICASE;
85 
86 	/* Add extended regex search */
87 	regex_flags |= REG_EXTENDED;
88 
89 	pat = palloc(sizeof(char) * (len + 3));
90 	if (strncmp(pattern, "^", 1) != 0)
91 	{
92 		strncpy(pat, "^", 2);
93 		strncat(pat, pattern, len + 1);
94 	}
95 	else
96 	{
97 		strncpy(pat, pattern, len + 1);
98 	}
99 
100 	if (len == 0 || (len > 0 && pattern[len - 1] != '$'))
101 	{
102 		strncat(pat, "$", 2);
103 	}
104 
105 	/* Compile our regex */
106 	regex = palloc(sizeof(regex_t));
107 	if (regcomp(regex, pat, regex_flags) != 0)
108 	{
109 		ereport(WARNING,
110 				(errmsg("failed to add regex pattern, invalid regex pattern: \"%s\" (%s)", pattern, pat)));
111 		pfree(regex);
112 		pfree(pat);
113 		return -1;
114 	}
115 	pfree(pat);
116 
117 	if (ar->pos == ar->size)
118 	{
119 		ar->size += AR_ALLOC_UNIT;
120 		ar->regex = repalloc(ar->regex, sizeof(regex_t *) * ar->size);
121 	}
122 	ar->regex[ar->pos] = regex;
123 	ar->pos++;
124 
125 	return 0;
126 }
127 
128 /*
129  * Execute regex matching. Returns matched array index.
130  */
131 int
regex_array_match(RegArray * ar,char * pattern)132 regex_array_match(RegArray * ar, char *pattern)
133 {
134 	int			i;
135 
136 	if (ar == NULL)
137 	{
138 		ereport(WARNING,
139 				(errmsg("failed to execute regex matching, regex array is NULL")));
140 		return -1;
141 	}
142 
143 	if (pattern == NULL)
144 	{
145 		ereport(WARNING,
146 				(errmsg("failed to execute regex matching, pattern is NULL")));
147 		return -1;
148 	}
149 
150 	for (i = 0; i < ar->pos; i++)
151 	{
152 		if (regexec(ar->regex[i], pattern, 0, 0, 0) == 0)
153 			return i;
154 	}
155 	return -1;
156 }
157 
158 /*
159  * Destroy RegArray object
160  */
161 void
destroy_regex_arrary(RegArray * ar)162 destroy_regex_arrary(RegArray * ar)
163 {
164 	pfree(ar->regex);
165 	pfree(ar);
166 }
167 
168 /*
169  * Create L-R token array
170  */
171 Left_right_tokens *
create_lrtoken_array(void)172 create_lrtoken_array(void)
173 {
174 	Left_right_tokens *ar;
175 
176 	ar = palloc(sizeof(Left_right_tokens));
177 	ar->pos = 0;
178 	ar->size = AR_ALLOC_UNIT;
179 	ar->token = (Left_right_token *) palloc(sizeof(Left_right_token) * ar->size);
180 
181 	return ar;
182 }
183 
184 /*
185  * Extract tokens separated by delimi from str. Each token is separeted by delim2,
186  * and token lists are returned to left_tokens and right_tokens respectively.
187  * Nnumber of tokens is set to *n.
188  */
189 void
extract_string_tokens2(char * str,char * delimi,char delimi2,Left_right_tokens * lrtokens)190 extract_string_tokens2(char *str, char *delimi, char delimi2, Left_right_tokens * lrtokens)
191 {
192 	char	   *token;
193 	char	   *mystr;
194 
195 	mystr = pstrdup(str);
196 
197 	for (token = strtok(mystr, delimi); token != NULL; token = strtok(NULL, delimi))
198 	{
199 		int			len;
200 		char	   *left_token;
201 		char	   *right_token;
202 		char	   *weight_token = NULL;
203 		int			i,
204 					j;
205 
206 		len = strlen(token) + 1;
207 		left_token = palloc(len);
208 		right_token = palloc(len);
209 		weight_token = palloc(len);
210 
211 		for (i = 0; token[i] && token[i] != delimi2; i++)
212 			left_token[i] = token[i];
213 
214 		left_token[i] = '\0';
215 
216 		if (i == len - 1)
217 		{
218 			pfree(left_token);
219 			pfree(right_token);
220 			pfree(mystr);
221 			pfree(weight_token);
222 			return;
223 		}
224 
225 		/* Skip delimiter 2 */
226 		i++;
227 		j = 0;
228 
229 		for (; token[i] && token[i] != '('; i++)
230 			right_token[j++] = token[i];
231 
232 		right_token[j] = '\0';
233 
234 		/* delimiter 3 */
235 		int			k = 0;
236 
237 		if (token[i] == '(')
238 		{
239 			i++;
240 			for (; token[i] && token[i] != ')'; i++)
241 				weight_token[k++] = token[i];
242 		}
243 		weight_token[k] = '\0';
244 
245 		if (lrtokens->pos == lrtokens->size)
246 		{
247 			lrtokens->size += AR_ALLOC_UNIT;
248 			lrtokens->token = repalloc(lrtokens->token, sizeof(Left_right_token) * lrtokens->size);
249 		}
250 		lrtokens->token[lrtokens->pos].left_token = left_token;
251 		lrtokens->token[lrtokens->pos].right_token = right_token;
252 		if (weight_token[0] != '\0')
253 			lrtokens->token[lrtokens->pos].weight_token = atof(weight_token);
254 		else
255 			lrtokens->token[lrtokens->pos].weight_token = 1.0;
256 
257 		lrtokens->pos++;
258 		pfree(weight_token);
259 	}
260 	pfree(mystr);
261 }
262