rpms/curl/devel curl-7.19.7-content-disposition.patch, NONE, 1.1 curl.spec, 1.137, 1.138 curl-7.19.7-nss-i686.patch, 1.1, NONE

Kamil Dudka kdudka at fedoraproject.org
Fri Jan 29 01:00:04 UTC 2010


Author: kdudka

Update of /cvs/extras/rpms/curl/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv17259

Modified Files:
	curl.spec 
Added Files:
	curl-7.19.7-content-disposition.patch 
Removed Files:
	curl-7.19.7-nss-i686.patch 
Log Message:
- upstream patch adding a new option -J/--remote-header-name
- dropped temporary workaround for #545779

curl-7.19.7-content-disposition.patch:
 docs/curl.1 |    3 +
 src/main.c  |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 132 insertions(+), 10 deletions(-)

--- NEW FILE curl-7.19.7-content-disposition.patch ---
diff --git a/docs/curl.1 b/docs/curl.1
index e4f5a00..7b7d549 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -598,6 +598,9 @@ time only.
 make it discard all "session cookies". This will basically have the same effect
 as if a new session is started. Typical browsers always discard session
 cookies when they're closed down.
+.IP "-J/--remote-header-name"
+(HTTP) This option tells the -O/--remote-name option to use the server-specified
+Content-Disposition filename instead of extracting a filename from the URL.
 .IP "-k/--insecure"
 (SSL) This option explicitly allows curl to perform "insecure" SSL connections
 and transfers. All SSL connections are attempted to be made secure by using
diff --git a/src/main.c b/src/main.c
index dae96ee..84ed7d2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -612,6 +612,7 @@ struct Configurable {
   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 */
@@ -817,6 +818,7 @@ static void help(void)
     "    --krb <level>   Enable Kerberos with specified security level (F)",
     "    --libcurl <file> Dump libcurl equivalent code of this command line",
     "    --limit-rate <rate> Limit transfer speed to this rate",
+    " -J/--remote-header-name Use the header-provided filename (H)",
     " -l/--list-only     List only names of an FTP directory (F)",
     "    --local-port <num>[-num] Force use of these local port numbers",
     " -L/--location      Follow Location: hints (H)",
@@ -1777,6 +1779,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     {"i", "include",     FALSE},
     {"I", "head",        FALSE},
     {"j", "junk-session-cookies", FALSE},
+    {"J", "remote-header-name", FALSE},
     {"k", "insecure",    FALSE},
     {"K", "config",      TRUE},
     {"l", "list-only",   FALSE},
@@ -2634,6 +2637,14 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
                         &config->httpreq))
         return PARAM_BAD_USE;
       break;
+    case 'J': /* --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;
+      break;
     case 'k': /* allow insecure SSL connects */
       config->insecure_ok = toggle;
       break;
@@ -3288,19 +3299,37 @@ static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
   struct OutStruct *out=(struct OutStruct *)stream;
   struct Configurable *config = out->config;
 
+  /*
+   * Once that libcurl has called back my_fwrite() the returned value
+   * is checked against the amount that was intended to be written, if
+   * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+   * point returning a value different from sz*nmemb indicates failure.
+   */
+  const size_t err_rc = (sz * nmemb) ? 0 : 1;
+
   if(!out->stream) {
+    if (!out->filename) {
+      warnf(config, "Remote filename has no length!\n");
+      return err_rc; /* Failure */
+    }
+
+    if (config->content_disposition) {
+      /* don't overwrite existing files */
+      FILE* f = fopen(out->filename, "r");
+      if (f) {
+        fclose(f);
+        warnf(config, "Refusing to overwrite %s: %s\n", out->filename,
+              strerror(EEXIST));
+        return err_rc; /* Failure */
+      }
+    }
+
     /* open file for writing */
     out->stream=fopen(out->filename, "wb");
     if(!out->stream) {
-      warnf(config, "Failed to create the file %s\n", out->filename);
-      /*
-       * Once that libcurl has called back my_fwrite() the returned value
-       * is checked against the amount that was intended to be written, if
-       * it does not match then it fails with CURLE_WRITE_ERROR. So at this
-       * point returning a value different from sz*nmemb indicates failure.
-       */
-      rc = (0 == (sz * nmemb)) ? 1 : 0;
-      return rc; /* failure */
+      warnf(config, "Failed to create the file %s: %s\n", out->filename,
+            strerror(errno));
+      return err_rc; /* failure */
     }
   }
 
@@ -4011,6 +4040,87 @@ static bool stdin_upload(const char *uploadfile)
   return curlx_strequal(uploadfile, "-") || curlx_strequal(uploadfile, ".");
 }
 
+static char*
+parse_filename(char *ptr, int len)
+{
+  char* copy;
+  char* p;
+  char* q;
+  char quote = 0;
+
+  /* simple implementation of strndup() */
+  copy = malloc(len+1);
+  if (!copy)
+    return NULL;
+  strncpy(copy, ptr, len);
+  copy[len] = 0;
+  
+  p = copy;
+  if (*p == '\'' || *p == '"') {
+    /* store the starting quote */
+    quote = *p;
+    p++;
+  }
+
+  /* if the filename contains a path, only use filename portion */
+  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 = (struct OutStruct*)stream;
+  const char* str = (char*)ptr;
+  const size_t cb = size*nmemb;
+  const char* end = (char*)ptr + cb;
+
+  if (cb > 20 && curlx_strnequal(str, "Content-disposition:", 20)) {
+    char *p = (char*)str + 20;
+
+    /* look for the 'filename=' parameter
+       (encoded filenames (*=) are not supported) */
+    while (1) {
+      char *filename;
+
+      while (p < end && !isalpha(*p))
+        p++;
+      if (p > end-9)
+        break;
+
+      if (memcmp(p, "filename=", 9)) {
+        /* no match, find next parameter */
+        while ((p < end) && (*p != ';'))
+          p++;
+        continue;
+      }
+      p+=9;
+      filename = parse_filename(p, cb - (p - str));
+      if (filename) {
+        outs->filename = filename;
+        break;
+      }
+    }
+  }
+
+  return cb;
+}
+
 static int
 operate(struct Configurable *config, int argc, argv_item_t argv[])
 {
@@ -4393,7 +4503,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
               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);
@@ -4994,6 +5104,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
         my_setopt(curl, CURLOPT_POSTREDIR, config->post301 |
                   (config->post302 ? CURL_REDIR_POST_302 : FALSE));
 
+        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();
@@ -5005,6 +5121,9 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
             break;
           }
 
+          if (config->content_disposition && outs.stream && !config->mute)
+            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 &&


Index: curl.spec
===================================================================
RCS file: /cvs/extras/rpms/curl/devel/curl.spec,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -p -r1.137 -r1.138
--- curl.spec	14 Jan 2010 19:32:09 -0000	1.137
+++ curl.spec	29 Jan 2010 01:00:04 -0000	1.138
@@ -1,7 +1,7 @@
 Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
 Name: curl
 Version: 7.19.7
-Release: 10%{?dist}
+Release: 11%{?dist}
 License: MIT
 Group: Applications/Internet
 Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma
@@ -10,7 +10,7 @@ Patch1: curl-7.19.7-nss-nonblock.patch
 Patch2: curl-7.19.7-ssl-retry.patch
 Patch3: curl-7.19.7-modelfree.patch
 Patch4: curl-7.19.7-nss-warning.patch
-Patch5: curl-7.19.7-nss-i686.patch
+Patch5: curl-7.19.7-content-disposition.patch
 Patch101: curl-7.15.3-multilib.patch
 Patch102: curl-7.16.0-privlibs.patch
 Patch103: curl-7.19.4-debug.patch
@@ -86,9 +86,9 @@ use cURL's capabilities internally.
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
+%patch5 -p1
 
 # Fedora patches
-%patch5 -p1
 %patch101 -p1
 %patch102 -p1
 %patch103 -p1
@@ -196,6 +196,10 @@ rm -rf $RPM_BUILD_ROOT
 %{_datadir}/aclocal/libcurl.m4
 
 %changelog
+* Fri Jan 29 2010 Kamil Dudka <kdudka at redhat.com> 7.19.7-11
+- upstream patch adding a new option -J/--remote-header-name
+- dropped temporary workaround for #545779
+
 * Thu Jan 14 2010 Chris Weyl <cweyl at alumni.drew.edu> 7.19.7-10
 - bump for libssh2 rebuild
 


--- curl-7.19.7-nss-i686.patch DELETED ---



More information about the scm-commits mailing list