]> 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/*
2 * "$Id: template.c 4921 2006-01-12 21:26:26Z mike $"
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"
37
38
39/*
40 * Local functions...
41 */
42
43static void cgi_copy(FILE *out, FILE *in, int element, char term);
44static void cgi_puts(const char *s, FILE *out);
45
46
47/*
48 * 'cgiCopyTemplateFile()' - Copy a template file and replace all the
49 * '{variable}' strings with the variable value.
50 */
51
52void
53cgiCopyTemplateFile(FILE *out, /* I - Output file */
54 const char *tmpl) /* I - Template file to read */
55{
56 FILE *in; /* Input file */
57
58
59 /*
60 * Open the template file...
61 */
62
63 if ((in = fopen(tmpl, "r")) == NULL)
64 return;
65
66 /*
67 * Parse the file to the end...
68 */
69
70 cgi_copy(out, in, 0, 0);
71
72 /*
73 * Close the template file and return...
74 */
75
76 fclose(in);
77}
78
79
80/*
81 * 'cgiCopyTemplateLang()' - Copy a template file using a language...
82 */
83
84void
85cgiCopyTemplateLang(const char *tmpl) /* I - Base filename */
86{
87 int i; /* Looping var */
88 char filename[1024], /* Filename */
89 locale[16]; /* Locale name */
90 const char *directory, /* Directory for templates */
91 *lang; /* Language */
92 FILE *in; /* Input file */
93
94
95 /*
96 * Convert the language to a locale name...
97 */
98
99 if ((lang = getenv("LANG")) != NULL)
100 {
101 for (i = 0; lang[i] && i < 15; i ++)
102 if (isalnum(lang[i] & 255))
103 locale[i] = tolower(lang[i]);
104 else
105 locale[i] = '_';
106
107 locale[i] = '\0';
108 }
109 else
110 locale[0] = '\0';
111
112 /*
113 * See if we have a template file for this language...
114 */
115
116 directory = cgiGetTemplateDir();
117
118 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
119 if (access(filename, 0))
120 {
121 locale[2] = '\0';
122
123 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
124 if (access(filename, 0))
125 snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl);
126 }
127
128 /*
129 * Open the template file...
130 */
131
132 if ((in = fopen(filename, "r")) == NULL)
133 return;
134
135 /*
136 * Parse the file to the end...
137 */
138
139 cgi_copy(stdout, in, 0, 0);
140
141 /*
142 * Close the template file and return...
143 */
144
145 fclose(in);
146}
147
148
149/*
150 * 'cgiGetTemplateDir()' - Get the templates directory...
151 */
152
153char * /* O - Template directory */
154cgiGetTemplateDir(void)
155{
156 const char *datadir; /* CUPS_DATADIR env var */
157 static char templates[1024] = ""; /* Template directory */
158
159
160 if (!templates[0])
161 {
162 /*
163 * Build the template directory pathname...
164 */
165
166 if ((datadir = getenv("CUPS_DATADIR")) == NULL)
167 datadir = CUPS_DATADIR;
168
169 snprintf(templates, sizeof(templates), "%s/templates", datadir);
170 }
171
172 return (templates);
173}
174
175
176/*
177 * 'cgiSetServerVersion()' - Set the server name and CUPS version...
178 */
179
180void
181cgiSetServerVersion(void)
182{
183 cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME"));
184 cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER"));
185 cgiSetVariable("CUPS_VERSION", CUPS_SVERSION);
186
187#ifdef LC_TIME
188 setlocale(LC_TIME, "");
189#endif /* LC_TIME */
190}
191
192
193/*
194 * 'cgi_copy()' - Copy the template file, substituting as needed...
195 */
196
197static void
198cgi_copy(FILE *out, /* I - Output file */
199 FILE *in, /* I - Input file */
200 int element, /* I - Element number (0 to N) */
201 char term) /* I - Terminating character */
202{
203 int ch; /* Character from file */
204 char op; /* Operation */
205 char name[255], /* Name of variable */
206 *nameptr, /* Pointer into name */
207 innername[255], /* Inner comparison name */
208 *innerptr, /* Pointer into inner name */
209 *s; /* String pointer */
210 const char *value; /* Value of variable */
211 const char *innerval; /* Inner value */
212 const char *outptr; /* Output string pointer */
213 char outval[1024], /* Formatted output string */
214 compare[1024]; /* Comparison string */
215 int result; /* Result of comparison */
216
217
218 /*
219 * Parse the file to the end...
220 */
221
222 while ((ch = getc(in)) != EOF)
223 if (ch == term)
224 break;
225 else if (ch == '{')
226 {
227 /*
228 * Get a variable name...
229 */
230
231 for (s = name; (ch = getc(in)) != EOF;)
232 if (strchr("}]<>=! \t\n", ch))
233 break;
234 else if (s > name && ch == '?')
235 break;
236 else if (s < (name + sizeof(name) - 1))
237 *s++ = ch;
238
239 *s = '\0';
240
241 if (s == name && isspace(ch & 255))
242 {
243 if (out)
244 {
245 putc('{', out);
246 putc(ch, out);
247 }
248
249 continue;
250 }
251
252 /*
253 * See if it has a value...
254 */
255
256 if (name[0] == '?')
257 {
258 /*
259 * Insert value only if it exists...
260 */
261
262 if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255))
263 {
264 *nameptr++ = '\0';
265
266 if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL)
267 outptr = value;
268 else
269 {
270 outval[0] = '\0';
271 outptr = outval;
272 }
273 }
274 else if ((value = cgiGetArray(name + 1, element)) != NULL)
275 outptr = value;
276 else
277 {
278 outval[0] = '\0';
279 outptr = outval;
280 }
281 }
282 else if (name[0] == '#')
283 {
284 /*
285 * Insert count...
286 */
287
288 if (name[1])
289 sprintf(outval, "%d", cgiGetSize(name + 1));
290 else
291 sprintf(outval, "%d", element + 1);
292
293 outptr = outval;
294 }
295 else if (name[0] == '[')
296 {
297 /*
298 * Loop for # of elements...
299 */
300
301 int i; /* Looping var */
302 long pos; /* File position */
303 int count; /* Number of elements */
304
305
306 if (isdigit(name[1] & 255))
307 count = atoi(name + 1);
308 else
309 count = cgiGetSize(name + 1);
310
311 pos = ftell(in);
312
313 if (count > 0)
314 {
315 for (i = 0; i < count; i ++)
316 {
317 fseek(in, pos, SEEK_SET);
318 cgi_copy(out, in, i, '}');
319 }
320 }
321 else
322 cgi_copy(NULL, in, 0, '}');
323
324 continue;
325 }
326 else
327 {
328 /*
329 * Insert variable or variable name (if element is NULL)...
330 */
331
332 if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255))
333 {
334 *nameptr++ = '\0';
335 if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL)
336 {
337 snprintf(outval, sizeof(outval), "{%s}", name);
338 outptr = outval;
339 }
340 else
341 outptr = value;
342 }
343 else if ((value = cgiGetArray(name, element)) == NULL)
344 {
345 snprintf(outval, sizeof(outval), "{%s}", name);
346 outptr = outval;
347 }
348 else
349 outptr = value;
350 }
351
352 /*
353 * See if the terminating character requires another test...
354 */
355
356 if (ch == '}')
357 {
358 /*
359 * End of substitution...
360 */
361
362 if (out)
363 cgi_puts(outptr, out);
364
365 continue;
366 }
367
368 /*
369 * OK, process one of the following checks:
370 *
371 * {name?exist:not-exist} Exists?
372 * {name=value?true:false} Equal
373 * {name<value?true:false} Less than
374 * {name>value?true:false} Greater than
375 * {name!value?true:false} Not equal
376 */
377
378 if (ch == '?')
379 {
380 /*
381 * Test for existance...
382 */
383
384 result = cgiGetArray(name, element) != NULL && outptr[0];
385 }
386 else
387 {
388 /*
389 * Compare to a string...
390 */
391
392 op = ch;
393
394 for (s = compare; (ch = getc(in)) != EOF;)
395 if (ch == '?')
396 break;
397 else if (s >= (compare + sizeof(compare) - 1))
398 continue;
399 else if (ch == '#')
400 {
401 sprintf(s, "%d", element + 1);
402 s += strlen(s);
403 }
404 else if (ch == '{')
405 {
406 /*
407 * Grab the value of a variable...
408 */
409
410 innerptr = innername;
411 while ((ch = getc(in)) != EOF && ch != '}')
412 if (innerptr < (innername + sizeof(innername) - 1))
413 *innerptr++ = ch;
414 *innerptr = '\0';
415
416 if (innername[0] == '#')
417 sprintf(s, "%d", cgiGetSize(innername + 1));
418 else if ((innerptr = strrchr(innername, '-')) != NULL &&
419 isdigit(innerptr[1] & 255))
420 {
421 *innerptr++ = '\0';
422 if ((innerval = cgiGetArray(innername, atoi(innerptr) - 1)) == NULL)
423 *s = '\0';
424 else
425 strlcpy(s, innerval, sizeof(compare) - (s - compare));
426 }
427 else if (innername[0] == '?')
428 {
429 if ((innerval = cgiGetArray(innername + 1, element)) == NULL)
430 *s = '\0';
431 else
432 strlcpy(s, innerval, sizeof(compare) - (s - compare));
433 }
434 else if ((innerval = cgiGetArray(innername, element)) == NULL)
435 snprintf(s, sizeof(compare) - (s - compare), "{%s}", innername);
436 else
437 strlcpy(s, innerval, sizeof(compare) - (s - compare));
438
439 s += strlen(s);
440 }
441 else if (ch == '\\')
442 *s++ = getc(in);
443 else
444 *s++ = ch;
445
446 *s = '\0';
447
448 if (ch != '?')
449 return;
450
451 /*
452 * Do the comparison...
453 */
454
455 switch (op)
456 {
457 case '<' :
458 result = strcasecmp(outptr, compare) < 0;
459 break;
460 case '>' :
461 result = strcasecmp(outptr, compare) > 0;
462 break;
463 case '=' :
464 result = strcasecmp(outptr, compare) == 0;
465 break;
466 case '!' :
467 result = strcasecmp(outptr, compare) != 0;
468 break;
469 default :
470 result = 1;
471 break;
472 }
473 }
474
475 if (result)
476 {
477 /*
478 * Comparison true; output first part and ignore second...
479 */
480
481 cgi_copy(out, in, element, ':');
482 cgi_copy(NULL, in, element, '}');
483 }
484 else
485 {
486 /*
487 * Comparison false; ignore first part and output second...
488 */
489
490 cgi_copy(NULL, in, element, ':');
491 cgi_copy(out, in, element, '}');
492 }
493 }
494 else if (ch == '\\') /* Quoted char */
495 {
496 if (out)
497 putc(getc(in), out);
498 else
499 getc(in);
500 }
501 else if (out)
502 putc(ch, out);
503
504 /*
505 * Flush any pending output...
506 */
507
508 if (out)
509 fflush(out);
510}
511
512
513/*
514 * 'cgi_puts()' - Put a string to the output file, quoting as needed...
515 */
516
517static void
518cgi_puts(const char *s, /* I - String to output */
519 FILE *out) /* I - Output file */
520{
521 while (*s)
522 {
523 if (*s == '<')
524 {
525 /*
526 * Pass <A HREF="url"> and </A>, otherwise quote it...
527 */
528
529 if (!strncasecmp(s, "<A HREF=\"", 9))
530 {
531 fputs("<A HREF=\"", out);
532 s += 9;
533
534 while (*s && *s != '\"')
535 {
536 if (*s == '&')
537 fputs("&amp;", out);
538 else
539 putc(*s, out);
540
541 s ++;
542 }
543
544 if (*s)
545 s ++;
546
547 fputs("\">", out);
548 }
549 else if (!strncasecmp(s, "</A>", 4))
550 {
551 fputs("</A>", out);
552 s += 3;
553 }
554 else
555 fputs("&lt;", out);
556 }
557 else if (*s == '>')
558 fputs("&gt;", out);
559 else if (*s == '\"')
560 fputs("&quot;", out);
561 else if (*s == '&')
562 fputs("&amp;", out);
563 else
564 putc(*s, out);
565
566 s ++;
567 }
568}
569
570
571/*
572 * End of "$Id: template.c 4921 2006-01-12 21:26:26Z mike $".
573 */