]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/var.c
2 * CGI form variable and array functions for CUPS.
4 * Copyright © 2007-2019 by Apple Inc.
5 * Copyright © 1997-2005 by Easy Software Products.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers...
16 #include "cgi-private.h"
17 #include <cups/http.h>
24 #define CUPS_SID "org.cups.sid"
28 * Data structure to hold all the CGI form variables and arrays...
31 typedef struct /**** Form variable structure ****/
33 char *name
; /* Name of variable */
34 int nvalues
, /* Number of values */
35 avalues
; /* Number of values allocated */
36 char **values
; /* Value(s) of variable */
44 static int num_cookies
= 0;/* Number of cookies */
45 static cups_option_t
*cookies
= NULL
;/* Cookies */
46 static int form_count
= 0, /* Form variable count */
47 form_alloc
= 0; /* Number of variables allocated */
48 static _cgi_var_t
*form_vars
= NULL
;
50 static cgi_file_t
*form_file
= NULL
;
58 static void cgi_add_variable(const char *name
, int element
,
60 static int cgi_compare_variables(const _cgi_var_t
*v1
,
61 const _cgi_var_t
*v2
);
62 static _cgi_var_t
*cgi_find_variable(const char *name
);
63 static void cgi_initialize_cookies(void);
64 static int cgi_initialize_get(void);
65 static int cgi_initialize_multipart(const char *boundary
);
66 static int cgi_initialize_post(void);
67 static int cgi_initialize_string(const char *data
);
68 static const char *cgi_passwd(const char *prompt
);
69 static const char *cgi_set_sid(void);
70 static void cgi_sort_variables(void);
71 static void cgi_unlink_file(void);
75 * 'cgiCheckVariables()' - Check for the presence of "required" variables.
77 * Names may be separated by spaces and/or commas.
80 int /* O - 1 if all variables present, 0 otherwise */
81 cgiCheckVariables(const char *names
) /* I - Variables to look for */
83 char name
[255], /* Current variable name */
84 *s
; /* Pointer in string */
85 const char *val
; /* Value of variable */
86 int element
; /* Array element number */
92 while (*names
!= '\0')
94 while (*names
== ' ' || *names
== ',')
97 for (s
= name
; *names
!= '\0' && *names
!= ' ' && *names
!= ','; s
++, names
++)
104 if ((s
= strrchr(name
, '-')) != NULL
)
107 element
= atoi(s
+ 1) - 1;
108 val
= cgiGetArray(name
, element
);
111 val
= cgiGetVariable(name
);
119 return (0); /* Can't be blank, either! */
130 * 'cgiClearVariables()' - Clear all form variables.
134 cgiClearVariables(void)
136 int i
, j
; /* Looping vars */
137 _cgi_var_t
*v
; /* Current variable */
140 fputs("DEBUG: cgiClearVariables called.\n", stderr
);
142 for (v
= form_vars
, i
= form_count
; i
> 0; v
++, i
--)
145 for (j
= 0; j
< v
->nvalues
; j
++)
157 * 'cgiGetArray()' - Get an element from a form array.
160 char * /* O - Element value or NULL */
161 cgiGetArray(const char *name
, /* I - Name of array variable */
162 int element
) /* I - Element number (0 to N) */
164 _cgi_var_t
*var
; /* Pointer to variable */
167 if ((var
= cgi_find_variable(name
)) == NULL
)
170 if (element
< 0 || element
>= var
->nvalues
)
173 if (var
->values
[element
] == NULL
)
176 return (strdup(var
->values
[element
]));
181 * 'cgiGetCookie()' - Get a cookie value.
184 const char * /* O - Value or NULL */
185 cgiGetCookie(const char *name
) /* I - Name of cookie */
187 return (cupsGetOption(name
, num_cookies
, cookies
));
192 * 'cgiGetFile()' - Get the file (if any) that was submitted in the form.
195 const cgi_file_t
* /* O - Attached file or NULL */
203 * 'cgiGetSize()' - Get the size of a form array value.
206 int /* O - Number of elements */
207 cgiGetSize(const char *name
) /* I - Name of variable */
209 _cgi_var_t
*var
; /* Pointer to variable */
212 if ((var
= cgi_find_variable(name
)) == NULL
)
215 return (var
->nvalues
);
220 * 'cgiGetVariable()' - Get a CGI variable from the database.
222 * Returns NULL if the variable doesn't exist. If the variable is an
223 * array of values, returns the last element.
226 char * /* O - Value of variable */
227 cgiGetVariable(const char *name
) /* I - Name of variable */
229 const _cgi_var_t
*var
; /* Returned variable */
232 var
= cgi_find_variable(name
);
234 return ((var
== NULL
) ? NULL
: strdup(var
->values
[var
->nvalues
- 1]));
239 * 'cgiInitialize()' - Initialize the CGI variable "database".
242 int /* O - Non-zero if there was form data */
245 const char *method
, /* Form posting method */
246 *content_type
, /* Content-Type of post data */
247 *cups_sid_cookie
, /* SID cookie */
248 *cups_sid_form
; /* SID form variable */
252 * Setup a password callback for authentication...
255 cupsSetPasswordCB(cgi_passwd
);
258 * Set the locale so that times, etc. are formatted properly...
261 setlocale(LC_ALL
, "");
265 * Disable output buffering to find bugs...
268 setbuf(stdout
, NULL
);
275 cgi_initialize_cookies();
277 if ((cups_sid_cookie
= cgiGetCookie(CUPS_SID
)) == NULL
)
279 fputs("DEBUG: " CUPS_SID
" cookie not found, initializing!\n", stderr
);
280 cups_sid_cookie
= cgi_set_sid();
283 fprintf(stderr
, "DEBUG: " CUPS_SID
" cookie is \"%s\"\n", cups_sid_cookie
);
286 * Get the request method (GET or POST)...
289 method
= getenv("REQUEST_METHOD");
290 content_type
= getenv("CONTENT_TYPE");
295 * Grab form data from the corresponding location...
298 if (!_cups_strcasecmp(method
, "GET"))
299 return (cgi_initialize_get());
300 else if (!_cups_strcasecmp(method
, "POST") && content_type
)
302 const char *boundary
= strstr(content_type
, "boundary=");
307 if (content_type
&& !strncmp(content_type
, "multipart/form-data; ", 21))
309 if (!cgi_initialize_multipart(boundary
))
312 else if (!cgi_initialize_post())
315 if ((cups_sid_form
= cgiGetVariable(CUPS_SID
)) == NULL
||
316 strcmp(cups_sid_cookie
, cups_sid_form
))
319 fprintf(stderr
, "DEBUG: " CUPS_SID
" form variable is \"%s\"\n",
322 fputs("DEBUG: " CUPS_SID
" form variable is not present.\n", stderr
);
324 free((void *)cups_sid_form
);
332 free((void *)cups_sid_form
);
343 * 'cgiIsPOST()' - Determine whether this page was POSTed.
346 int /* O - 1 if POST, 0 if GET */
349 const char *method
; /* REQUEST_METHOD environment variable */
352 if ((method
= getenv("REQUEST_METHOD")) == NULL
)
355 return (!strcmp(method
, "POST"));
360 * 'cgiSetArray()' - Set array element N to the specified string.
362 * If the variable array is smaller than (element + 1), the intervening
363 * elements are set to NULL.
367 cgiSetArray(const char *name
, /* I - Name of variable */
368 int element
, /* I - Element number (0 to N) */
369 const char *value
) /* I - Value of variable */
371 int i
; /* Looping var */
372 _cgi_var_t
*var
; /* Returned variable */
375 if (name
== NULL
|| value
== NULL
|| element
< 0 || element
> 100000)
378 fprintf(stderr
, "DEBUG: cgiSetArray: %s[%d]=\"%s\"\n", name
, element
, value
);
380 if ((var
= cgi_find_variable(name
)) == NULL
)
382 cgi_add_variable(name
, element
, value
);
383 cgi_sort_variables();
387 if (element
>= var
->avalues
)
389 char **temp
; /* Temporary pointer */
391 temp
= (char **)realloc((void *)(var
->values
), sizeof(char *) * (size_t)(element
+ 16));
395 var
->avalues
= element
+ 16;
399 if (element
>= var
->nvalues
)
401 for (i
= var
->nvalues
; i
< element
; i
++)
402 var
->values
[i
] = NULL
;
404 var
->nvalues
= element
+ 1;
406 else if (var
->values
[element
])
407 free((char *)var
->values
[element
]);
409 var
->values
[element
] = strdup(value
);
415 * 'cgiSetCookie()' - Set a cookie value.
419 cgiSetCookie(const char *name
, /* I - Name */
420 const char *value
, /* I - Value */
421 const char *path
, /* I - Path (typically "/") */
422 const char *domain
, /* I - Domain name */
423 time_t expires
, /* I - Expiration date (0 for session) */
424 int secure
) /* I - Require SSL */
426 num_cookies
= cupsAddOption(name
, value
, num_cookies
, &cookies
);
428 printf("Set-Cookie: %s=%s;", name
, value
);
430 printf(" path=%s;", path
);
432 printf(" domain=%s;", domain
);
435 char date
[256]; /* Date string */
437 printf(" expires=%s;", httpGetDateString2(expires
, date
, sizeof(date
)));
440 puts(" httponly; secure;");
447 * 'cgiSetSize()' - Set the array size.
451 cgiSetSize(const char *name
, /* I - Name of variable */
452 int size
) /* I - Number of elements (0 to N) */
454 int i
; /* Looping var */
455 _cgi_var_t
*var
; /* Returned variable */
458 if (name
== NULL
|| size
< 0 || size
> 100000)
461 if ((var
= cgi_find_variable(name
)) == NULL
)
464 if (size
>= var
->avalues
)
466 char **temp
; /* Temporary pointer */
468 temp
= (char **)realloc((void *)(var
->values
), sizeof(char *) * (size_t)(size
+ 16));
472 var
->avalues
= size
+ 16;
476 if (size
> var
->nvalues
)
478 for (i
= var
->nvalues
; i
< size
; i
++)
479 var
->values
[i
] = NULL
;
481 else if (size
< var
->nvalues
)
483 for (i
= size
; i
< var
->nvalues
; i
++)
485 free((void *)(var
->values
[i
]));
493 * 'cgiSetVariable()' - Set a CGI variable in the database.
495 * If the variable is an array, this truncates the array to a single element.
499 cgiSetVariable(const char *name
, /* I - Name of variable */
500 const char *value
) /* I - Value of variable */
502 int i
; /* Looping var */
503 _cgi_var_t
*var
; /* Returned variable */
506 if (name
== NULL
|| value
== NULL
)
509 fprintf(stderr
, "cgiSetVariable: %s=\"%s\"\n", name
, value
);
511 if ((var
= cgi_find_variable(name
)) == NULL
)
513 cgi_add_variable(name
, 0, value
);
514 cgi_sort_variables();
518 for (i
= 0; i
< var
->nvalues
; i
++)
520 free((char *)var
->values
[i
]);
522 var
->values
[0] = strdup(value
);
529 * 'cgi_add_variable()' - Add a form variable.
533 cgi_add_variable(const char *name
, /* I - Variable name */
534 int element
, /* I - Array element number */
535 const char *value
) /* I - Variable value */
537 _cgi_var_t
*var
; /* New variable */
540 if (name
== NULL
|| value
== NULL
|| element
< 0 || element
> 100000)
543 if (form_count
>= form_alloc
)
545 _cgi_var_t
*temp_vars
; /* Temporary form pointer */
549 temp_vars
= malloc(sizeof(_cgi_var_t
) * 16);
551 temp_vars
= realloc(form_vars
, (size_t)(form_alloc
+ 16) * sizeof(_cgi_var_t
));
556 form_vars
= temp_vars
;
560 var
= form_vars
+ form_count
;
562 if ((var
->values
= calloc((size_t)element
+ 1, sizeof(char *))) == NULL
)
565 var
->name
= strdup(name
);
566 var
->nvalues
= element
+ 1;
567 var
->avalues
= element
+ 1;
568 var
->values
[element
] = strdup(value
);
575 * 'cgi_compare_variables()' - Compare two variables.
578 static int /* O - Result of comparison */
579 cgi_compare_variables(
580 const _cgi_var_t
*v1
, /* I - First variable */
581 const _cgi_var_t
*v2
) /* I - Second variable */
583 return (_cups_strcasecmp(v1
->name
, v2
->name
));
588 * 'cgi_find_variable()' - Find a variable.
591 static _cgi_var_t
* /* O - Variable pointer or NULL */
592 cgi_find_variable(const char *name
) /* I - Name of variable */
594 _cgi_var_t key
; /* Search key */
597 if (form_count
< 1 || name
== NULL
)
600 key
.name
= (char *)name
;
602 return ((_cgi_var_t
*)bsearch(&key
, form_vars
, (size_t)form_count
, sizeof(_cgi_var_t
),
603 (int (*)(const void *, const void *))cgi_compare_variables
));
608 * 'cgi_initialize_cookies()' - Initialize cookies.
612 cgi_initialize_cookies(void)
614 const char *cookie
; /* HTTP_COOKIE environment variable */
615 char name
[128], /* Name string */
616 value
[512], /* Value string */
617 *ptr
; /* Pointer into name/value */
620 if ((cookie
= getenv("HTTP_COOKIE")) == NULL
)
625 int skip
= 0; /* Skip this cookie? */
628 * Skip leading whitespace...
631 while (isspace(*cookie
& 255))
640 for (ptr
= name
; *cookie
&& *cookie
!= '=';)
641 if (ptr
< (name
+ sizeof(name
) - 1))
663 for (cookie
++, ptr
= value
; *cookie
&& *cookie
!= '\"';)
664 if (ptr
< (value
+ sizeof(value
) - 1))
681 for (ptr
= value
; *cookie
&& *cookie
!= ';';)
682 if (ptr
< (value
+ sizeof(value
) - 1))
701 * Then add the cookie to an array as long as the name doesn't start with
705 if (name
[0] != '$' && !skip
)
706 num_cookies
= cupsAddOption(name
, value
, num_cookies
, &cookies
);
712 * 'cgi_initialize_get()' - Initialize form variables using the GET method.
715 static int /* O - 1 if form data read */
716 cgi_initialize_get(void)
718 char *data
; /* Pointer to form data string */
722 * Check to see if there is anything for us to read...
725 data
= getenv("QUERY_STRING");
726 if (data
== NULL
|| strlen(data
) == 0)
730 * Parse it out and return...
733 return (cgi_initialize_string(data
));
738 * 'cgi_initialize_multipart()' - Initialize variables and file using the POST
741 * TODO: Update to support files > 2GB.
744 static int /* O - 1 if form data was read */
745 cgi_initialize_multipart(
746 const char *boundary
) /* I - Boundary string */
748 char line
[10240], /* MIME header line */
749 name
[1024], /* Form variable name */
750 filename
[1024], /* Form filename */
751 mimetype
[1024], /* MIME media type */
752 bstring
[256], /* Boundary string to look for */
753 *ptr
, /* Pointer into name/filename */
754 *end
; /* End of buffer */
755 int ch
, /* Character from file */
756 fd
; /* Temporary file descriptor */
757 size_t blen
; /* Length of boundary string */
761 * Read multipart form data until we run out...
768 snprintf(bstring
, sizeof(bstring
), "\r\n--%s", boundary
);
769 blen
= strlen(bstring
);
771 while (fgets(line
, sizeof(line
), stdin
))
773 if (!strcmp(line
, "\r\n"))
776 * End of headers, grab value...
782 * Read an embedded file...
788 * Remove previous file...
795 * Allocate memory for the new file...
798 if ((form_file
= calloc(1, sizeof(cgi_file_t
))) == NULL
)
801 form_file
->name
= strdup(name
);
802 form_file
->filename
= strdup(filename
);
803 form_file
->mimetype
= strdup(mimetype
);
805 fd
= cupsTempFd(form_file
->tempfile
, sizeof(form_file
->tempfile
));
810 atexit(cgi_unlink_file
);
813 * Copy file data to the temp file...
818 while ((ch
= getchar()) != EOF
)
822 if ((size_t)(ptr
- line
) >= blen
&& !memcmp(ptr
- blen
, bstring
, blen
))
828 if ((ptr
- line
- (int)blen
) >= 8192)
831 * Write out the first 8k of the buffer...
834 write(fd
, line
, 8192);
835 memmove(line
, line
+ 8192, (size_t)(ptr
- line
- 8192));
841 * Write the rest of the data and close the temp file...
845 write(fd
, line
, (size_t)(ptr
- line
));
852 * Just get a form variable; the current code only handles
853 * form values up to 10k in size...
857 end
= line
+ sizeof(line
) - 1;
859 while ((ch
= getchar()) != EOF
)
864 if ((size_t)(ptr
- line
) >= blen
&& !memcmp(ptr
- blen
, bstring
, blen
))
874 * Set the form variable...
877 if ((ptr
= strrchr(name
, '-')) != NULL
&& isdigit(ptr
[1] & 255))
880 * Set a specific index in the array...
885 cgiSetArray(name
, atoi(ptr
) - 1, line
);
887 else if ((ptr
= cgiGetVariable(name
)) != NULL
)
890 * Add another element in the array...
894 cgiSetArray(name
, cgiGetSize(name
), line
);
899 * Just set the line...
902 cgiSetVariable(name
, line
);
907 * Read the rest of the current line...
910 fgets(line
, sizeof(line
), stdin
);
913 * Clear the state vars...
920 else if (!_cups_strncasecmp(line
, "Content-Disposition:", 20))
922 if ((ptr
= strstr(line
+ 20, " name=\"")) != NULL
)
924 strlcpy(name
, ptr
+ 7, sizeof(name
));
926 if ((ptr
= strchr(name
, '\"')) != NULL
)
930 if ((ptr
= strstr(line
+ 20, " filename=\"")) != NULL
)
932 strlcpy(filename
, ptr
+ 11, sizeof(filename
));
934 if ((ptr
= strchr(filename
, '\"')) != NULL
)
938 else if (!_cups_strncasecmp(line
, "Content-Type:", 13))
940 for (ptr
= line
+ 13; isspace(*ptr
& 255); ptr
++);
942 strlcpy(mimetype
, ptr
, sizeof(mimetype
));
944 for (ptr
= mimetype
+ strlen(mimetype
) - 1;
945 ptr
> mimetype
&& isspace(*ptr
& 255);
951 * Return 1 for "form data found"...
959 * 'cgi_initialize_post()' - Initialize variables using the POST method.
962 static int /* O - 1 if form data was read */
963 cgi_initialize_post(void)
965 char *content_length
, /* Length of input data (string) */
966 *data
; /* Pointer to form data string */
967 size_t length
, /* Length of input data */
968 tbytes
; /* Total number of bytes read */
969 ssize_t nbytes
; /* Number of bytes read this read() */
970 int status
; /* Return status */
974 * Check to see if there is anything for us to read...
977 content_length
= getenv("CONTENT_LENGTH");
978 if (content_length
== NULL
|| atoi(content_length
) <= 0)
982 * Get the length of the input stream and allocate a buffer for it...
985 length
= (size_t)strtol(content_length
, NULL
, 10);
986 data
= malloc(length
+ 1); // lgtm [cpp/uncontrolled-allocation-size]
992 * Read the data into the buffer...
995 for (tbytes
= 0; tbytes
< length
; tbytes
+= (size_t)nbytes
)
996 if ((nbytes
= read(0, data
+ tbytes
, (size_t)(length
- tbytes
))) < 0)
1006 else if (nbytes
== 0)
1009 * CUPS STR #3176: OpenBSD: Early end-of-file on POST data causes 100% CPU
1011 * This should never happen, but does on OpenBSD. If we see early end-of-
1012 * file, treat this as an error and process no data.
1019 data
[length
] = '\0';
1025 status
= cgi_initialize_string(data
);
1028 * Free the data and return...
1038 * 'cgi_initialize_string()' - Initialize form variables from a string.
1041 static int /* O - 1 if form data was processed */
1042 cgi_initialize_string(const char *data
) /* I - Form data string */
1044 int done
; /* True if we're done reading a form variable */
1045 char *s
, /* Pointer to current form string */
1046 ch
, /* Temporary character */
1047 name
[255], /* Name of form variable */
1048 value
[65536], /* Variable value */
1049 *temp
; /* Temporary pointer */
1060 * Loop until we've read all the form data...
1063 while (*data
!= '\0')
1066 * Get the variable name...
1069 for (s
= name
; *data
!= '\0'; data
++)
1072 else if (*data
>= ' ' && s
< (name
+ sizeof(name
) - 1))
1082 * Read the variable value...
1085 for (s
= value
, done
= 0; !done
&& *data
!= '\0'; data
++)
1088 case '&' : /* End of data... */
1092 case '+' : /* Escaped space character */
1093 if (s
< (value
+ sizeof(value
) - 1))
1097 case '%' : /* Escaped control character */
1099 * Read the hex code...
1102 if (!isxdigit(data
[1] & 255) || !isxdigit(data
[2] & 255))
1105 if (s
< (value
+ sizeof(value
) - 1))
1111 *s
= (char)(ch
<< 4);
1123 default : /* Other characters come straight through */
1124 if (*data
>= ' ' && s
< (value
+ sizeof(value
) - 1))
1129 *s
= '\0'; /* nul terminate the string */
1132 * Remove trailing whitespace...
1138 while (s
>= value
&& isspace(*s
& 255))
1142 * Add the string to the variable "database"...
1145 if ((s
= strrchr(name
, '-')) != NULL
&& isdigit(s
[1] & 255))
1149 cgiSetArray(name
, atoi(s
) - 1, value
);
1151 else if ((temp
= cgiGetVariable(name
)) != NULL
)
1154 cgiSetArray(name
, cgiGetSize(name
), value
);
1157 cgiSetVariable(name
, value
);
1165 * 'cgi_passwd()' - Catch authentication requests and notify the server.
1167 * This function sends a Status header and exits, forcing authentication
1171 static const char * /* O - NULL (no return) */
1172 cgi_passwd(const char *prompt
) /* I - Prompt (not used) */
1176 fprintf(stderr
, "DEBUG: cgi_passwd(prompt=\"%s\") called!\n",
1177 prompt
? prompt
: "(null)");
1180 * Send a 401 (unauthorized) status to the server, so it can notify
1181 * the client that authentication is required.
1184 puts("Status: 401\n");
1188 * This code is never executed, but is present to satisfy the compiler.
1196 * 'cgi_set_sid()' - Set the CUPS session ID.
1199 static const char * /* O - New session ID */
1202 char buffer
[512], /* SID data */
1203 sid
[33]; /* SID string */
1204 unsigned char sum
[16]; /* MD5 sum */
1205 const char *remote_addr
, /* REMOTE_ADDR */
1206 *server_name
, /* SERVER_NAME */
1207 *server_port
; /* SERVER_PORT */
1208 struct timeval curtime
; /* Current time */
1211 if ((remote_addr
= getenv("REMOTE_ADDR")) == NULL
)
1212 remote_addr
= "REMOTE_ADDR";
1213 if ((server_name
= getenv("SERVER_NAME")) == NULL
)
1214 server_name
= "SERVER_NAME";
1215 if ((server_port
= getenv("SERVER_PORT")) == NULL
)
1216 server_port
= "SERVER_PORT";
1218 gettimeofday(&curtime
, NULL
);
1219 CUPS_SRAND(curtime
.tv_sec
+ curtime
.tv_usec
);
1220 snprintf(buffer
, sizeof(buffer
), "%s:%s:%s:%02X%02X%02X%02X%02X%02X%02X%02X",
1221 remote_addr
, server_name
, server_port
,
1222 (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
1223 (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
1224 (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
1225 (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255);
1226 cupsHashData("md5", (unsigned char *)buffer
, strlen(buffer
), sum
, sizeof(sum
));
1228 cgiSetCookie(CUPS_SID
, cupsHashString(sum
, sizeof(sum
), sid
, sizeof(sid
)), "/", NULL
, 0, 0);
1230 return (cupsGetOption(CUPS_SID
, num_cookies
, cookies
));
1235 * 'cgi_sort_variables()' - Sort all form variables for faster lookup.
1239 cgi_sort_variables(void)
1244 qsort(form_vars
, (size_t)form_count
, sizeof(_cgi_var_t
),
1245 (int (*)(const void *, const void *))cgi_compare_variables
);
1250 * 'cgi_unlink_file()' - Remove the uploaded form.
1254 cgi_unlink_file(void)
1259 * Remove the temporary file...
1262 unlink(form_file
->tempfile
);
1265 * Free memory used...
1268 free(form_file
->name
);
1269 free(form_file
->filename
);
1270 free(form_file
->mimetype
);