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