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