]> git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/var.c
Merge changes from CUPS 1.5svn-r8916.
[thirdparty/cups.git] / cgi-bin / var.c
1 /*
2 * "$Id: var.c 7460 2008-04-16 02:19:54Z mike $"
3 *
4 * CGI form variable and array functions.
5 *
6 * Copyright 2007-2009 by Apple Inc.
7 * Copyright 1997-2005 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * Contents:
16 *
17 * cgiCheckVariables() - Check for the presence of "required" variables.
18 * cgiClearVariables() - Clear all form variables.
19 * cgiGetArray() - Get an element from a form array...
20 * cgiGetFile() - Get the file (if any) that was submitted in the form.
21 * cgiGetSize() - Get the size of a form array value.
22 * cgiGetVariable() - Get a CGI variable from the database...
23 * cgiInitialize() - Initialize the CGI variable "database"...
24 * cgiIsPOST() - Determine whether this page was POSTed.
25 * cgiSetArray() - Set array element N to the specified string.
26 * cgiSetSize() - Set the array size.
27 * cgiSetVariable() - Set a CGI variable in the database...
28 * cgi_add_variable() - Add a form variable.
29 * cgi_compare_variables() - Compare two variables.
30 * cgi_find_variable() - Find a variable...
31 * cgi_initialize_get() - Initialize form variables using the GET method.
32 * cgi_initialize_multipart() - Initialize variables and file using the POST method.
33 * cgi_initialize_post() - Initialize variables using the POST method.
34 * cgi_initialize_string() - Initialize form variables from a string.
35 * cgi_passwd() - Catch authentication requests and notify the server.
36 * cgi_sort_variables() - Sort all form variables for faster lookup.
37 * cgi_unlink_file() - Remove the uploaded form.
38 */
39
40 /*#define DEBUG*/
41 #include "cgi-private.h"
42 #include <errno.h>
43
44
45 /*
46 * Data structure to hold all the CGI form variables and arrays...
47 */
48
49 typedef struct /**** Form variable structure ****/
50 {
51 const char *name; /* Name of variable */
52 int nvalues, /* Number of values */
53 avalues; /* Number of values allocated */
54 const char **values; /* Value(s) of variable */
55 } _cgi_var_t;
56
57
58 /*
59 * Local globals...
60 */
61
62 static int form_count = 0, /* Form variable count */
63 form_alloc = 0; /* Number of variables allocated */
64 static _cgi_var_t *form_vars = NULL;
65 /* Form variables */
66 static cgi_file_t *form_file = NULL;
67 /* Uploaded file */
68
69
70 /*
71 * Local functions...
72 */
73
74 static void cgi_add_variable(const char *name, int element,
75 const char *value);
76 static int cgi_compare_variables(const _cgi_var_t *v1,
77 const _cgi_var_t *v2);
78 static _cgi_var_t *cgi_find_variable(const char *name);
79 static int cgi_initialize_get(void);
80 static int cgi_initialize_multipart(const char *boundary);
81 static int cgi_initialize_post(void);
82 static int cgi_initialize_string(const char *data);
83 static const char *cgi_passwd(const char *prompt);
84 static void cgi_sort_variables(void);
85 static void cgi_unlink_file(void);
86
87
88 /*
89 * 'cgiCheckVariables()' - Check for the presence of "required" variables.
90 *
91 * Names may be separated by spaces and/or commas.
92 */
93
94 int /* O - 1 if all variables present, 0 otherwise */
95 cgiCheckVariables(const char *names) /* I - Variables to look for */
96 {
97 char name[255], /* Current variable name */
98 *s; /* Pointer in string */
99 const char *val; /* Value of variable */
100 int element; /* Array element number */
101
102
103 if (names == NULL)
104 return (1);
105
106 while (*names != '\0')
107 {
108 while (*names == ' ' || *names == ',')
109 names ++;
110
111 for (s = name; *names != '\0' && *names != ' ' && *names != ','; s ++, names ++)
112 *s = *names;
113
114 *s = 0;
115 if (name[0] == '\0')
116 break;
117
118 if ((s = strrchr(name, '-')) != NULL)
119 {
120 *s = '\0';
121 element = atoi(s + 1) - 1;
122 val = cgiGetArray(name, element);
123 }
124 else
125 val = cgiGetVariable(name);
126
127 if (val == NULL)
128 return (0);
129
130 if (*val == '\0')
131 return (0); /* Can't be blank, either! */
132 }
133
134 return (1);
135 }
136
137
138 /*
139 * 'cgiClearVariables()' - Clear all form variables.
140 */
141
142 void
143 cgiClearVariables(void)
144 {
145 int i, j; /* Looping vars */
146 _cgi_var_t *v; /* Current variable */
147
148
149 for (v = form_vars, i = form_count; i > 0; v ++, i --)
150 {
151 _cupsStrFree(v->name);
152 for (j = 0; j < v->nvalues; j ++)
153 if (v->values[j])
154 _cupsStrFree(v->values[j]);
155 }
156
157 form_count = 0;
158
159 cgi_unlink_file();
160 }
161
162
163 /*
164 * 'cgiGetArray()' - Get an element from a form array...
165 */
166
167 const char * /* O - Element value or NULL */
168 cgiGetArray(const char *name, /* I - Name of array variable */
169 int element) /* I - Element number (0 to N) */
170 {
171 _cgi_var_t *var; /* Pointer to variable */
172
173
174 if ((var = cgi_find_variable(name)) == NULL)
175 return (NULL);
176
177 if (element < 0 || element >= var->nvalues)
178 return (NULL);
179
180 return (_cupsStrRetain(var->values[element]));
181 }
182
183
184 /*
185 * 'cgiGetFile()' - Get the file (if any) that was submitted in the form.
186 */
187
188 const cgi_file_t * /* O - Attached file or NULL */
189 cgiGetFile(void)
190 {
191 return (form_file);
192 }
193
194
195 /*
196 * 'cgiGetSize()' - Get the size of a form array value.
197 */
198
199 int /* O - Number of elements */
200 cgiGetSize(const char *name) /* I - Name of variable */
201 {
202 _cgi_var_t *var; /* Pointer to variable */
203
204
205 if ((var = cgi_find_variable(name)) == NULL)
206 return (0);
207
208 return (var->nvalues);
209 }
210
211
212 /*
213 * 'cgiGetVariable()' - Get a CGI variable from the database...
214 *
215 * Returns NULL if the variable doesn't exist. If the variable is an
216 * array of values, returns the last element...
217 */
218
219 const char * /* O - Value of variable */
220 cgiGetVariable(const char *name) /* I - Name of variable */
221 {
222 const _cgi_var_t *var; /* Returned variable */
223
224
225 var = cgi_find_variable(name);
226
227 #ifdef DEBUG
228 if (var == NULL)
229 DEBUG_printf(("cgiGetVariable(\"%s\") is returning NULL...\n", name));
230 else
231 DEBUG_printf(("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name,
232 var->values[var->nvalues - 1]));
233 #endif /* DEBUG */
234
235 return ((var == NULL) ? NULL : _cupsStrRetain(var->values[var->nvalues - 1]));
236 }
237
238
239 /*
240 * 'cgiInitialize()' - Initialize the CGI variable "database"...
241 */
242
243 int /* O - Non-zero if there was form data */
244 cgiInitialize(void)
245 {
246 const char *method; /* Form posting method */
247 const char *content_type; /* Content-Type of post data */
248
249
250 /*
251 * Setup a password callback for authentication...
252 */
253
254 cupsSetPasswordCB(cgi_passwd);
255
256 /*
257 * Set the locale so that times, etc. are formatted properly...
258 */
259
260 setlocale(LC_ALL, "");
261
262 #ifdef DEBUG
263 /*
264 * Disable output buffering to find bugs...
265 */
266
267 setbuf(stdout, NULL);
268 #endif /* DEBUG */
269
270 /*
271 * Get the request method (GET or POST)...
272 */
273
274 method = getenv("REQUEST_METHOD");
275 content_type = getenv("CONTENT_TYPE");
276 if (!method)
277 return (0);
278
279 /*
280 * Grab form data from the corresponding location...
281 */
282
283 if (!strcasecmp(method, "GET"))
284 return (cgi_initialize_get());
285 else if (!strcasecmp(method, "POST") && content_type)
286 {
287 const char *boundary = strstr(content_type, "boundary=");
288
289 if (boundary)
290 boundary += 9;
291
292 if (content_type && !strncmp(content_type, "multipart/form-data; ", 21))
293 return (cgi_initialize_multipart(boundary));
294 else
295 return (cgi_initialize_post());
296 }
297 else
298 return (0);
299 }
300
301
302 /*
303 * 'cgiIsPOST()' - Determine whether this page was POSTed.
304 */
305
306 int /* O - 1 if POST, 0 if GET */
307 cgiIsPOST(void)
308 {
309 const char *method; /* REQUEST_METHOD environment variable */
310
311
312 if ((method = getenv("REQUEST_METHOD")) == NULL)
313 return (0);
314 else
315 return (!strcmp(method, "POST"));
316 }
317
318
319 /*
320 * 'cgiSetArray()' - Set array element N to the specified string.
321 *
322 * If the variable array is smaller than (element + 1), the intervening
323 * elements are set to NULL.
324 */
325
326 void
327 cgiSetArray(const char *name, /* I - Name of variable */
328 int element, /* I - Element number (0 to N) */
329 const char *value) /* I - Value of variable */
330 {
331 int i; /* Looping var */
332 _cgi_var_t *var; /* Returned variable */
333
334
335 if (name == NULL || value == NULL || element < 0 || element > 100000)
336 return;
337
338 if ((var = cgi_find_variable(name)) == NULL)
339 {
340 cgi_add_variable(name, element, value);
341 cgi_sort_variables();
342 }
343 else
344 {
345 if (element >= var->avalues)
346 {
347 const char **temp; /* Temporary pointer */
348
349 temp = (const char **)realloc((void *)(var->values),
350 sizeof(char *) * (element + 16));
351 if (!temp)
352 return;
353
354 var->avalues = element + 16;
355 var->values = temp;
356 }
357
358 if (element >= var->nvalues)
359 {
360 for (i = var->nvalues; i < element; i ++)
361 var->values[i] = NULL;
362
363 var->nvalues = element + 1;
364 }
365 else if (var->values[element])
366 _cupsStrFree((char *)var->values[element]);
367
368 var->values[element] = _cupsStrAlloc(value);
369 }
370 }
371
372
373 /*
374 * 'cgiSetSize()' - Set the array size.
375 */
376
377 void
378 cgiSetSize(const char *name, /* I - Name of variable */
379 int size) /* I - Number of elements (0 to N) */
380 {
381 int i; /* Looping var */
382 _cgi_var_t *var; /* Returned variable */
383
384
385 if (name == NULL || size < 0 || size > 100000)
386 return;
387
388 if ((var = cgi_find_variable(name)) == NULL)
389 return;
390
391 if (size >= var->avalues)
392 {
393 const char **temp; /* Temporary pointer */
394
395 temp = (const char **)realloc((void *)(var->values),
396 sizeof(char *) * (size + 16));
397 if (!temp)
398 return;
399
400 var->avalues = size + 16;
401 var->values = temp;
402 }
403
404 if (size > var->nvalues)
405 {
406 for (i = var->nvalues; i < size; i ++)
407 var->values[i] = NULL;
408 }
409 else if (size < var->nvalues)
410 {
411 for (i = size; i < var->nvalues; i ++)
412 if (var->values[i])
413 _cupsStrFree((void *)(var->values[i]));
414 }
415
416 var->nvalues = size;
417 }
418
419
420 /*
421 * 'cgiSetVariable()' - Set a CGI variable in the database...
422 *
423 * If the variable is an array, this truncates the array to a single element.
424 */
425
426 void
427 cgiSetVariable(const char *name, /* I - Name of variable */
428 const char *value) /* I - Value of variable */
429 {
430 int i; /* Looping var */
431 _cgi_var_t *var; /* Returned variable */
432
433
434 if (name == NULL || value == NULL)
435 return;
436
437 if ((var = cgi_find_variable(name)) == NULL)
438 {
439 cgi_add_variable(name, 0, value);
440 cgi_sort_variables();
441 }
442 else
443 {
444 for (i = 0; i < var->nvalues; i ++)
445 if (var->values[i])
446 _cupsStrFree((char *)var->values[i]);
447
448 var->values[0] = _cupsStrAlloc(value);
449 var->nvalues = 1;
450 }
451 }
452
453
454 /*
455 * 'cgi_add_variable()' - Add a form variable.
456 */
457
458 static void
459 cgi_add_variable(const char *name, /* I - Variable name */
460 int element, /* I - Array element number */
461 const char *value) /* I - Variable value */
462 {
463 _cgi_var_t *var; /* New variable */
464
465
466 if (name == NULL || value == NULL || element < 0 || element > 100000)
467 return;
468
469 DEBUG_printf(("cgi_add_variable: Adding variable \'%s\' with value "
470 "\'%s\'...\n", name, value));
471
472 if (form_count >= form_alloc)
473 {
474 _cgi_var_t *temp_vars; /* Temporary form pointer */
475
476
477 if (form_alloc == 0)
478 temp_vars = malloc(sizeof(_cgi_var_t) * 16);
479 else
480 temp_vars = realloc(form_vars, (form_alloc + 16) * sizeof(_cgi_var_t));
481
482 if (!temp_vars)
483 return;
484
485 form_vars = temp_vars;
486 form_alloc += 16;
487 }
488
489 var = form_vars + form_count;
490
491 if ((var->values = calloc(element + 1, sizeof(char *))) == NULL)
492 return;
493
494 var->name = _cupsStrAlloc(name);
495 var->nvalues = element + 1;
496 var->avalues = element + 1;
497 var->values[element] = _cupsStrAlloc(value);
498
499 form_count ++;
500 }
501
502
503 /*
504 * 'cgi_compare_variables()' - Compare two variables.
505 */
506
507 static int /* O - Result of comparison */
508 cgi_compare_variables(
509 const _cgi_var_t *v1, /* I - First variable */
510 const _cgi_var_t *v2) /* I - Second variable */
511 {
512 return (strcasecmp(v1->name, v2->name));
513 }
514
515
516 /*
517 * 'cgi_find_variable()' - Find a variable...
518 */
519
520 static _cgi_var_t * /* O - Variable pointer or NULL */
521 cgi_find_variable(const char *name) /* I - Name of variable */
522 {
523 _cgi_var_t key; /* Search key */
524
525
526 if (form_count < 1 || name == NULL)
527 return (NULL);
528
529 key.name = name;
530
531 return ((_cgi_var_t *)bsearch(&key, form_vars, form_count, sizeof(_cgi_var_t),
532 (int (*)(const void *, const void *))cgi_compare_variables));
533 }
534
535
536 /*
537 * 'cgi_initialize_get()' - Initialize form variables using the GET method.
538 */
539
540 static int /* O - 1 if form data read */
541 cgi_initialize_get(void)
542 {
543 char *data; /* Pointer to form data string */
544
545
546 DEBUG_puts("cgi_initialize_get: Initializing variables using GET method...");
547
548 /*
549 * Check to see if there is anything for us to read...
550 */
551
552 data = getenv("QUERY_STRING");
553 if (data == NULL || strlen(data) == 0)
554 return (0);
555
556 /*
557 * Parse it out and return...
558 */
559
560 return (cgi_initialize_string(data));
561 }
562
563
564 /*
565 * 'cgi_initialize_multipart()' - Initialize variables and file using the POST method.
566 *
567 * TODO: Update to support files > 2GB.
568 */
569
570 static int /* O - 1 if form data was read */
571 cgi_initialize_multipart(
572 const char *boundary) /* I - Boundary string */
573 {
574 char line[10240], /* MIME header line */
575 name[1024], /* Form variable name */
576 filename[1024], /* Form filename */
577 mimetype[1024], /* MIME media type */
578 bstring[256], /* Boundary string to look for */
579 *ptr, /* Pointer into name/filename */
580 *end; /* End of buffer */
581 int ch, /* Character from file */
582 fd, /* Temporary file descriptor */
583 blen; /* Length of boundary string */
584
585
586 DEBUG_printf(("cgi_initialize_multipart(boundary=\"%s\")\n", boundary));
587
588 /*
589 * Read multipart form data until we run out...
590 */
591
592 name[0] = '\0';
593 filename[0] = '\0';
594 mimetype[0] = '\0';
595
596 snprintf(bstring, sizeof(bstring), "\r\n--%s", boundary);
597 blen = strlen(bstring);
598
599 while (fgets(line, sizeof(line), stdin))
600 {
601 if (!strcmp(line, "\r\n"))
602 {
603 /*
604 * End of headers, grab value...
605 */
606
607 if (filename[0])
608 {
609 /*
610 * Read an embedded file...
611 */
612
613 if (form_file)
614 {
615 /*
616 * Remove previous file...
617 */
618
619 cgi_unlink_file();
620 }
621
622 /*
623 * Allocate memory for the new file...
624 */
625
626 if ((form_file = calloc(1, sizeof(cgi_file_t))) == NULL)
627 return (0);
628
629 form_file->name = strdup(name);
630 form_file->filename = strdup(filename);
631 form_file->mimetype = strdup(mimetype);
632
633 fd = cupsTempFd(form_file->tempfile, sizeof(form_file->tempfile));
634
635 if (fd < 0)
636 return (0);
637
638 atexit(cgi_unlink_file);
639
640 /*
641 * Copy file data to the temp file...
642 */
643
644 ptr = line;
645
646 while ((ch = getchar()) != EOF)
647 {
648 *ptr++ = ch;
649
650 if ((ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen))
651 {
652 ptr -= blen;
653 break;
654 }
655
656 if ((ptr - line - blen) >= 8192)
657 {
658 /*
659 * Write out the first 8k of the buffer...
660 */
661
662 write(fd, line, 8192);
663 memmove(line, line + 8192, ptr - line - 8192);
664 ptr -= 8192;
665 }
666 }
667
668 /*
669 * Write the rest of the data and close the temp file...
670 */
671
672 if (ptr > line)
673 write(fd, line, ptr - line);
674
675 close(fd);
676 }
677 else
678 {
679 /*
680 * Just get a form variable; the current code only handles
681 * form values up to 10k in size...
682 */
683
684 ptr = line;
685 end = line + sizeof(line) - 1;
686
687 while ((ch = getchar()) != EOF)
688 {
689 if (ptr < end)
690 *ptr++ = ch;
691
692 if ((ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen))
693 {
694 ptr -= blen;
695 break;
696 }
697 }
698
699 *ptr = '\0';
700
701 /*
702 * Set the form variable...
703 */
704
705 if ((ptr = strrchr(name, '-')) != NULL && isdigit(ptr[1] & 255))
706 {
707 /*
708 * Set a specific index in the array...
709 */
710
711 *ptr++ = '\0';
712 if (line[0])
713 cgiSetArray(name, atoi(ptr) - 1, line);
714 }
715 else if (cgiGetVariable(name))
716 {
717 /*
718 * Add another element in the array...
719 */
720
721 cgiSetArray(name, cgiGetSize(name), line);
722 }
723 else
724 {
725 /*
726 * Just set the line...
727 */
728
729 cgiSetVariable(name, line);
730 }
731 }
732
733 /*
734 * Read the rest of the current line...
735 */
736
737 fgets(line, sizeof(line), stdin);
738
739 /*
740 * Clear the state vars...
741 */
742
743 name[0] = '\0';
744 filename[0] = '\0';
745 mimetype[0] = '\0';
746 }
747 else if (!strncasecmp(line, "Content-Disposition:", 20))
748 {
749 if ((ptr = strstr(line + 20, " name=\"")) != NULL)
750 {
751 strlcpy(name, ptr + 7, sizeof(name));
752
753 if ((ptr = strchr(name, '\"')) != NULL)
754 *ptr = '\0';
755 }
756
757 if ((ptr = strstr(line + 20, " filename=\"")) != NULL)
758 {
759 strlcpy(filename, ptr + 11, sizeof(filename));
760
761 if ((ptr = strchr(filename, '\"')) != NULL)
762 *ptr = '\0';
763 }
764 }
765 else if (!strncasecmp(line, "Content-Type:", 13))
766 {
767 for (ptr = line + 13; isspace(*ptr & 255); ptr ++);
768
769 strlcpy(mimetype, ptr, sizeof(mimetype));
770
771 for (ptr = mimetype + strlen(mimetype) - 1;
772 ptr > mimetype && isspace(*ptr & 255);
773 *ptr-- = '\0');
774 }
775 }
776
777 /*
778 * Return 1 for "form data found"...
779 */
780
781 return (1);
782 }
783
784
785 /*
786 * 'cgi_initialize_post()' - Initialize variables using the POST method.
787 */
788
789 static int /* O - 1 if form data was read */
790 cgi_initialize_post(void)
791 {
792 char *content_length, /* Length of input data (string) */
793 *data; /* Pointer to form data string */
794 int length, /* Length of input data */
795 nbytes, /* Number of bytes read this read() */
796 tbytes, /* Total number of bytes read */
797 status; /* Return status */
798
799
800 DEBUG_puts("cgi_initialize_post: Initializing variables using POST method...");
801
802 /*
803 * Check to see if there is anything for us to read...
804 */
805
806 content_length = getenv("CONTENT_LENGTH");
807 if (content_length == NULL || atoi(content_length) <= 0)
808 return (0);
809
810 /*
811 * Get the length of the input stream and allocate a buffer for it...
812 */
813
814 length = atoi(content_length);
815 data = malloc(length + 1);
816
817 if (data == NULL)
818 return (0);
819
820 /*
821 * Read the data into the buffer...
822 */
823
824 for (tbytes = 0; tbytes < length; tbytes += nbytes)
825 if ((nbytes = read(0, data + tbytes, length - tbytes)) < 0)
826 {
827 if (errno != EAGAIN)
828 {
829 free(data);
830 return (0);
831 }
832 else
833 nbytes = 0;
834 }
835 else if (nbytes == 0)
836 {
837 /*
838 * CUPS STR #3176: OpenBSD: Early end-of-file on POST data causes 100% CPU
839 *
840 * This should never happen, but does on OpenBSD. If we see early end-of-
841 * file, treat this as an error and process no data.
842 */
843
844 free(data);
845 return (0);
846 }
847
848 data[length] = '\0';
849
850 /*
851 * Parse it out...
852 */
853
854 status = cgi_initialize_string(data);
855
856 /*
857 * Free the data and return...
858 */
859
860 free(data);
861
862 return (status);
863 }
864
865
866 /*
867 * 'cgi_initialize_string()' - Initialize form variables from a string.
868 */
869
870 static int /* O - 1 if form data was processed */
871 cgi_initialize_string(const char *data) /* I - Form data string */
872 {
873 int done; /* True if we're done reading a form variable */
874 char *s, /* Pointer to current form string */
875 ch, /* Temporary character */
876 name[255], /* Name of form variable */
877 value[65536]; /* Variable value... */
878
879
880 /*
881 * Check input...
882 */
883
884 if (data == NULL)
885 return (0);
886
887 /*
888 * Loop until we've read all the form data...
889 */
890
891 while (*data != '\0')
892 {
893 /*
894 * Get the variable name...
895 */
896
897 for (s = name; *data != '\0'; data ++)
898 if (*data == '=')
899 break;
900 else if (*data >= ' ' && s < (name + sizeof(name) - 1))
901 *s++ = *data;
902
903 *s = '\0';
904 if (*data == '=')
905 data ++;
906 else
907 return (0);
908
909 /*
910 * Read the variable value...
911 */
912
913 for (s = value, done = 0; !done && *data != '\0'; data ++)
914 switch (*data)
915 {
916 case '&' : /* End of data... */
917 done = 1;
918 break;
919
920 case '+' : /* Escaped space character */
921 if (s < (value + sizeof(value) - 1))
922 *s++ = ' ';
923 break;
924
925 case '%' : /* Escaped control character */
926 /*
927 * Read the hex code...
928 */
929
930 if (s < (value + sizeof(value) - 1))
931 {
932 data ++;
933 ch = *data - '0';
934 if (ch > 9)
935 ch -= 7;
936 *s = ch << 4;
937
938 data ++;
939 ch = *data - '0';
940 if (ch > 9)
941 ch -= 7;
942 *s++ |= ch;
943 }
944 else
945 data += 2;
946 break;
947
948 default : /* Other characters come straight through */
949 if (*data >= ' ' && s < (value + sizeof(value) - 1))
950 *s++ = *data;
951 break;
952 }
953
954 *s = '\0'; /* nul terminate the string */
955
956 /*
957 * Remove trailing whitespace...
958 */
959
960 if (s > value)
961 s --;
962
963 while (s >= value && isspace(*s & 255))
964 *s-- = '\0';
965
966 /*
967 * Add the string to the variable "database"...
968 */
969
970 if ((s = strrchr(name, '-')) != NULL && isdigit(s[1] & 255))
971 {
972 *s++ = '\0';
973 if (value[0])
974 cgiSetArray(name, atoi(s) - 1, value);
975 }
976 else if (cgiGetVariable(name) != NULL)
977 cgiSetArray(name, cgiGetSize(name), value);
978 else
979 cgiSetVariable(name, value);
980 }
981
982 return (1);
983 }
984
985
986 /*
987 * 'cgi_passwd()' - Catch authentication requests and notify the server.
988 *
989 * This function sends a Status header and exits, forcing authentication
990 * for this request.
991 */
992
993 static const char * /* O - NULL (no return) */
994 cgi_passwd(const char *prompt) /* I - Prompt (not used) */
995 {
996 (void)prompt;
997
998 fprintf(stderr, "DEBUG: cgi_passwd(prompt=\"%s\") called!\n",
999 prompt ? prompt : "(null)");
1000
1001 /*
1002 * Send a 401 (unauthorized) status to the server, so it can notify
1003 * the client that authentication is required.
1004 */
1005
1006 puts("Status: 401\n");
1007 exit(0);
1008
1009 /*
1010 * This code is never executed, but is present to satisfy the compiler.
1011 */
1012
1013 return (NULL);
1014 }
1015
1016
1017 /*
1018 * 'cgi_sort_variables()' - Sort all form variables for faster lookup.
1019 */
1020
1021 static void
1022 cgi_sort_variables(void)
1023 {
1024 #ifdef DEBUG
1025 int i;
1026
1027
1028 DEBUG_puts("cgi_sort_variables: Sorting variables...");
1029 #endif /* DEBUG */
1030
1031 if (form_count < 2)
1032 return;
1033
1034 qsort(form_vars, form_count, sizeof(_cgi_var_t),
1035 (int (*)(const void *, const void *))cgi_compare_variables);
1036
1037 #ifdef DEBUG
1038 DEBUG_puts("cgi_sort_variables: Sorted variable list is:");
1039 for (i = 0; i < form_count; i ++)
1040 DEBUG_printf(("cgi_sort_variables: %d: %s (%d) = \"%s\" ...\n", i,
1041 form_vars[i].name, form_vars[i].nvalues,
1042 form_vars[i].values[0]));
1043 #endif /* DEBUG */
1044 }
1045
1046
1047 /*
1048 * 'cgi_unlink_file()' - Remove the uploaded form.
1049 */
1050
1051 static void
1052 cgi_unlink_file(void)
1053 {
1054 if (form_file)
1055 {
1056 /*
1057 * Remove the temporary file...
1058 */
1059
1060 unlink(form_file->tempfile);
1061
1062 /*
1063 * Free memory used...
1064 */
1065
1066 free(form_file->name);
1067 free(form_file->filename);
1068 free(form_file->mimetype);
1069 free(form_file);
1070
1071 form_file = NULL;
1072 }
1073 }
1074
1075
1076 /*
1077 * End of "$Id: var.c 7460 2008-04-16 02:19:54Z mike $".
1078 */