1 /***************************************************************************/
2 /* This code is part of WWW grabber called pavuk */
3 /* Copyright (c) 1997 - 2001 Stefan Ondrejicka */
4 /* Distributed under GPL 2 or later */
5 /***************************************************************************/
6
7 #include "config.h"
8
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <errno.h>
14 #ifdef HAVE_FNMATCH
15 #include <fnmatch.h>
16 #else
17 #include "fnmatch.h"
18 #endif
19
20 #include "lfname.h"
21 #include "url.h"
22 #include "tools.h"
23 #include "tr.h"
24 #include "dlhash_tools.h"
25 #include "http.h"
26 #include "form.h"
27 #include "mime.h"
28 #include "jsbind.h"
29
30 enum lfname_lsp_type
31 {
32 LF_LSP_UNKNOWN, /*** unknown ***/
33 LF_LSP_STR, /*** string variable ***/
34 LF_LSP_NUM, /*** number variable ***/
35 LF_LSP_MACRO, /*** macro variable ***/
36 LF_LSP_SUB, /*** subpart from regex ***/
37 LF_LSP_SC, /*** strcat function ***/
38 LF_LSP_SS, /*** substr function ***/
39 LF_LSP_HASH, /*** hash function ***/
40 LF_LSP_MD5, /*** md5 function ***/
41 LF_LSP_LOWER, /*** lowerstr function ***/
42 LF_LSP_UPPER, /*** upperstr function ***/
43 LF_LSP_UENC, /*** urlencode function ***/
44 LF_LSP_UDEC, /*** urldecode function ***/
45 LF_LSP_DELCHR, /*** delchr function ***/
46 LF_LSP_TRCHR, /*** trchr function ***/
47 LF_LSP_TRSTR, /*** trstr function ***/
48 LF_LSP_STRSPN, /*** strspn function ***/
49 LF_LSP_STRCSPN, /*** strcspn function ***/
50 LF_LSP_STRLEN, /*** strlen function ***/
51 LF_LSP_NRSTR, /*** nrtostr function ***/
52 LF_LSP_LCHR, /*** last character offset ***/
53 LF_LSP_PLS, /*** plus ***/
54 LF_LSP_MNS, /*** minus ***/
55 LF_LSP_MOD, /*** mod ***/
56 LF_LSP_MUL, /*** multiply ***/
57 LF_LSP_DIV, /*** divide ***/
58 LF_LSP_REMOVEPARAMETER, /*** removes a parameter from an url string */
59 LF_LSP_GETVALUE,/*** reads a value from a parameter of an url string */
60 LF_LSP_SIF, /*** if condition ***/
61 LF_LSP_NOT, /*** logical not ***/
62 LF_LSP_AND, /*** logical and ***/
63 LF_LSP_OR, /*** logical or ***/
64 LF_LSP_GETEXT, /*** get extension from path ***/
65 #ifdef HAVE_MOZJS
66 LF_LSP_JSF, /*** result of JavaScript function ***/
67 #endif
68 LF_LSP_SEQ /*** string equal ***/
69 };
70
71 struct lfname_lsp_var
72 {
73 enum lfname_lsp_type type;
74 union
75 {
76 char *str;
77 int num;
78 char macro;
79 } val;
80 enum lfname_lsp_type rettype;
81 union
82 {
83 char *str;
84 int num;
85 } ret_val;
86 struct lfname_lsp_var *param1;
87 struct lfname_lsp_var *param2;
88 struct lfname_lsp_var *param3;
89 };
90
91
92 static char *lfname_lsp_get_by_url(struct lfname_lsp_interp *);
93 static struct lfname_lsp_var *lfname_lsp_analyze(const char **);
94 static void lfname_lsp_var_free(struct lfname_lsp_var *);
95
_strfindnchr(char * str,int chr,int n)96 static char *_strfindnchr(char *str, int chr, int n)
97 {
98 int cnt;
99 char *p;
100
101 for(p = str, cnt = 0; *p && cnt < n; p++)
102 {
103 if(*p == chr)
104 cnt++;
105 }
106 if(cnt != n)
107 return NULL;
108 else
109 return p - 1;
110 }
111
_strrfindnchr(char * str,int chr,int n)112 static char *_strrfindnchr(char *str, int chr, int n)
113 {
114 int cnt;
115 char *p;
116
117 for(p = str + strlen(str) - 1, cnt = 0; p >= str && cnt < n; p--)
118 {
119 if(*p == chr)
120 cnt++;
121 }
122 if(cnt != n)
123 return NULL;
124 else
125 return p + 1;
126 }
127
128 #ifdef HAVE_REGEX
lfname_re_sub(lfname * lfnamep,const char * urlstr,int nr)129 char *lfname_re_sub(lfname * lfnamep, const char *urlstr, int nr)
130 {
131 char pom[4096];
132
133 pom[0] = '\0';
134
135 if(lfnamep->type != LFNAME_REGEX)
136 return tl_strdup(pom);
137
138 #ifdef HAVE_POSIX_REGEX
139 {
140 regmatch_t *pmatch = lfnamep->pmatch;
141 if(nr >= 0 && nr <= lfnamep->preg.re_nsub)
142 {
143 strncpy(pom, urlstr + pmatch[nr].rm_so,
144 pmatch[nr].rm_eo - pmatch[nr].rm_so); /* FIXME: Security */
145 pom[pmatch[nr].rm_eo - pmatch[nr].rm_so] = '\0';
146 }
147 }
148 #elif defined(HAVE_V8_REGEX)
149 #ifdef HAVE_V8_REGSUB
150 {
151 char ssect[10];
152 if(nr)
153 sprintf(ssect, "\\%d", nr);
154 else
155 strcpy(ssect, "&");
156 regsub(lfnamep->preg, ssect, pom);
157 }
158 #endif
159 #elif defined(HAVE_GNU_REGEX)
160 if(nr >= 0 && nr < lfnamep->preg.re_nsub)
161 {
162 strncpy(pom, urlstr + lfnamep->pmatch.start[nr],
163 lfnamep->pmatch.end[nr] - lfnamep->pmatch.start[nr]); /* FIXME: Security */
164 pom[lfnamep->pmatch.end[nr] - lfnamep->pmatch.start[nr]] = '\0';
165 }
166 #elif defined(HAVE_PCRE_REGEX)
167 if(nr >= 0 && nr < lfnamep->pmatch_nr)
168 {
169 strncpy(pom, urlstr + lfnamep->pmatch[2 * nr],
170 lfnamep->pmatch[2 * nr + 1] - lfnamep->pmatch[2 * nr]); /* FIXME: Security */
171 pom[lfnamep->pmatch[2 * nr + 1] - lfnamep->pmatch[2 * nr]] = '\0';
172 }
173 #endif
174 return tl_strdup(pom);
175 }
176 #endif
177
178 /* $x - x-th match section */
179 /* %i - protocol id */
180 /* %p - password */
181 /* %u - user name */
182 /* %h - host name */
183 /* %m - domain name */
184 /* %r - port number */
185 /* %d - doc path */
186 /* %n - doc name */
187 /* %b - base name of document */
188 /* %e - extension */
189 /* %s - search string */
190 /* %q - POST query string */
191 /* %M - mime type */
192 /* %E - extension by mime type */
193 /* %o - default doc name */
194 /* %-x - x-th dirname from end */
195 /* %x - x-th dirname from start */
196
lfname_get_by_url(url * urlp,const char * urlstr,const char * mime_type,lfname * lfnamep)197 char *lfname_get_by_url(url * urlp, const char *urlstr, const char *mime_type,
198 lfname * lfnamep)
199 {
200 char *ps, *pd, *pp, *p1, *p2;
201 char pom[4096];
202 char pstr[4096];
203 int nr;
204 char *n, *d, *t, *e, *b, *m, *q, *o;
205 const char *mimeext;
206 char *retv = NULL;
207
208 p1 = url_get_path(urlp);
209 if(urlp->type == URLT_GOPHER)
210 {
211 if(urlp->p.gopher.selector[0] == '1')
212 snprintf(pstr, sizeof(pstr), "/%s/%s", urlp->p.gopher.selector, priv_cfg.index_name);
213 else
214 snprintf(pstr, sizeof(pstr), "/%s", urlp->p.gopher.selector);
215
216 }
217 else if(tl_is_dirname(p1) ||
218 ((urlp->type == URLT_FTP || urlp->type == URLT_FTPS) && urlp->p.ftp.dir))
219 {
220 snprintf(pstr, sizeof(pstr), "%s/%s", p1, priv_cfg.index_name);
221 }
222 else
223 {
224 strncpy(pstr, p1, sizeof(pstr));
225 pstr[sizeof(pstr) - 1] = '\0';
226 }
227
228 t = get_abs_file_path(pstr);
229
230 strncpy(pstr, t, sizeof(pstr));
231 pstr[sizeof(pstr) - 1] = '\0';
232
233 p1 = strrchr(pstr, '/');
234
235 d = p1 ? tl_strndup(pstr, p1 - pstr) : tl_strdup("");
236
237 n = p1 ? tl_strdup(p1 + 1) : tl_strdup(pstr);
238
239 e = tl_strdup(tl_get_extension(pstr));
240
241 p1 = strrchr(n, '.');
242
243 if(p1)
244 b = tl_strndup(n, p1 - n);
245 else
246 b = tl_strdup(n);
247
248 m = url_get_site(urlp);
249 p1 = strchr(m, '.');
250 if(p1)
251 m = p1 + 1;
252
253 q = NULL;
254 if(urlp->status & URL_FORM_ACTION)
255 {
256 form_info *fi = (form_info *) urlp->extension;
257
258 p1 = form_encode_urlencoded(fi->infos);
259 if(p1)
260 {
261 strncpy(pstr, p1, sizeof(pstr) - 1);
262 pstr[sizeof(pstr) - 1] = '\0';
263 q = tl_strdup(pstr);
264 }
265 _free(p1);
266 }
267 if(!q)
268 q = tl_strdup("");
269
270 o = url_get_default_local_name(urlp);
271 mimeext = mime_get_type_ext(mime_type);
272
273 pom[0] = '\0';
274
275 if(lfnamep->transstr[0] == '(')
276 {
277 struct lfname_lsp_interp interp;
278 char port[10];
279
280 interp.urlp = urlp;
281 interp.urlstr = urlstr;
282 interp.scheme = prottable[urlp->type].dirname;
283 interp.passwd = url_get_pass(urlp, NULL) ? url_get_pass(urlp, NULL) : "";
284 interp.user = url_get_user(urlp, NULL) ? url_get_user(urlp, NULL) : "";
285 interp.host = url_get_site(urlp) ? url_get_site(urlp) : "";
286 interp.domain = m;
287 sprintf(port, "%d", url_get_port(urlp));
288 interp.port = port;
289 interp.path = d;
290 interp.name = n;
291 interp.basename = b;
292 interp.extension = e;
293 interp.query = url_get_search_str(urlp) ? url_get_search_str(urlp) : "";
294 interp.post_query = q;
295 interp.deflt = o;
296 interp.mime_type = mime_type;
297 interp.mime_type_ext = mimeext;
298 interp.orig = lfnamep;
299
300 retv = lfname_lsp_get_by_url(&interp);
301 }
302 else
303 {
304 for(ps = lfnamep->transstr, pd = pom; *ps; ps++)
305 {
306 if(!*(ps + 1))
307 {
308 *pd = *ps;
309 pd++;
310 *pd = '\0';
311 continue;
312 }
313 switch (*ps)
314 {
315 case '\\':
316 ps++;
317 *pd = *ps;
318 pd++;
319 *pd = '\0';
320 break;
321 #ifdef HAVE_REGEX
322 case '$':
323 ps++;
324 nr = strtol(ps, &pp, 10);
325 p1 = lfname_re_sub(lfnamep, urlstr, nr);
326 strncpy(pd, p1, sizeof(pom)-(pd-pom));
327 pd[sizeof(pom) - (pd-pom) - 1] = '\0';
328 _free(p1);
329 while(*pd)
330 pd++;
331 ps = pp - 1;
332 break;
333 #endif
334 case '%':
335 ps++;
336 pstr[0] = '\0';
337 switch (*ps)
338 {
339 case 'i':
340 strncpy(pstr, prottable[urlp->type].dirname, sizeof(pstr));
341 break;
342 case 'p':
343 strncpy(pstr, url_get_pass(urlp, NULL) ? url_get_pass(urlp,
344 NULL) : "", sizeof(pstr));
345 break;
346 case 'u':
347 strncpy(pstr, url_get_user(urlp, NULL) ? url_get_user(urlp,
348 NULL) : "", sizeof(pstr));
349 break;
350 case 'h':
351 strncpy(pstr, url_get_site(urlp) ? url_get_site(urlp) : "",
352 sizeof(pstr));
353 break;
354 case 'm':
355 strncpy(pstr, m, sizeof(pstr));
356 break;
357 case 'r':
358 sprintf(pstr, "%d", url_get_port(urlp));
359 break;
360 case 't':
361 strncpy(pstr, t, sizeof(pstr));
362 break;
363 case 'd':
364 strncpy(pstr, d, sizeof(pstr));
365 break;
366 case 'n':
367 strncpy(pstr, n, sizeof(pstr));
368 break;
369 case 'b':
370 strncpy(pstr, b, sizeof(pstr));
371 break;
372 case 'e':
373 strncpy(pstr, e, sizeof(pstr));
374 break;
375 case 's':
376 strncpy(pstr,
377 url_get_search_str(urlp) ? url_get_search_str(urlp) : "",
378 sizeof(pstr));
379 break;
380 case 'q':
381 strncpy(pstr, q, sizeof(pstr));
382 break;
383 case 'M':
384 strncpy(pstr, mime_type ? mime_type : "", sizeof(pstr));
385 break;
386 case 'E':
387 strncpy(pstr, mimeext ? mimeext : "", sizeof(pstr));
388 break;
389 case 'o':
390 strncpy(pstr, o, sizeof(pstr));
391 break;
392 case '-':
393 nr = strtol(ps + 1, &pp, 10);
394 p1 = _strrfindnchr(d, '/', nr);
395 p2 = _strrfindnchr(d, '/', nr + 1);
396 if(!p1)
397 pstr[0] = '\0';
398 else if(p2)
399 {
400 strncpy(pstr, p2 + 1, p1 - 1 - p2); /* FIXME: Security */
401 *(pstr + (p1 - 1 - p2)) = '\0';
402 }
403 else
404 pstr[0] = '\0';
405 ps = pp - 1;
406 break;
407 case '1':
408 case '2':
409 case '3':
410 case '4':
411 case '5':
412 case '6':
413 case '7':
414 case '8':
415 case '9':
416 nr = strtol(ps, &pp, 10);
417 p1 = _strfindnchr(d, '/', nr);
418 p2 = _strfindnchr(d, '/', nr + 1);
419 if(!p1)
420 pstr[0] = '\0';
421 else if(p2)
422 {
423 strncpy(pstr, p1 + 1, p2 - 1 - p1); /* FIXME: Security */
424 *(pstr + (p2 - 1 - p1)) = '\0';
425 }
426 else
427 strncpy(pstr, p1 + 1, sizeof(pstr));
428 ps = pp - 1;
429 break;
430 default:
431 pstr[0] = *(ps - 1);
432 pstr[1] = *ps;
433 pstr[2] = '\0';
434 }
435 pstr[sizeof(pstr) - 1] = '\0';
436 strcat(pd, pstr); /* FIXME: Security */
437 while(*pd)
438 pd++;
439 break;
440 default:
441 *pd = *ps;
442 pd++;
443 *pd = '\0';
444 }
445 }
446 retv = tl_strdup(pom);
447 }
448 free(e);
449 free(n);
450 free(t);
451 free(d);
452 free(q);
453 free(o);
454 return retv;
455 }
456
lfname_free(lfname * lfnamep)457 void lfname_free(lfname * lfnamep)
458 {
459 #ifdef HAVE_REGEX
460 if(lfnamep->type == LFNAME_REGEX)
461 {
462 #ifdef HAVE_POSIX_REGEX
463 regfree(&(lfnamep->preg));
464 _free(lfnamep->pmatch);
465 #elif defined(HAVE_V8_REGEX)
466 _free(lfnamep->preg);
467 #elif defined(HAVE_GNU_REGEX)
468 regfree(&lfnamep->preg);
469 _free(lfnamep->pmatch.start);
470 _free(lfnamep->pmatch.end);
471 #elif defined(HAVE_PCRE_REGEX)
472 _free(lfnamep->preg);
473 _free(lfnamep->preg_extra);
474 _free(lfnamep->pmatch);
475 #endif
476 }
477 #endif
478
479 _free(lfnamep->matchstr);
480 _free(lfnamep->transstr);
481 _free(lfnamep);
482 }
483
lfname_new(lfname_type type,const char * mpt,const char * str)484 lfname *lfname_new(lfname_type type, const char *mpt, const char *str)
485 {
486 lfname *rv;
487 const char *p;
488
489 rv = _malloc(sizeof(lfname));
490 rv->type = type;
491 rv->matchstr = NULL;
492 rv->transstr = NULL;
493 #ifdef HAVE_REGEX
494 if(type == LFNAME_REGEX)
495 {
496 #ifdef HAVE_POSIX_REGEX
497 int ec;
498 if((ec = regcomp(&(rv->preg), mpt, REG_EXTENDED)))
499 {
500 char pom[PATH_MAX];
501 xprintf(0, gettext("Error compiling regular expression : %s\n"), mpt);
502 regerror(ec, &(rv->preg), pom, sizeof(pom));
503 xprintf(0, "%s\n", pom);
504 regfree(&(rv->preg));
505 free(rv);
506 return NULL;
507 }
508 rv->pmatch = _malloc((rv->preg.re_nsub + 1) * sizeof(regmatch_t));
509 #elif defined(HAVE_V8_REGEX)
510 if(!(rv->preg = regcomp(mpt)))
511 {
512 xprintf(0, gettext("Error compiling regular expression : %s\n"), mpt);
513 free(rv->preg);
514 free(rv);
515 return NULL;
516 }
517 #elif defined(HAVE_BSD_REGEX)
518 if((p = re_comp(mpt)))
519 {
520 xprintf(0, gettext("Error compiling regular expression : %s\n"), mpt);
521 xprintf(0, "%s", p);
522 free(rv);
523 return NULL;
524 }
525 #elif defined(HAVE_GNU_REGEX)
526 rv->preg.allocated = 0;
527 rv->preg.buffer = NULL;
528 rv->preg.fastmap = NULL;
529 re_set_syntax(r_2phase_star);
530 if((p = re_compile_pattern(mpt, strlen(mpt), &rv->preg)))
531 {
532 xprintf(0, gettext("Error compiling regular expression : %s\n"), mpt);
533 xprintf(0, "%s\n", p);
534 regfree(&(rv->preg));
535 free(rv);
536 return NULL;
537 }
538 rv->pmatch.start =
539 _malloc((rv->preg.re_nsub + 1) * sizeof(*rv->pmatch.start));
540 rv->pmatch.end =
541 _malloc((rv->preg.re_nsub + 1) * sizeof(*rv->pmatch.end));
542 rv->pmatch.num_regs = rv->preg.re_nsub + 1;
543 rv->preg.regs_allocated = REGS_FIXED;
544 #elif defined(HAVE_PCRE_REGEX)
545 int errcode = 0;
546
547 if((rv->preg = pcre_compile(mpt, 0, (const char **) &p, &errcode, NULL)))
548 {
549 rv->preg_extra = pcre_study(rv->preg, 0, (const char **) &p);
550 pcre_fullinfo(rv->preg, rv->preg_extra, PCRE_INFO_CAPTURECOUNT,
551 &rv->pmatch_nr);
552 rv->pmatch_nr++;
553 rv->pmatch = (int *) _malloc(rv->pmatch_nr * 3 * sizeof(int));
554 }
555 else
556 {
557 xprintf(0, gettext("Error compiling regular expression : %s\n"), mpt);
558 xprintf(0, "%s\n", p);
559 _free(rv);
560 return NULL;
561 }
562 #endif
563 }
564 #endif
565 if(str[0] == '(')
566 {
567 struct lfname_lsp_var *variant;
568 p = str;
569 if((variant = lfname_lsp_analyze(&p)))
570 {
571 lfname_lsp_var_free(variant);
572 if(*p)
573 {
574 xprintf(0, gettext("LSP analyze error: bad token at - %s\n"), p);
575 lfname_free(rv);
576 return NULL;
577 }
578 else
579 {
580 rv->transstr = tl_strdup(str);
581 }
582 }
583 else
584 {
585 lfname_free(rv);
586 return NULL;
587 }
588 }
589 else
590 rv->transstr = tl_strdup(str);
591 rv->matchstr = tl_strdup(mpt);
592 return rv;
593 }
594
lfname_match(lfname * lfnamep,const char * urlstr)595 int lfname_match(lfname * lfnamep, const char *urlstr)
596 {
597 #ifdef HAVE_REGEX
598 if(lfnamep->type == LFNAME_REGEX)
599 {
600 #ifdef HAVE_POSIX_REGEX
601 return !regexec(&(lfnamep->preg), urlstr, lfnamep->preg.re_nsub + 1,
602 lfnamep->pmatch, 0);
603 #elif defined(HAVE_V8_REGEX)
604 return regexec(lfnamep->preg, urlstr);
605 #elif defined(HAVE_BSD_REGEX)
606 re_comp(lfnamep->matchstr);
607 return re_exec(urlstr);
608 #elif defined(HAVE_GNU_REGEX)
609 return re_match(&(lfnamep->preg), urlstr, strlen(urlstr), 0,
610 &lfnamep->pmatch) >= 0;
611 #elif defined(HAVE_PCRE_REGEX)
612 return pcre_exec(lfnamep->preg, lfnamep->preg_extra, urlstr,
613 strlen(urlstr), 0, 0, lfnamep->pmatch, 3 * lfnamep->pmatch_nr) >= 0;
614 #endif
615 }
616 else
617 #endif
618 return !fnmatch(lfnamep->matchstr, urlstr, 0);
619 }
620
lfname_check_rule(const char * str)621 int lfname_check_rule(const char *str)
622 {
623 if(str[0] == '(')
624 {
625 const char *p = str;
626 struct lfname_lsp_var *variant;
627
628 if((variant = lfname_lsp_analyze(&p)))
629 {
630 lfname_lsp_var_free(variant);
631 if(*p)
632 {
633 xprintf(0, gettext("LSP analyze error: bad token at - %s\n"), p);
634 return FALSE;
635 }
636 else
637 return TRUE;
638 }
639 else
640 return FALSE;
641 }
642 return TRUE;
643 }
644
lfname_check_pattern(lfname_type type,const char * str)645 int lfname_check_pattern(lfname_type type, const char *str)
646 {
647 #ifdef HAVE_REGEX
648 if(type == LFNAME_REGEX)
649 {
650 #ifdef HAVE_POSIX_REGEX
651 int ec;
652 char pom[PATH_MAX];
653 regex_t preg;
654
655 ec = regcomp(&preg, str, REG_EXTENDED);
656
657 if(ec)
658 {
659 xprintf(0, gettext("Error compiling regular expression : %s\n"), str);
660 regerror(ec, &preg, pom, sizeof(pom));
661 xprintf(0, "%s\n", pom);
662 }
663 regfree(&preg);
664 return !ec;
665 #elif defined(HAVE_V8_REGEX)
666 regexp *preg;
667
668 preg = regcomp(str);
669
670 if(!preg)
671 xprintf(0, gettext("Error compiling regular expression : %s\n"), str);
672 else
673 free(preg);
674 return preg != NULL;
675 #elif defined(HAVE_BSD_REGEX)
676 char *p;
677
678 p = re_comp(str);
679
680 if(p)
681 {
682 xprintf(0, gettext("Error compiling regular expression : %s\n"), str);
683 xprintf(0, "%s", p);
684 }
685 return p == NULL;
686 #elif defined(HAVE_GNU_REGEX)
687 char *p;
688 struct re_pattern_buffer preg;
689
690 preg.allocated = 0;
691 preg.buffer = NULL;
692 preg.fastmap = NULL;
693
694 if((p = re_compile_pattern(str, strlen(str), &preg)))
695 {
696 xprintf(0, gettext("Error compiling regular expression : %s\n"), str);
697 xprintf(0, "%s\n", p);
698 }
699 regfree(&preg);
700 return p == NULL;
701 #elif defined(HAVE_PCRE_REGEX)
702 pcre *re;
703 const char *errmsg = NULL;
704 int errcode = 0;
705
706 if(!(re = pcre_compile(str, 0, &errmsg, &errcode, NULL)))
707 {
708 xprintf(0, gettext("Error compiling regular expression : %s\n"), str);
709 xprintf(0, "%s\n", errmsg);
710 return -1;
711 }
712 else
713 free(re);
714
715 return re != NULL;
716 #endif
717 }
718 else
719 #endif
720 return TRUE;
721 }
722
lfname_interp_get_macro(struct lfname_lsp_interp * interp,int macro)723 const char *lfname_interp_get_macro(struct lfname_lsp_interp *interp,
724 int macro)
725 {
726 switch (macro)
727 {
728 case 'i':
729 return interp->scheme;
730 case 'p':
731 return interp->passwd;
732 case 'u':
733 return interp->user;
734 case 'h':
735 return interp->host;
736 case 'm':
737 return interp->domain;
738 case 'r':
739 return interp->port;
740 case 'd':
741 return interp->path;
742 case 'n':
743 return interp->name;
744 case 'b':
745 return interp->basename;
746 case 'e':
747 return interp->extension;
748 case 's':
749 return interp->query;
750 case 'q':
751 return interp->post_query;
752 case 'U':
753 return interp->urlstr;
754 case 'o':
755 return interp->deflt;
756 case 'M':
757 return interp->mime_type;
758 case 'E':
759 return interp->mime_type_ext;
760 }
761 return NULL;
762 }
763
lfname_check_macro(int macro)764 int lfname_check_macro(int macro)
765 {
766 return strchr("ipuhmrdnbesUoqEM", macro) != NULL;
767 }
768
769 static const struct
770 {
771 enum lfname_lsp_type type;
772 enum lfname_lsp_type rettype;
773 char *name;
774 short params;
775 enum lfname_lsp_type p1type;
776 enum lfname_lsp_type p2type;
777 enum lfname_lsp_type p3type;
778 } lfname_lsp_ftbl[] =
779 {
780 {LF_LSP_UNKNOWN, LF_LSP_UNKNOWN, NULL, 0,
781 LF_LSP_UNKNOWN, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
782 {LF_LSP_STR, LF_LSP_STR, NULL, 0,
783 LF_LSP_UNKNOWN, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
784 {LF_LSP_NUM, LF_LSP_NUM, NULL, 0,
785 LF_LSP_UNKNOWN, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
786 {LF_LSP_MACRO, LF_LSP_STR, NULL, 0,
787 LF_LSP_UNKNOWN, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
788 {LF_LSP_SUB, LF_LSP_STR, "sp ", 1,
789 LF_LSP_NUM, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
790 {LF_LSP_SC, LF_LSP_STR, "sc ", 2, LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
791 {LF_LSP_SS, LF_LSP_STR, "ss ", 3, LF_LSP_STR, LF_LSP_NUM, LF_LSP_NUM},
792 {LF_LSP_HASH, LF_LSP_NUM, "hsh ", 2, LF_LSP_STR, LF_LSP_NUM, LF_LSP_UNKNOWN},
793 {LF_LSP_MD5, LF_LSP_STR, "md5 ", 1,
794 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
795 {LF_LSP_LOWER, LF_LSP_STR, "lo ", 1,
796 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
797 {LF_LSP_UPPER, LF_LSP_STR, "up ", 1,
798 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
799 {LF_LSP_UENC, LF_LSP_STR, "ue ", 2, LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
800 {LF_LSP_UDEC, LF_LSP_STR, "ud ", 1,
801 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
802 {LF_LSP_DELCHR, LF_LSP_STR, "dc ", 2,
803 LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
804 {LF_LSP_TRCHR, LF_LSP_STR, "tc ", 3, LF_LSP_STR, LF_LSP_STR, LF_LSP_STR},
805 {LF_LSP_TRSTR, LF_LSP_STR, "ts ", 3, LF_LSP_STR, LF_LSP_STR, LF_LSP_STR},
806 {LF_LSP_STRSPN, LF_LSP_NUM, "spn ", 2,
807 LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
808 {LF_LSP_STRCSPN, LF_LSP_NUM, "cspn ", 2,
809 LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
810 {LF_LSP_STRLEN, LF_LSP_NUM, "sl ", 1,
811 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
812 {LF_LSP_NRSTR, LF_LSP_STR, "ns ", 2, LF_LSP_STR, LF_LSP_NUM, LF_LSP_UNKNOWN},
813 {LF_LSP_LCHR, LF_LSP_NUM, "lc ", 2, LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
814 {LF_LSP_PLS, LF_LSP_NUM, "+ ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
815 {LF_LSP_MNS, LF_LSP_NUM, "- ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
816 {LF_LSP_MOD, LF_LSP_NUM, "% ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
817 {LF_LSP_MUL, LF_LSP_NUM, "* ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
818 {LF_LSP_DIV, LF_LSP_NUM, "/ ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
819 {LF_LSP_REMOVEPARAMETER, LF_LSP_STR, "rmpar ", 2,
820 LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
821 {LF_LSP_GETVALUE, LF_LSP_STR, "getval ", 2,
822 LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN},
823 {LF_LSP_SIF, LF_LSP_STR, "sif ", 3, LF_LSP_NUM, LF_LSP_STR, LF_LSP_STR},
824 {LF_LSP_NOT, LF_LSP_NUM, "! ", 1,
825 LF_LSP_NUM, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
826 {LF_LSP_AND, LF_LSP_NUM, "& ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
827 {LF_LSP_OR, LF_LSP_NUM, "| ", 2, LF_LSP_NUM, LF_LSP_NUM, LF_LSP_UNKNOWN},
828 {LF_LSP_GETEXT, LF_LSP_STR, "getext ", 1,
829 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
830 #ifdef HAVE_MOZJS
831 {LF_LSP_JSF, LF_LSP_STR, "jsf ", 1,
832 LF_LSP_STR, LF_LSP_UNKNOWN, LF_LSP_UNKNOWN},
833 #endif
834 {LF_LSP_SEQ, LF_LSP_NUM, "seq ", 2, LF_LSP_STR, LF_LSP_STR, LF_LSP_UNKNOWN}
835 };
836
lfname_lsp_token_type(const char ** pstr)837 static enum lfname_lsp_type lfname_lsp_token_type(const char **pstr)
838 {
839 const char *p = *pstr;
840 enum lfname_lsp_type retv = LF_LSP_UNKNOWN;
841
842 while(*p == ' ')
843 p++;
844
845 if(*p == '(')
846 {
847 int i;
848 for(i = 0; i < NUM_ELEM(lfname_lsp_ftbl); i++)
849 {
850 if(lfname_lsp_ftbl[i].name &&
851 !strncmp(p + 1, lfname_lsp_ftbl[i].name,
852 strlen(lfname_lsp_ftbl[i].name)))
853 {
854 retv = lfname_lsp_ftbl[i].type;
855 p += 1 + strlen(lfname_lsp_ftbl[i].name);
856 break;
857 }
858 }
859 }
860 else if(*p == '\"')
861 {
862 retv = LF_LSP_STR;
863 p++;
864 }
865 else if(*p == '%')
866 {
867 retv = LF_LSP_MACRO;
868 p++;
869 }
870 else if(tl_ascii_isdigit(*p) || *p == '-')
871 retv = LF_LSP_NUM;
872
873 *pstr = p;
874
875 return retv;
876 }
877
lfname_lsp_var_new(enum lfname_lsp_type type)878 static struct lfname_lsp_var *lfname_lsp_var_new(enum lfname_lsp_type type)
879 {
880 struct lfname_lsp_var *retv = NULL;
881
882 retv = _malloc(sizeof(struct lfname_lsp_var));
883 retv->type = type;
884 retv->val.str = NULL;
885 retv->rettype = lfname_lsp_ftbl[type].rettype;
886 retv->ret_val.str = NULL;
887 retv->param1 = NULL;
888 retv->param2 = NULL;
889 retv->param3 = NULL;
890
891 return retv;
892 }
893
lfname_lsp_var_ret_free(struct lfname_lsp_var * var)894 static void lfname_lsp_var_ret_free(struct lfname_lsp_var *var)
895 {
896 if(!var)
897 return;
898
899 lfname_lsp_var_ret_free(var->param1);
900 lfname_lsp_var_ret_free(var->param2);
901 lfname_lsp_var_ret_free(var->param3);
902 if(var->rettype == LF_LSP_STR)
903 _free(var->ret_val.str);
904 }
905
lfname_lsp_var_free(struct lfname_lsp_var * var)906 static void lfname_lsp_var_free(struct lfname_lsp_var *var)
907 {
908 if(!var)
909 return;
910
911 lfname_lsp_var_free(var->param1);
912 lfname_lsp_var_free(var->param2);
913 lfname_lsp_var_free(var->param3);
914 if(var->type == LF_LSP_STR)
915 _free(var->val.str);
916 _free(var);
917 }
918
lfname_lsp_analyze(const char ** pstr)919 static struct lfname_lsp_var *lfname_lsp_analyze(const char **pstr)
920 {
921 struct lfname_lsp_var *retv = NULL;
922 enum lfname_lsp_type type;
923 char *p;
924 const char *cp;
925
926 type = lfname_lsp_token_type(pstr);
927
928 switch (type)
929 {
930 case LF_LSP_UNKNOWN:
931 xprintf(0, gettext("LSP analyze error: bad token at - %s\n"), *pstr);
932 break;
933 case LF_LSP_NUM:
934 {
935 int nval;
936
937 errno = 0;
938 nval = strtol(*pstr, &p, 0);
939
940 if((errno == ERANGE) || (*p != '\0' && *p != ')' && *p != ' '))
941 {
942 xprintf(0, gettext("LSP analyze error: bad numeric value at - %s\n"),
943 *pstr);
944 break;
945 }
946 retv = lfname_lsp_var_new(type);
947 retv->val.num = nval;
948 *pstr = p;
949 }
950 break;
951 case LF_LSP_MACRO:
952 {
953 if(!lfname_check_macro(**pstr) ||
954 (*(*pstr + 1) != '\0' && *(*pstr + 1) != ')' && *(*pstr + 1) != ' '))
955 {
956 xprintf(0, gettext("LSP analyze error: bad macro at - %s\n"),
957 *pstr - 1);
958 break;
959 }
960 retv = lfname_lsp_var_new(type);
961 retv->val.macro = **pstr;
962 *pstr += 1;
963 }
964 break;
965 case LF_LSP_STR:
966 {
967 char *tmp = _malloc(strlen(*pstr) + 1);
968 char *tp;
969
970 cp = *pstr;
971 tp = tmp;
972
973 while(*cp)
974 {
975 if(*cp == '\"')
976 break;
977 if(*cp == '\\')
978 cp++;
979 *tp = *cp;
980 tp++;
981 if(*cp)
982 cp++;
983 }
984 *tp = '\0';
985
986 if(*cp != '\"')
987 {
988 xprintf(0,
989 gettext("LSP analyze error: unterminated string at - %s\n"),
990 *pstr - 1);
991 break;
992 }
993 retv = lfname_lsp_var_new(type);
994 retv->val.str = tl_strdup(tmp);
995 _free(tmp);
996 *pstr = cp + 1;
997 }
998 break;
999 default:
1000 {
1001 struct lfname_lsp_var *p1 = NULL;
1002 struct lfname_lsp_var *p2 = NULL;
1003 struct lfname_lsp_var *p3 = NULL;
1004 if(lfname_lsp_ftbl[type].params >= 1)
1005 {
1006 cp = *pstr;
1007 p1 = lfname_lsp_analyze(pstr);
1008 if(!p1)
1009 break;
1010 if(p1->rettype != lfname_lsp_ftbl[type].p1type)
1011 {
1012 xprintf(0,
1013 gettext("LSP analyze error: bad parameter type at - %s\n"), cp);
1014 lfname_lsp_var_free(p1);
1015 break;
1016 }
1017 }
1018 if(p1 && lfname_lsp_ftbl[type].params >= 2)
1019 {
1020 cp = *pstr;
1021 p2 = lfname_lsp_analyze(pstr);
1022 if(!p2)
1023 {
1024 lfname_lsp_var_free(p1);
1025 break;
1026 }
1027 if(p2->rettype != lfname_lsp_ftbl[type].p2type)
1028 {
1029 xprintf(0,
1030 gettext("LSP analyze error: bad parameter type at - %s\n"), cp);
1031 lfname_lsp_var_free(p1);
1032 lfname_lsp_var_free(p2);
1033 break;
1034 }
1035 }
1036 if(p2 && lfname_lsp_ftbl[type].params >= 3)
1037 {
1038 cp = *pstr;
1039 p3 = lfname_lsp_analyze(pstr);
1040 if(!p3)
1041 {
1042 lfname_lsp_var_free(p1);
1043 lfname_lsp_var_free(p2);
1044 break;
1045 }
1046 if(p3->rettype != lfname_lsp_ftbl[type].p3type)
1047 {
1048 xprintf(0,
1049 gettext("LSP analyze error: bad parameter type at - %s\n"), cp);
1050 lfname_lsp_var_free(p1);
1051 lfname_lsp_var_free(p2);
1052 lfname_lsp_var_free(p3);
1053 break;
1054 }
1055 }
1056 while(**pstr == ' ')
1057 (*pstr)++;
1058 if(**pstr != ')')
1059 {
1060 xprintf(0, gettext("LSP analyze error: bad token at - %s\n"), *pstr);
1061 if(p1)
1062 lfname_lsp_var_free(p1);
1063 if(p2)
1064 lfname_lsp_var_free(p2);
1065 if(p3)
1066 lfname_lsp_var_free(p3);
1067 }
1068 else
1069 {
1070 (*pstr)++;
1071 retv = lfname_lsp_var_new(type);
1072 retv->param1 = p1;
1073 retv->param2 = p2;
1074 retv->param3 = p3;
1075 }
1076 }
1077 break;
1078 }
1079
1080 return retv;
1081 }
1082
1083 /*
1084 Removes a parameter from an URL-String.
1085 e.g. removeparameter("myurl.php3?var=something","var") will convert the
1086 URL to "myurl.php3?"
1087 */
lfname_fn_removeparameter(char * urlstr,char * var)1088 static char *lfname_fn_removeparameter(char *urlstr, char *var)
1089 {
1090 char *p, *found;
1091 int pos1;
1092 int parlen;
1093
1094 /* &var= */
1095 p = tl_str_concat(NULL, "&", var, "=", NULL);
1096 parlen = strlen(p);
1097
1098 found = strstr(urlstr, p);
1099 if(!found)
1100 {
1101 /* ?var= */
1102 *p = '?';
1103 found = strstr(urlstr, p);
1104 if(!found)
1105 {
1106 /* var= */
1107 if((parlen > 1) && !strncmp(urlstr, p + 1, parlen - 1))
1108 {
1109 found = urlstr;
1110 }
1111 }
1112 }
1113 _free(p);
1114
1115 if(!found)
1116 return tl_strdup(urlstr);
1117
1118 pos1 = found - urlstr + 1;
1119
1120 found = strstr((urlstr + pos1 + 1), "&");
1121 if(!found)
1122 {
1123 return tl_strndup(urlstr, pos1 - 1);
1124 }
1125
1126 urlstr = tl_strndup(urlstr, pos1);
1127
1128 return tl_str_concat(urlstr, found + 1, NULL);
1129 }
1130
1131 /*
1132 reads a value from parameter of an URL-String.
1133 e.g. lfname_fn_getvalue("myurl.php3?var=value","var") results in value
1134 */
lfname_fn_getvalue(char * urlstr,char * var)1135 static char *lfname_fn_getvalue(char *urlstr, char *var)
1136 {
1137 char *p, *found;
1138 int parlen;
1139
1140 /* &var= */
1141 p = tl_str_concat(NULL, "&", var, "=", NULL);
1142 parlen = strlen(p);
1143
1144 found = strstr(urlstr, p);
1145 if(!found)
1146 {
1147 /* ?var= */
1148 *p = '?';
1149 found = strstr(urlstr, p);
1150 if(!found)
1151 {
1152 /* var= */
1153 if((parlen > 1) && !strncmp(urlstr, p + 1, parlen - 1))
1154 {
1155 parlen--;
1156 found = urlstr;
1157 }
1158 }
1159 }
1160 _free(p);
1161
1162 if(!found)
1163 return tl_strdup("");
1164
1165 return tl_strndup(found + parlen, strcspn(found + parlen, "&"));
1166 }
1167
lfname_lsp_eval(struct lfname_lsp_interp * interp,struct lfname_lsp_var * var)1168 static int lfname_lsp_eval(struct lfname_lsp_interp *interp,
1169 struct lfname_lsp_var *var)
1170 {
1171 if(var->param1)
1172 lfname_lsp_eval(interp, var->param1);
1173 if(var->param2)
1174 lfname_lsp_eval(interp, var->param2);
1175 if(var->param3)
1176 lfname_lsp_eval(interp, var->param3);
1177
1178 var->ret_val.str = NULL;
1179
1180 switch (var->type)
1181 {
1182 case LF_LSP_UNKNOWN:
1183 break;
1184 case LF_LSP_STR:
1185 var->ret_val.str = tl_strdup(var->val.str);
1186 break;
1187 case LF_LSP_NUM:
1188 var->ret_val.num = var->val.num;
1189 break;
1190 case LF_LSP_MACRO:
1191 var->ret_val.str =
1192 tl_strdup(lfname_interp_get_macro(interp, var->val.macro));
1193 break;
1194 case LF_LSP_SUB:
1195 #ifdef HAVE_REGEX
1196 var->ret_val.str = lfname_re_sub(interp->orig,
1197 interp->urlstr, var->param1->ret_val.num);
1198 #endif
1199 break;
1200 case LF_LSP_SC:
1201 {
1202 char *p;
1203 p =
1204 _malloc(strlen(var->param1->ret_val.str) +
1205 strlen(var->param2->ret_val.str) + 1);
1206 strcpy(p, var->param1->ret_val.str);
1207 strcat(p, var->param2->ret_val.str);
1208 var->ret_val.str = p;
1209 }
1210 break;
1211 case LF_LSP_SS:
1212 {
1213 char *p;
1214 p = var->param1->ret_val.str;
1215 if(var->param2->ret_val.num > 0)
1216 p +=
1217 (strlen(p) >=
1218 var->param2->ret_val.num) ? var->param2->ret_val.num : strlen(p);
1219 if(var->param3->ret_val.num > 0)
1220 var->ret_val.str = tl_strndup(p, var->param3->ret_val.num);
1221 else
1222 var->ret_val.str = tl_strdup(p);
1223 }
1224 break;
1225 case LF_LSP_HASH:
1226 var->ret_val.num = str_hash_func(var->param2->ret_val.num,
1227 (dllist_t) var->param1->ret_val.str);
1228 break;
1229 case LF_LSP_MD5:
1230 var->ret_val.str = _md5(var->param1->ret_val.str);
1231 break;
1232 case LF_LSP_LOWER:
1233 var->ret_val.str = lowerstr(var->param1->ret_val.str);
1234 break;
1235 case LF_LSP_UPPER:
1236 var->ret_val.str = upperstr(var->param1->ret_val.str);
1237 break;
1238 case LF_LSP_UENC:
1239 var->ret_val.str = url_encode_str(var->param1->ret_val.str,
1240 var->param2->ret_val.str);
1241 break;
1242 case LF_LSP_UDEC:
1243 var->ret_val.str = url_decode_str(var->param1->ret_val.str,
1244 strlen(var->param1->ret_val.str));
1245 break;
1246 case LF_LSP_DELCHR:
1247 var->ret_val.str = tr_del_chr(var->param2->ret_val.str,
1248 var->param1->ret_val.str);
1249 break;
1250 case LF_LSP_TRCHR:
1251 var->ret_val.str = tr_chr_chr(var->param2->ret_val.str,
1252 var->param3->ret_val.str, var->param1->ret_val.str);
1253 break;
1254 case LF_LSP_TRSTR:
1255 var->ret_val.str = tr_str_str(var->param2->ret_val.str,
1256 var->param3->ret_val.str, var->param1->ret_val.str);
1257 break;
1258 case LF_LSP_STRSPN:
1259 var->ret_val.num = strspn(var->param1->ret_val.str,
1260 var->param2->ret_val.str);
1261 break;
1262 case LF_LSP_STRCSPN:
1263 var->ret_val.num = strcspn(var->param1->ret_val.str,
1264 var->param2->ret_val.str);
1265 break;
1266 case LF_LSP_STRLEN:
1267 var->ret_val.num = strlen(var->param1->ret_val.str);
1268 break;
1269 case LF_LSP_NRSTR:
1270 {
1271 char pom[1024];
1272 snprintf(pom, sizeof(pom), var->param1->ret_val.str, var->param2->ret_val.num);
1273 var->ret_val.str = tl_strdup(pom);
1274 }
1275 break;
1276 case LF_LSP_LCHR:
1277 {
1278 char *p;
1279 p = strrchr(var->param1->ret_val.str, *var->param2->ret_val.str);
1280 var->ret_val.num = p ? p - var->param1->ret_val.str : 0;
1281 }
1282 break;
1283 case LF_LSP_PLS:
1284 var->ret_val.num = var->param1->ret_val.num + var->param2->ret_val.num;
1285 break;
1286 case LF_LSP_MNS:
1287 var->ret_val.num = var->param1->ret_val.num - var->param2->ret_val.num;
1288 break;
1289 case LF_LSP_MOD:
1290 var->ret_val.num = var->param1->ret_val.num % var->param2->ret_val.num;
1291 break;
1292 case LF_LSP_MUL:
1293 var->ret_val.num = var->param1->ret_val.num * var->param2->ret_val.num;
1294 break;
1295 case LF_LSP_DIV:
1296 var->ret_val.num = var->param1->ret_val.num / var->param2->ret_val.num;
1297 break;
1298 case LF_LSP_REMOVEPARAMETER:
1299 var->ret_val.str =
1300 lfname_fn_removeparameter(var->param1->ret_val.str,
1301 var->param2->ret_val.str);
1302 break;
1303 case LF_LSP_GETVALUE:
1304 var->ret_val.str =
1305 lfname_fn_getvalue(var->param1->ret_val.str, var->param2->ret_val.str);
1306 break;
1307 case LF_LSP_SIF:
1308 var->ret_val.str = var->param1->ret_val.num ?
1309 tl_strdup(var->param2->ret_val.str) :
1310 tl_strdup(var->param3->ret_val.str);
1311 break;
1312 case LF_LSP_NOT:
1313 var->ret_val.num = !var->param1->ret_val.num;
1314 break;
1315 case LF_LSP_AND:
1316 var->ret_val.num = var->param1->ret_val.num && var->param2->ret_val.num;
1317 break;
1318 case LF_LSP_OR:
1319 var->ret_val.num = var->param1->ret_val.num || var->param2->ret_val.num;
1320 break;
1321 case LF_LSP_GETEXT:
1322 var->ret_val.str = tl_strdup(tl_get_extension(var->param1->ret_val.str));
1323 break;
1324 case LF_LSP_SEQ:
1325 var->ret_val.num = !strcmp(var->param1->ret_val.str,
1326 var->param2->ret_val.str);
1327 break;
1328 #ifdef HAVE_MOZJS
1329 case LF_LSP_JSF:
1330 var->ret_val.str = pjs_run_fnrules_func(var->param1->ret_val.str, interp);
1331 break;
1332 #endif
1333 }
1334 if(var->rettype == LF_LSP_STR && !var->ret_val.str)
1335 var->ret_val.str = tl_strdup("");
1336
1337 return 0;
1338 }
1339
lfname_lsp_get_by_url(struct lfname_lsp_interp * interp)1340 static char *lfname_lsp_get_by_url(struct lfname_lsp_interp *interp)
1341 {
1342 char *retv = NULL;
1343 struct lfname_lsp_var *variant;
1344 const char *p;
1345 p = interp->orig->transstr;
1346
1347 variant = lfname_lsp_analyze(&p);
1348
1349 if(variant)
1350 {
1351 lfname_lsp_eval(interp, variant);
1352 if(variant->rettype == LF_LSP_NUM)
1353 {
1354 char nr[10];
1355 sprintf(nr, "%d", variant->ret_val.num);
1356 retv = tl_strdup(nr);
1357 }
1358 else
1359 {
1360 retv = tl_strdup(variant->ret_val.str);
1361 }
1362 lfname_lsp_var_free(variant);
1363 }
1364
1365 return retv;
1366 }
1367