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