https://issues.shibboleth.net/jira/browse/CPPXT-10
[shibboleth/cpp-xmltooling.git] / xmltooling / exceptions.cpp
index 4b15451..1d0e883 100644 (file)
-/*
- *  Copyright 2001-2007 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.
- */
-
-/**
- * exceptions.cpp
- * 
- * Exception classes
- */
-#include "internal.h"
-#include "exceptions.h"
-#include "XMLToolingConfig.h"
-#include "util/URLEncoder.h"
-#include "util/XMLConstants.h"
-#include "util/XMLHelper.h"
-
-#include <stdarg.h>
-#include <sstream>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace xmltooling;
-using namespace std;
-using xmlconstants::XMLTOOLING_NS;
-
-params::params(int count,...)
-{
-    va_list args;
-    va_start(args,count);
-    while (count--)
-        v.push_back(va_arg(args,char*));
-    va_end(args);
-}
-
-namedparams::namedparams(int count,...)
-{
-    count*=2;
-    va_list args;
-    va_start(args,count);
-    while (count--)
-        v.push_back(va_arg(args,char*));
-    va_end(args);
-}
-
-XMLToolingException::ExceptionFactoryMap XMLToolingException::m_factoryMap;
-
-XMLToolingException* XMLToolingException::getInstance(const char* exceptionClass)
-{
-    if (exceptionClass) {
-        ExceptionFactoryMap::const_iterator i=m_factoryMap.find(exceptionClass);
-        if (i!=m_factoryMap.end())
-            return (i->second)();
-    }
-    return new XMLToolingException();
-}
-
-XMLToolingException::XMLToolingException(const char* msg, const params& p)
-{
-    if (msg)
-        m_msg=msg;
-    addProperties(p);
-}
-
-XMLToolingException::XMLToolingException(const char* msg, const namedparams& p)
-{
-    if (msg)
-        m_msg=msg;
-    addProperties(p);
-}
-
-XMLToolingException::XMLToolingException(const std::string& msg, const params& p) : m_msg(msg)
-{
-    addProperties(p);
-}
-
-XMLToolingException::XMLToolingException(const std::string& msg, const namedparams& p) : m_msg(msg)
-{
-    addProperties(p);
-}
-
-void XMLToolingException::setMessage(const char* msg)
-{
-    if (msg)
-        m_msg=msg;
-    else
-        m_msg.erase();
-    m_processedmsg.erase();
-}
-
-inline const char* get_digit_character()
-{
-    static const char  s_characters[19] = 
-    {
-            '9'
-        ,   '8'
-        ,   '7'
-        ,   '6'
-        ,   '5'
-        ,   '4'
-        ,   '3'
-        ,   '2'
-        ,   '1'
-        ,   '0'
-        ,   '1'
-        ,   '2'
-        ,   '3'
-        ,   '4'
-        ,   '5'
-        ,   '6'
-        ,   '7'
-        ,   '8'
-        ,   '9'
-    };
-    static const char  *s_mid  =   s_characters + 9;
-
-    return s_mid;
-}
-
-inline const char* unsigned_integer_to_string(char* buf, size_t cchBuf, int i)
-{
-    char* psz=buf + cchBuf - 1;     // Set psz to last char
-    *psz = 0;                       // Set terminating null
-
-    do {
-        unsigned int lsd = i % 10;  // Get least significant
-                                    // digit
-
-        i /= 10;                    // Prepare for next most
-                                    // significant digit
-
-        --psz;                      // Move back
-
-        *psz = get_digit_character()[lsd]; // Place the digit
-
-    } while(i!=0 && psz>buf);
-
-    return psz;
-}
-
-void XMLToolingException::addProperties(const params& p)
-{
-    m_processedmsg.erase();
-    int i=m_params.size()+1;
-    char buf[20];
-    const vector<const char*>& v=p.get();
-    for (vector<const char*>::const_iterator ci=v.begin(); ci!=v.end(); ci++) {
-        m_params[unsigned_integer_to_string(buf,sizeof(buf),i++)] = *ci;
-    }
-}
-        
-void XMLToolingException::addProperties(const namedparams& p)
-{
-    m_processedmsg.erase();
-    const vector<const char*>& v=p.get();
-    for (vector<const char*>::const_iterator ci=v.begin(); ci!=v.end(); ci++) {
-        m_params.erase(*ci);
-        m_params[*ci] = *(ci+1);
-        ci++;   // advance past name to value, then loop will advance it again
-    }
-}
-
-const char* XMLToolingException::getProperty(unsigned int index) const
-{
-    char buf[20];
-    map<string,string>::const_iterator i=m_params.find(unsigned_integer_to_string(buf,sizeof(buf),index));
-    return (i==m_params.end()) ? NULL : i->second.c_str();
-}
-
-const char* XMLToolingException::getProperty(const char* name) const
-{
-    map<string,string>::const_iterator i=m_params.find(name);
-    return (i==m_params.end()) ? NULL : i->second.c_str();
-}
-
-const char* XMLToolingException::getMessage() const
-{
-    if (!m_processedmsg.empty())
-        return m_processedmsg.c_str();
-    else if (m_params.empty())
-        return m_msg.c_str();
-
-    static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_";
-
-    // Replace any parameters in the message.
-    string::size_type i=0,start=0;
-    while (start!=string::npos && start<m_msg.length() && (i=m_msg.find("$",start))!=string::npos) {
-        if (i>start)
-            m_processedmsg += m_msg.substr(start,i-start);  // append everything in between
-        start=i+1;                                  // move start to the beginning of the token name
-        i=m_msg.find_first_not_of(legal,start);     // find token delimiter
-        if (i==start) {                             // append a non legal character
-           m_processedmsg+=m_msg[start++];
-           continue;
-        }
-        
-        // search for token in map
-        map<string,string>::const_iterator param=m_params.find(m_msg.substr(start,(i==string::npos) ? i : i-start));
-        if (param!=m_params.end()) {
-            m_processedmsg+=param->second;
-            start=i;
-        }
-    }
-    if (start!=string::npos && start<m_msg.length())
-        m_processedmsg += m_msg.substr(start,i);    // append rest of string
-    return m_processedmsg.c_str();
-}
-
-void xml_encode(string& s, const char* pre, const char* start, const char* post)
-{
-    s += pre;
-    size_t pos;
-    while (start && *start) {
-        pos = strcspn(start, "\"<>&");
-        if (pos > 0) {
-            s.append(start, pos);
-            start += pos;
-        }
-        else {
-            switch (*start) {
-                case '\'':  s += "&apos;";     break;
-                case '<':   s += "&lt;";       break;
-                case '>':   s += "&gt;";       break;
-                case '&':   s += "&amp;";      break;
-                default:    s += *start;
-            }
-            start++;
-        }
-    }
-    s += post;
-}
-
-string XMLToolingException::toString() const
-{
-    string xml=string("<exception xmlns='http://www.opensaml.org/xmltooling' type='") + getClassName() + "'>";
-    const char* msg=getMessage();
-    if (msg)
-        xml_encode(xml, "<message>", msg, "</message>");
-    for (map<string,string>::const_iterator i=m_params.begin(); i!=m_params.end(); i++) {
-        xml_encode(xml, "<param name='", i->first.c_str(), "'");
-        xml_encode(xml, ">", i->second.c_str(), "</param>");
-    }
-    xml+="</exception>";
-    return xml;
-}
-
-string XMLToolingException::toQueryString() const
-{
-    string q;
-    const URLEncoder* enc = XMLToolingConfig::getConfig().getURLEncoder();
-    for (map<string,string>::const_iterator i=m_params.begin(); i!=m_params.end(); i++) {
-        if (!q.empty())
-            q += '&';
-        q = q + i->first + '=' + enc->encode(i->second.c_str());
-    }
-    return q;
-}
-
-XMLToolingException* XMLToolingException::fromStream(std::istream& in)
-{
-    static const XMLCh exception[] =    UNICODE_LITERAL_9(e,x,c,e,p,t,i,o,n);
-    static const XMLCh message[] =      UNICODE_LITERAL_7(m,e,s,s,a,g,e);
-    static const XMLCh name[] =         UNICODE_LITERAL_4(n,a,m,e);
-    static const XMLCh param[] =        UNICODE_LITERAL_5(p,a,r,a,m);
-    static const XMLCh type[] =         UNICODE_LITERAL_4(t,y,p,e);
-
-    DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
-    
-    // Check root element.
-    const DOMElement* root=doc->getDocumentElement();
-    if (!XMLHelper::isNodeNamed(root,XMLTOOLING_NS,exception)) {
-        doc->release();
-        throw XMLToolingException("Invalid root element on serialized exception.");
-    }
-    
-    auto_ptr_char classname(root->getAttributeNS(NULL,type));
-    auto_ptr<XMLToolingException> excep(XMLToolingException::getInstance(classname.get()));
-    
-    DOMElement* child=XMLHelper::getFirstChildElement(root,XMLTOOLING_NS,message);
-    if (child && child->hasChildNodes()) {
-        auto_ptr_char m(child->getFirstChild()->getNodeValue());
-        excep->setMessage(m.get());
-    }
-    
-    child=XMLHelper::getFirstChildElement(root,XMLTOOLING_NS,param);
-    while (child && child->hasChildNodes()) {
-        auto_ptr_char n(child->getAttributeNS(NULL,name));
-        char* v=toUTF8(child->getFirstChild()->getNodeValue());
-        if (n.get() && v)
-            excep->addProperty(n.get(), v);
-        delete[] v;
-        child=XMLHelper::getNextSiblingElement(child,XMLTOOLING_NS,param);
-    }
-
-    doc->release();
-    return excep.release();
-}
-        
-XMLToolingException* XMLToolingException::fromString(const char* s)
-{
-    istringstream in(s);
-    return fromStream(in);
-}
+/*\r
+ *  Copyright 2001-2007 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * exceptions.cpp\r
+ * \r
+ * Exception classes\r
+ */\r
\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "XMLToolingConfig.h"\r
+#include "util/URLEncoder.h"\r
+#include "util/XMLConstants.h"\r
+#include "util/XMLHelper.h"\r
+\r
+#include <stdarg.h>\r
+#include <memory>\r
+#include <sstream>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+using namespace xmltooling;\r
+using namespace std;\r
+using xmlconstants::XMLTOOLING_NS;\r
+\r
+params::params(int count,...)\r
+{\r
+    va_list args;\r
+    va_start(args,count);\r
+    while (count--)\r
+        v.push_back(va_arg(args,char*));\r
+    va_end(args);\r
+}\r
+\r
+namedparams::namedparams(int count,...)\r
+{\r
+    count*=2;\r
+    va_list args;\r
+    va_start(args,count);\r
+    while (count--)\r
+        v.push_back(va_arg(args,char*));\r
+    va_end(args);\r
+}\r
+\r
+XMLToolingException::ExceptionFactoryMap XMLToolingException::m_factoryMap;\r
+\r
+XMLToolingException* XMLToolingException::getInstance(const char* exceptionClass)\r
+{\r
+    if (exceptionClass) {\r
+        ExceptionFactoryMap::const_iterator i=m_factoryMap.find(exceptionClass);\r
+        if (i!=m_factoryMap.end())\r
+            return (i->second)();\r
+    }\r
+    return new XMLToolingException();\r
+}\r
+\r
+XMLToolingException::XMLToolingException(const char* msg, const params& p)\r
+{\r
+    if (msg)\r
+        m_msg=msg;\r
+    addProperties(p);\r
+}\r
+\r
+XMLToolingException::XMLToolingException(const char* msg, const namedparams& p)\r
+{\r
+    if (msg)\r
+        m_msg=msg;\r
+    addProperties(p);\r
+}\r
+\r
+XMLToolingException::XMLToolingException(const std::string& msg, const params& p) : m_msg(msg)\r
+{\r
+    addProperties(p);\r
+}\r
+\r
+XMLToolingException::XMLToolingException(const std::string& msg, const namedparams& p) : m_msg(msg)\r
+{\r
+    addProperties(p);\r
+}\r
+\r
+void XMLToolingException::setMessage(const char* msg)\r
+{\r
+    if (msg)\r
+        m_msg=msg;\r
+    else\r
+        m_msg.erase();\r
+    m_processedmsg.erase();\r
+}\r
+\r
+inline const char* get_digit_character()\r
+{\r
+    static const char  s_characters[19] = \r
+    {\r
+            '9'\r
+        ,   '8'\r
+        ,   '7'\r
+        ,   '6'\r
+        ,   '5'\r
+        ,   '4'\r
+        ,   '3'\r
+        ,   '2'\r
+        ,   '1'\r
+        ,   '0'\r
+        ,   '1'\r
+        ,   '2'\r
+        ,   '3'\r
+        ,   '4'\r
+        ,   '5'\r
+        ,   '6'\r
+        ,   '7'\r
+        ,   '8'\r
+        ,   '9'\r
+    };\r
+    static const char  *s_mid  =   s_characters + 9;\r
+\r
+    return s_mid;\r
+}\r
+\r
+inline const char* unsigned_integer_to_string(char* buf, size_t cchBuf, int i)\r
+{\r
+    char* psz=buf + cchBuf - 1;     // Set psz to last char\r
+    *psz = 0;                       // Set terminating null\r
+\r
+    do {\r
+        unsigned int lsd = i % 10;  // Get least significant\r
+                                    // digit\r
+\r
+        i /= 10;                    // Prepare for next most\r
+                                    // significant digit\r
+\r
+        --psz;                      // Move back\r
+\r
+        *psz = get_digit_character()[lsd]; // Place the digit\r
+\r
+    } while(i!=0 && psz>buf);\r
+\r
+    return psz;\r
+}\r
+\r
+void XMLToolingException::addProperties(const params& p)\r
+{\r
+    m_processedmsg.erase();\r
+    int i=m_params.size()+1;\r
+    char buf[20];\r
+    const vector<const char*>& v=p.get();\r
+    for (vector<const char*>::const_iterator ci=v.begin(); ci!=v.end(); ci++) {\r
+        m_params[unsigned_integer_to_string(buf,sizeof(buf),i++)] = *ci;\r
+    }\r
+}\r
+        \r
+void XMLToolingException::addProperties(const namedparams& p)\r
+{\r
+    m_processedmsg.erase();\r
+    const vector<const char*>& v=p.get();\r
+    for (vector<const char*>::const_iterator ci=v.begin(); ci!=v.end(); ci++) {\r
+        m_params.erase(*ci);\r
+        m_params[*ci] = *(ci+1);\r
+        ci++;   // advance past name to value, then loop will advance it again\r
+    }\r
+}\r
+\r
+const char* XMLToolingException::getProperty(unsigned int index) const\r
+{\r
+    char buf[20];\r
+    map<string,string>::const_iterator i=m_params.find(unsigned_integer_to_string(buf,sizeof(buf),index));\r
+    return (i==m_params.end()) ? NULL : i->second.c_str();\r
+}\r
+\r
+const char* XMLToolingException::getProperty(const char* name) const\r
+{\r
+    map<string,string>::const_iterator i=m_params.find(name);\r
+    return (i==m_params.end()) ? NULL : i->second.c_str();\r
+}\r
+\r
+const char* XMLToolingException::getMessage() const\r
+{\r
+    if (!m_processedmsg.empty())\r
+        return m_processedmsg.c_str();\r
+    else if (m_params.empty())\r
+        return m_msg.c_str();\r
+\r
+    static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_";\r
+\r
+    // Replace any parameters in the message.\r
+    string::size_type i=0,start=0;\r
+    while (start!=string::npos && start<m_msg.length() && (i=m_msg.find("$",start))!=string::npos) {\r
+        if (i>start)\r
+            m_processedmsg += m_msg.substr(start,i-start);  // append everything in between\r
+        start=i+1;                                  // move start to the beginning of the token name\r
+        i=m_msg.find_first_not_of(legal,start);     // find token delimiter\r
+        if (i==start) {                             // append a non legal character\r
+           m_processedmsg+=m_msg[start++];\r
+           continue;\r
+        }\r
+        \r
+        // search for token in map\r
+        map<string,string>::const_iterator param=m_params.find(m_msg.substr(start,(i==string::npos) ? i : i-start));\r
+        if (param!=m_params.end()) {\r
+            m_processedmsg+=param->second;\r
+            start=i;\r
+        }\r
+    }\r
+    if (start!=string::npos && start<m_msg.length())\r
+        m_processedmsg += m_msg.substr(start,i);    // append rest of string\r
+    return m_processedmsg.c_str();\r
+}\r
+\r
+void xml_encode(string& s, const char* pre, const char* start, const char* post)\r
+{\r
+    s += pre;\r
+    size_t pos;\r
+    while (start && *start) {\r
+        pos = strcspn(start, "\"<>&");\r
+        if (pos > 0) {\r
+            s.append(start, pos);\r
+            start += pos;\r
+        }\r
+        else {\r
+            switch (*start) {\r
+                case '\'':  s += "&apos;";     break;\r
+                case '<':   s += "&lt;";       break;\r
+                case '>':   s += "&gt;";       break;\r
+                case '&':   s += "&amp;";      break;\r
+                default:    s += *start;\r
+            }\r
+            start++;\r
+        }\r
+    }\r
+    s += post;\r
+}\r
+\r
+string XMLToolingException::toString() const\r
+{\r
+    string xml=string("<exception xmlns='http://www.opensaml.org/xmltooling' type='") + getClassName() + "'>";\r
+    const char* msg=getMessage();\r
+    if (msg)\r
+        xml_encode(xml, "<message>", msg, "</message>");\r
+    for (map<string,string>::const_iterator i=m_params.begin(); i!=m_params.end(); i++) {\r
+        xml_encode(xml, "<param name='", i->first.c_str(), "'");\r
+        xml_encode(xml, ">", i->second.c_str(), "</param>");\r
+    }\r
+    xml+="</exception>";\r
+    return xml;\r
+}\r
+\r
+string XMLToolingException::toQueryString() const\r
+{\r
+    string q;\r
+    const URLEncoder* enc = XMLToolingConfig::getConfig().getURLEncoder();\r
+    for (map<string,string>::const_iterator i=m_params.begin(); i!=m_params.end(); i++) {\r
+        if (!q.empty())\r
+            q += '&';\r
+        q = q + i->first + '=' + enc->encode(i->second.c_str());\r
+    }\r
+    return q;\r
+}\r
+\r
+XMLToolingException* XMLToolingException::fromStream(std::istream& in)\r
+{\r
+    static const XMLCh exception[] =    UNICODE_LITERAL_9(e,x,c,e,p,t,i,o,n);\r
+    static const XMLCh message[] =      UNICODE_LITERAL_7(m,e,s,s,a,g,e);\r
+    static const XMLCh name[] =         UNICODE_LITERAL_4(n,a,m,e);\r
+    static const XMLCh param[] =        UNICODE_LITERAL_5(p,a,r,a,m);\r
+    static const XMLCh type[] =         UNICODE_LITERAL_4(t,y,p,e);\r
+\r
+    DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
+    \r
+    // Check root element.\r
+    const DOMElement* root=doc->getDocumentElement();\r
+    if (!XMLHelper::isNodeNamed(root,XMLTOOLING_NS,exception)) {\r
+        doc->release();\r
+        throw XMLToolingException("Invalid root element on serialized exception.");\r
+    }\r
+    \r
+    auto_ptr_char classname(root->getAttributeNS(NULL,type));\r
+    auto_ptr<XMLToolingException> excep(XMLToolingException::getInstance(classname.get()));\r
+    \r
+    DOMElement* child=XMLHelper::getFirstChildElement(root,XMLTOOLING_NS,message);\r
+    if (child && child->hasChildNodes()) {\r
+        auto_ptr_char m(child->getFirstChild()->getNodeValue());\r
+        excep->setMessage(m.get());\r
+    }\r
+    \r
+    child=XMLHelper::getFirstChildElement(root,XMLTOOLING_NS,param);\r
+    while (child && child->hasChildNodes()) {\r
+        auto_ptr_char n(child->getAttributeNS(NULL,name));\r
+        char* v=toUTF8(child->getFirstChild()->getNodeValue());\r
+        if (n.get() && v)\r
+            excep->addProperty(n.get(), v);\r
+        delete[] v;\r
+        child=XMLHelper::getNextSiblingElement(child,XMLTOOLING_NS,param);\r
+    }\r
+\r
+    doc->release();\r
+    return excep.release();\r
+}\r
+        \r
+XMLToolingException* XMLToolingException::fromString(const char* s)\r
+{\r
+    istringstream in(s);\r
+    return fromStream(in);\r
+}\r