]> git.ipfire.org Git - thirdparty/cups.git/blame - cgi-bin/template.c
Load cups into easysw/current.
[thirdparty/cups.git] / cgi-bin / template.c
CommitLineData
ef416fc2 1/*
a74454a7 2 * "$Id: template.c 5461 2006-04-25 17:15:45Z mike $"
ef416fc2 3 *
4 * CGI template function.
5 *
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * cgiCopyTemplateFile() - Copy a template file and replace all the
27 * '{variable}' strings with the variable value.
28 * cgiCopyTemplateLang() - Copy a template file using a language...
29 * cgiGetTemplateDir() - Get the templates directory...
30 * cgiSetServerVersion() - Set the server name and CUPS version...
31 * cgi_copy() - Copy the template file, substituting as needed...
32 * cgi_puts() - Put a string to the output file, quoting as
33 * needed...
34 */
35
36#include "cgi-private.h"
bd7854cb 37#include <errno.h>
ef416fc2 38
39
40/*
41 * Local functions...
42 */
43
bd7854cb 44static void cgi_copy(FILE *out, FILE *in, int element, char term,
45 int indent);
ef416fc2 46static void cgi_puts(const char *s, FILE *out);
a74454a7 47static void cgi_puturi(const char *s, FILE *out);
ef416fc2 48
49
50/*
51 * 'cgiCopyTemplateFile()' - Copy a template file and replace all the
52 * '{variable}' strings with the variable value.
53 */
54
55void
56cgiCopyTemplateFile(FILE *out, /* I - Output file */
57 const char *tmpl) /* I - Template file to read */
58{
59 FILE *in; /* Input file */
60
61
bd7854cb 62 fprintf(stderr, "DEBUG: cgiCopyTemplateFile(out=%p, tmpl=\"%s\")\n", out,
63 tmpl);
64
ef416fc2 65 /*
66 * Open the template file...
67 */
68
69 if ((in = fopen(tmpl, "r")) == NULL)
bd7854cb 70 {
71 fprintf(stderr, "ERROR: Unable to open template file \"%s\" - %s\n",
72 tmpl, strerror(errno));
ef416fc2 73 return;
bd7854cb 74 }
ef416fc2 75
76 /*
77 * Parse the file to the end...
78 */
79
bd7854cb 80 cgi_copy(out, in, 0, 0, 0);
ef416fc2 81
82 /*
83 * Close the template file and return...
84 */
85
86 fclose(in);
87}
88
89
90/*
91 * 'cgiCopyTemplateLang()' - Copy a template file using a language...
92 */
93
94void
95cgiCopyTemplateLang(const char *tmpl) /* I - Base filename */
96{
97 int i; /* Looping var */
98 char filename[1024], /* Filename */
99 locale[16]; /* Locale name */
100 const char *directory, /* Directory for templates */
101 *lang; /* Language */
102 FILE *in; /* Input file */
103
104
bd7854cb 105 fprintf(stderr, "DEBUG: cgiCopyTemplateLang(tmpl=\"%s\")\n", tmpl);
106
ef416fc2 107 /*
108 * Convert the language to a locale name...
109 */
110
111 if ((lang = getenv("LANG")) != NULL)
112 {
113 for (i = 0; lang[i] && i < 15; i ++)
d6ae789d 114 if (isalnum(lang[i] & 255) || lang[i] == '_')
ef416fc2 115 locale[i] = tolower(lang[i]);
bd7854cb 116 else if (lang[i] == '-')
ef416fc2 117 locale[i] = '_';
bd7854cb 118 else
119 break;
ef416fc2 120
121 locale[i] = '\0';
122 }
123 else
124 locale[0] = '\0';
125
bd7854cb 126 fprintf(stderr, "DEBUG: locale=\"%s\"...\n", locale);
127
ef416fc2 128 /*
129 * See if we have a template file for this language...
130 */
131
132 directory = cgiGetTemplateDir();
133
134 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
135 if (access(filename, 0))
136 {
137 locale[2] = '\0';
138
139 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
140 if (access(filename, 0))
141 snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl);
142 }
143
bd7854cb 144 fprintf(stderr, "DEBUG: Template file is \"%s\"...\n", filename);
145
ef416fc2 146 /*
147 * Open the template file...
148 */
149
150 if ((in = fopen(filename, "r")) == NULL)
bd7854cb 151 {
152 fprintf(stderr, "ERROR: Unable to open template file \"%s\" - %s\n",
153 filename, strerror(errno));
ef416fc2 154 return;
bd7854cb 155 }
ef416fc2 156
157 /*
158 * Parse the file to the end...
159 */
160
bd7854cb 161 cgi_copy(stdout, in, 0, 0, 0);
ef416fc2 162
163 /*
164 * Close the template file and return...
165 */
166
167 fclose(in);
168}
169
170
171/*
172 * 'cgiGetTemplateDir()' - Get the templates directory...
173 */
174
175char * /* O - Template directory */
176cgiGetTemplateDir(void)
177{
178 const char *datadir; /* CUPS_DATADIR env var */
179 static char templates[1024] = ""; /* Template directory */
180
181
182 if (!templates[0])
183 {
184 /*
185 * Build the template directory pathname...
186 */
187
188 if ((datadir = getenv("CUPS_DATADIR")) == NULL)
189 datadir = CUPS_DATADIR;
190
191 snprintf(templates, sizeof(templates), "%s/templates", datadir);
192 }
193
194 return (templates);
195}
196
197
198/*
199 * 'cgiSetServerVersion()' - Set the server name and CUPS version...
200 */
201
202void
203cgiSetServerVersion(void)
204{
205 cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME"));
206 cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER"));
207 cgiSetVariable("CUPS_VERSION", CUPS_SVERSION);
208
209#ifdef LC_TIME
210 setlocale(LC_TIME, "");
211#endif /* LC_TIME */
212}
213
214
215/*
216 * 'cgi_copy()' - Copy the template file, substituting as needed...
217 */
218
219static void
bd7854cb 220cgi_copy(FILE *out, /* I - Output file */
221 FILE *in, /* I - Input file */
222 int element, /* I - Element number (0 to N) */
223 char term, /* I - Terminating character */
224 int indent) /* I - Debug info indentation */
ef416fc2 225{
bd7854cb 226 int ch; /* Character from file */
227 char op; /* Operation */
228 char name[255], /* Name of variable */
229 *nameptr, /* Pointer into name */
230 innername[255], /* Inner comparison name */
231 *innerptr, /* Pointer into inner name */
232 *s; /* String pointer */
233 const char *value; /* Value of variable */
234 const char *innerval; /* Inner value */
235 const char *outptr; /* Output string pointer */
236 char outval[1024], /* Formatted output string */
237 compare[1024]; /* Comparison string */
238 int result; /* Result of comparison */
a74454a7 239 int uriencode; /* Encode as URI */
bd7854cb 240
241
242 fprintf(stderr, "DEBUG: %*sStarting at file position %ld...\n", indent, "",
243 ftell(in));
ef416fc2 244
245 /*
246 * Parse the file to the end...
247 */
248
249 while ((ch = getc(in)) != EOF)
250 if (ch == term)
251 break;
252 else if (ch == '{')
253 {
254 /*
255 * Get a variable name...
256 */
257
a74454a7 258 uriencode = 0;
259
ef416fc2 260 for (s = name; (ch = getc(in)) != EOF;)
261 if (strchr("}]<>=! \t\n", ch))
262 break;
a74454a7 263 else if (s == name && ch == '%')
264 uriencode = 1;
ef416fc2 265 else if (s > name && ch == '?')
266 break;
267 else if (s < (name + sizeof(name) - 1))
268 *s++ = ch;
269
270 *s = '\0';
271
272 if (s == name && isspace(ch & 255))
273 {
bd7854cb 274 fprintf(stderr, "DEBUG: %*sLone { at %ld...\n", indent, "", ftell(in));
275
ef416fc2 276 if (out)
277 {
278 putc('{', out);
279 putc(ch, out);
280 }
281
282 continue;
283 }
284
bd7854cb 285 if (ch == '}')
286 fprintf(stderr, "DEBUG: %*s\"{%s}\" at %ld...\n", indent, "", name,
287 ftell(in));
288
ef416fc2 289 /*
290 * See if it has a value...
291 */
292
293 if (name[0] == '?')
294 {
295 /*
296 * Insert value only if it exists...
297 */
298
299 if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255))
300 {
301 *nameptr++ = '\0';
302
303 if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL)
304 outptr = value;
305 else
306 {
307 outval[0] = '\0';
308 outptr = outval;
309 }
310 }
311 else if ((value = cgiGetArray(name + 1, element)) != NULL)
312 outptr = value;
313 else
314 {
315 outval[0] = '\0';
316 outptr = outval;
317 }
318 }
319 else if (name[0] == '#')
320 {
321 /*
322 * Insert count...
323 */
324
325 if (name[1])
326 sprintf(outval, "%d", cgiGetSize(name + 1));
327 else
328 sprintf(outval, "%d", element + 1);
329
330 outptr = outval;
331 }
332 else if (name[0] == '[')
333 {
334 /*
335 * Loop for # of elements...
336 */
337
338 int i; /* Looping var */
339 long pos; /* File position */
340 int count; /* Number of elements */
341
342
343 if (isdigit(name[1] & 255))
344 count = atoi(name + 1);
345 else
346 count = cgiGetSize(name + 1);
347
348 pos = ftell(in);
349
bd7854cb 350 fprintf(stderr, "DEBUG: %*sLooping on \"%s\" at %ld, count=%d...\n",
351 indent, "", name + 1, pos, count);
352
ef416fc2 353 if (count > 0)
354 {
355 for (i = 0; i < count; i ++)
356 {
bd7854cb 357 if (i)
358 fseek(in, pos, SEEK_SET);
359
360 cgi_copy(out, in, i, '}', indent + 2);
ef416fc2 361 }
362 }
363 else
bd7854cb 364 cgi_copy(NULL, in, 0, '}', indent + 2);
365
366 fprintf(stderr, "DEBUG: %*sFinished looping on \"%s\"...\n", indent,
367 "", name + 1);
ef416fc2 368
369 continue;
370 }
371 else
372 {
373 /*
374 * Insert variable or variable name (if element is NULL)...
375 */
376
377 if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255))
378 {
379 *nameptr++ = '\0';
380 if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL)
381 {
382 snprintf(outval, sizeof(outval), "{%s}", name);
383 outptr = outval;
384 }
385 else
386 outptr = value;
387 }
388 else if ((value = cgiGetArray(name, element)) == NULL)
389 {
390 snprintf(outval, sizeof(outval), "{%s}", name);
391 outptr = outval;
392 }
393 else
394 outptr = value;
395 }
396
397 /*
398 * See if the terminating character requires another test...
399 */
400
401 if (ch == '}')
402 {
403 /*
404 * End of substitution...
405 */
406
407 if (out)
a74454a7 408 {
409 if (uriencode)
410 cgi_puturi(outptr, out);
411 else
412 cgi_puts(outptr, out);
413 }
ef416fc2 414
415 continue;
416 }
417
418 /*
419 * OK, process one of the following checks:
420 *
421 * {name?exist:not-exist} Exists?
422 * {name=value?true:false} Equal
423 * {name<value?true:false} Less than
424 * {name>value?true:false} Greater than
425 * {name!value?true:false} Not equal
426 */
427
bd7854cb 428 op = ch;
429
ef416fc2 430 if (ch == '?')
431 {
432 /*
433 * Test for existance...
434 */
435
bd7854cb 436 result = cgiGetArray(name, element) != NULL && outptr[0];
437 compare[0] = '\0';
ef416fc2 438 }
439 else
440 {
441 /*
442 * Compare to a string...
443 */
444
ef416fc2 445 for (s = compare; (ch = getc(in)) != EOF;)
446 if (ch == '?')
447 break;
448 else if (s >= (compare + sizeof(compare) - 1))
449 continue;
450 else if (ch == '#')
451 {
452 sprintf(s, "%d", element + 1);
453 s += strlen(s);
454 }
455 else if (ch == '{')
456 {
457 /*
458 * Grab the value of a variable...
459 */
460
461 innerptr = innername;
462 while ((ch = getc(in)) != EOF && ch != '}')
463 if (innerptr < (innername + sizeof(innername) - 1))
464 *innerptr++ = ch;
465 *innerptr = '\0';
466
467 if (innername[0] == '#')
468 sprintf(s, "%d", cgiGetSize(innername + 1));
469 else if ((innerptr = strrchr(innername, '-')) != NULL &&
470 isdigit(innerptr[1] & 255))
471 {
472 *innerptr++ = '\0';
473 if ((innerval = cgiGetArray(innername, atoi(innerptr) - 1)) == NULL)
474 *s = '\0';
475 else
476 strlcpy(s, innerval, sizeof(compare) - (s - compare));
477 }
478 else if (innername[0] == '?')
479 {
480 if ((innerval = cgiGetArray(innername + 1, element)) == NULL)
481 *s = '\0';
482 else
483 strlcpy(s, innerval, sizeof(compare) - (s - compare));
484 }
485 else if ((innerval = cgiGetArray(innername, element)) == NULL)
486 snprintf(s, sizeof(compare) - (s - compare), "{%s}", innername);
487 else
488 strlcpy(s, innerval, sizeof(compare) - (s - compare));
489
490 s += strlen(s);
491 }
492 else if (ch == '\\')
493 *s++ = getc(in);
494 else
495 *s++ = ch;
496
497 *s = '\0';
498
499 if (ch != '?')
bd7854cb 500 {
501 fprintf(stderr,
502 "DEBUG: %*sBad terminator '%c' at file position %ld...\n",
503 indent, "", ch, ftell(in));
ef416fc2 504 return;
bd7854cb 505 }
ef416fc2 506
507 /*
508 * Do the comparison...
509 */
510
511 switch (op)
512 {
513 case '<' :
514 result = strcasecmp(outptr, compare) < 0;
515 break;
516 case '>' :
517 result = strcasecmp(outptr, compare) > 0;
518 break;
519 case '=' :
520 result = strcasecmp(outptr, compare) == 0;
521 break;
522 case '!' :
523 result = strcasecmp(outptr, compare) != 0;
524 break;
525 default :
526 result = 1;
527 break;
528 }
529 }
530
bd7854cb 531 fprintf(stderr,
532 "DEBUG: %*sStarting \"{%s%c%s\" at %ld, result=%d...\n",
533 indent, "", name, op, compare, ftell(in), result);
534
ef416fc2 535 if (result)
536 {
537 /*
538 * Comparison true; output first part and ignore second...
539 */
540
bd7854cb 541 fprintf(stderr, "DEBUG: %*sOutput first part...\n", indent, "");
542 cgi_copy(out, in, element, ':', indent + 2);
543
544 fprintf(stderr, "DEBUG: %*sSkip second part...\n", indent, "");
545 cgi_copy(NULL, in, element, '}', indent + 2);
ef416fc2 546 }
547 else
548 {
549 /*
550 * Comparison false; ignore first part and output second...
551 */
552
bd7854cb 553 fprintf(stderr, "DEBUG: %*sSkip first part...\n", indent, "");
554 cgi_copy(NULL, in, element, ':', indent + 2);
555
556 fprintf(stderr, "DEBUG: %*sOutput second part...\n", indent, "");
557 cgi_copy(out, in, element, '}', indent + 2);
ef416fc2 558 }
bd7854cb 559
560 fprintf(stderr, "DEBUG: %*sFinished \"{%s%c%s\", out=%p...\n", indent, "",
561 name, op, compare, out);
ef416fc2 562 }
563 else if (ch == '\\') /* Quoted char */
564 {
565 if (out)
566 putc(getc(in), out);
567 else
568 getc(in);
569 }
570 else if (out)
571 putc(ch, out);
572
bd7854cb 573 if (ch == EOF)
574 fprintf(stderr, "DEBUG: %*sReturning at file position %ld on EOF...\n",
575 indent, "", ftell(in));
576 else
577 fprintf(stderr,
578 "DEBUG: %*sReturning at file position %ld on character '%c'...\n",
579 indent, "", ftell(in), ch);
580
581 if (ch == EOF && term)
582 fprintf(stderr, "ERROR: %*sSaw EOF, expected '%c'!\n", indent, "", term);
583
ef416fc2 584 /*
585 * Flush any pending output...
586 */
587
588 if (out)
589 fflush(out);
590}
591
592
593/*
594 * 'cgi_puts()' - Put a string to the output file, quoting as needed...
595 */
596
597static void
598cgi_puts(const char *s, /* I - String to output */
599 FILE *out) /* I - Output file */
600{
601 while (*s)
602 {
603 if (*s == '<')
604 {
605 /*
606 * Pass <A HREF="url"> and </A>, otherwise quote it...
607 */
608
609 if (!strncasecmp(s, "<A HREF=\"", 9))
610 {
611 fputs("<A HREF=\"", out);
612 s += 9;
613
614 while (*s && *s != '\"')
615 {
616 if (*s == '&')
617 fputs("&amp;", out);
618 else
619 putc(*s, out);
620
621 s ++;
622 }
623
624 if (*s)
625 s ++;
626
627 fputs("\">", out);
628 }
629 else if (!strncasecmp(s, "</A>", 4))
630 {
631 fputs("</A>", out);
632 s += 3;
633 }
634 else
635 fputs("&lt;", out);
636 }
637 else if (*s == '>')
638 fputs("&gt;", out);
639 else if (*s == '\"')
640 fputs("&quot;", out);
641 else if (*s == '&')
642 fputs("&amp;", out);
643 else
644 putc(*s, out);
645
646 s ++;
647 }
648}
649
650
651/*
a74454a7 652 * 'cgi_puturi()' - Put a URI string to the output file, quoting as needed...
653 */
654
655static void
656cgi_puturi(const char *s, /* I - String to output */
657 FILE *out) /* I - Output file */
658{
659 while (*s)
660 {
661 if (strchr("%&+ <>#=", *s) || *s & 128)
662 fprintf(out, "%%%02X", *s & 255);
663 else
664 putc(*s, out);
665
666 s ++;
667 }
668}
669
670
671/*
672 * End of "$Id: template.c 5461 2006-04-25 17:15:45Z mike $".
ef416fc2 673 */