]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/template.c
2 * CGI template function.
4 * Copyright 2007-2015 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
10 #include "cgi-private.h"
19 static void cgi_copy(FILE *out
, FILE *in
, int element
, char term
,
21 static void cgi_puts(const char *s
, FILE *out
);
22 static void cgi_puturi(const char *s
, FILE *out
);
26 * 'cgiCopyTemplateFile()' - Copy a template file and replace all the
27 * '{variable}' strings with the variable value.
31 cgiCopyTemplateFile(FILE *out
, /* I - Output file */
32 const char *tmpl
) /* I - Template file to read */
34 FILE *in
; /* Input file */
37 fprintf(stderr
, "DEBUG2: cgiCopyTemplateFile(out=%p, tmpl=\"%s\")\n", out
,
38 tmpl
? tmpl
: "(null)");
41 * Range check input...
48 * Open the template file...
51 if ((in
= fopen(tmpl
, "r")) == NULL
)
53 fprintf(stderr
, "ERROR: Unable to open template file \"%s\" - %s\n",
54 tmpl
? tmpl
: "(null)", strerror(errno
));
59 * Parse the file to the end...
62 cgi_copy(out
, in
, 0, 0, 0);
65 * Close the template file and return...
73 * 'cgiCopyTemplateLang()' - Copy a template file using a language...
77 cgiCopyTemplateLang(const char *tmpl
) /* I - Base filename */
79 char filename
[1024], /* Filename */
80 locale
[16], /* Locale name */
81 *locptr
; /* Pointer into locale name */
82 const char *directory
, /* Directory for templates */
84 FILE *in
; /* Input file */
87 fprintf(stderr
, "DEBUG2: cgiCopyTemplateLang(tmpl=\"%s\")\n",
88 tmpl
? tmpl
: "(null)");
91 * Convert the language to a locale name...
96 if ((lang
= getenv("LANG")) != NULL
)
99 strlcpy(locale
+ 1, lang
, sizeof(locale
) - 1);
101 if ((locptr
= strchr(locale
, '.')) != NULL
)
102 *locptr
= '\0'; /* Strip charset */
105 fprintf(stderr
, "DEBUG2: lang=\"%s\", locale=\"%s\"...\n",
106 lang
? lang
: "(null)", locale
);
109 * See if we have a template file for this language...
112 directory
= cgiGetTemplateDir();
114 snprintf(filename
, sizeof(filename
), "%s%s/%s", directory
, locale
, tmpl
);
115 if ((in
= fopen(filename
, "r")) == NULL
)
119 snprintf(filename
, sizeof(filename
), "%s%s/%s", directory
, locale
, tmpl
);
120 if ((in
= fopen(filename
, "r")) == NULL
)
122 snprintf(filename
, sizeof(filename
), "%s/%s", directory
, tmpl
);
123 in
= fopen(filename
, "r");
127 fprintf(stderr
, "DEBUG2: Template file is \"%s\"...\n", filename
);
130 * Open the template file...
135 fprintf(stderr
, "ERROR: Unable to open template file \"%s\" - %s\n",
136 filename
, strerror(errno
));
141 * Parse the file to the end...
144 cgi_copy(stdout
, in
, 0, 0, 0);
147 * Close the template file and return...
155 * 'cgiGetTemplateDir()' - Get the templates directory...
158 char * /* O - Template directory */
159 cgiGetTemplateDir(void)
161 const char *datadir
; /* CUPS_DATADIR env var */
162 static char templates
[1024] = ""; /* Template directory */
168 * Build the template directory pathname...
171 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
172 datadir
= CUPS_DATADIR
;
174 snprintf(templates
, sizeof(templates
), "%s/templates", datadir
);
182 * 'cgiSetServerVersion()' - Set the server name and CUPS version...
186 cgiSetServerVersion(void)
188 cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME"));
189 cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER"));
190 cgiSetVariable("CUPS_VERSION", CUPS_SVERSION
);
193 setlocale(LC_TIME
, "");
199 * 'cgi_copy()' - Copy the template file, substituting as needed...
203 cgi_copy(FILE *out
, /* I - Output file */
204 FILE *in
, /* I - Input file */
205 int element
, /* I - Element number (0 to N) */
206 char term
, /* I - Terminating character */
207 int indent
) /* I - Debug info indentation */
209 int ch
; /* Character from file */
210 char op
; /* Operation */
211 char name
[255], /* Name of variable */
212 *nameptr
, /* Pointer into name */
213 innername
[255], /* Inner comparison name */
214 *innerptr
, /* Pointer into inner name */
215 *s
; /* String pointer */
216 const char *value
; /* Value of variable */
217 const char *innerval
; /* Inner value */
218 const char *outptr
; /* Output string pointer */
219 char outval
[1024], /* Formatted output string */
220 compare
[1024]; /* Comparison string */
221 int result
; /* Result of comparison */
222 int uriencode
; /* Encode as URI */
223 regex_t re
; /* Regular expression to match */
226 fprintf(stderr
, "DEBUG2: %*sStarting at file position %ld...\n", indent
, "",
230 * Parse the file to the end...
233 while ((ch
= getc(in
)) != EOF
)
239 * Get a variable name...
244 for (s
= name
; (ch
= getc(in
)) != EOF
;)
245 if (strchr("}]<>=!~ \t\n", ch
))
247 else if (s
== name
&& ch
== '%')
249 else if (s
> name
&& ch
== '?')
251 else if (s
< (name
+ sizeof(name
) - 1))
256 if (s
== name
&& isspace(ch
& 255))
258 fprintf(stderr
, "DEBUG2: %*sLone { at %ld...\n", indent
, "", ftell(in
));
270 fprintf(stderr
, "DEBUG2: %*s\"{%s}\" at %ld...\n", indent
, "", name
,
274 * See if it has a value...
280 * Insert value only if it exists...
283 if ((nameptr
= strrchr(name
, '-')) != NULL
&& isdigit(nameptr
[1] & 255))
287 if ((value
= cgiGetArray(name
+ 1, atoi(nameptr
) - 1)) != NULL
)
295 else if ((value
= cgiGetArray(name
+ 1, element
)) != NULL
)
303 else if (name
[0] == '#')
310 sprintf(outval
, "%d", cgiGetSize(name
+ 1));
312 sprintf(outval
, "%d", element
+ 1);
316 else if (name
[0] == '[')
319 * Loop for # of elements...
322 int i
; /* Looping var */
323 long pos
; /* File position */
324 int count
; /* Number of elements */
327 if (isdigit(name
[1] & 255))
328 count
= atoi(name
+ 1);
330 count
= cgiGetSize(name
+ 1);
334 fprintf(stderr
, "DEBUG2: %*sLooping on \"%s\" at %ld, count=%d...\n",
335 indent
, "", name
+ 1, pos
, count
);
339 for (i
= 0; i
< count
; i
++)
342 fseek(in
, pos
, SEEK_SET
);
344 cgi_copy(out
, in
, i
, '}', indent
+ 2);
348 cgi_copy(NULL
, in
, 0, '}', indent
+ 2);
350 fprintf(stderr
, "DEBUG2: %*sFinished looping on \"%s\"...\n", indent
,
355 else if (name
[0] == '$')
358 * Insert cookie value or nothing if not defined.
361 if ((value
= cgiGetCookie(name
+ 1)) != NULL
)
372 * Insert variable or variable name (if element is NULL)...
375 if ((nameptr
= strrchr(name
, '-')) != NULL
&& isdigit(nameptr
[1] & 255))
378 if ((value
= cgiGetArray(name
, atoi(nameptr
) - 1)) == NULL
)
380 snprintf(outval
, sizeof(outval
), "{%s}", name
);
386 else if ((value
= cgiGetArray(name
, element
)) == NULL
)
388 snprintf(outval
, sizeof(outval
), "{%s}", name
);
396 * See if the terminating character requires another test...
402 * End of substitution...
408 cgi_puturi(outptr
, out
);
409 else if (!_cups_strcasecmp(name
, "?cupsdconf_default"))
410 fputs(outptr
, stdout
);
412 cgi_puts(outptr
, out
);
419 * OK, process one of the following checks:
421 * {name?exist:not-exist} Exists?
422 * {name=value?true:false} Equal
423 * {name<value?true:false} Less than
424 * {name>value?true:false} Greater than
425 * {name!value?true:false} Not equal
426 * {name~refex?true:false} Regex match
434 * Test for existance...
438 result
= cgiGetArray(name
+ 1, element
) != NULL
;
439 else if (name
[0] == '#')
440 result
= cgiGetVariable(name
+ 1) != NULL
;
442 result
= cgiGetArray(name
, element
) != NULL
;
444 result
= result
&& outptr
[0];
450 * Compare to a string...
453 for (s
= compare
; (ch
= getc(in
)) != EOF
;)
456 else if (s
>= (compare
+ sizeof(compare
) - 1))
460 sprintf(s
, "%d", element
+ 1);
466 * Grab the value of a variable...
469 innerptr
= innername
;
470 while ((ch
= getc(in
)) != EOF
&& ch
!= '}')
471 if (innerptr
< (innername
+ sizeof(innername
) - 1))
472 *innerptr
++ = (char)ch
;
475 if (innername
[0] == '#')
476 sprintf(s
, "%d", cgiGetSize(innername
+ 1));
477 else if ((innerptr
= strrchr(innername
, '-')) != NULL
&&
478 isdigit(innerptr
[1] & 255))
481 if ((innerval
= cgiGetArray(innername
, atoi(innerptr
) - 1)) == NULL
)
484 strlcpy(s
, innerval
, sizeof(compare
) - (size_t)(s
- compare
));
486 else if (innername
[0] == '?')
488 if ((innerval
= cgiGetArray(innername
+ 1, element
)) == NULL
)
491 strlcpy(s
, innerval
, sizeof(compare
) - (size_t)(s
- compare
));
493 else if ((innerval
= cgiGetArray(innername
, element
)) == NULL
)
494 snprintf(s
, sizeof(compare
) - (size_t)(s
- compare
), "{%s}", innername
);
496 strlcpy(s
, innerval
, sizeof(compare
) - (size_t)(s
- compare
));
501 *s
++ = (char)getc(in
);
510 "DEBUG2: %*sBad terminator '%c' at file position %ld...\n",
511 indent
, "", ch
, ftell(in
));
516 * Do the comparison...
522 result
= _cups_strcasecmp(outptr
, compare
) < 0;
525 result
= _cups_strcasecmp(outptr
, compare
) > 0;
528 result
= _cups_strcasecmp(outptr
, compare
) == 0;
531 result
= _cups_strcasecmp(outptr
, compare
) != 0;
534 fprintf(stderr
, "DEBUG: Regular expression \"%s\"\n", compare
);
536 if (regcomp(&re
, compare
, REG_EXTENDED
| REG_ICASE
))
539 "ERROR: Unable to compile regular expression \"%s\"!\n",
545 regmatch_t matches
[10];
549 if (!regexec(&re
, outptr
, 10, matches
, 0))
552 for (i
= 0; i
< 10; i
++)
554 fprintf(stderr
, "DEBUG: matches[%d].rm_so=%d\n", i
,
555 (int)matches
[i
].rm_so
);
556 if (matches
[i
].rm_so
< 0)
573 "DEBUG2: %*sStarting \"{%s%c%s\" at %ld, result=%d...\n",
574 indent
, "", name
, op
, compare
, ftell(in
), result
);
579 * Comparison true; output first part and ignore second...
582 fprintf(stderr
, "DEBUG2: %*sOutput first part...\n", indent
, "");
583 cgi_copy(out
, in
, element
, ':', indent
+ 2);
585 fprintf(stderr
, "DEBUG2: %*sSkip second part...\n", indent
, "");
586 cgi_copy(NULL
, in
, element
, '}', indent
+ 2);
591 * Comparison false; ignore first part and output second...
594 fprintf(stderr
, "DEBUG2: %*sSkip first part...\n", indent
, "");
595 cgi_copy(NULL
, in
, element
, ':', indent
+ 2);
597 fprintf(stderr
, "DEBUG2: %*sOutput second part...\n", indent
, "");
598 cgi_copy(out
, in
, element
, '}', indent
+ 2);
601 fprintf(stderr
, "DEBUG2: %*sFinished \"{%s%c%s\", out=%p...\n", indent
, "",
602 name
, op
, compare
, out
);
604 else if (ch
== '\\') /* Quoted char */
615 fprintf(stderr
, "DEBUG2: %*sReturning at file position %ld on EOF...\n",
616 indent
, "", ftell(in
));
619 "DEBUG2: %*sReturning at file position %ld on character '%c'...\n",
620 indent
, "", ftell(in
), ch
);
622 if (ch
== EOF
&& term
)
623 fprintf(stderr
, "ERROR: %*sSaw EOF, expected '%c'!\n", indent
, "", term
);
626 * Flush any pending output...
635 * 'cgi_puts()' - Put a string to the output file, quoting as needed...
639 cgi_puts(const char *s
, /* I - String to output */
640 FILE *out
) /* I - Output file */
649 fputs(""", out
);
663 * 'cgi_puturi()' - Put a URI string to the output file, quoting as needed...
667 cgi_puturi(const char *s
, /* I - String to output */
668 FILE *out
) /* I - Output file */
672 if (strchr("%@&+ <>#=", *s
) || *s
< ' ' || *s
& 128)
673 fprintf(out
, "%%%02X", *s
& 255);