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