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  */
create_regex_array(void)41 RegArray *create_regex_array(void)
42 {
43 	RegArray *ar;
44 
45 	ar = palloc(sizeof(RegArray));
46 	ar->pos = 0;
47 	ar->size = AR_ALLOC_UNIT;
48 	ar->regex = (regex_t **)palloc(sizeof(regex_t *) * ar->size);
49 
50 	return ar;
51 }
52 
53 /*
54  * Add an regular expression pattern
55  */
add_regex_array(RegArray * ar,char * pattern)56 int add_regex_array(RegArray *ar, char *pattern)
57 {
58 	int regex_flags;
59 	regex_t *regex;
60 	char *pat;
61 	int len;
62 
63 	if (ar == NULL)
64 	{
65 		ereport(WARNING,
66 				(errmsg("failed to add regex pattern, regex array is NULL")));
67 
68 		return -1;
69 	}
70 
71 	if (pattern == NULL)
72 	{
73 		ereport(WARNING,
74 				(errmsg("failed to add regex pattern, regex pattern is NULL")));
75 		return -1;
76 	}
77 
78 	len = strlen(pattern);
79 
80 	/* Force case insensitive pattern matching */
81 	regex_flags = REG_NOSUB;
82 	regex_flags |= REG_ICASE;
83 
84 	/* Add extended regex search */
85 	regex_flags |= REG_EXTENDED;
86 
87 	pat = palloc(sizeof(char)*(len+3));
88 	if (strncmp(pattern, "^", 1) != 0)
89 	{
90 		strncpy(pat, "^", 2);
91 		strncat(pat, pattern, len + 1);
92 	}
93 	else
94 	{
95 		strncpy(pat, pattern, len + 1);
96 	}
97 
98 	if (len == 0 || (len > 0 && pattern[len - 1] != '$'))
99 	{
100 		strncat(pat, "$", 2);
101 	}
102 
103 	/* Compile our regex */
104 	regex = palloc(sizeof(regex_t));
105 	if (regcomp(regex, pat, regex_flags) != 0)
106 	{
107 		ereport(WARNING,
108 				(errmsg("failed to add regex pattern, invalid regex pattern: \"%s\" (%s)", pattern, pat)));
109 		pfree(regex);
110 		pfree(pat);
111 		return -1;
112 	}
113 	pfree(pat);
114 
115 	if (ar->pos == ar->size)
116 	{
117 		ar->size += AR_ALLOC_UNIT;
118 		ar->regex = repalloc(ar->regex, sizeof(regex_t *) * ar->size);
119 	}
120 	ar->regex[ar->pos] = regex;
121 	ar->pos++;
122 
123 	return 0;
124 }
125 
126 /*
127  * Execute regex matching. Returns matched array index.
128  */
regex_array_match(RegArray * ar,char * pattern)129 int regex_array_match(RegArray *ar, char *pattern)
130 {
131 	int i;
132 
133 	if (ar == NULL)
134 	{
135 		ereport(WARNING,
136 				(errmsg("failed to execute regex matching, regex array is NULL")));
137 		return -1;
138 	}
139 
140 	if (pattern == NULL)
141 	{
142 		ereport(WARNING,
143 				(errmsg("failed to execute regex matching, pattern is NULL")));
144 		return -1;
145 	}
146 
147 	for (i=0;i<ar->pos;i++)
148 	{
149 		if (regexec(ar->regex[i], pattern, 0, 0, 0) == 0)
150 			return i;
151 	}
152 	return -1;
153 }
154 
155 /*
156  * Destroy RegArray object
157  */
destroy_regex_arrary(RegArray * ar)158 void destroy_regex_arrary(RegArray *ar)
159 {
160 	pfree(ar->regex);
161 	pfree(ar);
162 }
163 
164 /*
165  * Create L-R token array
166  */
create_lrtoken_array(void)167 Left_right_tokens *create_lrtoken_array(void)
168 {
169 	Left_right_tokens *ar;
170 
171 	ar = palloc(sizeof(Left_right_tokens));
172 	ar->pos = 0;
173 	ar->size = AR_ALLOC_UNIT;
174 	ar->token = (Left_right_token *)palloc(sizeof(Left_right_token) * ar->size);
175 
176 	return ar;
177 }
178 
179 /*
180  * Extract tokens separated by delimi from str. Each token is separeted by delim2,
181  * and token lists are returned to left_tokens and right_tokens respectively.
182  * Nnumber of tokens is set to *n.
183  */
extract_string_tokens2(char * str,char * delimi,char delimi2,Left_right_tokens * lrtokens)184 void extract_string_tokens2(char *str, char *delimi, char delimi2, Left_right_tokens *lrtokens)
185 {
186 	char *token;
187 	char *mystr;
188 
189 	mystr = pstrdup(str);
190 
191 	for (token = strtok(mystr, delimi); token != NULL; token = strtok(NULL, delimi))
192 	{
193 		int len;
194 		char *left_token;
195 		char *right_token;
196 		int i,j;
197 
198 		len = strlen(token)+1;
199 		left_token = palloc(len);
200 		right_token = palloc(len);
201 
202 		for (i=0;token[i] && token[i] != delimi2;i++)
203 			left_token[i] = token[i];
204 
205 		left_token[i] = '\0';
206 
207 		if (i == len -1)
208 		{
209 			pfree(left_token);
210 			pfree(right_token);
211 			pfree(mystr);
212 			return;
213 		}
214 
215 		/* Skip delimiter 2 */
216 		i++;
217 		j = 0;
218 
219 		for (;token[i];i++)
220 			right_token[j++] = token[i];
221 
222 		right_token[j] = '\0';
223 
224 		if (lrtokens->pos == lrtokens->size)
225 		{
226 			lrtokens->size += AR_ALLOC_UNIT;
227 			lrtokens->token = repalloc(lrtokens->token, sizeof(Left_right_token) * lrtokens->size);
228 		}
229 		lrtokens->token[lrtokens->pos].left_token = left_token;
230 		lrtokens->token[lrtokens->pos].right_token = right_token;
231 		lrtokens->pos++;
232 	}
233 	pfree(mystr);
234 }
235