+
+static bool
+extract_param_value_delim (const char *begin, const char *end,
+ const char *param_name, char **param_value)
+{
+ const char *p;
+ int len;
+
+ assert (begin);
+ assert (end);
+ assert (param_name);
+ assert (param_value);
+
+ len = strlen (param_name);
+
+ /* skip initial whitespaces */
+ p = begin;
+ while (*p && ISSPACE (*p) && p < end) ++p;
+
+ if (end - p > len
+ && 0 == strncasecmp (p, param_name, len))
+ {
+ const char *e;
+
+ /* skip white spaces, equal sign and inital quote */
+ p += len;
+ while (*p && (ISSPACE (*p) || *p == '\"' || *p == '=') && p < end) ++p;
+
+ /* find last quote */
+ e = p;
+ while (*e && *e != '\"' && e < end) ++e;
+
+ *param_value = strdupdelim (p, e);
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Parse the `Content-Disposition' header and extract the information it
+ contains. Returns true if successful, false otherwise. */
+static bool
+parse_content_disposition (const char *hdrval, char **filename)
+{
+ const char *b = hdrval; /* b - begin */
+ const char *e = hdrval; /* e - end */
+
+ assert (hdrval);
+ assert (filename);
+
+ for (; *e; ++e)
+ {
+ if (*e == ';'
+ && e > b)
+ {
+ /* process chars b->e-1 */
+ if (true == extract_param_value_delim (b, e - 1, "filename", filename))
+ return true;
+
+ b = e + 1;
+ }
+ }
+
+ if (b != e)
+ {
+ /* process chars b->e */
+ if (true == extract_param_value_delim (b, e, "filename", filename))
+ return true;
+ }
+
+ return false;
+}