-/*\r
- * Copyright 2001-2009 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 xercesc;\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, size_t i)\r
-{\r
- char* psz=buf + cchBuf - 1; // Set psz to last char\r
- *psz = 0; // Set terminating null\r
-\r
- do {\r
- size_t 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
- map<string,string>::size_type 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 += "'"; break;\r
- case '<': s += "<"; break;\r
- case '>': s += ">"; break;\r
- case '&': s += "&"; 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
- const URLEncoder* encoder = XMLToolingConfig::getConfig().getURLEncoder();\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, ">", encoder->encode(i->second.c_str()).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
- const URLEncoder* encoder = XMLToolingConfig::getConfig().getURLEncoder();\r
- child=XMLHelper::getFirstChildElement(root,XMLTOOLING_NS,param);\r
- while (child && child->hasChildNodes()) {\r
- auto_ptr_char n(child->getAttributeNS(NULL,name));\r
- char* encoded = XMLString::transcode(child->getFirstChild()->getNodeValue());\r
- if (n.get() && encoded) {\r
- encoder->decode(encoded);\r
- excep->addProperty(n.get(), encoded);\r
- }\r
- XMLString::release(&encoded);\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
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you 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 <memory>
+#include <sstream>
+#include <boost/lexical_cast.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace xmltooling;
+using namespace xercesc;
+using namespace boost;
+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();
+}
+
+void XMLToolingException::addProperties(const params& p)
+{
+ m_processedmsg.erase();
+ map<string,string>::size_type i = m_params.size() + 1;
+ const vector<const char*>& v=p.get();
+ for (vector<const char*>::const_iterator ci = v.begin(); ci != v.end(); ++ci) {
+ try {
+ m_params[lexical_cast<string>(i++)] = *ci;
+ }
+ catch (bad_lexical_cast&) {
+ }
+ }
+}
+
+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
+{
+ try {
+ map<string,string>::const_iterator i = m_params.find(lexical_cast<string>(index));
+ return (i==m_params.end()) ? nullptr : i->second.c_str();
+ }
+ catch (bad_lexical_cast&) {
+ return nullptr;
+ }
+}
+
+const char* XMLToolingException::getProperty(const char* name) const
+{
+ map<string,string>::const_iterator i = m_params.find(name);
+ return (i==m_params.end()) ? nullptr : 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 += "'"; break;
+ case '<': s += "<"; break;
+ case '>': s += ">"; break;
+ case '&': s += "&"; 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>");
+ const URLEncoder* encoder = XMLToolingConfig::getConfig().getURLEncoder();
+ 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, ">", encoder->encode(i->second.c_str()).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(nullptr,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());
+ }
+
+ const URLEncoder* encoder = XMLToolingConfig::getConfig().getURLEncoder();
+ child=XMLHelper::getFirstChildElement(root,XMLTOOLING_NS,param);
+ while (child && child->hasChildNodes()) {
+ auto_ptr_char n(child->getAttributeNS(nullptr,name));
+ char* encoded = XMLString::transcode(child->getFirstChild()->getNodeValue());
+ if (n.get() && encoded) {
+ encoder->decode(encoded);
+ excep->addProperty(n.get(), encoded);
+ }
+ XMLString::release(&encoded);
+ child=XMLHelper::getNextSiblingElement(child,XMLTOOLING_NS,param);
+ }
+
+ doc->release();
+ return excep.release();
+}
+
+XMLToolingException* XMLToolingException::fromString(const char* s)
+{
+ istringstream in(s);
+ return fromStream(in);
+}