]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/anyp/UriScheme.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / anyp / UriScheme.cc
index 65445d43480d1367a3d0136663b0dadadbcec298..e53ed1d436abd648aba64f7d6ff65ae970370128 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
 #include "squid.h"
 #include "anyp/UriScheme.h"
 
-char const *
-AnyP::UriScheme::c_str() const
+AnyP::UriScheme::LowercaseSchemeNames AnyP::UriScheme::LowercaseSchemeNames_;
+
+AnyP::UriScheme::UriScheme(AnyP::ProtocolType const aScheme, const char *img) :
+    theScheme_(aScheme)
 {
-    if (theScheme_ == AnyP::PROTO_UNKNOWN)
-        return "(unknown)";
+    // RFC 3986 section 3.1: schemes are case-insensitive.
+
+    // To improve diagnostic, remember exactly how an unsupported scheme looks like.
+    // XXX: Object users may rely on toLower() canonicalization that we refuse to provide.
+    if (img && theScheme_ == AnyP::PROTO_UNKNOWN)
+        image_ = img;
+
+    // XXX: A broken caller supplies an image of an absent scheme?
+    // XXX: We assume that the caller is using a lower-case image.
+    else if (img && theScheme_ == AnyP::PROTO_NONE)
+        image_ = img;
+
+    else if (theScheme_ > AnyP::PROTO_NONE && theScheme_ < AnyP::PROTO_MAX)
+        image_ = LowercaseSchemeNames_.at(theScheme_);
+    // else, the image remains empty (e.g., "://example.com/")
+    // hopefully, theScheme_ is PROTO_NONE here
+}
 
-    static char out[BUFSIZ];
-    int p = 0;
+void
+AnyP::UriScheme::Init()
+{
+    if (LowercaseSchemeNames_.empty()) {
+        LowercaseSchemeNames_.reserve(sizeof(SBuf) * AnyP::PROTO_MAX);
+        // TODO: use base/EnumIterator.h if possible
+        for (int i = AnyP::PROTO_NONE; i < AnyP::PROTO_MAX; ++i) {
+            SBuf image(ProtocolType_str[i]);
+            image.toLower();
+            LowercaseSchemeNames_.emplace_back(image);
+        }
+    }
+}
 
-    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]);
+const AnyP::ProtocolType
+AnyP::UriScheme::FindProtocolType(const SBuf &scheme)
+{
+    if (scheme.isEmpty())
+        return AnyP::PROTO_NONE;
+
+    Init();
+
+    auto img = scheme;
+    img.toLower();
+    // TODO: use base/EnumIterator.h if possible
+    for (int i = AnyP::PROTO_NONE + 1; i < AnyP::PROTO_UNKNOWN; ++i) {
+        if (LowercaseSchemeNames_.at(i) == img)
+            return AnyP::ProtocolType(i);
     }
-    out[p] = '\0';
-    return out;
+
+    return AnyP::PROTO_UNKNOWN;
 }
 
 unsigned short