]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/breg.c
crypto: convert EVP_PKEY access and remainings bits for OpenSSL 1.1
[bacula/bacula] / bacula / src / lib / breg.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Manipulation routines for BREGEXP list
21  *
22  *  Eric Bollengier, March 2007
23  *
24  */
25
26
27 #include "bacula.h"
28
29 #include "breg.h"
30 #include "mem_pool.h"
31
32 BREGEXP *new_bregexp(const char *motif)
33 {
34    Dmsg0(500, "bregexp: creating new bregexp object\n");
35    BREGEXP *self = (BREGEXP *)bmalloc(sizeof(BREGEXP));
36    memset(self, 0, sizeof(BREGEXP));
37
38    if (!self->extract_regexp(motif)) {
39       Dmsg0(100, "bregexp: extract_regexp error\n");
40       free_bregexp(self);
41       return NULL;
42    }
43
44    self->result = get_pool_memory(PM_FNAME);
45    self->result[0] = '\0';
46
47    return self;
48 }
49
50 void free_bregexp(BREGEXP *self)
51 {
52    Dmsg0(500, "bregexp: freeing BREGEXP object\n");
53
54    if (!self) {
55       return;
56    }
57
58    if (self->expr) {
59       bfree(self->expr);
60    }
61    if (self->result) {
62       free_pool_memory(self->result);
63    }
64    regfree(&self->preg);
65    bfree(self);
66 }
67
68 /* Free a bregexps alist
69  */
70 void free_bregexps(alist *bregexps)
71 {
72    BREGEXP *elt;
73    Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
74    if (!bregexps) {
75       return;
76    }
77    foreach_alist(elt, bregexps) {
78       free_bregexp(elt);
79    }
80 }
81
82 /* Apply all regexps to fname
83  */
84 bool apply_bregexps(const char *fname, alist *bregexps, char **result)
85 {
86    BREGEXP *elt;
87    bool ok=false;
88
89    char *ret = (char *) fname;
90    foreach_alist(elt, bregexps) {
91       ret = elt->replace(ret);
92       ok = ok || elt->success;
93    }
94    Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
95
96    *result = ret;
97    return ok;
98 }
99
100 /* return an alist of BREGEXP or return NULL if it's not a
101  * where=!tmp!opt!ig,!temp!opt!i
102  */
103 alist *get_bregexps(const char *where)
104 {
105    char *p = (char *)where;
106    alist *list = New(alist(10, not_owned_by_alist));
107    BREGEXP *reg;
108
109    reg = new_bregexp(p);
110
111    while(reg) {
112       p = reg->eor;
113       list->append(reg);
114       reg = new_bregexp(p);
115    }
116
117    if (list->size()) {
118       return list;
119    } else {
120       delete list;
121       return NULL;
122    }
123 }
124
125 bool BREGEXP::extract_regexp(const char *motif)
126 {
127    if ( !motif ) {
128       return false;
129    }
130
131    char sep = motif[0];
132
133    if (!(sep == '!' ||
134          sep == ':' ||
135          sep == ';' ||
136          sep == '|' ||
137          sep == ',' ||
138          sep == '&' ||
139          sep == '%' ||
140          sep == '=' ||
141          sep == '~' ||
142          sep == '/' ||
143          sep == '<' ||
144          sep == '#'   ))
145    {
146       return false;
147    }
148
149    char *search = (char *) motif + 1;
150    int options = REG_EXTENDED | REG_NEWLINE;
151    bool ok = false;
152
153    /* extract 1st part */
154    char *dest = expr = bstrdup(motif);
155
156    while (*search && !ok) {
157       if (search[0] == '\\' && search[1] == sep) {
158          *dest++ = *++search;       /* we skip separator */
159
160       } else if (search[0] == '\\' && search[1] == '\\') {
161          *dest++ = *++search;       /* we skip the second \ */
162
163       } else if (*search == sep) {  /* we found end of expression */
164          *dest++ = '\0';
165
166          if (subst) {           /* already have found motif */
167             ok = true;
168
169          } else {
170             *dest++ = *++search; /* we skip separator */
171             subst = dest;        /* get replaced string */
172          }
173
174       } else {
175          *dest++ = *search++;
176       }
177    }
178    *dest = '\0';                /* in case of */
179
180    if (!ok || !subst) {
181       /* bad regexp */
182       return false;
183    }
184
185    ok = false;
186    /* find options */
187    while (*search && !ok) {
188       if (*search == 'i') {
189          options |= REG_ICASE;
190
191       } else if (*search == 'g') {
192               /* recherche multiple*/
193
194       } else if (*search == sep) {
195          /* skip separator */
196
197       } else {                  /* end of options */
198          ok = true;
199       }
200       search++;
201    }
202
203    int rc = regcomp(&preg, expr, options);
204    if (rc != 0) {
205       char prbuf[500];
206       regerror(rc, &preg, prbuf, sizeof(prbuf));
207       Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
208       return false;
209    }
210
211    eor = search;                /* useful to find the next regexp in where */
212
213    return true;
214 }
215
216 /* return regexp->result */
217 char *BREGEXP::replace(const char *fname)
218 {
219    success = false;             /* use this.success to known if it's ok */
220    int flen = strlen(fname);
221    int rc = regexec(&preg, fname, BREG_NREGS, regs, 0);
222
223    if (rc == REG_NOMATCH) {
224       Dmsg0(500, "bregexp: regex mismatch\n");
225       return return_fname(fname, flen);
226    }
227
228    int len = compute_dest_len(fname, regs);
229
230    if (len) {
231       result = check_pool_memory_size(result, len);
232       edit_subst(fname, regs);
233       success = true;
234       Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
235
236    } else {                     /* error in substitution */
237       Dmsg0(100, "bregexp: error in substitution\n");
238       return return_fname(fname, flen);
239    }
240
241    return result;
242 }
243
244 char *BREGEXP::return_fname(const char *fname, int len)
245 {
246    result = check_pool_memory_size(result, len+1);
247    strcpy(result,fname);
248    return result;
249 }
250
251 int BREGEXP::compute_dest_len(const char *fname, regmatch_t breg[])
252 {
253    int len=0;
254    char *p;
255    char *psubst = subst;
256    int no;
257
258    if (!fname || !breg) {
259       return 0;
260    }
261
262    /* match failed ? */
263    if (breg[0].rm_so < 0) {
264       return 0;
265    }
266
267    for (p = psubst++; *p ; p = psubst++) {
268       /* match $1 \1 back references */
269       if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
270          no = *psubst++ - '0';
271
272          /* we check if the back reference exists */
273          /* references can not match if we are using (..)? */
274
275          if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
276             len += breg[no].rm_eo - breg[no].rm_so;
277          }
278
279       } else {
280          len++;
281       }
282    }
283
284    /* $0 is replaced by subst */
285    len -= breg[0].rm_eo - breg[0].rm_so;
286    len += strlen(fname) + 1;
287
288    return len;
289 }
290
291 char *BREGEXP::edit_subst(const char *fname, regmatch_t breg[])
292 {
293    int i;
294    char *p;
295    char *psubst = subst;
296    int no;
297    int len;
298
299    /* il faut recopier fname dans dest
300     *  on recopie le debut fname -> breg->start[0]
301     */
302
303    for (i = 0; i < breg[0].rm_so ; i++) {
304       result[i] = fname[i];
305    }
306
307    /* on recopie le motif de remplacement (avec tous les $x) */
308
309    for (p = psubst++; *p ; p = psubst++) {
310       /* match $1 \1 back references */
311       if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
312          no = *psubst++ - '0';
313
314          /* have a back reference ? */
315          if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
316             len = breg[no].rm_eo - breg[no].rm_so;
317             bstrncpy(result + i, fname + breg[no].rm_so, len + 1);
318             i += len ;
319          }
320
321       } else {
322          result[i++] = *p;
323       }
324    }
325
326    /* we copy what is out of the match */
327    strcpy(result + i, fname + breg[0].rm_eo);
328
329    return result;
330 }
331
332 /* escape sep char and \
333  * dest must be long enough (src*2+1)
334  * return end of the string */
335 char *bregexp_escape_string(char *dest, const char *src, const char sep)
336 {
337    char *ret = dest;
338    while (*src)
339    {
340       if (*src == sep) {
341          *dest++ = '\\';
342       } else if (*src == '\\') {
343          *dest++ = '\\';
344       }
345       *dest++ = *src++;
346    }
347    *dest = '\0';
348
349    return ret;
350 }
351
352 static const char regexp_sep = '!';
353 static const char *str_strip_prefix = "!%s!!i";
354 static const char *str_add_prefix   = "!^!%s!";
355 static const char *str_add_suffix   = "!([^/])$!$1%s!";
356
357 int bregexp_get_build_where_size(char *strip_prefix,
358                                  char *add_prefix,
359                                  char *add_suffix)
360 {
361    int str_size = ((strip_prefix?strlen(strip_prefix)+strlen(str_strip_prefix):0) +
362                    (add_prefix?strlen(add_prefix)+strlen(str_add_prefix)      :0) +
363                    (add_suffix?strlen(add_suffix)+strlen(str_add_suffix)      :0) )
364          /* escape + 3*, + \0 */
365             * 2    + 3   + 1;
366
367    Dmsg1(200, "bregexp_get_build_where_size = %i\n", str_size);
368    return str_size;
369 }
370
371 /* build a regexp string with user arguments
372  * Usage :
373  *
374  * int len = bregexp_get_build_where_size(a,b,c) ;
375  * char *dest = (char *) bmalloc (len * sizeof(char));
376  * bregexp_build_where(dest, len, a, b, c);
377  * bfree(dest);
378  *
379  */
380 char *bregexp_build_where(char *dest, int str_size,
381                           char *strip_prefix,
382                           char *add_prefix,
383                           char *add_suffix)
384 {
385    int len=0;
386
387    POOLMEM *str_tmp = get_memory(str_size);
388
389    *str_tmp = *dest = '\0';
390
391    if (strip_prefix) {
392       len += bsnprintf(dest, str_size - len, str_strip_prefix,
393                        bregexp_escape_string(str_tmp, strip_prefix, regexp_sep));
394    }
395
396    if (add_suffix) {
397       if (len) dest[len++] = ',';
398
399       len += bsnprintf(dest + len,  str_size - len, str_add_suffix,
400                        bregexp_escape_string(str_tmp, add_suffix, regexp_sep));
401    }
402
403    if (add_prefix) {
404       if (len) dest[len++] = ',';
405
406       len += bsnprintf(dest + len, str_size - len, str_add_prefix,
407                        bregexp_escape_string(str_tmp, add_prefix, regexp_sep));
408    }
409
410    free_pool_memory(str_tmp);
411
412    return dest;
413 }
414
415
416 void BREGEXP::debug()
417 {
418    printf("expr=[%s]\n", expr);
419    printf("subst=[%s]\n", subst);
420    printf("result=%s\n", NPRT(result));
421 }