1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
24 #include <curl/curl.h>
28 #define ENABLE_CURLX_PRINTF
29 /* use our own printf() functions */
32 #include "tool_cfgable.h"
33 #include "tool_cb_hdr.h"
35 #include "memdebug.h" /* keep this as LAST include */
37 static char *parse_filename(const char *ptr, size_t len);
40 ** callback for CURLOPT_HEADERFUNCTION
43 size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
45 struct OutStruct *outs = userdata;
46 const char *str = ptr;
47 const size_t cb = size * nmemb;
48 const char *end = (char*)ptr + cb;
50 if(cb > 20 && checkprefix("Content-disposition:", str)) {
51 const char *p = str + 20;
53 /* look for the 'filename=' parameter
54 (encoded filenames (*=) are not supported) */
59 while(*p && (p < end) && !ISALPHA(*p))
64 if(memcmp(p, "filename=", 9)) {
65 /* no match, find next parameter */
66 while((p < end) && (*p != ';'))
72 /* this expression below typecasts 'cb' only to avoid
73 warning: signed and unsigned type in conditional expression
75 len = (ssize_t)cb - (p - str);
76 filename = parse_filename(p, len);
77 /* TODO: OOM handling - return (size_t)-1 ? */
79 outs->filename = filename;
80 outs->alloc_filename = TRUE;
90 * Copies a file name part and returns an ALLOCATED data buffer.
92 static char *parse_filename(const char *ptr, size_t len)
99 /* simple implementation of strndup() */
100 copy = malloc(len+1);
103 memcpy(copy, ptr, len);
107 if(*p == '\'' || *p == '"') {
108 /* store the starting quote */
115 /* if the filename contains a path, only use filename portion */
116 q = strrchr(copy, '/');
125 /* If the filename contains a backslash, only use filename portion. The idea
126 is that even systems that don't handle backslashes as path separators
127 probably want the path removed for convenience. */
128 q = strrchr(p, '\\');
137 /* scan for the end letter and stop there */
140 if(q[1] && (q[0] == '\\'))
142 else if(q[0] == stop)
148 /* make sure the file name doesn't end in \r or \n */
158 memmove(copy, p, strlen(p) + 1);
160 /* in case we built curl debug enabled, we allow an evironment variable
161 * named CURL_TESTDIR to prefix the given file name to put it into a
166 char *tdir = curlx_getenv("CURL_TESTDIR");
168 char buffer[512]; /* suitably large */
169 snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy);
171 copy = strdup(buffer); /* clone the buffer, we don't use the libcurl
172 aprintf() or similar since we want to use the
173 same memory code as the "real" parse_filename