Convert logging to log4shib via compile time switch.
[shibboleth/cpp-sp.git] / shibsp / attribute / ScopedAttributeDecoder.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  * ScopedAttributeDecoder.cpp\r
19  * \r
20  * Decodes SAML into ScopedAttributes\r
21  */\r
22 \r
23 #include "internal.h"\r
24 #include "attribute/AttributeDecoder.h"\r
25 #include "attribute/ScopedAttribute.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     static const XMLCh Scope[] =            UNICODE_LITERAL_5(S,c,o,p,e);\r
38     static const XMLCh scopeDelimeter[] =   UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,e,t,e,r);\r
39 \r
40     class SHIBSP_DLLLOCAL ScopedAttributeDecoder : virtual public AttributeDecoder\r
41     {\r
42     public:\r
43         ScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimeter('@') {\r
44             if (e) {\r
45                 if (e->hasAttributeNS(NULL,scopeDelimeter)) {\r
46                     auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimeter));\r
47                     m_delimeter = *(d.get());\r
48                 }\r
49             }\r
50         }\r
51         ~ScopedAttributeDecoder() {}\r
52 \r
53         shibsp::Attribute* decode(\r
54             const char* id, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
55             ) const;\r
56 \r
57     private:\r
58         char m_delimeter;\r
59     };\r
60 \r
61     AttributeDecoder* SHIBSP_DLLLOCAL ScopedAttributeDecoderFactory(const DOMElement* const & e)\r
62     {\r
63         return new ScopedAttributeDecoder(e);\r
64     }\r
65 };\r
66 \r
67 shibsp::Attribute* ScopedAttributeDecoder::decode(\r
68     const char* id, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
69     ) const\r
70 {\r
71     char* val;\r
72     char* scope;\r
73     const XMLCh* xmlscope;\r
74     QName scopeqname(NULL,Scope);\r
75     auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(id,m_delimeter));\r
76     scoped->setCaseSensitive(m_caseSensitive);\r
77     vector< pair<string,string> >& dest = scoped->getValues();\r
78     vector<XMLObject*>::const_iterator v,stop;\r
79 \r
80     Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder");\r
81     \r
82     if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
83         const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
84         if (saml2attr) {\r
85             const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
86             v = values.begin();\r
87             stop = values.end();\r
88             if (log.isDebugEnabled()) {\r
89                 auto_ptr_char n(saml2attr->getName());\r
90                 log.debug("decoding ScopedAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
91             }\r
92         }\r
93         else {\r
94             const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
95             if (saml1attr) {\r
96                 const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
97                 v = values.begin();\r
98                 stop = values.end();\r
99                 if (log.isDebugEnabled()) {\r
100                     auto_ptr_char n(saml1attr->getAttributeName());\r
101                     log.debug("decoding ScopedAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
102                 }\r
103             }\r
104             else {\r
105                 log.warn("XMLObject type not recognized by ScopedAttributeDecoder, no values returned");\r
106                 return NULL;\r
107             }\r
108         }\r
109 \r
110         for (; v!=stop; ++v) {\r
111             if (!(*v)->hasChildren()) {\r
112                 val = toUTF8((*v)->getTextContent());\r
113                 if (val && *val) {\r
114                     const AttributeExtensibleXMLObject* aexo=dynamic_cast<const AttributeExtensibleXMLObject*>(*v);\r
115                     xmlscope = aexo->getAttribute(scopeqname);\r
116                     if (xmlscope && *xmlscope) {\r
117                         scope = toUTF8(xmlscope);\r
118                         dest.push_back(make_pair(val,scope));\r
119                         delete[] scope;\r
120                     }\r
121                     else {\r
122                         scope = strchr(val, m_delimeter);\r
123                         if (scope) {\r
124                             *scope++ = 0;\r
125                             if (*scope)\r
126                                 dest.push_back(make_pair(val,scope));\r
127                             else\r
128                                 log.warn("ignoring unscoped AttributeValue");\r
129                         }\r
130                         else {\r
131                             log.warn("ignoring unscoped AttributeValue");\r
132                         }\r
133                     }\r
134                 }\r
135                 else {\r
136                     log.warn("skipping empty AttributeValue");\r
137                 }\r
138                 delete[] val;\r
139             }\r
140             else {\r
141                 log.warn("skipping complex AttributeValue");\r
142             }\r
143         }\r
144 \r
145         return dest.empty() ? NULL : scoped.release();\r
146     }\r
147 \r
148     const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
149     if (saml2name) {\r
150         if (log.isDebugEnabled()) {\r
151             auto_ptr_char f(saml2name->getFormat());\r
152             log.debug("decoding ScopedAttribute (%s) from SAML 2 NameID with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
153         }\r
154         val = toUTF8(saml2name->getName());\r
155     }\r
156     else {\r
157         const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
158         if (saml1name) {\r
159             if (log.isDebugEnabled()) {\r
160                 auto_ptr_char f(saml1name->getFormat());\r
161                 log.debug("decoding ScopedAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
162             }\r
163             val = toUTF8(saml1name->getName());\r
164         }\r
165         else {\r
166             log.warn("XMLObject type not recognized by ScopedAttributeDecoder, no values returned");\r
167             return NULL;\r
168         }\r
169     }\r
170 \r
171     if (val && *val && *val!=m_delimeter) {\r
172         scope = strchr(val, m_delimeter);\r
173         if (scope) {\r
174             *scope++ = 0;\r
175             if (*scope)\r
176                 dest.push_back(make_pair(val,scope));\r
177             else\r
178                 log.warn("ignoring NameID with no scope");\r
179         }\r
180         else {\r
181             log.warn("ignoring NameID with no scope delimiter (%c)", m_delimeter);\r
182         }\r
183     }\r
184     else {\r
185         log.warn("ignoring empty NameID");\r
186     }\r
187     delete[] val;\r
188     return dest.empty() ? NULL : scoped.release();\r
189 }\r