]>
Commit | Line | Data |
---|---|---|
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 | ||
43 | static void cgi_copy(FILE *out, FILE *in, int element, char term); | |
44 | static 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 | ||
52 | void | |
53 | cgiCopyTemplateFile(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 | ||
84 | void | |
85 | cgiCopyTemplateLang(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 | ||
153 | char * /* O - Template directory */ | |
154 | cgiGetTemplateDir(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 | ||
180 | void | |
181 | cgiSetServerVersion(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 | ||
197 | static void | |
198 | cgi_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 | ||
517 | static void | |
518 | cgi_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("&", 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("<", out); | |
556 | } | |
557 | else if (*s == '>') | |
558 | fputs(">", out); | |
559 | else if (*s == '\"') | |
560 | fputs(""", out); | |
561 | else if (*s == '&') | |
562 | fputs("&", 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 | */ |