Imported Upstream version 2.2.1+dfsg
[shibboleth/sp.git] / shibsp / attribute / StringAttributeDecoder.cpp
1 /*\r
2  *  Copyright 2001-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  * StringAttributeDecoder.cpp\r
19  *\r
20  * Decodes SAML into SimpleAttributes\r
21  */\r
22 \r
23 #include "internal.h"\r
24 #include "attribute/AttributeDecoder.h"\r
25 #include "attribute/SimpleAttribute.h"\r
26 \r
27 #include <saml/saml1/core/Assertions.h>\r
28 #include <saml/saml2/core/Assertions.h>\r
29 \r
30 using namespace shibsp;\r
31 using namespace opensaml::saml1;\r
32 using namespace opensaml::saml2;\r
33 using namespace xmltooling;\r
34 using namespace std;\r
35 \r
36 namespace shibsp {\r
37     class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder\r
38     {\r
39     public:\r
40         StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
41         ~StringAttributeDecoder() {}\r
42 \r
43         shibsp::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 \r
48     AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)\r
49     {\r
50         return new StringAttributeDecoder(e);\r
51     }\r
52 };\r
53 \r
54 shibsp::Attribute* StringAttributeDecoder::decode(\r
55     const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
56     ) const\r
57 {\r
58     char* val;\r
59     auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));\r
60     vector<string>& dest = simple->getValues();\r
61     vector<XMLObject*>::const_iterator v,stop;\r
62 \r
63     Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");\r
64 \r
65     if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
66         const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
67         if (saml2attr) {\r
68             const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
69             v = values.begin();\r
70             stop = values.end();\r
71             if (log.isDebugEnabled()) {\r
72                 auto_ptr_char n(saml2attr->getName());\r
73                 log.debug(\r
74                     "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
75                     ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
76                     );\r
77             }\r
78         }\r
79         else {\r
80             const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
81             if (saml1attr) {\r
82                 const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
83                 v = values.begin();\r
84                 stop = values.end();\r
85                 if (log.isDebugEnabled()) {\r
86                     auto_ptr_char n(saml1attr->getAttributeName());\r
87                 log.debug(\r
88                     "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
89                     ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
90                     );\r
91                 }\r
92             }\r
93             else {\r
94                 log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
95                 return NULL;\r
96             }\r
97         }\r
98 \r
99         for (; v!=stop; ++v) {\r
100             if (!(*v)->hasChildren()) {\r
101                 val = toUTF8((*v)->getTextContent());\r
102                 if (val && *val)\r
103                     dest.push_back(val);\r
104                 else\r
105                     log.warn("skipping empty AttributeValue");\r
106                 delete[] val;\r
107             }\r
108             else {\r
109                 log.warn("skipping complex AttributeValue");\r
110             }\r
111         }\r
112 \r
113         return dest.empty() ? NULL : _decode(simple.release());\r
114     }\r
115 \r
116     const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
117     if (saml2name) {\r
118         if (log.isDebugEnabled()) {\r
119             auto_ptr_char f(saml2name->getFormat());\r
120             log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
121         }\r
122         val = toUTF8(saml2name->getName());\r
123     }\r
124     else {\r
125         const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
126         if (saml1name) {\r
127             if (log.isDebugEnabled()) {\r
128                 auto_ptr_char f(saml1name->getFormat());\r
129                 log.debug(\r
130                     "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
131                     ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
132                     );\r
133             }\r
134             val = toUTF8(saml1name->getName());\r
135         }\r
136         else {\r
137             log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
138             return NULL;\r
139         }\r
140     }\r
141 \r
142     if (val && *val)\r
143         dest.push_back(val);\r
144     else\r
145         log.warn("ignoring empty NameID");\r
146     delete[] val;\r
147     return dest.empty() ? NULL : _decode(simple.release());\r
148 }\r