]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
75bd9771 | 2 | * "$Id: template.c 7219 2008-01-14 22:00:02Z mike $" |
ef416fc2 | 3 | * |
4 | * CGI template function. | |
5 | * | |
88f9aafc | 6 | * Copyright 2007-2011 by Apple Inc. |
ef416fc2 | 7 | * Copyright 1997-2006 by Easy Software Products. |
8 | * | |
9 | * These coded instructions, statements, and computer programs are the | |
bc44d920 | 10 | * property of Apple Inc. and are protected by Federal copyright |
11 | * law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
12 | * which should have been included with this file. If this file is | |
13 | * file is missing or damaged, see the license at "http://www.cups.org/". | |
ef416fc2 | 14 | * |
15 | * Contents: | |
16 | * | |
17 | * cgiCopyTemplateFile() - Copy a template file and replace all the | |
18 | * '{variable}' strings with the variable value. | |
19 | * cgiCopyTemplateLang() - Copy a template file using a language... | |
20 | * cgiGetTemplateDir() - Get the templates directory... | |
21 | * cgiSetServerVersion() - Set the server name and CUPS version... | |
22 | * cgi_copy() - Copy the template file, substituting as needed... | |
23 | * cgi_puts() - Put a string to the output file, quoting as | |
24 | * needed... | |
25 | */ | |
26 | ||
27 | #include "cgi-private.h" | |
bd7854cb | 28 | #include <errno.h> |
2e4ff8af | 29 | #include <regex.h> |
ef416fc2 | 30 | |
31 | ||
32 | /* | |
33 | * Local functions... | |
34 | */ | |
35 | ||
bd7854cb | 36 | static void cgi_copy(FILE *out, FILE *in, int element, char term, |
37 | int indent); | |
ef416fc2 | 38 | static void cgi_puts(const char *s, FILE *out); |
a74454a7 | 39 | static void cgi_puturi(const char *s, FILE *out); |
ef416fc2 | 40 | |
41 | ||
42 | /* | |
43 | * 'cgiCopyTemplateFile()' - Copy a template file and replace all the | |
44 | * '{variable}' strings with the variable value. | |
45 | */ | |
46 | ||
47 | void | |
48 | cgiCopyTemplateFile(FILE *out, /* I - Output file */ | |
49 | const char *tmpl) /* I - Template file to read */ | |
50 | { | |
51 | FILE *in; /* Input file */ | |
52 | ||
53 | ||
355e94dc | 54 | fprintf(stderr, "DEBUG2: cgiCopyTemplateFile(out=%p, tmpl=\"%s\")\n", out, |
f301802f | 55 | tmpl ? tmpl : "(null)"); |
bd7854cb | 56 | |
91c84a35 MS |
57 | /* |
58 | * Range check input... | |
59 | */ | |
60 | ||
61 | if (!tmpl || !out) | |
62 | return; | |
63 | ||
ef416fc2 | 64 | /* |
65 | * Open the template file... | |
66 | */ | |
67 | ||
68 | if ((in = fopen(tmpl, "r")) == NULL) | |
bd7854cb | 69 | { |
70 | fprintf(stderr, "ERROR: Unable to open template file \"%s\" - %s\n", | |
f301802f | 71 | tmpl ? tmpl : "(null)", strerror(errno)); |
ef416fc2 | 72 | return; |
bd7854cb | 73 | } |
ef416fc2 | 74 | |
75 | /* | |
76 | * Parse the file to the end... | |
77 | */ | |
78 | ||
bd7854cb | 79 | cgi_copy(out, in, 0, 0, 0); |
ef416fc2 | 80 | |
81 | /* | |
82 | * Close the template file and return... | |
83 | */ | |
84 | ||
85 | fclose(in); | |
86 | } | |
87 | ||
88 | ||
89 | /* | |
90 | * 'cgiCopyTemplateLang()' - Copy a template file using a language... | |
91 | */ | |
92 | ||
93 | void | |
94 | cgiCopyTemplateLang(const char *tmpl) /* I - Base filename */ | |
95 | { | |
ef416fc2 | 96 | char filename[1024], /* Filename */ |
db1f069b MS |
97 | locale[16], /* Locale name */ |
98 | *locptr; /* Pointer into locale name */ | |
ef416fc2 | 99 | const char *directory, /* Directory for templates */ |
100 | *lang; /* Language */ | |
101 | FILE *in; /* Input file */ | |
102 | ||
103 | ||
355e94dc | 104 | fprintf(stderr, "DEBUG2: cgiCopyTemplateLang(tmpl=\"%s\")\n", |
f301802f | 105 | tmpl ? tmpl : "(null)"); |
bd7854cb | 106 | |
ef416fc2 | 107 | /* |
108 | * Convert the language to a locale name... | |
109 | */ | |
110 | ||
db1f069b MS |
111 | locale[0] = '\0'; |
112 | ||
ef416fc2 | 113 | if ((lang = getenv("LANG")) != NULL) |
114 | { | |
db1f069b MS |
115 | locale[0] = '/'; |
116 | strlcpy(locale + 1, lang, sizeof(locale) - 1); | |
ef416fc2 | 117 | |
db1f069b MS |
118 | if ((locptr = strchr(locale, '.')) != NULL) |
119 | *locptr = '\0'; /* Strip charset */ | |
ef416fc2 | 120 | } |
ef416fc2 | 121 | |
ef55b745 | 122 | fprintf(stderr, "DEBUG2: lang=\"%s\", locale=\"%s\"...\n", |
db1f069b | 123 | lang ? lang : "(null)", locale); |
bd7854cb | 124 | |
ef416fc2 | 125 | /* |
126 | * See if we have a template file for this language... | |
127 | */ | |
128 | ||
129 | directory = cgiGetTemplateDir(); | |
130 | ||
db1f069b MS |
131 | snprintf(filename, sizeof(filename), "%s%s/%s", directory, locale, tmpl); |
132 | if ((in = fopen(filename, "r")) == NULL) | |
ef416fc2 | 133 | { |
db1f069b | 134 | locale[3] = '\0'; |
ef416fc2 | 135 | |
db1f069b MS |
136 | snprintf(filename, sizeof(filename), "%s%s/%s", directory, locale, tmpl); |
137 | if ((in = fopen(filename, "r")) == NULL) | |
138 | { | |
ef416fc2 | 139 | snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl); |
db1f069b MS |
140 | in = fopen(filename, "r"); |
141 | } | |
ef416fc2 | 142 | } |
143 | ||
355e94dc | 144 | fprintf(stderr, "DEBUG2: Template file is \"%s\"...\n", filename); |
bd7854cb | 145 | |
ef416fc2 | 146 | /* |
147 | * Open the template file... | |
148 | */ | |
149 | ||
db1f069b | 150 | if (!in) |
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 | ||
175 | char * /* O - Template directory */ | |
176 | cgiGetTemplateDir(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 | ||
202 | void | |
203 | cgiSetServerVersion(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 | ||
219 | static void | |
bd7854cb | 220 | cgi_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 */ |
2e4ff8af | 240 | regex_t re; /* Regular expression to match */ |
bd7854cb | 241 | |
242 | ||
355e94dc | 243 | fprintf(stderr, "DEBUG2: %*sStarting at file position %ld...\n", indent, "", |
bd7854cb | 244 | ftell(in)); |
ef416fc2 | 245 | |
246 | /* | |
247 | * Parse the file to the end... | |
248 | */ | |
249 | ||
250 | while ((ch = getc(in)) != EOF) | |
251 | if (ch == term) | |
252 | break; | |
253 | else if (ch == '{') | |
254 | { | |
255 | /* | |
256 | * Get a variable name... | |
257 | */ | |
258 | ||
a74454a7 | 259 | uriencode = 0; |
260 | ||
ef416fc2 | 261 | for (s = name; (ch = getc(in)) != EOF;) |
2e4ff8af | 262 | if (strchr("}]<>=!~ \t\n", ch)) |
ef416fc2 | 263 | break; |
a74454a7 | 264 | else if (s == name && ch == '%') |
265 | uriencode = 1; | |
ef416fc2 | 266 | else if (s > name && ch == '?') |
267 | break; | |
268 | else if (s < (name + sizeof(name) - 1)) | |
269 | *s++ = ch; | |
270 | ||
271 | *s = '\0'; | |
272 | ||
273 | if (s == name && isspace(ch & 255)) | |
274 | { | |
355e94dc | 275 | fprintf(stderr, "DEBUG2: %*sLone { at %ld...\n", indent, "", ftell(in)); |
bd7854cb | 276 | |
ef416fc2 | 277 | if (out) |
278 | { | |
279 | putc('{', out); | |
280 | putc(ch, out); | |
281 | } | |
282 | ||
283 | continue; | |
284 | } | |
285 | ||
bd7854cb | 286 | if (ch == '}') |
355e94dc | 287 | fprintf(stderr, "DEBUG2: %*s\"{%s}\" at %ld...\n", indent, "", name, |
bd7854cb | 288 | ftell(in)); |
289 | ||
ef416fc2 | 290 | /* |
291 | * See if it has a value... | |
292 | */ | |
293 | ||
294 | if (name[0] == '?') | |
295 | { | |
296 | /* | |
297 | * Insert value only if it exists... | |
298 | */ | |
299 | ||
300 | if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255)) | |
301 | { | |
302 | *nameptr++ = '\0'; | |
303 | ||
304 | if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL) | |
305 | outptr = value; | |
306 | else | |
307 | { | |
308 | outval[0] = '\0'; | |
309 | outptr = outval; | |
310 | } | |
311 | } | |
312 | else if ((value = cgiGetArray(name + 1, element)) != NULL) | |
313 | outptr = value; | |
314 | else | |
315 | { | |
316 | outval[0] = '\0'; | |
317 | outptr = outval; | |
318 | } | |
319 | } | |
320 | else if (name[0] == '#') | |
321 | { | |
322 | /* | |
323 | * Insert count... | |
324 | */ | |
325 | ||
326 | if (name[1]) | |
327 | sprintf(outval, "%d", cgiGetSize(name + 1)); | |
328 | else | |
329 | sprintf(outval, "%d", element + 1); | |
330 | ||
331 | outptr = outval; | |
332 | } | |
333 | else if (name[0] == '[') | |
334 | { | |
335 | /* | |
336 | * Loop for # of elements... | |
337 | */ | |
338 | ||
339 | int i; /* Looping var */ | |
340 | long pos; /* File position */ | |
341 | int count; /* Number of elements */ | |
342 | ||
343 | ||
344 | if (isdigit(name[1] & 255)) | |
345 | count = atoi(name + 1); | |
346 | else | |
347 | count = cgiGetSize(name + 1); | |
348 | ||
349 | pos = ftell(in); | |
350 | ||
355e94dc | 351 | fprintf(stderr, "DEBUG2: %*sLooping on \"%s\" at %ld, count=%d...\n", |
bd7854cb | 352 | indent, "", name + 1, pos, count); |
353 | ||
ef416fc2 | 354 | if (count > 0) |
355 | { | |
356 | for (i = 0; i < count; i ++) | |
357 | { | |
bd7854cb | 358 | if (i) |
359 | fseek(in, pos, SEEK_SET); | |
360 | ||
361 | cgi_copy(out, in, i, '}', indent + 2); | |
ef416fc2 | 362 | } |
363 | } | |
364 | else | |
bd7854cb | 365 | cgi_copy(NULL, in, 0, '}', indent + 2); |
366 | ||
355e94dc | 367 | fprintf(stderr, "DEBUG2: %*sFinished looping on \"%s\"...\n", indent, |
bd7854cb | 368 | "", name + 1); |
ef416fc2 | 369 | |
370 | continue; | |
371 | } | |
f8b3a85b MS |
372 | else if (name[0] == '$') |
373 | { | |
374 | /* | |
375 | * Insert cookie value or nothing if not defined. | |
376 | */ | |
377 | ||
378 | if ((value = cgiGetCookie(name + 1)) != NULL) | |
379 | outptr = value; | |
380 | else | |
381 | { | |
382 | outval[0] = '\0'; | |
383 | outptr = outval; | |
384 | } | |
385 | } | |
ef416fc2 | 386 | else |
387 | { | |
388 | /* | |
389 | * Insert variable or variable name (if element is NULL)... | |
390 | */ | |
391 | ||
392 | if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255)) | |
393 | { | |
394 | *nameptr++ = '\0'; | |
395 | if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL) | |
396 | { | |
397 | snprintf(outval, sizeof(outval), "{%s}", name); | |
398 | outptr = outval; | |
399 | } | |
400 | else | |
401 | outptr = value; | |
402 | } | |
403 | else if ((value = cgiGetArray(name, element)) == NULL) | |
404 | { | |
405 | snprintf(outval, sizeof(outval), "{%s}", name); | |
406 | outptr = outval; | |
407 | } | |
408 | else | |
409 | outptr = value; | |
410 | } | |
411 | ||
412 | /* | |
413 | * See if the terminating character requires another test... | |
414 | */ | |
415 | ||
416 | if (ch == '}') | |
417 | { | |
418 | /* | |
419 | * End of substitution... | |
420 | */ | |
421 | ||
422 | if (out) | |
a74454a7 | 423 | { |
424 | if (uriencode) | |
425 | cgi_puturi(outptr, out); | |
88f9aafc | 426 | else if (!_cups_strcasecmp(name, "?cupsdconf_default")) |
355e94dc | 427 | fputs(outptr, stdout); |
a74454a7 | 428 | else |
429 | cgi_puts(outptr, out); | |
430 | } | |
ef416fc2 | 431 | |
432 | continue; | |
433 | } | |
434 | ||
435 | /* | |
436 | * OK, process one of the following checks: | |
437 | * | |
438 | * {name?exist:not-exist} Exists? | |
439 | * {name=value?true:false} Equal | |
440 | * {name<value?true:false} Less than | |
441 | * {name>value?true:false} Greater than | |
442 | * {name!value?true:false} Not equal | |
2e4ff8af | 443 | * {name~refex?true:false} Regex match |
ef416fc2 | 444 | */ |
445 | ||
bd7854cb | 446 | op = ch; |
447 | ||
ef416fc2 | 448 | if (ch == '?') |
449 | { | |
450 | /* | |
451 | * Test for existance... | |
452 | */ | |
453 | ||
f8b3a85b MS |
454 | if (name[0] == '?') |
455 | result = cgiGetArray(name + 1, element) != NULL; | |
456 | else if (name[0] == '#') | |
457 | result = cgiGetVariable(name + 1) != NULL; | |
458 | else | |
459 | result = cgiGetArray(name, element) != NULL; | |
460 | ||
461 | result = result && outptr[0]; | |
bd7854cb | 462 | compare[0] = '\0'; |
ef416fc2 | 463 | } |
464 | else | |
465 | { | |
466 | /* | |
467 | * Compare to a string... | |
468 | */ | |
469 | ||
ef416fc2 | 470 | for (s = compare; (ch = getc(in)) != EOF;) |
471 | if (ch == '?') | |
472 | break; | |
473 | else if (s >= (compare + sizeof(compare) - 1)) | |
474 | continue; | |
475 | else if (ch == '#') | |
476 | { | |
477 | sprintf(s, "%d", element + 1); | |
478 | s += strlen(s); | |
479 | } | |
480 | else if (ch == '{') | |
481 | { | |
482 | /* | |
483 | * Grab the value of a variable... | |
484 | */ | |
485 | ||
486 | innerptr = innername; | |
487 | while ((ch = getc(in)) != EOF && ch != '}') | |
488 | if (innerptr < (innername + sizeof(innername) - 1)) | |
489 | *innerptr++ = ch; | |
490 | *innerptr = '\0'; | |
491 | ||
492 | if (innername[0] == '#') | |
493 | sprintf(s, "%d", cgiGetSize(innername + 1)); | |
494 | else if ((innerptr = strrchr(innername, '-')) != NULL && | |
495 | isdigit(innerptr[1] & 255)) | |
496 | { | |
497 | *innerptr++ = '\0'; | |
498 | if ((innerval = cgiGetArray(innername, atoi(innerptr) - 1)) == NULL) | |
499 | *s = '\0'; | |
500 | else | |
501 | strlcpy(s, innerval, sizeof(compare) - (s - compare)); | |
502 | } | |
503 | else if (innername[0] == '?') | |
504 | { | |
505 | if ((innerval = cgiGetArray(innername + 1, element)) == NULL) | |
506 | *s = '\0'; | |
507 | else | |
508 | strlcpy(s, innerval, sizeof(compare) - (s - compare)); | |
509 | } | |
510 | else if ((innerval = cgiGetArray(innername, element)) == NULL) | |
511 | snprintf(s, sizeof(compare) - (s - compare), "{%s}", innername); | |
512 | else | |
513 | strlcpy(s, innerval, sizeof(compare) - (s - compare)); | |
514 | ||
515 | s += strlen(s); | |
516 | } | |
517 | else if (ch == '\\') | |
518 | *s++ = getc(in); | |
519 | else | |
520 | *s++ = ch; | |
521 | ||
522 | *s = '\0'; | |
523 | ||
524 | if (ch != '?') | |
bd7854cb | 525 | { |
526 | fprintf(stderr, | |
355e94dc | 527 | "DEBUG2: %*sBad terminator '%c' at file position %ld...\n", |
bd7854cb | 528 | indent, "", ch, ftell(in)); |
ef416fc2 | 529 | return; |
bd7854cb | 530 | } |
ef416fc2 | 531 | |
532 | /* | |
533 | * Do the comparison... | |
534 | */ | |
535 | ||
536 | switch (op) | |
537 | { | |
538 | case '<' : | |
88f9aafc | 539 | result = _cups_strcasecmp(outptr, compare) < 0; |
ef416fc2 | 540 | break; |
541 | case '>' : | |
88f9aafc | 542 | result = _cups_strcasecmp(outptr, compare) > 0; |
ef416fc2 | 543 | break; |
544 | case '=' : | |
88f9aafc | 545 | result = _cups_strcasecmp(outptr, compare) == 0; |
ef416fc2 | 546 | break; |
547 | case '!' : | |
88f9aafc | 548 | result = _cups_strcasecmp(outptr, compare) != 0; |
ef416fc2 | 549 | break; |
2e4ff8af MS |
550 | case '~' : |
551 | fprintf(stderr, "DEBUG: Regular expression \"%s\"\n", compare); | |
552 | ||
553 | if (regcomp(&re, compare, REG_EXTENDED | REG_ICASE)) | |
554 | { | |
555 | fprintf(stderr, | |
556 | "ERROR: Unable to compile regular expresion \"%s\"!\n", | |
557 | compare); | |
558 | result = 0; | |
559 | } | |
560 | else | |
561 | { | |
562 | regmatch_t matches[10]; | |
563 | ||
564 | result = 0; | |
565 | ||
566 | if (!regexec(&re, outptr, 10, matches, 0)) | |
567 | { | |
568 | int i; | |
569 | for (i = 0; i < 10; i ++) | |
570 | { | |
571 | fprintf(stderr, "DEBUG: matches[%d].rm_so=%d\n", i, | |
572 | (int)matches[i].rm_so); | |
573 | if (matches[i].rm_so < 0) | |
574 | break; | |
575 | ||
576 | result ++; | |
577 | } | |
578 | } | |
579 | ||
580 | regfree(&re); | |
581 | } | |
582 | break; | |
ef416fc2 | 583 | default : |
584 | result = 1; | |
585 | break; | |
586 | } | |
587 | } | |
588 | ||
bd7854cb | 589 | fprintf(stderr, |
355e94dc | 590 | "DEBUG2: %*sStarting \"{%s%c%s\" at %ld, result=%d...\n", |
bd7854cb | 591 | indent, "", name, op, compare, ftell(in), result); |
592 | ||
ef416fc2 | 593 | if (result) |
594 | { | |
595 | /* | |
596 | * Comparison true; output first part and ignore second... | |
597 | */ | |
598 | ||
355e94dc | 599 | fprintf(stderr, "DEBUG2: %*sOutput first part...\n", indent, ""); |
bd7854cb | 600 | cgi_copy(out, in, element, ':', indent + 2); |
601 | ||
355e94dc | 602 | fprintf(stderr, "DEBUG2: %*sSkip second part...\n", indent, ""); |
bd7854cb | 603 | cgi_copy(NULL, in, element, '}', indent + 2); |
ef416fc2 | 604 | } |
605 | else | |
606 | { | |
607 | /* | |
608 | * Comparison false; ignore first part and output second... | |
609 | */ | |
610 | ||
355e94dc | 611 | fprintf(stderr, "DEBUG2: %*sSkip first part...\n", indent, ""); |
bd7854cb | 612 | cgi_copy(NULL, in, element, ':', indent + 2); |
613 | ||
355e94dc | 614 | fprintf(stderr, "DEBUG2: %*sOutput second part...\n", indent, ""); |
bd7854cb | 615 | cgi_copy(out, in, element, '}', indent + 2); |
ef416fc2 | 616 | } |
bd7854cb | 617 | |
355e94dc | 618 | fprintf(stderr, "DEBUG2: %*sFinished \"{%s%c%s\", out=%p...\n", indent, "", |
bd7854cb | 619 | name, op, compare, out); |
ef416fc2 | 620 | } |
621 | else if (ch == '\\') /* Quoted char */ | |
622 | { | |
623 | if (out) | |
624 | putc(getc(in), out); | |
625 | else | |
626 | getc(in); | |
627 | } | |
628 | else if (out) | |
629 | putc(ch, out); | |
630 | ||
bd7854cb | 631 | if (ch == EOF) |
355e94dc | 632 | fprintf(stderr, "DEBUG2: %*sReturning at file position %ld on EOF...\n", |
bd7854cb | 633 | indent, "", ftell(in)); |
634 | else | |
635 | fprintf(stderr, | |
355e94dc | 636 | "DEBUG2: %*sReturning at file position %ld on character '%c'...\n", |
bd7854cb | 637 | indent, "", ftell(in), ch); |
638 | ||
639 | if (ch == EOF && term) | |
640 | fprintf(stderr, "ERROR: %*sSaw EOF, expected '%c'!\n", indent, "", term); | |
641 | ||
ef416fc2 | 642 | /* |
643 | * Flush any pending output... | |
644 | */ | |
645 | ||
646 | if (out) | |
647 | fflush(out); | |
648 | } | |
649 | ||
650 | ||
651 | /* | |
652 | * 'cgi_puts()' - Put a string to the output file, quoting as needed... | |
653 | */ | |
654 | ||
655 | static void | |
656 | cgi_puts(const char *s, /* I - String to output */ | |
657 | FILE *out) /* I - Output file */ | |
658 | { | |
659 | while (*s) | |
660 | { | |
661 | if (*s == '<') | |
662 | { | |
663 | /* | |
664 | * Pass <A HREF="url"> and </A>, otherwise quote it... | |
665 | */ | |
666 | ||
88f9aafc | 667 | if (!_cups_strncasecmp(s, "<A HREF=\"", 9)) |
ef416fc2 | 668 | { |
669 | fputs("<A HREF=\"", out); | |
670 | s += 9; | |
671 | ||
672 | while (*s && *s != '\"') | |
673 | { | |
674 | if (*s == '&') | |
675 | fputs("&", out); | |
676 | else | |
677 | putc(*s, out); | |
678 | ||
679 | s ++; | |
680 | } | |
681 | ||
682 | if (*s) | |
683 | s ++; | |
684 | ||
685 | fputs("\">", out); | |
686 | } | |
88f9aafc | 687 | else if (!_cups_strncasecmp(s, "</A>", 4)) |
ef416fc2 | 688 | { |
689 | fputs("</A>", out); | |
690 | s += 3; | |
691 | } | |
692 | else | |
693 | fputs("<", out); | |
694 | } | |
695 | else if (*s == '>') | |
696 | fputs(">", out); | |
697 | else if (*s == '\"') | |
698 | fputs(""", out); | |
ef55b745 MS |
699 | else if (*s == '\'') |
700 | fputs("'", out); | |
ef416fc2 | 701 | else if (*s == '&') |
702 | fputs("&", out); | |
703 | else | |
704 | putc(*s, out); | |
705 | ||
706 | s ++; | |
707 | } | |
708 | } | |
709 | ||
710 | ||
711 | /* | |
a74454a7 | 712 | * 'cgi_puturi()' - Put a URI string to the output file, quoting as needed... |
713 | */ | |
714 | ||
715 | static void | |
716 | cgi_puturi(const char *s, /* I - String to output */ | |
717 | FILE *out) /* I - Output file */ | |
718 | { | |
719 | while (*s) | |
720 | { | |
ef55b745 | 721 | if (strchr("%@&+ <>#=", *s) || *s < ' ' || *s & 128) |
a74454a7 | 722 | fprintf(out, "%%%02X", *s & 255); |
723 | else | |
724 | putc(*s, out); | |
725 | ||
726 | s ++; | |
727 | } | |
728 | } | |
729 | ||
730 | ||
731 | /* | |
75bd9771 | 732 | * End of "$Id: template.c 7219 2008-01-14 22:00:02Z mike $". |
ef416fc2 | 733 | */ |