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