]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/var.c
4 * CGI form variable and array functions.
6 * Copyright 1997-2005 by Easy Software Products.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * cgiInitialize() - Initialize the CGI variable "database"...
25 * cgiIsPOST() - Determine whether this page was POSTed.
26 * cgiCheckVariables() - Check for the presence of "required" variables.
27 * cgiGetArray() - Get an element from a form array...
28 * cgiGetSize() - Get the size of a form array value.
29 * cgiGetVariable() - Get a CGI variable from the database...
30 * cgiSetArray() - Set array element N to the specified string.
31 * cgiSetVariable() - Set a CGI variable in the database...
32 * cgi_add_variable() - Add a form variable.
33 * cgi_compare_variables() - Compare two variables.
34 * cgi_find_variable() - Find a variable...
35 * cgi_initialize_get() - Initialize form variables using the GET method.
36 * cgi_initialize_post() - Initialize variables using the POST method.
37 * cgi_initialize_string() - Initialize form variables from a string.
38 * cgi_sort_variables() - Sort all form variables for faster lookup.
43 #include <cups/cups.h>
49 * Data structure to hold all the CGI form variables and arrays...
54 const char *name
; /* Name of variable */
55 int nvalues
, /* Number of values */
56 avalues
; /* Number of values allocated */
57 const char **values
; /* Value(s) of variable */
65 static int form_count
= 0, /* Form variable count */
66 form_alloc
= 0; /* Number of variables allocated */
67 static var_t
*form_vars
= NULL
; /* Form variables */
74 static void cgi_add_variable(const char *name
, int element
,
76 static int cgi_compare_variables(const var_t
*v1
, const var_t
*v2
);
77 static var_t
*cgi_find_variable(const char *name
);
78 static int cgi_initialize_get(void);
79 static int cgi_initialize_post(void);
80 static int cgi_initialize_string(const char *data
);
81 static const char *cgi_passwd(const char *prompt
);
82 static void cgi_sort_variables(void);
86 * 'cgiInitialize()' - Initialize the CGI variable "database"...
89 int /* O - Non-zero if there was form data */
92 const char *method
; /* Form posting method */
96 * Setup a password callback for authentication...
99 cupsSetPasswordCB(cgi_passwd
);
103 * Disable output buffering to find bugs...
106 setbuf(stdout
, NULL
);
107 puts("Content-type: text/plain\n");
111 * Get the request method (GET or POST)...
114 method
= getenv("REQUEST_METHOD");
120 * Grab form data from the corresponding location...
123 if (!strcasecmp(method
, "GET"))
124 return (cgi_initialize_get());
125 else if (!strcasecmp(method
, "POST"))
126 return (cgi_initialize_post());
133 * 'cgiCheckVariables()' - Check for the presence of "required" variables.
135 * Names may be separated by spaces and/or commas.
138 int /* O - 1 if all variables present, 0 otherwise */
139 cgiCheckVariables(const char *names
) /* I - Variables to look for */
141 char name
[255], /* Current variable name */
142 *s
; /* Pointer in string */
143 const char *val
; /* Value of variable */
144 int element
; /* Array element number */
150 while (*names
!= '\0')
152 while (*names
== ' ' || *names
== ',')
155 for (s
= name
; *names
!= '\0' && *names
!= ' ' && *names
!= ','; s
++, names
++)
162 if ((s
= strrchr(name
, '-')) != NULL
)
165 element
= atoi(s
+ 1) - 1;
166 val
= cgiGetArray(name
, element
);
169 val
= cgiGetVariable(name
);
175 return (0); /* Can't be blank, either! */
183 * 'cgiIsPOST()' - Determine whether this page was POSTed.
186 int /* O - 1 if POST, 0 if GET */
189 const char *method
; /* REQUEST_METHOD environment variable */
192 if ((method
= getenv("REQUEST_METHOD")) == NULL
)
195 return (!strcmp(method
, "POST"));
200 * 'cgiGetArray()' - Get an element from a form array...
203 const char * /* O - Element value or NULL */
204 cgiGetArray(const char *name
, /* I - Name of array variable */
205 int element
) /* I - Element number (0 to N) */
207 var_t
*var
; /* Pointer to variable */
210 if ((var
= cgi_find_variable(name
)) == NULL
)
213 if (var
->nvalues
== 1)
214 return (var
->values
[0]);
216 if (element
< 0 || element
>= var
->nvalues
)
219 return (var
->values
[element
]);
224 * 'cgiGetSize()' - Get the size of a form array value.
227 int /* O - Number of elements */
228 cgiGetSize(const char *name
) /* I - Name of variable */
230 var_t
*var
; /* Pointer to variable */
233 if ((var
= cgi_find_variable(name
)) == NULL
)
236 return (var
->nvalues
);
241 * 'cgiGetVariable()' - Get a CGI variable from the database...
243 * Returns NULL if the variable doesn't exist... If the variable is an
244 * array of values, returns the last element...
247 const char * /* O - Value of variable */
248 cgiGetVariable(const char *name
)/* I - Name of variable */
250 const var_t
*var
; /* Returned variable */
253 var
= cgi_find_variable(name
);
257 printf("cgiGetVariable(\"%s\") is returning NULL...\n", name
);
259 printf("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name
,
260 var
->values
[var
->nvalues
- 1]);
263 return ((var
== NULL
) ? NULL
: var
->values
[var
->nvalues
- 1]);
268 * 'cgiSetArray()' - Set array element N to the specified string.
270 * If the variable array is smaller than (element + 1), the intervening
271 * elements are set to NULL.
275 cgiSetArray(const char *name
, /* I - Name of variable */
276 int element
, /* I - Element number (0 to N) */
277 const char *value
) /* I - Value of variable */
279 int i
; /* Looping var */
280 var_t
*var
; /* Returned variable */
283 if (name
== NULL
|| value
== NULL
|| element
< 0 || element
> 100000)
286 if ((var
= cgi_find_variable(name
)) == NULL
)
288 cgi_add_variable(name
, element
, value
);
289 cgi_sort_variables();
293 if (element
>= var
->avalues
)
295 var
->avalues
= element
+ 16;
296 var
->values
= (const char **)realloc((void *)(var
->values
),
297 sizeof(char *) * var
->avalues
);
300 if (element
>= var
->nvalues
)
302 for (i
= var
->nvalues
; i
< element
; i
++)
303 var
->values
[i
] = NULL
;
305 var
->nvalues
= element
+ 1;
307 else if (var
->values
[element
])
308 free((char *)var
->values
[element
]);
310 var
->values
[element
] = strdup(value
);
316 * 'cgiSetSize()' - Set the array size.
320 cgiSetSize(const char *name
, /* I - Name of variable */
321 int size
) /* I - Number of elements (0 to N) */
323 int i
; /* Looping var */
324 var_t
*var
; /* Returned variable */
327 if (name
== NULL
|| size
< 0 || size
> 100000)
330 if ((var
= cgi_find_variable(name
)) == NULL
)
333 if (size
>= var
->avalues
)
335 var
->avalues
= size
+ 16;
336 var
->values
= (const char **)realloc((void *)(var
->values
),
337 sizeof(char *) * var
->avalues
);
340 if (size
> var
->nvalues
)
342 for (i
= var
->nvalues
; i
< size
; i
++)
343 var
->values
[i
] = NULL
;
345 else if (size
< var
->nvalues
)
347 for (i
= size
; i
< var
->nvalues
; i
++)
349 free((void *)(var
->values
[i
]));
357 * 'cgiSetVariable()' - Set a CGI variable in the database...
359 * If the variable is an array, this truncates the array to a single element.
363 cgiSetVariable(const char *name
, /* I - Name of variable */
364 const char *value
) /* I - Value of variable */
366 int i
; /* Looping var */
367 var_t
*var
; /* Returned variable */
370 if (name
== NULL
|| value
== NULL
)
373 if ((var
= cgi_find_variable(name
)) == NULL
)
375 cgi_add_variable(name
, 0, value
);
376 cgi_sort_variables();
380 for (i
= 0; i
< var
->nvalues
; i
++)
382 free((char *)var
->values
[i
]);
384 var
->values
[0] = strdup(value
);
391 * 'cgi_add_variable()' - Add a form variable.
395 cgi_add_variable(const char *name
, /* I - Variable name */
396 int element
, /* I - Array element number */
397 const char *value
) /* I - Variable value */
399 var_t
*var
; /* New variable */
402 if (name
== NULL
|| value
== NULL
|| element
< 0 || element
> 100000)
406 printf("Adding variable \'%s\' with value \'%s\'...\n", name
, value
);
409 if (form_count
>= form_alloc
)
412 form_vars
= malloc(sizeof(var_t
) * 16);
414 form_vars
= realloc(form_vars
, (form_alloc
+ 16) * sizeof(var_t
));
419 var
= form_vars
+ form_count
;
420 var
->name
= strdup(name
);
421 var
->nvalues
= element
+ 1;
422 var
->avalues
= element
+ 1;
423 var
->values
= calloc(element
+ 1, sizeof(char *));
424 var
->values
[element
] = strdup(value
);
431 * 'cgi_compare_variables()' - Compare two variables.
434 static int /* O - Result of comparison */
435 cgi_compare_variables(const var_t
*v1
, /* I - First variable */
436 const var_t
*v2
) /* I - Second variable */
438 return (strcasecmp(v1
->name
, v2
->name
));
443 * 'cgi_find_variable()' - Find a variable...
446 static var_t
* /* O - Variable pointer or NULL */
447 cgi_find_variable(const char *name
) /* I - Name of variable */
449 var_t key
; /* Search key */
452 if (form_count
< 1 || name
== NULL
)
457 return ((var_t
*)bsearch(&key
, form_vars
, form_count
, sizeof(var_t
),
458 (int (*)(const void *, const void *))cgi_compare_variables
));
463 * 'cgi_initialize_get()' - Initialize form variables using the GET method.
466 static int /* O - 1 if form data read */
467 cgi_initialize_get(void)
469 char *data
; /* Pointer to form data string */
473 puts("Initializing variables using GET method...");
477 * Check to see if there is anything for us to read...
480 data
= getenv("QUERY_STRING");
481 if (data
== NULL
|| strlen(data
) == 0)
485 * Parse it out and return...
488 return (cgi_initialize_string(data
));
493 * 'cgi_initialize_post()' - Initialize variables using the POST method.
496 static int /* O - 1 if form data was read */
497 cgi_initialize_post(void)
499 char *content_length
, /* Length of input data (string) */
500 *data
; /* Pointer to form data string */
501 int length
, /* Length of input data */
502 nbytes
, /* Number of bytes read this read() */
503 tbytes
, /* Total number of bytes read */
504 status
; /* Return status */
508 puts("Initializing variables using POST method...");
512 * Check to see if there is anything for us to read...
515 content_length
= getenv("CONTENT_LENGTH");
516 if (content_length
== NULL
|| atoi(content_length
) <= 0)
520 * Get the length of the input stream and allocate a buffer for it...
523 length
= atoi(content_length
);
524 data
= malloc(length
+ 1);
530 * Read the data into the buffer...
533 for (tbytes
= 0; tbytes
< length
; tbytes
+= nbytes
)
534 if ((nbytes
= read(0, data
+ tbytes
, length
- tbytes
)) < 0)
547 status
= cgi_initialize_string(data
);
550 * Free the data and return...
560 * 'cgi_initialize_string()' - Initialize form variables from a string.
564 cgi_initialize_string(const char *data
) /* I - Form data string */
566 int done
; /* True if we're done reading a form variable */
567 char *s
, /* Pointer to current form string */
568 ch
, /* Temporary character */
569 name
[255], /* Name of form variable */
570 value
[65536]; /* Variable value... */
581 * Loop until we've read all the form data...
584 while (*data
!= '\0')
587 * Get the variable name...
590 for (s
= name
; *data
!= '\0'; data
++)
593 else if (*data
>= ' ' && s
< (name
+ sizeof(name
) - 1))
603 * Read the variable value...
606 for (s
= value
, done
= 0; !done
&& *data
!= '\0'; data
++)
609 case '&' : /* End of data... */
613 case '+' : /* Escaped space character */
614 if (s
< (value
+ sizeof(value
) - 1))
618 case '%' : /* Escaped control character */
620 * Read the hex code...
623 if (s
< (value
+ sizeof(value
) - 1))
641 default : /* Other characters come straight through */
642 if (*data
>= ' ' && s
< (value
+ sizeof(value
) - 1))
647 *s
= '\0'; /* nul terminate the string */
650 * Remove trailing whitespace...
656 while (s
>= value
&& *s
== ' ')
660 * Add the string to the variable "database"...
663 if ((s
= strrchr(name
, '-')) != NULL
&& isdigit(s
[1] & 255))
667 cgiSetArray(name
, atoi(s
) - 1, value
);
669 else if (cgiGetVariable(name
) != NULL
)
670 cgiSetArray(name
, cgiGetSize(name
), value
);
672 cgiSetVariable(name
, value
);
680 * 'cgi_passwd()' - Catch authentication requests and notify the server.
682 * This function sends a Status header and exits, forcing authentication
686 static const char * /* O - NULL (no return) */
687 cgi_passwd(const char *prompt
) /* I - Prompt (not used) */
692 * Send a 401 (unauthorized) status to the server, so it can notify
693 * the client that authentication is required.
696 puts("Status: 401\n");
700 * This code is never executed, but is present to satisfy the compiler.
708 * 'cgi_sort_variables()' - Sort all form variables for faster lookup.
712 cgi_sort_variables(void)
718 puts("Sorting variables...");
724 qsort(form_vars
, form_count
, sizeof(var_t
),
725 (int (*)(const void *, const void *))cgi_compare_variables
);
728 puts("Sorted variable list is:");
729 for (i
= 0; i
< form_count
; i
++)
730 printf("%d: %s (%d) = \"%s\" ...\n", i
, form_vars
[i
].name
,
731 form_vars
[i
].nvalues
, form_vars
[i
].values
[0]);