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