aboutsummaryrefslogtreecommitdiffstats
path: root/res/res_http_post.c
diff options
context:
space:
mode:
authordbailey <dbailey@f38db490-d61c-443f-a65b-d21fe96a405b>2008-10-23 15:09:20 +0000
committerdbailey <dbailey@f38db490-d61c-443f-a65b-d21fe96a405b>2008-10-23 15:09:20 +0000
commit4a053dbc117bed6add3f3ac3bc4fa829b2cd9737 (patch)
tree3a871795c25a5b902bc50b00b4305d6d2ce5210a /res/res_http_post.c
parentd0c024c267c2567db71666c580cf98904c53dde9 (diff)
Add patch to handle how IE7 issues POST requests using Window path spec including backslash delimiters
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@151722 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res/res_http_post.c')
-rw-r--r--res/res_http_post.c143
1 files changed, 136 insertions, 7 deletions
diff --git a/res/res_http_post.c b/res/res_http_post.c
index 3e265c4d5..28a78e60a 100644
--- a/res/res_http_post.c
+++ b/res/res_http_post.c
@@ -153,17 +153,140 @@ static int process_message(GMimeMessage *message, const char *post_dir)
return cbinfo.count;
}
+
+/* Find a sequence of bytes within a binary array. */
+static int find_sequence(char * inbuf, int inlen, char * matchbuf, int matchlen)
+{
+ int current;
+ int comp;
+ int found = 0;
+
+ for (current = 0; current < inlen-matchlen; current++, inbuf++) {
+ if (*inbuf == *matchbuf) {
+ found=1;
+ for (comp = 1; comp < matchlen; comp++) {
+ if (inbuf[comp] != matchbuf[comp]) {
+ found = 0;
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ if (found) {
+ return current;
+ } else {
+ return -1;
+ }
+}
+
+/*
+* The following is a work around to deal with how IE7 embeds the local file name
+* within the Mime header using full WINDOWS file path with backslash directory delimiters.
+* This section of code attempts to isolate the directory path and remove it
+* from what is written into the output file. In addition, it changes
+* esc chars (i.e. backslashes) to forward slashes.
+* This function has two modes. The first to find a boundary marker. The
+* second is to find the filename immediately after the boundary.
+*/
+static int readmimefile(FILE * fin, FILE * fout, char * boundary, int contentlen)
+{
+ int find_filename = 0;
+ char buf[4096];
+ int marker;
+ int x;
+ int char_in_buf = 0;
+ int num_to_read;
+ int boundary_len;
+ char * path_end, * path_start, * filespec;
+
+ if (NULL == fin || NULL == fout || NULL == boundary || 0 >= contentlen) {
+ return -1;
+ }
+
+ boundary_len = strlen(boundary);
+ while (0 < contentlen || 0 < char_in_buf) {
+ /* determine how much I will read into the buffer */
+ if (contentlen > sizeof(buf) - char_in_buf) {
+ num_to_read = sizeof(buf)- char_in_buf;
+ } else {
+ num_to_read = contentlen;
+ }
+
+ if(0 < num_to_read) {
+ fread(&(buf[char_in_buf]), 1, num_to_read, fin);
+ contentlen -= num_to_read;
+ char_in_buf += num_to_read;
+ }
+ /* If I am looking for the filename spec */
+ if (find_filename) {
+ path_end = filespec = NULL;
+ x = strlen("filename=\"");
+ marker = find_sequence(buf, char_in_buf, "filename=\"", x );
+ if (0 <= marker) {
+ marker += x; /* Index beyond the filename marker */
+ path_start = &buf[marker];
+ for (path_end = path_start, x = 0; x < char_in_buf-marker; x++, path_end++) {
+ if ('\\' == *path_end) { /* convert backslashses to forward slashes */
+ *path_end = '/';
+ }
+ if ('\"' == *path_end) { /* If at the end of the file name spec */
+ *path_end = '\0'; /* temporarily null terminate the file spec for basename */
+ filespec = basename(path_start);
+ *path_end = '\"';
+ break;
+ }
+ }
+ }
+ if (filespec) { /* If the file name path was found in the header */
+ fwrite(buf, 1, marker, fout);
+ x = (int)(path_end+1 - filespec);
+ fwrite(filespec, 1, x, fout);
+ x = (int)(path_end+1 - buf);
+ memmove(buf, &(buf[x]), char_in_buf-x);
+ char_in_buf -= x;
+ }
+ find_filename = 0;
+ } else { /* I am looking for the boundary marker */
+ marker = find_sequence(buf, char_in_buf, boundary, boundary_len);
+ if (0 > marker) {
+ if (char_in_buf < (boundary_len)) {
+ /*no possibility to find the boundary, write all you have */
+ fwrite(buf, 1, char_in_buf, fout);
+ char_in_buf = 0;
+ } else {
+ /* write all except for area where the boundary marker could be */
+ fwrite(buf, 1, char_in_buf -(boundary_len -1), fout);
+ x = char_in_buf -(boundary_len -1);
+ memmove(buf, &(buf[x]), char_in_buf-x);
+ char_in_buf = (boundary_len -1);
+ }
+ } else {
+ /* write up through the boundary, then look for filename in the rest */
+ fwrite(buf, 1, marker + boundary_len, fout);
+ x = marker + boundary_len;
+ memmove(buf, &(buf[x]), char_in_buf-x);
+ char_in_buf -= marker + boundary_len;
+ find_filename =1;
+ }
+ }
+ }
+ return 0;
+}
+
+
static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength)
{
struct ast_variable *var;
unsigned long ident = 0;
- char buf[4096];
FILE *f;
- size_t res;
int content_len = 0;
struct ast_str *post_dir;
GMimeMessage *message;
int message_count = 0;
+ char * boundary_marker = NULL;
if (!urih) {
return ast_http_error((*status = 400),
@@ -213,17 +336,23 @@ static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *se
return NULL;
}
ast_debug(1, "Got a Content-Length of %d\n", content_len);
+ } else if (!strcasecmp(var->name, "Content-Type")) {
+ boundary_marker = strstr(var->value, "boundary=");
+ if (boundary_marker) {
+ boundary_marker += strlen("boundary=");
+ }
}
}
fprintf(f, "\r\n");
- for (res = sizeof(buf); content_len; content_len -= res) {
- if (content_len < res) {
- res = content_len;
+ if (0 > readmimefile(ser->f, f, boundary_marker, content_len)) {
+ if (option_debug) {
+ ast_log(LOG_DEBUG, "Cannot find boundary marker in POST request.\n");
}
- fread(buf, 1, res, ser->f);
- fwrite(buf, 1, res, f);
+ fclose(f);
+
+ return NULL;
}
if (fseek(f, SEEK_SET, 0)) {