1 /* Copyright (C) 2000-2015 Lavtech.com corp. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "udm_config.h"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24
25 #define UDM_MATCH_PRIV
26
27 #include "udm_common.h"
28 #include "udm_regex.h"
29 #include "udm_utils.h"
30 #include "udm_wild.h"
31 #include "udm_match.h"
32 #include "udm_vars.h"
33
34
UdmMatchPatternConstStr(const UDM_MATCH * Match)35 const char *UdmMatchPatternConstStr(const UDM_MATCH *Match)
36 {
37 return Match->Pattern.str;
38 }
39
40
UdmMatchPatternLength(const UDM_MATCH * Match)41 size_t UdmMatchPatternLength(const UDM_MATCH *Match)
42 {
43 return Match->Pattern.length;
44 }
45
46
47 udm_bool_t
UdmMatchIsCaseInsensitive(const UDM_MATCH * Match)48 UdmMatchIsCaseInsensitive(const UDM_MATCH *Match)
49 {
50 return UDM_TEST(Match->Param.flags & UDM_MATCH_FLAG_CASE_INSENSITIVE);
51 }
52
53
54 udm_bool_t
UdmMatchIsNegative(const UDM_MATCH * Match)55 UdmMatchIsNegative(const UDM_MATCH *Match)
56 {
57 return UDM_TEST(Match->Param.flags & UDM_MATCH_FLAG_NEGATIVE);
58 }
59
60
61 void
UdmMatchParamSetCaseInsensitive(UDM_MATCH_PARAM * P,udm_bool_t on)62 UdmMatchParamSetCaseInsensitive(UDM_MATCH_PARAM *P, udm_bool_t on)
63 {
64 if (on)
65 P->flags|= UDM_MATCH_FLAG_CASE_INSENSITIVE;
66 else
67 P->flags&= ~UDM_MATCH_FLAG_CASE_INSENSITIVE;
68 }
69
70
71 void
UdmMatchParamSetNegative(UDM_MATCH_PARAM * P,udm_bool_t on)72 UdmMatchParamSetNegative(UDM_MATCH_PARAM *P, udm_bool_t on)
73 {
74 if (on)
75 P->flags|= UDM_MATCH_FLAG_NEGATIVE;
76 else
77 P->flags&= ~UDM_MATCH_FLAG_NEGATIVE;
78 }
79
80
81 void
UdmMatchParamSetOptimization(UDM_MATCH_PARAM * P,udm_bool_t on)82 UdmMatchParamSetOptimization(UDM_MATCH_PARAM *P, udm_bool_t on)
83 {
84 if (!on)
85 P->flags|= UDM_MATCH_FLAG_SKIP_OPTIMIZATION;
86 else
87 P->flags&= ~UDM_MATCH_FLAG_SKIP_OPTIMIZATION;
88 }
89
90
91 const char *
UdmMatchCaseSensitivityStr(const UDM_MATCH * Match)92 UdmMatchCaseSensitivityStr(const UDM_MATCH *Match)
93 {
94 return UdmMatchIsCaseInsensitive(Match) ? "Insensitive" : "Sensitive";
95 }
96
97
98 static int
IsSimpleWildEnding(const char * p)99 IsSimpleWildEnding(const char *p)
100 {
101 if (*p++ != '*' || !*p)
102 return 0;
103 for (; *p; p++)
104 {
105 if (*p == '*' || *p =='?')
106 return 0;
107 }
108 return 1;
109 }
110
111
112 static regex_t *
UdmMatchGetRegex(const UDM_MATCH * Match)113 UdmMatchGetRegex(const UDM_MATCH *Match)
114 {
115 return (regex_t *) Match->specific;
116 }
117
118
119 /*
120 Compile the given patter to Match->specific.
121 Doesn't touch Match->Pattern.
122 */
123 static udm_rc_t
UdmMatchCompSpecificRegexInternal(UDM_MATCH * Match,const char * pattern,char * errstr,size_t errstrsize)124 UdmMatchCompSpecificRegexInternal(UDM_MATCH *Match, const char *pattern,
125 char *errstr, size_t errstrsize)
126 {
127 int err, flag= REG_EXTENDED;
128 errstr[0]= '\0';
129 Match->specific= (regex_t*)UdmRealloc(Match->specific, sizeof(regex_t));
130 bzero((void*)Match->specific, sizeof(regex_t));
131 if (UdmMatchIsCaseInsensitive(Match))
132 flag|= REG_ICASE;
133 if ((err= regcomp(UdmMatchGetRegex(Match), pattern, flag)))
134 {
135 regerror(err, UdmMatchGetRegex(Match), errstr, errstrsize); /* TODO-OVERFLOW */
136 UDM_FREE(Match->specific);
137 return UDM_ERROR;
138 }
139 return UDM_OK;
140 }
141
142
143 udm_rc_t
UdmMatchCompSpecificRegex(UDM_MATCH * Match,const char * pattern,char * errstr,size_t errstrsize)144 UdmMatchCompSpecificRegex(UDM_MATCH *Match, const char *pattern,
145 char *errstr, size_t errstrsize)
146 {
147 Match->Param.match_mode= UDM_MATCH_REGEX;
148 return UdmMatchCompSpecificRegexInternal(Match, pattern, errstr, errstrsize);
149 }
150
151
152 udm_rc_t
UdmMatchComp(UDM_MATCH * Match,char * errstr,size_t errstrsize)153 UdmMatchComp(UDM_MATCH *Match,char *errstr,size_t errstrsize)
154 {
155 Match->Pattern.length= strlen(Match->Pattern.str);
156
157 switch (Match->Param.match_mode)
158 {
159 case UDM_MATCH_REGEX:
160 if (UdmMatchCompSpecificRegex(Match, Match->Pattern.str, errstr, errstrsize))
161 return UDM_ERROR;
162 break;
163 case UDM_MATCH_WILD:
164 errstr[0]= '\0';
165 if (!(Match->Param.flags & UDM_MATCH_FLAG_SKIP_OPTIMIZATION) &&
166 IsSimpleWildEnding(Match->Pattern.str))
167 {
168 /* Convert simple UDM_MATCH_WILD cases to UDM_MATCH_END */
169 memmove(Match->Pattern.str, Match->Pattern.str + 1, Match->Pattern.length);
170 Match->Param.match_mode= UDM_MATCH_END;
171 Match->Pattern.length--;
172 }
173 break;
174 case UDM_MATCH_BEGIN:
175 case UDM_MATCH_END:
176 case UDM_MATCH_SUBSTR:
177 case UDM_MATCH_FULL:
178 errstr[0]= '\0';
179 break;
180 case UDM_MATCH_SUBNET:
181 case UDM_MATCH_NUMERIC_LT:
182 case UDM_MATCH_NUMERIC_GT:
183 case UDM_MATCH_RANGE:
184 udm_snprintf(errstr, errstrsize, "Unknown match type '%d'",
185 Match->Param.match_mode);
186 return UDM_ERROR;
187 }
188 return UDM_OK;
189 }
190
191
192 void
UdmMatchParamInit(UDM_MATCH_PARAM * M)193 UdmMatchParamInit(UDM_MATCH_PARAM *M)
194 {
195 bzero((void*) M, sizeof(*M));
196 }
197
198
199 void
UdmMatchInit(UDM_MATCH * M)200 UdmMatchInit(UDM_MATCH *M)
201 {
202 bzero((void*)M, sizeof(*M));
203 }
204
205
UdmMatchFree(UDM_MATCH * Match)206 void UdmMatchFree(UDM_MATCH * Match)
207 {
208 UDM_FREE(Match->Pattern.str);
209 Match->Pattern.length= 0;
210 if (Match->specific)
211 {
212 regfree((regex_t*) Match->specific);
213 UDM_FREE(Match->specific);
214 }
215 }
216
217
UdmMatchFreeAndInit(UDM_MATCH * Match)218 void UdmMatchFreeAndInit(UDM_MATCH *Match)
219 {
220 UdmMatchFree(Match);
221 UdmMatchInit(Match);
222 }
223
224
225 #define UDM_NSUBS 10
226
227 int
UdmMatchExec(const UDM_MATCH * Match,const char * string,size_t string_length,const char * net_string,size_t nparts,UDM_MATCH_PART * Parts)228 UdmMatchExec(const UDM_MATCH * Match,
229 const char *string, size_t string_length,
230 const char *net_string,
231 size_t nparts,UDM_MATCH_PART * Parts)
232 {
233 size_t i;
234 int res=0;
235 regmatch_t subs[UDM_NSUBS];
236 const char *se;
237
238 UdmDebugEnter();
239
240 switch (Match->Param.match_mode)
241 {
242 case UDM_MATCH_REGEX:
243 if(nparts>UDM_NSUBS)nparts=UDM_NSUBS;
244 res= regexec(UdmMatchGetRegex(Match), string, nparts, subs, 0);
245 if(res)
246 {
247 for(i=0;i<nparts;i++)Parts[i].beg=Parts[i].end=-1;
248 }
249 else
250 {
251 for(i=0;i<nparts;i++)
252 {
253 Parts[i].beg=subs[i].rm_so;
254 Parts[i].end=subs[i].rm_eo;
255 }
256 }
257 break;
258 case UDM_MATCH_WILD:
259 for(i=0;i<nparts;i++)Parts[i].beg=Parts[i].end=-1;
260 if (UdmMatchIsCaseInsensitive(Match))
261 {
262 res= UdmWildCaseCmp(string, Match->Pattern.str);
263 }
264 else
265 {
266 res= UdmWildCmp(string, Match->Pattern.str);
267 }
268 break;
269 case UDM_MATCH_SUBNET:
270 for(i = 0; i < nparts; i++) Parts[i].beg = Parts[i].end = -1;
271 if (UdmMatchIsCaseInsensitive(Match))
272 {
273 res= UdmWildCaseCmp(net_string, Match->Pattern.str);
274 }
275 else
276 {
277 res= UdmWildCmp(net_string, Match->Pattern.str);
278 }
279 break;
280 case UDM_MATCH_BEGIN:
281 for(i=0;i<nparts;i++)Parts[i].beg=Parts[i].end=-1;
282 if (UdmMatchIsCaseInsensitive(Match))
283 {
284 res= strncasecmp(Match->Pattern.str, string, Match->Pattern.length);
285 }
286 else
287 {
288 res= strncmp(Match->Pattern.str, string, Match->Pattern.length);
289 }
290 break;
291 case UDM_MATCH_FULL:
292 for(i=0;i<nparts;i++)Parts[i].beg=Parts[i].end=-1;
293 if (UdmMatchIsCaseInsensitive(Match))
294 {
295 res= strcasecmp(Match->Pattern.str, string);
296 }
297 else
298 {
299 res= strcmp(Match->Pattern.str, string);
300 }
301 break;
302 case UDM_MATCH_END:
303 for(i=0;i<nparts;i++)Parts[i].beg=Parts[i].end=-1;
304 if (string_length < Match->Pattern.length)
305 {
306 res= 1;
307 break;
308 }
309 se= string + string_length - Match->Pattern.length;
310 if (UdmMatchIsCaseInsensitive(Match))
311 {
312 res= strcasecmp(Match->Pattern.str, se);
313 }
314 else
315 {
316 res= strcmp(Match->Pattern.str, se);
317 }
318 break;
319
320 case UDM_MATCH_SUBSTR:
321 case UDM_MATCH_NUMERIC_LT:
322 case UDM_MATCH_NUMERIC_GT:
323 case UDM_MATCH_RANGE:
324 for(i=0;i<nparts;i++)Parts[i].beg=Parts[i].end=-1;
325 res=0;
326 }
327 if (UdmMatchIsNegative(Match))
328 res= !res;
329 UdmDebugReturn(res);
330 }
331
332
333 static int
UdmMatchSubNo(const char * str,const char * end)334 UdmMatchSubNo(const char *str, const char *end)
335 {
336 if (*str == '$' && str + 1 < end && str[1] >= '0' && str[1] <= '9')
337 return str[1] - '0';
338 return -1;
339 }
340
341 static size_t
UdmMatchPartLength(UDM_MATCH_PART * P)342 UdmMatchPartLength(UDM_MATCH_PART *P)
343 {
344 return ((P->beg > -1) && (P->end > P->beg)) ? P->end - P->beg : 0;
345 }
346
347
348 /*
349 Calc length which will be required for UdmMatchRegexApply(),
350 including traling '\0' character.
351 */
352 static size_t
UdmMatchRegexApplyLength(const char * repl,size_t repllen,size_t nparts,UDM_MATCH_PART * Parts)353 UdmMatchRegexApplyLength(const char *repl, size_t repllen,
354 size_t nparts, UDM_MATCH_PART *Parts)
355 {
356 size_t length;
357 const char *replend= repl + repllen;
358 for (length= 0; repl < replend; repl++)
359 {
360 int sub;
361 if ((sub= UdmMatchSubNo(repl, replend)) >= 0)
362 {
363 size_t part_length= UdmMatchPartLength(&Parts[sub]);
364 length+= part_length;
365 repl++;
366 }
367 else
368 {
369 length++;
370 }
371 }
372 return length + 1;
373 }
374
375
376 /*
377 Apply "regex" type of match parts.
378 previously generated by UdmMatchExec result.
379 res - where to put result to
380 size - size of res, must be at least 1 byte - for trailing '\0'.
381 string - source string
382 rpl - replacement pattern, with variables \0, \1, \2, ... \9
383 nparts - how many parts were found by UdmMatchExec
384 Parts - the parts themself
385
386 RETURNS - result length.
387 */
388 static size_t
UdmMatchRegexApply(char * res,size_t size,const char * string,const char * rpl,size_t rpllen,size_t nparts,UDM_MATCH_PART * Parts)389 UdmMatchRegexApply(char *res, size_t size,
390 const char *string,
391 const char *rpl, size_t rpllen,
392 size_t nparts, UDM_MATCH_PART *Parts)
393 {
394 char *dst= res, *dstend= res + size - 1;
395 const char *rplend= rpl + rpllen;
396
397 if (!res)
398 return UdmMatchRegexApplyLength(rpl, rpllen, nparts, Parts);
399
400 UDM_ASSERT(size>0);
401
402 while (rpl < rplend && dst < dstend)
403 {
404 int sub;
405 if ((sub= UdmMatchSubNo(rpl, rplend)) >= 0)
406 {
407 size_t part_length;
408 if((part_length= UdmMatchPartLength(&Parts[sub])))
409 {
410 size_t bytes_left= dstend - dst;
411 if (bytes_left <= part_length)
412 part_length= bytes_left;
413 memcpy(dst, string + Parts[sub].beg, part_length);
414 dst+= part_length;
415 }
416 rpl+= 2;
417 }
418 else
419 {
420 *dst++= *rpl++;
421 }
422 }
423 *dst='\0';
424 return dst - res;
425 }
426
427
428 size_t
UdmMatchApply(char * res,size_t size,const char * string,const char * rpl,size_t rpllen,const UDM_MATCH * Match,size_t nparts,UDM_MATCH_PART * Parts)429 UdmMatchApply(char *res, size_t size,
430 const char *string,
431 const char *rpl, size_t rpllen,
432 const UDM_MATCH *Match,
433 size_t nparts, UDM_MATCH_PART *Parts)
434 {
435 int len=0;
436 if(!size)return 0;
437
438 switch (Match->Param.match_mode)
439 {
440 case UDM_MATCH_REGEX:
441 len= UdmMatchRegexApply(res, size, string, rpl, rpllen, nparts, Parts);
442 break;
443
444 case UDM_MATCH_BEGIN:
445 len= udm_snprintf(res, size - 1, "%.*s%s",
446 (int) rpllen, rpl,
447 string + strlen(Match->Pattern.str));
448 break;
449
450 case UDM_MATCH_FULL:
451 case UDM_MATCH_SUBSTR:
452 case UDM_MATCH_END:
453 case UDM_MATCH_WILD:
454 case UDM_MATCH_SUBNET:
455 case UDM_MATCH_NUMERIC_LT:
456 case UDM_MATCH_NUMERIC_GT:
457 case UDM_MATCH_RANGE:
458 *res='\0';
459 len=0;
460 break;
461 }
462 return len;
463 }
464
465
466 udm_rc_t
UdmMatchSetPattern(UDM_MATCH * Match,const char * pattern)467 UdmMatchSetPattern(UDM_MATCH *Match, const char *pattern)
468 {
469 if (!pattern)
470 {
471 Match->Pattern.str= NULL;
472 Match->Pattern.length= 0;
473 return UDM_OK;
474 }
475 if (!(Match->Pattern.str= UdmStrdup(pattern)))
476 {
477 Match->Pattern.length= 0;
478 return UDM_ERROR;
479 }
480 Match->Pattern.length= strlen(pattern);
481 return UDM_OK;
482 }
483
484
485 const char *
UdmMatchModeStr(udm_match_mode_t m)486 UdmMatchModeStr(udm_match_mode_t m)
487 {
488 switch(m)
489 {
490 case UDM_MATCH_REGEX: return "Regex";
491 case UDM_MATCH_WILD: return "Wild";
492 case UDM_MATCH_BEGIN: return "Begin";
493 case UDM_MATCH_END: return "End";
494 case UDM_MATCH_SUBSTR: return "SubStr";
495 case UDM_MATCH_FULL: return "Full";
496 case UDM_MATCH_SUBNET: return "Subnet";
497 case UDM_MATCH_NUMERIC_LT: return "LT";
498 case UDM_MATCH_NUMERIC_GT: return "GT";
499 case UDM_MATCH_RANGE: return "Range";
500 }
501 return "<Unknown Match Type>";
502 }
503
504
505 void
UdmFilterListInit(UDM_FILTERLIST * L)506 UdmFilterListInit(UDM_FILTERLIST *L)
507 {
508 bzero((void*)L, sizeof(*L));
509 }
510
511
512 void
UdmFilterListFree(UDM_FILTERLIST * L)513 UdmFilterListFree(UDM_FILTERLIST *L)
514 {
515 size_t i;
516 for (i= 0; i < L->nitems; i++)
517 {
518 UdmMatchFree(&L->Item[i].Match);
519 }
520 L->nitems= L->mitems= 0;
521 UDM_FREE(L->Item);
522 }
523
524
525 udm_rc_t
UdmFilterListAdd(UDM_FILTERLIST * L,const UDM_MATCH_PARAM * MatchParam,udm_method_t method,const UDM_CONST_STR * Pattern,char * err,size_t errsize)526 UdmFilterListAdd(UDM_FILTERLIST *L,
527 const UDM_MATCH_PARAM *MatchParam, udm_method_t method,
528 const UDM_CONST_STR *Pattern,
529 char *err, size_t errsize)
530 {
531 UDM_FILTER *N;
532 udm_rc_t rc;
533
534 if (L->nitems >= L->mitems)
535 {
536 L->mitems= L->nitems + 32;
537 L->Item= (UDM_FILTER*) UdmRealloc(L->Item, L->mitems * sizeof(UDM_FILTER));
538 }
539
540 N= &L->Item[L->nitems];
541 UdmMatchInit(&N->Match);
542 UdmMatchSetPattern(&N->Match, Pattern->str);
543 N->Match.Param= *MatchParam;
544 N->method= method;
545
546 if (UDM_OK != (rc= UdmMatchComp(&N->Match, err, errsize)))
547 return rc;
548
549 L->nitems++;
550 return UDM_OK;
551 }
552
553
554 const UDM_FILTER *
UdmFilterListFind(const UDM_FILTERLIST * L,const char * str)555 UdmFilterListFind(const UDM_FILTERLIST *L, const char *str)
556 {
557 size_t i, slen= strlen(str);
558 for (i= 0; i < L->nitems; i++)
559 {
560 UDM_FILTER *F= &L->Item[i];
561 if (!UdmMatchExec(&F->Match, str, slen, str, 0, NULL))
562 return F;
563 }
564 return NULL;
565 }
566
567
568 void
UdmReplaceListInit(UDM_REPLACELIST * L)569 UdmReplaceListInit(UDM_REPLACELIST *L)
570 {
571 bzero((void*)L, sizeof(*L));
572 }
573
574
575 void
UdmReplaceListFree(UDM_REPLACELIST * L)576 UdmReplaceListFree(UDM_REPLACELIST *L)
577 {
578 size_t i;
579 for (i= 0; i < L->nitems; i++)
580 {
581 UDM_REPLACE *Replace= &L->Item[i];
582 UdmMatchFree(&Replace->Match);
583 UdmFree(Replace->Replace.str);
584 }
585 L->nitems= L->mitems= 0;
586 UDM_FREE(L->Item);
587 }
588
589
590 udm_rc_t
UdmReplaceListAdd(UDM_REPLACELIST * L,const UDM_MATCH_PARAM * MatchParam,const UDM_CONST_STR * Pattern,const UDM_CONST_STR * Replace,char * err,size_t errsize)591 UdmReplaceListAdd(UDM_REPLACELIST *L,
592 const UDM_MATCH_PARAM *MatchParam,
593 const UDM_CONST_STR *Pattern,
594 const UDM_CONST_STR *Replace,
595 char *err, size_t errsize)
596 {
597 UDM_REPLACE *N;
598 udm_rc_t rc;
599
600 if (L->nitems >= L->mitems)
601 {
602 L->mitems= L->nitems + 32;
603 L->Item= (UDM_REPLACE*) UdmRealloc(L->Item, L->mitems * sizeof(UDM_REPLACE));
604 }
605
606 N= &L->Item[L->nitems];
607 UdmMatchInit(&N->Match);
608 UdmMatchSetPattern(&N->Match, Pattern->str);
609 N->Match.Param= *MatchParam;
610 N->Replace.str= Replace->str ? udm_strndup(Replace->str, Replace->length) : NULL;
611 N->Replace.length= Replace->str ? Replace->length : 0;
612
613 if (UDM_OK != (rc= UdmMatchComp(&N->Match, err, errsize)))
614 return rc;
615
616 L->nitems++;
617 return UDM_OK;
618 }
619
620
621 const UDM_REPLACE *
UdmReplaceListFind(const UDM_REPLACELIST * L,const char * str,size_t nparts,UDM_MATCH_PART * Parts)622 UdmReplaceListFind(const UDM_REPLACELIST *L, const char *str,
623 size_t nparts, UDM_MATCH_PART *Parts)
624 {
625 size_t i, slen= strlen(str);
626 for (i= 0; i < L->nitems; i++)
627 {
628 UDM_REPLACE *F= &L->Item[i];
629 if (!UdmMatchExec(&F->Match, str, slen, str, nparts, Parts))
630 return F;
631 }
632 return NULL;
633 }
634
635
636 void
UdmSectionFilterListInit(UDM_SECTIONFILTERLIST * L)637 UdmSectionFilterListInit(UDM_SECTIONFILTERLIST *L)
638 {
639 bzero((void*)L, sizeof(*L));
640 }
641
642
643 void
UdmSectionFilterListFree(UDM_SECTIONFILTERLIST * L)644 UdmSectionFilterListFree(UDM_SECTIONFILTERLIST *L)
645 {
646 size_t i;
647 for (i= 0; i < L->nitems; i++)
648 {
649 UdmMatchFree(&L->Item[i].Filter.Match);
650 UdmFree(L->Item[i].section);
651 }
652 L->nitems= L->mitems= 0;
653 UDM_FREE(L->Item);
654 }
655
656
657 udm_rc_t
UdmSectionFilterListAdd(UDM_SECTIONFILTERLIST * L,const UDM_MATCH_PARAM * MatchParam,udm_method_t method,const UDM_CONST_STR * Pattern,const char * section,char * err,size_t errsize)658 UdmSectionFilterListAdd(UDM_SECTIONFILTERLIST *L,
659 const UDM_MATCH_PARAM *MatchParam, udm_method_t method,
660 const UDM_CONST_STR *Pattern, const char *section,
661 char *err, size_t errsize)
662 {
663 UDM_SECTIONFILTER *N;
664 udm_rc_t rc;
665
666 if (L->nitems >= L->mitems)
667 {
668 L->mitems= L->nitems + 32;
669 L->Item= (UDM_SECTIONFILTER*) UdmRealloc(L->Item, L->mitems * sizeof(UDM_SECTIONFILTER));
670 }
671
672 N= &L->Item[L->nitems];
673 UdmMatchInit(&N->Filter.Match);
674 UdmMatchSetPattern(&N->Filter.Match, Pattern->str);
675 N->Filter.Match.Param= *MatchParam;
676 N->Filter.method= method;
677 N->section= section ? UdmStrdup(section) : NULL;
678
679 if (UDM_OK != (rc= UdmMatchComp(&N->Filter.Match, err, errsize)))
680 return rc;
681
682 L->nitems++;
683 return UDM_OK;
684 }
685
686
687 const UDM_SECTIONFILTER *
UdmSectionFilterListFind(const UDM_SECTIONFILTERLIST * L,const char * str)688 UdmSectionFilterListFind(const UDM_SECTIONFILTERLIST *L, const char *str)
689 {
690 size_t i, slen= strlen(str);
691 for (i= 0; i < L->nitems; i++)
692 {
693 UDM_SECTIONFILTER *F= &L->Item[i];
694 if (!UdmMatchExec(&F->Filter.Match, str, slen, str, 0, NULL))
695 return F;
696 }
697 return NULL;
698 }
699
700
UdmExcerptFragmentInit(UDM_EXCERPT_FRAGMENT * dst)701 void UdmExcerptFragmentInit(UDM_EXCERPT_FRAGMENT *dst)
702 {
703 UdmMatchInit(&dst->Match);
704 dst->quality= 0;
705 }
706
707
UdmExcerptFragmentFree(UDM_EXCERPT_FRAGMENT * dst)708 void UdmExcerptFragmentFree(UDM_EXCERPT_FRAGMENT *dst)
709 {
710 UdmMatchFree(&dst->Match);
711 }
712
713