]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
squidclient: Improve shell-escape support in -H option
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 20 May 2016 05:25:58 +0000 (17:25 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 20 May 2016 05:25:58 +0000 (17:25 +1200)
The -H parameter takes a string with some limited shell-escaped
characters. Currently just \n was expanded to the CRLF sequence.
Other shell escaped characters were left untouched.

However, to properly test headers containing weird CR, LF and HTAB
positioning it needs to be able to receive these special characters
individually and thus unescape them.

Add a new function similar to perform shell unescape with special
characters \\, \r, \n, and \t. All other characters are un-escaped
to themselves and a warning printed at verbosity level 1.

tools/squidclient/squidclient.cc

index e084ee6193201d9a6e94a3cb7a55bd62a0a49b9f..e73ef2bf0e5c40a7bed4b8d9e04da8934c20c4a2 100644 (file)
@@ -111,7 +111,7 @@ usage(const char *progname)
             << "HTTP Options:" << std::endl
             << "    -a           Do NOT include Accept: header." << std::endl
             << "    -A           User-Agent: header. Use \"\" to omit." << std::endl
-            << "    -H 'string'  Extra headers to send. Use '\\n' for new lines." << std::endl
+            << "    -H 'string'  Extra headers to send. Supports '\\\\', '\\n', '\\r' and '\\t'." << std::endl
             << "    -i IMS       If-Modified-Since time (in Epoch seconds)." << std::endl
             << "    -j hosthdr   Host header content" << std::endl
             << "    -k           Keep the connection active. Default is to do only one request then close." << std::endl
@@ -132,6 +132,56 @@ usage(const char *progname)
     exit(1);
 }
 
+static void
+shellUnescape(char *buf)
+{
+    if (!buf)
+        return;
+
+    unsigned char *p, *d;
+
+    d = p = reinterpret_cast<unsigned char *>(buf);
+
+    while (auto ch = *p) {
+
+        if (ch == '\\') {
+            ++p;
+
+            switch (*p) {
+            case 'n':
+                ch = '\n';
+                break;
+            case 'r':
+                ch = '\r';
+                break;
+            case 't':
+                ch = '\t';
+                break;
+            case '\\':
+                ch = '\\';
+                break;
+            default:
+                ch = *p;
+                debugVerbose(1, "Warning: unsupported shell code '\\" << ch << "'");
+                break;
+            }
+
+            *d = ch;
+
+            if (!ch)
+                continue;
+
+        } else {
+            *d = *p;
+        }
+
+        ++p;
+        ++d;
+    }
+
+    *d = '\0';
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -262,10 +312,8 @@ main(int argc, char *argv[])
 
             case 'H':
                 if (strlen(optarg)) {
-                    char *t;
                     strncpy(extra_hdrs, optarg, sizeof(extra_hdrs));
-                    while ((t = strstr(extra_hdrs, "\\n")))
-                        *t = '\r', *(t + 1) = '\n';
+                    shellUnescape(extra_hdrs);
                 }
                 break;