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