]> git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/template.c
Copyright update...
[thirdparty/cups.git] / cgi-bin / template.c
1 /*
2 * "$Id: template.c,v 1.25 2002/01/02 17:58:37 mike Exp $"
3 *
4 * CGI template function.
5 *
6 * Copyright 1997-2002 by Easy Software Products.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * Contents:
23 *
24 * cgiCopyTemplateFile() - Copy a template file and replace all the
25 * '{variable}' strings with the variable value.
26 * cgiCopyTemplateLang() - Copy a template file using a language...
27 * cgi_copy() - Copy the template file, substituting as needed...
28 * cgi_puts() - Put a string to the output file, quoting as
29 * needed...
30 */
31
32 #include "cgi.h"
33
34
35 /*
36 * Local functions...
37 */
38
39 static void cgi_copy(FILE *out, FILE *in, int element, char term);
40 static void cgi_puts(const char *s, FILE *out);
41
42
43 /*
44 * 'cgiCopyTemplateFile()' - Copy a template file and replace all the
45 * '{variable}' strings with the variable value.
46 */
47
48 void
49 cgiCopyTemplateFile(FILE *out, /* I - Output file */
50 const char *tmpl) /* I - Template file to read */
51 {
52 FILE *in; /* Input file */
53
54
55 /*
56 * Open the template file...
57 */
58
59 if ((in = fopen(tmpl, "r")) == NULL)
60 return;
61
62 /*
63 * Parse the file to the end...
64 */
65
66 cgi_copy(out, in, 0, 0);
67
68 /*
69 * Close the template file and return...
70 */
71
72 fclose(in);
73 }
74
75
76 /*
77 * 'cgiCopyTemplateLang()' - Copy a template file using a language...
78 */
79
80 void
81 cgiCopyTemplateLang(FILE *out, /* I - Output file */
82 const char *directory, /* I - Directory */
83 const char *tmpl, /* I - Base filename */
84 const char *lang) /* I - Language */
85 {
86 int i; /* Looping var */
87 char filename[1024], /* Filename */
88 locale[16]; /* Locale name */
89 FILE *in; /* Input file */
90
91
92 /*
93 * Convert the language to a locale name...
94 */
95
96 if (lang != NULL)
97 {
98 for (i = 0; lang[i] && i < 15; i ++)
99 if (isalnum(lang[i]))
100 locale[i] = tolower(lang[i]);
101 else
102 locale[i] = '_';
103
104 locale[i] = '\0';
105 }
106 else
107 locale[0] = '\0';
108
109 /*
110 * See if we have a template file for this language...
111 */
112
113 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
114 if (access(filename, 0))
115 {
116 locale[2] = '\0';
117
118 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
119 if (access(filename, 0))
120 snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl);
121 }
122
123 /*
124 * Open the template file...
125 */
126
127 if ((in = fopen(filename, "r")) == NULL)
128 return;
129
130 /*
131 * Parse the file to the end...
132 */
133
134 cgi_copy(out, in, 0, 0);
135
136 /*
137 * Close the template file and return...
138 */
139
140 fclose(in);
141 }
142
143
144 /*
145 * 'cgi_copy()' - Copy the template file, substituting as needed...
146 */
147
148 static void
149 cgi_copy(FILE *out, /* I - Output file */
150 FILE *in, /* I - Input file */
151 int element, /* I - Element number (0 to N) */
152 char term) /* I - Terminating character */
153 {
154 int ch; /* Character from file */
155 char op; /* Operation */
156 char name[255], /* Name of variable */
157 *nameptr, /* Pointer into name */
158 innername[255], /* Inner comparison name */
159 *innerptr, /* Pointer into inner name */
160 *s; /* String pointer */
161 const char *value; /* Value of variable */
162 const char *innerval; /* Inner value */
163 const char *outptr; /* Output string pointer */
164 char outval[1024], /* Formatted output string */
165 compare[1024]; /* Comparison string */
166 int result; /* Result of comparison */
167
168
169 /*
170 * Parse the file to the end...
171 */
172
173 while ((ch = getc(in)) != EOF)
174 if (ch == term)
175 break;
176 else if (ch == '{')
177 {
178 /*
179 * Get a variable name...
180 */
181
182 for (s = name; (ch = getc(in)) != EOF;)
183 if (strchr("}]<>=! \t\n", ch))
184 break;
185 else if (s > name && ch == '?')
186 break;
187 else if (s < (name + sizeof(name) - 1))
188 *s++ = ch;
189
190 *s = '\0';
191
192 if (s == name && isspace(ch))
193 {
194 if (out)
195 {
196 putc('{', out);
197 putc(ch, out);
198 }
199
200 continue;
201 }
202
203 /*
204 * See if it has a value...
205 */
206
207 if (name[0] == '?')
208 {
209 /*
210 * Insert value only if it exists...
211 */
212
213 if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1]))
214 {
215 *nameptr++ = '\0';
216
217 if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL)
218 outptr = value;
219 else
220 {
221 outval[0] = '\0';
222 outptr = outval;
223 }
224 }
225 if ((value = cgiGetArray(name + 1, element)) != NULL)
226 outptr = value;
227 else
228 {
229 outval[0] = '\0';
230 outptr = outval;
231 }
232 }
233 else if (name[0] == '#')
234 {
235 /*
236 * Insert count...
237 */
238
239 if (name[1])
240 sprintf(outval, "%d", cgiGetSize(name + 1));
241 else
242 sprintf(outval, "%d", element + 1);
243
244 outptr = outval;
245 }
246 else if (name[0] == '[')
247 {
248 /*
249 * Loop for # of elements...
250 */
251
252 int i; /* Looping var */
253 long pos; /* File position */
254 int count; /* Number of elements */
255
256
257 if (isdigit(name[1]))
258 count = atoi(name + 1);
259 else
260 count = cgiGetSize(name + 1);
261
262 pos = ftell(in);
263
264 if (count > 0)
265 {
266 for (i = 0; i < count; i ++)
267 {
268 fseek(in, pos, SEEK_SET);
269 cgi_copy(out, in, i, '}');
270 }
271 }
272 else
273 cgi_copy(NULL, in, 0, '}');
274
275 continue;
276 }
277 else
278 {
279 /*
280 * Insert variable or variable name (if element is NULL)...
281 */
282
283 if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1]))
284 {
285 *nameptr++ = '\0';
286 if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL)
287 {
288 snprintf(outval, sizeof(outval), "{%s}", name);
289 outptr = outval;
290 }
291 else
292 outptr = value;
293 }
294 else if ((value = cgiGetArray(name, element)) == NULL)
295 {
296 snprintf(outval, sizeof(outval), "{%s}", name);
297 outptr = outval;
298 }
299 else
300 outptr = value;
301 }
302
303 /*
304 * See if the terminating character requires another test...
305 */
306
307 if (ch == '}')
308 {
309 /*
310 * End of substitution...
311 */
312
313 if (out)
314 cgi_puts(outptr, out);
315
316 continue;
317 }
318
319 /*
320 * OK, process one of the following checks:
321 *
322 * {name?exist:not-exist} Exists?
323 * {name=value?true:false} Equal
324 * {name<value?true:false} Less than
325 * {name>value?true:false} Greater than
326 * {name!value?true:false} Not equal
327 */
328
329 if (ch == '?')
330 {
331 /*
332 * Test for existance...
333 */
334
335 result = cgiGetArray(name, element) != NULL && outval[0];
336 }
337 else
338 {
339 /*
340 * Compare to a string...
341 */
342
343 op = ch;
344
345 for (s = compare; (ch = getc(in)) != EOF;)
346 if (ch == '?')
347 break;
348 else if (s >= (compare + sizeof(compare) - 1))
349 continue;
350 else if (ch == '#')
351 {
352 sprintf(s, "%d", element + 1);
353 s += strlen(s);
354 }
355 else if (ch == '{')
356 {
357 /*
358 * Grab the value of a variable...
359 */
360
361 innerptr = innername;
362 while ((ch = getc(in)) != EOF && ch != '}')
363 if (innerptr < (innername + sizeof(innername) - 1))
364 *innerptr++ = ch;
365 *innerptr = '\0';
366
367 if (innername[0] == '#')
368 sprintf(s, "%d", cgiGetSize(innername + 1));
369 else if ((innerptr = strrchr(innername, '-')) != NULL &&
370 isdigit(innerptr[1]))
371 {
372 *innerptr++ = '\0';
373 if ((innerval = cgiGetArray(innername, atoi(innerptr) - 1)) == NULL)
374 *s = '\0';
375 else
376 {
377 strncpy(s, innerval, sizeof(compare) - (s - compare) - 1);
378 compare[sizeof(compare) - 1] = '\0';
379 }
380 }
381 else if (innername[0] == '?')
382 {
383 if ((innerval = cgiGetArray(innername + 1, element)) == NULL)
384 *s = '\0';
385 else
386 {
387 strncpy(s, innerval, sizeof(compare) - (s - compare) - 1);
388 compare[sizeof(compare) - 1] = '\0';
389 }
390 }
391 else if ((innerval = cgiGetArray(innername, element)) == NULL)
392 snprintf(s, sizeof(s), "{%s}", innername);
393 else
394 {
395 strncpy(s, innerval, sizeof(compare) - (s - compare) - 1);
396 compare[sizeof(compare) - 1] = '\0';
397 }
398
399 s += strlen(s);
400 }
401 else if (ch == '\\')
402 *s++ = getc(in);
403 else
404 *s++ = ch;
405
406 *s = '\0';
407
408 if (ch != '?')
409 return;
410
411 /*
412 * Do the comparison...
413 */
414
415 switch (op)
416 {
417 case '<' :
418 result = strcasecmp(outptr, compare) < 0;
419 break;
420 case '>' :
421 result = strcasecmp(outptr, compare) > 0;
422 break;
423 case '=' :
424 result = strcasecmp(outptr, compare) == 0;
425 break;
426 case '!' :
427 result = strcasecmp(outptr, compare) != 0;
428 break;
429 default :
430 result = 1;
431 break;
432 }
433 }
434
435 if (result)
436 {
437 /*
438 * Comparison true; output first part and ignore second...
439 */
440
441 cgi_copy(out, in, element, ':');
442 cgi_copy(NULL, in, element, '}');
443 }
444 else
445 {
446 /*
447 * Comparison false; ignore first part and output second...
448 */
449
450 cgi_copy(NULL, in, element, ':');
451 cgi_copy(out, in, element, '}');
452 }
453 }
454 else if (ch == '\\') /* Quoted char */
455 {
456 if (out)
457 putc(getc(in), out);
458 else
459 getc(in);
460 }
461 else if (out)
462 putc(ch, out);
463
464 /*
465 * Flush any pending output...
466 */
467
468 if (out)
469 fflush(out);
470 }
471
472
473 /*
474 * 'cgi_puts()' - Put a string to the output file, quoting as needed...
475 */
476
477 static void
478 cgi_puts(const char *s,
479 FILE *out)
480 {
481 while (*s)
482 {
483 if (s[0] == '<')
484 fputs("&lt;", out);
485 else if (s[0] == '>')
486 fputs("&gt;", out);
487 else if (*s == '\"')
488 fputs("&quot;", out);
489 else if (s[0] == '&')
490 fputs("&amp;", out);
491 else
492 putc(*s, out);
493
494 s ++;
495 }
496 }
497
498
499 /*
500 * End of "$Id: template.c,v 1.25 2002/01/02 17:58:37 mike Exp $".
501 */