Index: src/main.c
===================================================================
RCS file: /cvsroot/curl/curl/src/main.c,v
retrieving revision 1.546
diff -u -r1.546 main.c
--- src/main.c	12 Dec 2009 21:54:02 -0000	1.546
+++ src/main.c	29 Dec 2009 22:52:01 -0000
@@ -614,6 +614,7 @@
   bool post302;
   bool nokeepalive; /* for keepalive needs */
   long alivetime;
+  bool content_disposition; /* use Content-disposition filename */
 
   int default_node_flags; /* default flags to seach for each 'node', which is
                              basically each given URL to transfer */
@@ -859,6 +860,7 @@
     " -e/--referer       Referer URL (H)",
     " -O/--remote-name   Write output to a file named as the remote file",
     "    --remote-name-all Use the remote file name for all URLs",
+    "    --remote-header-name Use the header-provided filename",
     " -R/--remote-time   Set the remote file's time on the local output",
     " -X/--request <command> Specify request command to use",
     "    --retry <num>   Retry request <num> times if transient problems occur",
@@ -1677,6 +1679,7 @@
 #endif
     {"*g", "trace",      TRUE},
     {"*h", "trace-ascii", TRUE},
+    {"*H", "remote-header-name", FALSE},
     {"*i", "limit-rate", TRUE},
     {"*j", "compressed",  FALSE}, /* might take an arg someday */
     {"*k", "digest",     FALSE},
@@ -1946,6 +1949,13 @@
                 "--trace-ascii overrides an earlier trace/verbose option\n");
         config->tracetype = TRACE_ASCII;
         break;
+      case 'H': /* --remote-header-name */
+        if (config->include_headers) {
+          warnf(config, "--include and --remote-header-name cannot be combined.\n");
+          return PARAM_BAD_USE;
+        }
+        config->content_disposition = toggle?TRUE:FALSE;
+        break;
       case 'i': /* --limit-rate */
         {
           /* We support G, M, K too */
@@ -3310,7 +3320,10 @@
     /* open file for writing */
     out->stream=fopen(out->filename, "wb");
     if(!out->stream) {
-      warnf(config, "Failed to create the file %s\n", out->filename);
+      if (out->filename)
+        warnf(config, "Failed to create the file %s\n", out->filename);
+      else
+        warnf(config, "Remote filename has no length!\n");
       /*
        * Once that libcurl has called back my_fwrite() the returned value
        * is checked against the amount that was intended to be written, if
@@ -4035,6 +4048,88 @@
   return curlx_strequal(uploadfile, "-") || curlx_strequal(uploadfile, ".");
 }
 
+static char*
+parse_filename(char *ptr, int len)
+{
+  char* copy;
+  char* p;
+  char* q;
+  char quote = 0;
+
+  copy = malloc(len+1);
+  if (!copy)
+    return NULL;
+  strncpy(copy, ptr, len);
+  copy[len] = 0;
+  
+  p = copy;
+  if (*p == '\'' || *p == '"') {
+    quote = *p;
+    p++;
+  }
+
+  q = strrchr(copy, '/');
+  if (q) {
+    p=q+1;
+    if (!*p) {
+      free(copy);
+      return NULL;
+    }
+  }
+
+  q = strrchr(p, quote);
+  if (q)
+    *q = 0;
+
+  if (copy!=p)
+    memmove(copy, p, strlen(p)+1);
+
+  return copy;
+}
+
+static size_t
+header_callback(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+  struct OutStruct* outs = stream;
+
+  if (curlx_strnequal(ptr, "Content-disposition:", 20)) {
+    char *p = (char*)ptr + 20;
+    while (1) {
+      /* encoded filenames (*=) not supported */
+      static const char *needle = "filename="; 
+      char *filename;
+      int i;
+
+      while (*p && !isalpha(*p))
+        p++;
+      if (!*p)
+        break;
+
+      for (i=0; i<9 && p[i]==needle[i]; i++);
+      if (i<9)
+        break;
+      p+=9;
+      filename = parse_filename(p, size*nmemb - (p - (char*)ptr));
+      if (filename) {
+        FILE* f = fopen(filename, "r");
+        if (f) {
+          fclose(f);
+          printf("\ncurl: Filename '%s' already exists. Aborting.\n",
+                 filename);
+          outs->filename = NULL;
+          return -1;
+        }
+        else {
+          outs->filename = filename;
+          break;
+        }
+      }
+    }
+  }
+
+  return size*nmemb;
+}
+
 static int
 operate(struct Configurable *config, int argc, argv_item_t argv[])
 {
@@ -4417,7 +4512,7 @@
               pc++;
               outfile = *pc ? strdup(pc): NULL;
             }
-            if(!outfile || !*outfile) {
+            if((!outfile || !*outfile) && !config->content_disposition) {
               helpf(config->errors, "Remote file name has no length!\n");
               res = CURLE_WRITE_ERROR;
               free(url);
@@ -5028,6 +5123,12 @@
         if(config->mail_rcpt)
           my_setopt_str(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
 
+        if ((urlnode->flags & GETOUT_USEREMOTE)
+            && config->content_disposition) {
+            my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
+            my_setopt(curl, CURLOPT_HEADERDATA, &outs);
+        }
+        
         retry_numretries = config->req_retry;
 
         retrystart = cutil_tvnow();
@@ -5039,6 +5140,9 @@
             break;
           }
 
+          if (config->content_disposition && outs.filename)
+              printf("curl: Saved to filename '%s'\n", outs.filename);
+
           /* if retry-max-time is non-zero, make sure we haven't exceeded the
              time */
           if(retry_numretries &&

