]> granicus.if.org Git - curl/commitdiff
curl: added --proto and --proto-redir
authorAlex Bligh <alex@alex.org.uk>
Sat, 24 Apr 2010 10:16:48 +0000 (12:16 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 24 Apr 2010 10:18:04 +0000 (12:18 +0200)
--proto tells curl to use the listed protocols for its initial
retrieval

--proto-redir tells curl to use the listed protocols after a
redirect

docs/curl.1
src/main.c

index 02cc3fb6326b7db23a8fe706509f6e488d6b47ef..aec3e48f5c65c2245b6eacf13a6d1f748bdc4b3e 100644 (file)
@@ -927,6 +927,52 @@ in web browsers, so curl does the conversion by default to maintain
 consistency. However, a server may require a POST to remain a POST after such
 a redirection. This option is meaningful only when using \fI-L/--location\fP
 (Added in 7.19.1)
+.IP "--proto <protocols>"
+Tells curl to use the listed protocols for its initial retrieval. Protocols
+are evaluated left to right, are comma separated, and are each a protocol
+name or 'all', optionally prefixed by zero or more modifiers. Available
+modifiers are:
+.RS
+.TP 3
+.B +
+Permit this protocol in addition to protocols already permitted (this is
+the default if no modifier is used).
+.TP
+.B -
+Deny this protocol, removing it from the list of protocols already permitted.
+.TP
+.B =
+Permit only this protocol (ignoring the list already permitted), though
+subject to later modification by subsequent entries in the comma separated
+list.
+.RE
+.IP
+For example:
+.RS
+.TP 15
+.B --proto -ftps
+uses the default protocols, but disables ftps
+.TP
+.B  --proto -all,https,+http
+only enables http and https
+.TP
+.B --proto =http,https
+also only enables http and https
+.RE
+.IP
+Unknown protocols produce a warning. This allows scripts to safely rely on
+being able to disable potentially dangerous protocols, without relying upon
+support for that protocol being built into curl to avoid an error.
+
+This option can be used multiple times, in which case the effect is the same
+as concatenating the protocols into one instance of the option.
+
+(Added in 7.20.2)
+.IP "--proto-redir <protocols>"
+Tells curl to use the listed protocols after a redirect. See --proto for
+how protocols are represented.
+
+(Added in 7.20.2)
 .IP "--proxy-anyauth"
 Tells curl to pick a suitable authentication method when communicating with
 the given proxy. This might cause an extra request/response round-trip. (Added
index 2dd6dc873c4b1ab9d131212da159f3b0d2b7ba4c..684869379371de9f6839f5954131690336bbb02e 100644 (file)
@@ -478,6 +478,10 @@ struct Configurable {
   bool disable_epsv;
   bool disable_eprt;
   bool ftp_pret;
+  long proto;
+  bool proto_present;
+  long proto_redir;
+  bool proto_redir_present;
   curl_off_t resume_from;
   char *postfields;
   curl_off_t postfieldsize;
@@ -841,6 +845,8 @@ static void help(void)
     "    --post301       Do not switch to GET after following a 301 redirect (H)",
     "    --post302       Do not switch to GET after following a 302 redirect (H)",
     " -#/--progress-bar  Display transfer progress as a progress bar",
+    "    --proto <protocols>       Enable/disable specified protocols",
+    "    --proto-redir <protocols> Enable/disable specified protocols on redirect",
     " -x/--proxy <host[:port]> Use HTTP proxy on given port",
     "    --proxy-anyauth Pick \"any\" proxy authentication method (H)",
     "    --proxy-basic   Use Basic authentication on the proxy (H)",
@@ -1492,6 +1498,109 @@ static int str2num(long *val, const char *str)
   return retcode;
 }
 
+/*
+ * Parse the string and modify the long in the given address. Return
+ * non-zero on failure, zero on success.
+ *
+ * The string is a list of protocols
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+static long proto2num(struct Configurable *config, long *val, const char *str)
+{
+  char *buffer;
+  const char *sep = ",";
+  char *token;
+
+  static struct sprotos {
+    const char *name;
+    long bit;
+  } const protos[] = {
+    { "all", CURLPROTO_ALL },
+    { "http", CURLPROTO_HTTP },
+    { "https", CURLPROTO_HTTPS },
+    { "ftp", CURLPROTO_FTP },
+    { "ftps", CURLPROTO_FTPS },
+    { "scp", CURLPROTO_SCP },
+    { "sftp", CURLPROTO_SFTP },
+    { "telnet", CURLPROTO_TELNET },
+    { "ldap", CURLPROTO_LDAP },
+    { "ldaps", CURLPROTO_LDAPS },
+    { "dict", CURLPROTO_DICT },
+    { "file", CURLPROTO_FILE },
+    { "tftp", CURLPROTO_TFTP },
+    { "imap", CURLPROTO_IMAP },
+    { "imaps", CURLPROTO_IMAPS },
+    { "pop3", CURLPROTO_POP3 },
+    { "pop3s", CURLPROTO_POP3S },
+    { "smtp", CURLPROTO_SMTP },
+    { "smtps", CURLPROTO_SMTPS },
+    { "rtsp", CURLPROTO_RTSP },
+    { NULL, 0 }
+  };
+
+  if(!str)
+    return 1;
+
+  buffer = strdup(str); /* because strtok corrupts it */
+
+  for (token = strtok(buffer, sep);
+       token;
+       token = strtok(NULL, sep)) {
+    enum e_action { allow, deny, set } action = allow;
+
+    struct sprotos const *pp;
+
+    /* Process token modifiers */
+    while (!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
+      switch (*token++) {
+      case '=':
+        action = set;
+        break;
+      case '-':
+        action = deny;
+        break;
+      case '+':
+        action = allow;
+        break;
+      default: /* Includes case of terminating NULL */
+        free(buffer);
+        return 1;
+      }
+    }
+
+    for (pp=protos; pp->name; pp++) {
+      if (curlx_raw_equal(token, pp->name)) {
+        switch (action) {
+        case deny:
+          *val &= ~(pp->bit);
+          break;
+        case allow:
+          *val |= pp->bit;
+          break;
+        case set:
+          *val = pp->bit;
+          break;
+        }
+        break;
+      }
+    }
+
+    if (!(pp->name)) { /* unknown protocol */
+      /* If they have specified only this protocol, we say treat it as
+         if no protocols are allowed */
+      if (action == set)
+        *val = 0;
+      warnf(config, "unrecognized protocol '%s'\n", token);
+    }
+  }
+  free(buffer);
+  return 0;
+}
+
 /**
  * Parses the given string looking for an offset (which may be
  * a larger-than-integer value).
@@ -1752,6 +1861,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     {"$A", "mail-from", TRUE},
     {"$B", "mail-rcpt", TRUE},
     {"$C", "ftp-pret",   FALSE},
+    {"$D", "proto",      TRUE},
+    {"$E", "proto-redir", TRUE},
     {"0", "http1.0",     FALSE},
     {"1", "tlsv1",       FALSE},
     {"2", "sslv2",       FALSE},
@@ -2294,6 +2405,16 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
       case 'C': /* --ftp-pret */
         config->ftp_pret = toggle;
         break;
+      case 'D': /* --proto */
+        config->proto_present = 1;
+        if(proto2num(config, &config->proto, nextarg))
+          return PARAM_BAD_USE;
+        break;
+      case 'E': /* --proto-redir */
+        config->proto_redir_present = 1;
+        if(proto2num(config, &config->proto_redir, nextarg))
+          return PARAM_BAD_USE;
+        break;
       }
       break;
     case '#': /* --progress-bar */
@@ -4362,6 +4483,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
   config->use_httpget=FALSE;
   config->create_dirs=FALSE;
   config->maxredirs = DEFAULT_MAXREDIRS;
+  config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
+  config->proto_present = FALSE;
+  config->proto_redir =
+    CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+  config->proto_redir_present = FALSE;
 
   if(argc>1 &&
      (!curlx_strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
@@ -5200,6 +5326,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
         if(config->ftp_pret)
           my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
 
+        if (config->proto_present)
+          my_setopt(curl, CURLOPT_PROTOCOLS, config->proto);
+        if (config->proto_redir_present)
+          my_setopt(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
+
         if ((urlnode->flags & GETOUT_USEREMOTE)
             && config->content_disposition) {
           my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);