/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 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