| iMatix home page | << | < | > | >> |
SFL Version 2.11 |
#include "sflhttp.h" DESCR * http_multipart_decode (const char *mime_file, const char *store_path, const char *local_format)
Parses a multipart-encoded file (as received by a web server as POST data) and returns a HTTP-encoded string containing the field data, in the format: "name=value&name=value&name=value...". For each field that refers to an uploaded file (INPUT field with type FILE), creates a temporary file holding the data. The name of this temporary file is put into a generated variable, whose name is built by using the local format string (ex: '%s_tmp'). The actual uploaded file is stored in a temporary file whose name is generated by the SFL get tmp file name() function. So, data for a file upload field called "doc" will be stored in a temporary file called (eg) "temp1234.tmp", and a field "doc_tmp" will be added, with the value "temp1234.tmp". The HTTP-encoded string is returned as a DESCR block, which you can decode using http query2strt(), passing the descriptor data. You must free the descriptor using mem_free() when you're finished with it.
{ FILE *f_source, *f_tmp = NULL; char *tmp_name = NULL, *p_head, *p_data, *p_next, *buffer; int offset, read_size, rest_read_size; static char separator [80 + 1]; static int sep_size; SYMTAB *table, *header_tab; qbyte tmp_index = 1; DESCR *descr = NULL; ASSERT (local_format); if (strstr (local_format, "%s") == NULL) return (NULL); buffer = mem_alloc (MULTI_BUFFER_SIZE + REST_BUFFER_SIZE + 1); if (buffer == NULL) return (NULL); table = sym create table (); if (table == NULL) { mem_free (buffer); return (NULL); } header_tab = sym create table (); if (header_tab == NULL) { mem_free (buffer); sym delete table (table); return (NULL); } f_source = fopen (mime_file, "rb"); if (f_source == NULL) { mem_free (buffer); sym delete table (table); sym delete table (header_tab); return (NULL); } memset (separator, 0, sizeof (separator)); separator [0] = 0x0D; separator [1] = 0x0A; fgets (&separator [2], 78, f_source); strconvch (&separator [2] , '\r', '\0'); strconvch (&separator [2] , '\n', '\0'); sep_size = strlen (separator); read_size = fread (buffer, 1, MULTI_BUFFER_SIZE, f_source); p_next = buffer; while (read_size > 0) { sym empty table (header_tab); p_head = p_next; p_data = (char *) memfind ((byte *) p_head, MULTI_BUFFER_SIZE + REST_BUFFER_SIZE - (p_head - buffer), (byte *) "\r\n\r\n", 4, FALSE); if (p_data) { *p_data = '\0'; p_data += 4; } if (p_head) { multipart_decode_header (p_head, header_tab); if (sym lookup symbol (header_tab, "filename") != NULL) { if (f_tmp != NULL) { ASSERT (tmp_name != NULL); fclose (f_tmp); f_tmp = NULL; if (get file size (tmp_name) == 0) file delete (tmp_name); } tmp_name = get tmp file name (store_path, &tmp_index, "tmp"); f_tmp = fopen (tmp_name, "wb"); } } p_next = (char *) memfind ((byte *) p_data, /* read_size */ MULTI_BUFFER_SIZE + REST_BUFFER_SIZE - (p_data - buffer), (byte *) separator, sep_size, FALSE); if (p_next != NULL) { /* The next attribute-value pair was found */ *p_next = '\0'; save_multipart_header (table, header_tab, p_data, tmp_name, local_format); if (f_tmp) { /* Special case: The next attribute value is found AND "f_tmp" is opened. That means that the download file is completely in the buffer and so we can save it to disk. */ fwrite (p_data, p_next - p_data, 1, f_tmp); fclose (f_tmp); f_tmp = NULL; if (get file size (tmp_name) == 0) file delete (tmp_name); /* Now we need to check the buffer. If the buffer is full then we must read the rest of "f_source". The rest will be written into the the buffer at REST_BUFFER_SIZE. */ if (read_size == MULTI_BUFFER_SIZE) rest_read_size = fread (&buffer [MULTI_BUFFER_SIZE], 1, REST_BUFFER_SIZE, f_source); } p_next += sep_size; /* Found end of file marker */ if (*p_next == '-' && *(p_next + 1) == '-') { if (f_tmp) { fclose (f_tmp); f_tmp = NULL; if (get file size (tmp_name) == 0) file delete (tmp_name); } break; } else while (*p_next == '\r' || *p_next == '\n') p_next++; } else { if (f_tmp) fwrite (p_data, &buffer [read_size - sep_size ] - p_data, 1, f_tmp); offset = 0; while (read_size > 0 && p_next == NULL) { memmove (buffer, &buffer [read_size - sep_size + offset ], sep_size); read_size = fread (&buffer [sep_size], 1, MULTI_BUFFER_SIZE - sep_size, f_source); p_next = (char *) memfind ((byte *) buffer, read_size + sep_size, (byte *) separator, sep_size, FALSE); if (p_next != NULL) { /* We need to test if the buffer is large enough. If not, we use the additional buffer size starting at position REST_BUFFER_SIZE. */ if (read_size == (MULTI_BUFFER_SIZE - sep_size)) { /* Attach the rest of the file */ rest_read_size = fread (&buffer [MULTI_BUFFER_SIZE], 1, REST_BUFFER_SIZE, f_source); } *p_next = '\0'; save_multipart_header (table, header_tab, p_data, tmp_name, local_format); if (f_tmp) { fwrite (buffer, p_next - buffer, 1, f_tmp); fclose (f_tmp); f_tmp = NULL; if (get file size (tmp_name) == 0) file delete (tmp_name); } p_next += sep_size; /* Found end of file marker */ if (*p_next == '-' && *(p_next + 1) == '-') { read_size = 0; break; } else while (*p_next == '\r' || *p_next == '\n') p_next++; read_size += sep_size; } else { /* We did not find the next separator, so we write the file and continue. */ if (f_tmp) fwrite (buffer, read_size, 1, f_tmp); offset = sep_size; } } } } if (f_tmp) { fclose (f_tmp); if (get file size (tmp_name) == 0) file delete (tmp_name); } sym delete table (header_tab); fclose (f_source); mem_free (buffer); descr = http_multipart2url (table); sym delete table (table); return (descr); }
| << | < | > | >> | Copyright © 1996-2000 iMatix Corporation |