From 1114253f9e24bc8b77967551ce9bceb0032d3bc5 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Wed, 27 Sep 2006 17:28:49 +0000 Subject: [PATCH] Moved URLEncoder into separate header, made it a global service. --- saml/Makefile.am | 4 +- saml/SAMLConfig.cpp | 18 ++++++ saml/SAMLConfig.h | 31 ++++++++-- saml/binding/MessageEncoder.h | 38 +----------- saml/binding/URLEncoder.h | 74 +++++++++++++++++++++++ saml/binding/impl/URLEncoder.cpp | 77 ++++++++++++++++++++++++ saml/saml.vcproj | 8 +++ saml/saml1/binding/impl/SAML1ArtifactEncoder.cpp | 1 + saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp | 1 + 9 files changed, 208 insertions(+), 44 deletions(-) create mode 100644 saml/binding/URLEncoder.h create mode 100644 saml/binding/impl/URLEncoder.cpp diff --git a/saml/Makefile.am b/saml/Makefile.am index 1aa5ff4..cc3ee2d 100644 --- a/saml/Makefile.am +++ b/saml/Makefile.am @@ -33,7 +33,8 @@ libsamlinclude_HEADERS = \ samlbindinclude_HEADERS = \ binding/ArtifactMap.h \ binding/MessageEncoder.h \ - binding/SAMLArtifact.h + binding/SAMLArtifact.h \ + binding/URLEncoder.h encinclude_HEADERS = \ encryption/EncryptedKeyResolver.h @@ -88,6 +89,7 @@ libsaml_la_SOURCES = \ SAMLConfig.cpp \ binding/impl/ArtifactMap.cpp \ binding/impl/SAMLArtifact.cpp \ + binding/impl/URLEncoder.cpp \ saml1/core/impl/AssertionsImpl.cpp \ saml1/core/impl/AssertionsSchemaValidators.cpp \ saml1/core/impl/ProtocolsImpl.cpp \ diff --git a/saml/SAMLConfig.cpp b/saml/SAMLConfig.cpp index 3d40148..5d68230 100644 --- a/saml/SAMLConfig.cpp +++ b/saml/SAMLConfig.cpp @@ -24,8 +24,10 @@ #include "internal.h" #include "exceptions.h" #include "SAMLConfig.h" +#include "binding/ArtifactMap.h" #include "binding/MessageEncoder.h" #include "binding/SAMLArtifact.h" +#include "binding/URLEncoder.h" #include "saml1/core/Assertions.h" #include "saml1/core/Protocols.h" #include "saml2/core/Protocols.h" @@ -82,6 +84,18 @@ SAMLInternalConfig& SAMLInternalConfig::getInternalConfig() return g_config; } +void SAMLConfig::setArtifactMap(ArtifactMap* artifactMap) +{ + delete m_artifactMap; + m_artifactMap = artifactMap; +} + +void SAMLConfig::setURLEncoder(URLEncoder* urlEncoder) +{ + delete m_urlEncoder; + m_urlEncoder = urlEncoder; +} + bool SAMLInternalConfig::init(bool initXMLTooling) { #ifdef _DEBUG @@ -109,6 +123,8 @@ bool SAMLInternalConfig::init(bool initXMLTooling) saml2md::registerMetadataProviders(); saml2md::registerMetadataFilters(); registerTrustEngines(); + + m_urlEncoder = new URLEncoder(); log.info("library initialization complete"); return true; @@ -134,6 +150,8 @@ void SAMLInternalConfig::term(bool termXMLTooling) delete m_artifactMap; m_artifactMap = NULL; + delete m_urlEncoder; + m_urlEncoder = NULL; if (termXMLTooling) { XMLToolingConfig::getConfig().term(); diff --git a/saml/SAMLConfig.h b/saml/SAMLConfig.h index 90e00ad..1d0dbd1 100644 --- a/saml/SAMLConfig.h +++ b/saml/SAMLConfig.h @@ -24,7 +24,6 @@ #define __saml_config_h__ #include -#include #include #include @@ -37,10 +36,12 @@ */ namespace opensaml { + class SAML_API ArtifactMap; class SAML_API MessageEncoder; class SAML_API MessageDecoder; class SAML_API SAMLArtifact; class SAML_API TrustEngine; + class SAML_API URLEncoder; namespace saml2md { class SAML_API MetadataProvider; @@ -100,10 +101,7 @@ namespace opensaml { * * @param artifactMap new ArtifactMap instance to store */ - void setArtifactMap(ArtifactMap* artifactMap) { - delete m_artifactMap; - m_artifactMap = artifactMap; - } + void setArtifactMap(ArtifactMap* artifactMap); /** * Returns the global ArtifactMap instance. @@ -113,6 +111,24 @@ namespace opensaml { ArtifactMap* getArtifactMap() const { return m_artifactMap; } + + /** + * Sets the global URLEncoder instance. + * This method must be externally synchronized with any code that uses the object. + * Any previously set object is destroyed. + * + * @param urlEncoder new URLEncoder instance to store + */ + void setURLEncoder(URLEncoder* urlEncoder); + + /** + * Returns the global URLEncoder instance. + * + * @return global URLEncoder + */ + URLEncoder* getURLEncoder() const { + return m_urlEncoder; + } /** * Generate random information using the underlying security library @@ -179,10 +195,13 @@ namespace opensaml { xmltooling::PluginManager MetadataFilterManager; protected: - SAMLConfig() : m_artifactMap(NULL) {} + SAMLConfig() : m_artifactMap(NULL), m_urlEncoder(NULL) {} /** Global ArtifactMap instance for use by artifact-related functions. */ ArtifactMap* m_artifactMap; + + /** Global URLEncoder instance for use by URL-related functions. */ + URLEncoder* m_urlEncoder; }; #if defined (_MSC_VER) diff --git a/saml/binding/MessageEncoder.h b/saml/binding/MessageEncoder.h index 81e39d2..2a5fc71 100644 --- a/saml/binding/MessageEncoder.h +++ b/saml/binding/MessageEncoder.h @@ -48,39 +48,6 @@ namespace opensaml { virtual ~MessageEncoder() {} /** - * Interface to caller-supplied URL-encoding mechanism. - * - * Since URL-encoding is not canonical, it's important that the same - * encoder is used during some binding-specific signature operations. - */ - class SAML_API URLEncoder { - MAKE_NONCOPYABLE(URLEncoder); - protected: - URLEncoder() {} - public: - virtual ~URLEncoder() {} - - /** - * Produce a URL-safe but equivalent version of the input string. - * - * @param s input string to encode - * @return a string object containing the result of encoding the input - */ - virtual std::string encode(const char* s) const=0; - }; - - /** - * Provides a URLEncoder implementation for the MessageEncoder to use. - * The implementation's lifetime must be longer than the lifetime of this object. - * This method must be externally synchronized. - * - * @param urlEncoder a URLEncoder implementation to use - */ - void setURLEncoder(const URLEncoder* urlEncoder) { - m_urlEncoder = urlEncoder; - } - - /** * Interface to caller-supplied artifact generation mechanism. * * Generating an artifact for storage and retrieval requires knowledge of @@ -162,7 +129,7 @@ namespace opensaml { ) const=0; protected: - MessageEncoder() : m_urlEncoder(NULL), m_artifactGenerator(NULL) {} + MessageEncoder() : m_artifactGenerator(NULL) {} /** * Helper function to build a new XML Signature with KeyInfo, based @@ -177,9 +144,6 @@ namespace opensaml { const XMLCh* sigAlgorithm=NULL ) const; - /** Pointer to a URLEncoder implementation. */ - const URLEncoder* m_urlEncoder; - /** Pointer to an ArtifactGenerator implementation. */ const ArtifactGenerator* m_artifactGenerator; }; diff --git a/saml/binding/URLEncoder.h b/saml/binding/URLEncoder.h new file mode 100644 index 0000000..2585d6d --- /dev/null +++ b/saml/binding/URLEncoder.h @@ -0,0 +1,74 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file saml/binding/URLEncoder.h + * + * Interface to a URL-encoding mechanism along with a + * default implementation. + */ + +#ifndef __saml_urlenc_h__ +#define __saml_urlenc_h__ + +#include + +namespace opensaml { + /** + * Interface to a URL-encoding mechanism along with a default implementation. + * + * Since URL-encoding is not canonical, it's important that the same + * encoder is used during some library operations and the calling code. + * Applications can supply an alternative implementation to the library + * if required. + */ + class SAML_API URLEncoder { + MAKE_NONCOPYABLE(URLEncoder); + public: + URLEncoder() {} + virtual ~URLEncoder() {} + + /** + * Produce a URL-safe but equivalent version of the input string. + * + * @param s input string to encode + * @return a string object containing the result of encoding the input + */ + virtual std::string encode(const char* s) const; + + /** + * Perform an in-place decoding operation on the input string. + * The resulting string will be NULL-terminated. + * + * @param s input string to decode in a writable buffer + */ + virtual void decode(char* s) const; + + protected: + /** + * Returns true iff the input character requires encoding. + * + * @param ch the character to check + * @return true iff the character should be encoded + */ + virtual bool isBad(char ch) const { + static char badchars[]="=&/?:\"\\+<>#%{}|^~[]`;@"; + return (strchr(badchars,ch) || ch<=0x20 || ch>=0x7F); + } + }; +}; + +#endif /* __saml_urlenc_h__ */ diff --git a/saml/binding/impl/URLEncoder.cpp b/saml/binding/impl/URLEncoder.cpp new file mode 100644 index 0000000..81f0a51 --- /dev/null +++ b/saml/binding/impl/URLEncoder.cpp @@ -0,0 +1,77 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * URLEncoder.cpp + * + * Interface to a URL-encoding mechanism along with a + * default implementation. + */ + +#include "internal.h" +#include "binding/URLEncoder.h" + +using namespace opensaml; +using namespace std; + +static char x2c(char *what) +{ + register char digit; + + digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); + digit *= 16; + digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); + return(digit); +} + +void URLEncoder::decode(char* s) const +{ + register int x,y; + + for(x=0,y=0;s[y];++x,++y) + { + if((s[x] = s[y]) == '%') + { + s[x] = x2c(&s[y+1]); + y+=2; + } + else if (s[x] == '+') + { + s[x] = ' '; + } + } + s[x] = '\0'; +} + +static inline char hexchar(unsigned short s) +{ + return (s<=9) ? ('0' + s) : ('A' + s - 10); +} + +string URLEncoder::encode(const char* s) const +{ + string ret; + for (; *s; s++) { + if (isBad(*s)) { + ret+='%'; + ret+=hexchar(*s >> 4); + ret+=hexchar(*s & 0x0F); + } + else + ret+=*s; + } + return ret; +} diff --git a/saml/saml.vcproj b/saml/saml.vcproj index 625c424..4a8d469 100644 --- a/saml/saml.vcproj +++ b/saml/saml.vcproj @@ -451,6 +451,10 @@ RelativePath=".\binding\impl\SAMLArtifact.cpp" > + + @@ -654,6 +658,10 @@ RelativePath=".\binding\SAMLArtifact.h" > + +