Imported Upstream version 2.2.1+dfsg
[shibboleth/sp.git] / shibsp / attribute / XMLAttributeDecoder.cpp
1 /*\r
2  *  Copyright 2009 Internet2\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 /**\r
18  * XMLAttributeDecoder.cpp\r
19  *\r
20  * Decodes arbitrary XML into an XMLAttribute.\r
21  */\r
22 \r
23 #include "internal.h"\r
24 #include "attribute/AttributeDecoder.h"\r
25 #include "attribute/XMLAttribute.h"\r
26 \r
27 #include <saml/saml1/core/Assertions.h>\r
28 #include <saml/saml2/core/Assertions.h>\r
29 #include <xmltooling/util/XMLHelper.h>\r
30 \r
31 using namespace shibsp;\r
32 using namespace opensaml;\r
33 using namespace xmltooling;\r
34 using namespace std;\r
35 \r
36 namespace shibsp {\r
37     class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder\r
38     {\r
39     public:\r
40         XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
41         ~XMLAttributeDecoder() {}\r
42 \r
43         Attribute* decode(\r
44             const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
45             ) const;\r
46 \r
47     private:\r
48         DDF convert(DOMElement* e, bool nameit=true) const;\r
49         auto_ptr_char m_formatter;\r
50         map<pair<xstring,xstring>,string> m_tagMap;\r
51     };\r
52 \r
53     AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)\r
54     {\r
55         return new XMLAttributeDecoder(e);\r
56     }\r
57 };\r
58 \r
59 \r
60 Attribute* XMLAttributeDecoder::decode(\r
61     const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
62     ) const\r
63 {\r
64     if (!xmlObject)\r
65         return NULL;\r
66 \r
67     Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");\r
68 \r
69     auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));\r
70     vector<string>& dest = attr->getValues();\r
71 \r
72     // Handle any non-Attribute object directly.\r
73     if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
74         DOMElement* e = xmlObject->getDOM();\r
75         if (e) {\r
76             if (log.isDebugEnabled()) {\r
77                 log.debug(\r
78                     "decoding XMLAttribute (%s) from XMLObject (%s)",\r
79                     ids.front().c_str(),\r
80                     (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()\r
81                     );\r
82             }\r
83             dest.push_back(string());\r
84             XMLHelper::serialize(e, dest.back());\r
85         }\r
86         else {\r
87             log.warn("skipping XMLObject without a backing DOM");\r
88         }\r
89         return dest.empty() ? NULL : _decode(attr.release());\r
90     }\r
91 \r
92     vector<XMLObject*>::const_iterator v,stop;\r
93 \r
94     const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
95     if (saml2attr) {\r
96         const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
97         v = values.begin();\r
98         stop = values.end();\r
99         if (log.isDebugEnabled()) {\r
100             auto_ptr_char n(saml2attr->getName());\r
101             log.debug(\r
102                 "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
103                 ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
104                 );\r
105         }\r
106     }\r
107     else {\r
108         const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
109         if (saml1attr) {\r
110             const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
111             v = values.begin();\r
112             stop = values.end();\r
113             if (log.isDebugEnabled()) {\r
114                 auto_ptr_char n(saml1attr->getAttributeName());\r
115                 log.debug(\r
116                     "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
117                     ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
118                     );\r
119             }\r
120         }\r
121         else {\r
122             log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");\r
123             return NULL;\r
124         }\r
125     }\r
126 \r
127     for (; v!=stop; ++v) {\r
128         DOMElement* e = (*v)->getDOM();\r
129         if (e) {\r
130             dest.push_back(string());\r
131             XMLHelper::serialize(e, dest.back());\r
132         }\r
133         else\r
134             log.warn("skipping AttributeValue without a backing DOM");\r
135     }\r
136 \r
137     return dest.empty() ? NULL : _decode(attr.release());\r
138 }\r