ca86390ed993d6e0d01d49df9e5f3024433a6e1c
[shibboleth/sp.git] / shibsp / attribute / StringAttributeDecoder.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  * 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     simple->setCaseSensitive(m_caseSensitive);\r
61     vector<string>& dest = simple->getValues();\r
62     vector<XMLObject*>::const_iterator v,stop;\r
63 \r
64     Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");\r
65 \r
66     if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
67         const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
68         if (saml2attr) {\r
69             const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
70             v = values.begin();\r
71             stop = values.end();\r
72             if (log.isDebugEnabled()) {\r
73                 auto_ptr_char n(saml2attr->getName());\r
74                 log.debug(\r
75                     "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
76                     ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
77                     );\r
78             }\r
79         }\r
80         else {\r
81             const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
82             if (saml1attr) {\r
83                 const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
84                 v = values.begin();\r
85                 stop = values.end();\r
86                 if (log.isDebugEnabled()) {\r
87                     auto_ptr_char n(saml1attr->getAttributeName());\r
88                 log.debug(\r
89                     "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
90                     ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
91                     );\r
92                 }\r
93             }\r
94             else {\r
95                 log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
96                 return NULL;\r
97             }\r
98         }\r
99 \r
100         for (; v!=stop; ++v) {\r
101             if (!(*v)->hasChildren()) {\r
102                 val = toUTF8((*v)->getTextContent());\r
103                 if (val && *val)\r
104                     dest.push_back(val);\r
105                 else\r
106                     log.warn("skipping empty AttributeValue");\r
107                 delete[] val;\r
108             }\r
109             else {\r
110                 log.warn("skipping complex AttributeValue");\r
111             }\r
112         }\r
113 \r
114         return dest.empty() ? NULL : simple.release();\r
115     }\r
116 \r
117     const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
118     if (saml2name) {\r
119         if (log.isDebugEnabled()) {\r
120             auto_ptr_char f(saml2name->getFormat());\r
121             log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
122         }\r
123         val = toUTF8(saml2name->getName());\r
124     }\r
125     else {\r
126         const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
127         if (saml1name) {\r
128             if (log.isDebugEnabled()) {\r
129                 auto_ptr_char f(saml1name->getFormat());\r
130                 log.debug(\r
131                     "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
132                     ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
133                     );\r
134             }\r
135             val = toUTF8(saml1name->getName());\r
136         }\r
137         else {\r
138             log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
139             return NULL;\r
140         }\r
141     }\r
142 \r
143     if (val && *val)\r
144         dest.push_back(val);\r
145     else\r
146         log.warn("ignoring empty NameID");\r
147     delete[] val;\r
148     return dest.empty() ? NULL : simple.release();\r
149 }\r