[squid-dev] [PATCH] Better support for unknown URL schemes

Amos Jeffries squid3 at treenet.co.nz
Tue Mar 15 15:36:35 UTC 2016


Squid already contains AnyP::PROTO_UNKNOWN support for unknown protocols
but currently does not preserve the actual string value received for them.

This adds a textual representation ('image') to the UriScheme object to
fill that gap and ensure that all URL representatinos (ie cache keys,
logs and outgoing messages) are generated with the scheme string as it
was received.

Future work:
* add ACL support for arbitrary scheme names
* support for comparisons of unknown schemes

Amos
-------------- next part --------------
=== modified file 'src/URL.h'
--- src/URL.h	2016-02-23 08:51:22 +0000
+++ src/URL.h	2016-03-15 11:03:44 +0000
@@ -43,6 +43,7 @@
 
     /// convert the URL scheme to that given
     void setScheme(const AnyP::ProtocolType &p) {scheme_=p; touch();}
+    void setSchemeImage(const char *str) {scheme_.setImage(str); touch();}
 
     void userInfo(const SBuf &s) {userInfo_=s; touch();}
     const SBuf &userInfo() const {return userInfo_;}

=== modified file 'src/anyp/UriScheme.cc'
--- src/anyp/UriScheme.cc	2016-01-01 00:12:18 +0000
+++ src/anyp/UriScheme.cc	2016-03-15 15:10:17 +0000
@@ -14,19 +14,17 @@
 char const *
 AnyP::UriScheme::c_str() const
 {
+    if (!schemeImage_.isEmpty())
+        return schemeImage_.c_str();
+
     if (theScheme_ == AnyP::PROTO_UNKNOWN)
-        return "(unknown)";
-
-    static char out[BUFSIZ];
-    int p = 0;
+        return "(unknown)"; // should have been set explicitly
 
     if (theScheme_ > AnyP::PROTO_NONE && theScheme_ < AnyP::PROTO_MAX) {
-        const char *in = AnyP::ProtocolType_str[theScheme_];
-        for (; p < (BUFSIZ-1) && in[p] != '\0'; ++p)
-            out[p] = xtolower(in[p]);
+        schemeImage_ = AnyP::ProtocolType_str[theScheme_];
+        schemeImage_.toLower();
     }
-    out[p] = '\0';
-    return out;
+    return schemeImage_.c_str();
 }
 
 unsigned short

=== modified file 'src/anyp/UriScheme.h'
--- src/anyp/UriScheme.h	2016-01-01 00:12:18 +0000
+++ src/anyp/UriScheme.h	2016-03-15 11:19:04 +0000
@@ -10,6 +10,7 @@
 #define SQUID_ANYP_URISCHEME_H
 
 #include "anyp/ProtocolType.h"
+#include "sbuf/SBuf.h"
 
 #include <iosfwd>
 
@@ -27,7 +28,7 @@
     ~UriScheme() {}
 
     operator AnyP::ProtocolType() const { return theScheme_; }
-
+    // XXX: does not account for comparison of unknown schemes (by image)
     bool operator != (AnyP::ProtocolType const & aProtocol) const { return theScheme_ != aProtocol; }
 
     /** Get a char string representation of the scheme.
@@ -41,9 +42,16 @@
 
     unsigned short defaultPort() const;
 
+    /// Sets the string representation of this scheme.
+    /// Only needed if the scheme type is PROTO_UNKNOWN.
+    void setImage(const char *str) {assert(theScheme_ == AnyP::PROTO_UNKNOWN); schemeImage_ = str;}
+
 private:
     /// This is a typecode pointer into the enum/registry of protocols handled.
     AnyP::ProtocolType theScheme_;
+
+    /// the string representation to use for theScheme_
+    mutable SBuf schemeImage_;
 };
 
 } // namespace AnyP

=== modified file 'src/url.cc'
--- src/url.cc	2016-01-01 00:12:18 +0000
+++ src/url.cc	2016-03-15 13:52:00 +0000
@@ -18,6 +18,7 @@
 
 static HttpRequest *urlParseFinish(const HttpRequestMethod& method,
                                    const AnyP::ProtocolType protocol,
+                                   const char *const protoStr,
                                    const char *const urlpath,
                                    const char *const host,
                                    const SBuf &login,
@@ -157,6 +158,9 @@
     if (strncasecmp(b, "whois", len) == 0)
         return AnyP::PROTO_WHOIS;
 
+    if (len > 0)
+        return AnyP::PROTO_UNKNOWN;
+
     return AnyP::PROTO_NONE;
 }
 
@@ -215,7 +219,7 @@
                URL::Asterisk().cmp(url) == 0) {
         protocol = AnyP::PROTO_HTTP;
         port = AnyP::UriScheme(protocol).defaultPort();
-        return urlParseFinish(method, protocol, url, host, SBuf(), port, request);
+        return urlParseFinish(method, protocol, proto, url, host, SBuf(), port, request);
     } else if (!strncmp(url, "urn:", 4)) {
         return urnParse(method, url, request);
     } else {
@@ -420,7 +424,7 @@
         }
     }
 
-    return urlParseFinish(method, protocol, urlpath, host, SBuf(login), port, request);
+    return urlParseFinish(method, protocol, proto, urlpath, host, SBuf(login), port, request);
 }
 
 /**
@@ -431,6 +435,7 @@
 static HttpRequest *
 urlParseFinish(const HttpRequestMethod& method,
                const AnyP::ProtocolType protocol,
+               const char *const protoStr, // for unknown protocols
                const char *const urlpath,
                const char *const host,
                const SBuf &login,
@@ -443,6 +448,9 @@
         request->initHTTP(method, protocol, urlpath);
     }
 
+    if (protocol == AnyP::PROTO_UNKNOWN)
+        request->url.setSchemeImage(protoStr);
+
     request->url.host(host);
     request->url.userInfo(login);
     request->url.port(port);



More information about the squid-dev mailing list