Update copyright.
[shibboleth/cpp-opensaml.git] / saml / saml1 / core / impl / ProtocolsImpl.cpp
1 /*
2  *  Copyright 2001-2007 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  * ProtocolsImpl.cpp
19  * 
20  * Implementation classes for SAML 1.x Protocols schema
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "saml1/core/Assertions.h"
26 #include "saml1/core/Protocols.h"
27
28 #include <xmltooling/AbstractComplexElement.h>
29 #include <xmltooling/AbstractSimpleElement.h>
30 #include <xmltooling/impl/AnyElement.h>
31 #include <xmltooling/io/AbstractXMLObjectMarshaller.h>
32 #include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>
33 #include <xmltooling/util/XMLHelper.h>
34
35 #include <ctime>
36 #include <xercesc/util/XMLUniDefs.hpp>
37
38 using namespace opensaml::saml1p;
39 using namespace opensaml::saml1;
40 using namespace opensaml;
41 using namespace xmlsignature;
42 using namespace xmltooling;
43 using namespace std;
44 using xmlconstants::XMLSIG_NS;
45 using xmlconstants::XML_ONE;
46 using samlconstants::SAML1P_NS;
47 using samlconstants::SAML1_NS;
48 using samlconstants::SAML1P_PREFIX;
49
50 #if defined (_MSC_VER)
51     #pragma warning( push )
52     #pragma warning( disable : 4250 4251 )
53 #endif
54
55 namespace opensaml {
56     namespace saml1p {
57     
58         DECL_XMLOBJECTIMPL_SIMPLE(SAML_DLLLOCAL,AssertionArtifact);
59         DECL_XMLOBJECTIMPL_SIMPLE(SAML_DLLLOCAL,StatusMessage);
60
61         class SAML_DLLLOCAL RespondWithImpl : public virtual RespondWith,
62             public AbstractSimpleElement,
63             public AbstractDOMCachingXMLObject,
64             public AbstractXMLObjectMarshaller,
65             public AbstractXMLObjectUnmarshaller
66         {
67             QName* m_qname;
68         public:
69             virtual ~RespondWithImpl() {
70                 delete m_qname;
71             }
72     
73             RespondWithImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
74                 : AbstractXMLObject(nsURI, localName, prefix, schemaType), m_qname(NULL) {
75             }
76                 
77             RespondWithImpl(const RespondWithImpl& src)
78                     : AbstractXMLObject(src), AbstractSimpleElement(src), AbstractDOMCachingXMLObject(src), m_qname(NULL) {
79                 setQName(src.getQName());
80             }
81             
82             QName* getQName() const {
83                 return m_qname;
84             }
85             
86             void setQName(const QName* qname) {
87                 m_qname=prepareForAssignment(m_qname,qname);
88                 if (m_qname) {
89                     auto_ptr_XMLCh temp(m_qname->toString().c_str());
90                     setTextContent(temp.get());
91                 }
92                 else
93                     setTextContent(NULL);
94             }
95             
96             IMPL_XMLOBJECT_CLONE(RespondWith);
97         };
98
99         class SAML_DLLLOCAL SubjectQueryImpl : public virtual SubjectQuery,
100             public AbstractComplexElement,
101             public AbstractDOMCachingXMLObject,
102             public AbstractXMLObjectMarshaller,
103             public AbstractXMLObjectUnmarshaller
104         {
105             void init() {
106                 m_Subject=NULL;
107                 m_children.push_back(NULL);
108                 m_pos_Subject=m_children.begin();
109             }
110         protected:
111             SubjectQueryImpl() {
112                 init();
113             }
114         public:
115             virtual ~SubjectQueryImpl() {}
116     
117             SubjectQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
118                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
119                 init();
120             }
121                 
122             SubjectQueryImpl(const SubjectQueryImpl& src)
123                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
124                 init();
125                 if (src.getSubject())
126                     setSubject(src.getSubject()->cloneSubject());
127             }
128             
129             IMPL_TYPED_CHILD(Subject);
130     
131         protected:
132             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
133                 PROC_TYPED_CHILD(Subject,SAML1_NS,true);
134                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
135             }
136         };
137
138         class SAML_DLLLOCAL AuthenticationQueryImpl : public virtual AuthenticationQuery, public SubjectQueryImpl
139         {
140             void init() {
141                 m_AuthenticationMethod=NULL;
142             }
143         public:
144             virtual ~AuthenticationQueryImpl() {
145                 XMLString::release(&m_AuthenticationMethod);
146             }
147     
148             AuthenticationQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
149                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
150                 init();
151             }
152                 
153             AuthenticationQueryImpl(const AuthenticationQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
154                 init();
155                 setAuthenticationMethod(src.getAuthenticationMethod());
156             }
157             
158             IMPL_XMLOBJECT_CLONE(AuthenticationQuery);
159             SubjectQuery* cloneSubjectQuery() const {
160                 return cloneAuthenticationQuery();
161             }
162             Query* cloneQuery() const {
163                 return cloneAuthenticationQuery();
164             }
165             IMPL_STRING_ATTRIB(AuthenticationMethod);
166     
167         protected:
168             void marshallAttributes(DOMElement* domElement) const {
169                 MARSHALL_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,NULL);
170                 SubjectQueryImpl::marshallAttributes(domElement);
171             }
172     
173             void processAttribute(const DOMAttr* attribute) {
174                 PROC_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,NULL);
175                 SubjectQueryImpl::processAttribute(attribute);
176             }
177         };
178
179         class SAML_DLLLOCAL AttributeQueryImpl : public virtual AttributeQuery, public SubjectQueryImpl
180         {
181             void init() {
182                 m_Resource=NULL;
183             }
184         public:
185             virtual ~AttributeQueryImpl() {
186                 XMLString::release(&m_Resource);
187             }
188     
189             AttributeQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
190                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
191                 init();
192             }
193                 
194             AttributeQueryImpl(const AttributeQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
195                 init();
196                 setResource(src.getResource());
197                 VectorOf(AttributeDesignator) v=getAttributeDesignators();
198                 for (vector<AttributeDesignator*>::const_iterator i=src.m_AttributeDesignators.begin(); i!=src.m_AttributeDesignators.end(); i++) {
199                     if (*i) {
200                         v.push_back((*i)->cloneAttributeDesignator());
201                     }
202                 }
203             }
204             
205             IMPL_XMLOBJECT_CLONE(AttributeQuery);
206             SubjectQuery* cloneSubjectQuery() const {
207                 return cloneAttributeQuery();
208             }
209             Query* cloneQuery() const {
210                 return cloneAttributeQuery();
211             }
212             IMPL_STRING_ATTRIB(Resource);
213             IMPL_TYPED_CHILDREN(AttributeDesignator,m_children.end());
214     
215         protected:
216             void marshallAttributes(DOMElement* domElement) const {
217                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,NULL);
218                 SubjectQueryImpl::marshallAttributes(domElement);
219             }
220     
221             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
222                 PROC_TYPED_CHILDREN(AttributeDesignator,SAML1_NS,true);
223                 SubjectQueryImpl::processChildElement(childXMLObject,root);
224             }
225     
226             void processAttribute(const DOMAttr* attribute) {
227                 PROC_STRING_ATTRIB(Resource,RESOURCE,NULL);
228                 SubjectQueryImpl::processAttribute(attribute);
229             }
230         };
231
232         class SAML_DLLLOCAL AuthorizationDecisionQueryImpl : public virtual AuthorizationDecisionQuery, public SubjectQueryImpl
233         {
234             void init() {
235                 m_Resource=NULL;
236                 m_Evidence=NULL;
237                 m_children.push_back(NULL);
238                 m_pos_Evidence=m_pos_Subject;
239                 ++m_pos_Evidence;
240             }
241         public:
242             virtual ~AuthorizationDecisionQueryImpl() {
243                 XMLString::release(&m_Resource);
244             }
245     
246             AuthorizationDecisionQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
247                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
248                 init();
249             }
250                 
251             AuthorizationDecisionQueryImpl(const AuthorizationDecisionQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
252                 init();
253                 setResource(src.getResource());
254                 if (src.getEvidence())
255                     setEvidence(src.getEvidence()->cloneEvidence());
256                 VectorOf(Action) v=getActions();
257                 for (vector<Action*>::const_iterator i=src.m_Actions.begin(); i!=src.m_Actions.end(); i++) {
258                     if (*i) {
259                         v.push_back((*i)->cloneAction());
260                     }
261                 }
262             }
263             
264             IMPL_XMLOBJECT_CLONE(AuthorizationDecisionQuery);
265             SubjectQuery* cloneSubjectQuery() const {
266                 return cloneAuthorizationDecisionQuery();
267             }
268             Query* cloneQuery() const {
269                 return cloneAuthorizationDecisionQuery();
270             }
271             IMPL_STRING_ATTRIB(Resource);
272             IMPL_TYPED_CHILD(Evidence);
273             IMPL_TYPED_CHILDREN(Action, m_pos_Evidence);
274     
275         protected:
276             void marshallAttributes(DOMElement* domElement) const {
277                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,NULL);
278                 SubjectQueryImpl::marshallAttributes(domElement);
279             }
280     
281             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
282                 PROC_TYPED_CHILD(Evidence,SAML1_NS,false);
283                 PROC_TYPED_CHILDREN(Action,SAML1_NS,false);
284                 SubjectQueryImpl::processChildElement(childXMLObject,root);
285             }
286     
287             void processAttribute(const DOMAttr* attribute) {
288                 PROC_STRING_ATTRIB(Resource,RESOURCE,NULL);
289                 SubjectQueryImpl::processAttribute(attribute);
290             }
291         };
292
293         class SAML_DLLLOCAL RequestAbstractTypeImpl : public virtual RequestAbstractType,
294             public AbstractComplexElement,
295             public AbstractDOMCachingXMLObject,
296             public AbstractXMLObjectMarshaller,
297             public AbstractXMLObjectUnmarshaller
298         {
299             void init() {
300                 m_MinorVersion=NULL;
301                 m_RequestID=NULL;
302                 m_IssueInstant=NULL;
303                 m_children.push_back(NULL);
304                 m_Signature=NULL;
305                 m_pos_Signature=m_children.begin();
306             }
307         protected:
308             RequestAbstractTypeImpl() {
309                 init();
310             }
311         public:
312             virtual ~RequestAbstractTypeImpl() {
313                 XMLString::release(&m_MinorVersion);
314                 XMLString::release(&m_RequestID);
315                 delete m_IssueInstant;
316             }
317     
318             RequestAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
319                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
320                 init();
321             }
322                 
323             RequestAbstractTypeImpl(const RequestAbstractTypeImpl& src)
324                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
325                 init();
326                 setMinorVersion(src.m_MinorVersion);
327                 setRequestID(src.getRequestID());
328                 setIssueInstant(src.getIssueInstant());
329                 if (src.getSignature())
330                     setSignature(src.getSignature()->cloneSignature());
331                 VectorOf(RespondWith) v=getRespondWiths();
332                 for (vector<RespondWith*>::const_iterator i=src.m_RespondWiths.begin(); i!=src.m_RespondWiths.end(); i++) {
333                     if (*i) {
334                         v.push_back((*i)->cloneRespondWith());
335                     }
336                 }
337             }
338             
339             //IMPL_TYPED_CHILD(Signature);
340             // Need customized setter.
341         protected:
342             Signature* m_Signature;
343             list<XMLObject*>::iterator m_pos_Signature;
344         public:
345             Signature* getSignature() const {
346                 return m_Signature;
347             }
348             
349             void setSignature(Signature* sig) {
350                 prepareForAssignment(m_Signature,sig);
351                 *m_pos_Signature=m_Signature=sig;
352                 // Sync content reference back up.
353                 if (m_Signature)
354                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
355             }
356
357             IMPL_INTEGER_ATTRIB(MinorVersion);
358             IMPL_STRING_ATTRIB(RequestID);    // have to special-case getXMLID
359             const XMLCh* getXMLID() const {
360                 pair<bool,int> v = getMinorVersion();
361                 return (!v.first || v.second > 0) ? m_RequestID : NULL;
362             }
363             const XMLCh* getID() const {
364                 return getRequestID();
365             }
366             IMPL_DATETIME_ATTRIB(IssueInstant,0);
367             IMPL_TYPED_CHILDREN(RespondWith,m_pos_Signature);
368     
369         protected:
370             void marshallAttributes(DOMElement* domElement) const {
371                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
372                 domElement->setAttributeNS(NULL,MAJORVERSION,XML_ONE);
373                 if (!m_MinorVersion)
374                     const_cast<RequestAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
375                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
376                 if (!m_RequestID)
377                     const_cast<RequestAbstractTypeImpl*>(this)->m_RequestID=SAMLConfig::getConfig().generateIdentifier();
378                 MARSHALL_ID_ATTRIB(RequestID,REQUESTID,NULL);
379                 if (!m_IssueInstant) {
380                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(NULL);
381                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
382                 }
383                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
384             }
385
386             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
387                 PROC_TYPED_CHILDREN(RespondWith,SAML1P_NS,false);
388                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
389                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
390             }
391
392             void processAttribute(const DOMAttr* attribute) {
393                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
394                 if (XMLHelper::isNodeNamed(attribute,NULL,MAJORVERSION)) {
395                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
396                         throw UnmarshallingException("Request has invalid major version.");
397                 }
398                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
399                 PROC_ID_ATTRIB(RequestID,REQUESTID,NULL);
400                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
401             }
402         };
403
404         class SAML_DLLLOCAL RequestImpl : public virtual Request, public RequestAbstractTypeImpl
405         {
406             void init() {
407                 m_children.push_back(NULL);
408                 m_Query=NULL;
409                 m_pos_Query=m_pos_Signature;
410                 ++m_pos_Query;
411             }
412         public:
413             virtual ~RequestImpl() {}
414     
415             RequestImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
416                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
417                 init();
418             }
419                 
420             RequestImpl(const RequestImpl& src) : AbstractXMLObject(src), RequestAbstractTypeImpl(src) {
421                 init();
422                 if (src.getQuery())
423                     setQuery(src.getQuery()->cloneQuery());
424                 VectorOf(AssertionIDReference) v=getAssertionIDReferences();
425                 for (vector<AssertionIDReference*>::const_iterator i=src.m_AssertionIDReferences.begin(); i!=src.m_AssertionIDReferences.end(); i++) {
426                     if (*i) {
427                         v.push_back((*i)->cloneAssertionIDReference());
428                     }
429                 }
430                 VectorOf(AssertionArtifact) v2=getAssertionArtifacts();
431                 for (vector<AssertionArtifact*>::const_iterator i=src.m_AssertionArtifacts.begin(); i!=src.m_AssertionArtifacts.end(); i++) {
432                     if (*i) {
433                         v2.push_back((*i)->cloneAssertionArtifact());
434                     }
435                 }
436             }
437             
438             IMPL_XMLOBJECT_CLONE(Request);
439             RequestAbstractType* cloneRequestAbstractType() const {
440                 return cloneRequest();
441             }
442             IMPL_TYPED_CHILD(Query);
443             
444             SubjectQuery* getSubjectQuery() const {
445                 return dynamic_cast<SubjectQuery*>(getQuery());
446             }
447             AuthenticationQuery* getAuthenticationQuery() const {
448                 return dynamic_cast<AuthenticationQuery*>(getQuery());
449             }
450             AttributeQuery* getAttributeQuery() const {
451                 return dynamic_cast<AttributeQuery*>(getQuery());
452             }
453             AuthorizationDecisionQuery* getAuthorizationDecisionQuery() const {
454                 return dynamic_cast<AuthorizationDecisionQuery*>(getQuery());
455             }
456
457             void setSubjectQuery(SubjectQuery* q) {
458                 setQuery(q);
459             }
460             void setAuthenticationQuery(AuthenticationQuery* q) {
461                 setQuery(q);
462             }
463             void setAttributeQuery(AttributeQuery* q) {
464                 setQuery(q);
465             }
466             void setAuthorizationDecisionQuery(AuthorizationDecisionQuery* q) {
467                 setQuery(q);
468             }
469             
470             IMPL_TYPED_CHILDREN(AssertionIDReference, m_children.end());
471             IMPL_TYPED_CHILDREN(AssertionArtifact, m_children.end());
472     
473         protected:
474             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
475                 PROC_TYPED_CHILD(Query,SAML1P_NS,true);
476                 PROC_TYPED_CHILDREN(AssertionIDReference,SAML1_NS,false);
477                 PROC_TYPED_CHILDREN(AssertionArtifact,SAML1P_NS,false);
478                 RequestAbstractTypeImpl::processChildElement(childXMLObject,root);
479             }
480         };
481
482         class SAML_DLLLOCAL StatusCodeImpl : public virtual StatusCode,
483             public AbstractComplexElement,
484             public AbstractDOMCachingXMLObject,
485             public AbstractXMLObjectMarshaller,
486             public AbstractXMLObjectUnmarshaller
487         {
488             void init() {
489                 m_Value=NULL;
490                 m_children.push_back(NULL);
491                 m_StatusCode=NULL;
492                 m_pos_StatusCode=m_children.begin();
493             }
494         public:
495             virtual ~StatusCodeImpl() {
496                 delete m_Value;
497             }
498     
499             StatusCodeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
500                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
501                 init();
502             }
503                 
504             StatusCodeImpl(const StatusCodeImpl& src)
505                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
506                 init();
507                 setValue(src.getValue());
508                 if (src.getStatusCode())
509                     setStatusCode(src.getStatusCode()->cloneStatusCode());
510             }
511             
512             IMPL_XMLOBJECT_CLONE(StatusCode);
513             IMPL_XMLOBJECT_ATTRIB(Value,QName);
514             IMPL_TYPED_CHILD(StatusCode);
515     
516         protected:
517             void marshallAttributes(DOMElement* domElement) const {
518                 MARSHALL_QNAME_ATTRIB(Value,VALUE,NULL);
519             }
520
521             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
522                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,true);
523                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
524             }
525
526             void processAttribute(const DOMAttr* attribute) {
527                 PROC_QNAME_ATTRIB(Value,VALUE,NULL);
528             }
529         };
530
531         class SAML_DLLLOCAL StatusDetailImpl : public virtual StatusDetail,
532             public AbstractComplexElement,
533             public AbstractDOMCachingXMLObject,
534             public AbstractXMLObjectMarshaller,
535             public AbstractXMLObjectUnmarshaller
536         {
537         public:
538             virtual ~StatusDetailImpl() {}
539     
540             StatusDetailImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
541                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
542             }
543                 
544             StatusDetailImpl(const StatusDetailImpl& src)
545                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
546                 VectorOf(XMLObject) v=getUnknownXMLObjects();
547                 for (vector<XMLObject*>::const_iterator i=src.m_UnknownXMLObjects.begin(); i!=src.m_UnknownXMLObjects.end(); ++i)
548                     v.push_back((*i)->clone());
549             }
550             
551             IMPL_XMLOBJECT_CLONE(StatusDetail);
552             IMPL_XMLOBJECT_CHILDREN(UnknownXMLObject,m_children.end());
553     
554         protected:
555             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
556                 getUnknownXMLObjects().push_back(childXMLObject);
557             }
558         };
559
560         class SAML_DLLLOCAL StatusImpl : public virtual Status,
561             public AbstractComplexElement,
562             public AbstractDOMCachingXMLObject,
563             public AbstractXMLObjectMarshaller,
564             public AbstractXMLObjectUnmarshaller
565         {
566             void init() {
567                 m_children.push_back(NULL);
568                 m_children.push_back(NULL);
569                 m_children.push_back(NULL);
570                 m_StatusCode=NULL;
571                 m_pos_StatusCode=m_children.begin();
572                 m_StatusMessage=NULL;
573                 m_pos_StatusMessage=m_pos_StatusCode;
574                 ++m_pos_StatusMessage;
575                 m_StatusDetail=NULL;
576                 m_pos_StatusDetail=m_pos_StatusMessage;
577                 ++m_pos_StatusDetail;
578             }
579         public:
580             virtual ~StatusImpl() {}
581     
582             StatusImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
583                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
584                 init();
585             }
586                 
587             StatusImpl(const StatusImpl& src)
588                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
589                 init();
590                 if (src.getStatusCode())
591                     setStatusCode(src.getStatusCode()->cloneStatusCode());
592                 if (src.getStatusMessage())
593                     setStatusMessage(src.getStatusMessage()->cloneStatusMessage());
594                 if (src.getStatusDetail())
595                     setStatusDetail(src.getStatusDetail()->cloneStatusDetail());
596             }
597             
598             IMPL_XMLOBJECT_CLONE(Status);
599             IMPL_TYPED_CHILD(StatusCode);
600             IMPL_TYPED_CHILD(StatusMessage);
601             IMPL_TYPED_CHILD(StatusDetail);
602     
603         protected:
604             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
605                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,false);
606                 PROC_TYPED_CHILD(StatusMessage,SAML1P_NS,false);
607                 PROC_TYPED_CHILD(StatusDetail,SAML1P_NS,false);
608                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
609             }
610         };
611
612         class SAML_DLLLOCAL ResponseAbstractTypeImpl : public virtual ResponseAbstractType,
613             public AbstractComplexElement,
614             public AbstractDOMCachingXMLObject,
615             public AbstractXMLObjectMarshaller,
616             public AbstractXMLObjectUnmarshaller
617         {
618             void init() {
619                 m_MinorVersion=NULL;
620                 m_ResponseID=NULL;
621                 m_InResponseTo=NULL;
622                 m_IssueInstant=NULL;
623                 m_Recipient=NULL;
624                 m_children.push_back(NULL);
625                 m_Signature=NULL;
626                 m_pos_Signature=m_children.begin();
627             }
628         protected:
629             ResponseAbstractTypeImpl() {
630                 init();
631             }
632         public:
633             virtual ~ResponseAbstractTypeImpl() {
634                 XMLString::release(&m_MinorVersion);
635                 XMLString::release(&m_ResponseID);
636                 XMLString::release(&m_InResponseTo);
637                 XMLString::release(&m_Recipient);
638                 delete m_IssueInstant;
639             }
640     
641             ResponseAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
642                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
643                 init();
644             }
645                 
646             ResponseAbstractTypeImpl(const ResponseAbstractTypeImpl& src)
647                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
648                 init();
649                 setMinorVersion(src.m_MinorVersion);
650                 setResponseID(src.getResponseID());
651                 setInResponseTo(src.getInResponseTo());
652                 setIssueInstant(src.getIssueInstant());
653                 setRecipient(src.getRecipient());
654                 if (src.getSignature())
655                     setSignature(src.getSignature()->cloneSignature());
656             }
657
658             //IMPL_TYPED_CHILD(Signature);
659             // Need customized setter.
660         protected:
661             Signature* m_Signature;
662             list<XMLObject*>::iterator m_pos_Signature;
663         public:
664             Signature* getSignature() const {
665                 return m_Signature;
666             }
667             
668             void setSignature(Signature* sig) {
669                 prepareForAssignment(m_Signature,sig);
670                 *m_pos_Signature=m_Signature=sig;
671                 // Sync content reference back up.
672                 if (m_Signature)
673                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
674             }
675
676             IMPL_INTEGER_ATTRIB(MinorVersion);
677             IMPL_STRING_ATTRIB(ResponseID);    // have to special-case getXMLID
678             const XMLCh* getXMLID() const {
679                 pair<bool,int> v = getMinorVersion();
680                 return (!v.first || v.second > 0) ? m_ResponseID : NULL;
681             }
682             const XMLCh* getID() const {
683                 return getResponseID();
684             }
685             IMPL_STRING_ATTRIB(InResponseTo);
686             IMPL_DATETIME_ATTRIB(IssueInstant,0);
687             IMPL_STRING_ATTRIB(Recipient);
688     
689         protected:
690             void marshallAttributes(DOMElement* domElement) const {
691                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
692                 domElement->setAttributeNS(NULL,MAJORVERSION,XML_ONE);
693                 if (!m_MinorVersion)
694                     const_cast<ResponseAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
695                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
696                 if (!m_ResponseID)
697                     const_cast<ResponseAbstractTypeImpl*>(this)->m_ResponseID=SAMLConfig::getConfig().generateIdentifier();
698                 MARSHALL_ID_ATTRIB(ResponseID,RESPONSEID,NULL);
699                 MARSHALL_STRING_ATTRIB(InResponseTo,INRESPONSETO,NULL);
700                 if (!m_IssueInstant) {
701                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(NULL);
702                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
703                 }
704                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
705                 MARSHALL_STRING_ATTRIB(Recipient,RECIPIENT,NULL);
706             }
707
708             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
709                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
710                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
711             }
712
713             void processAttribute(const DOMAttr* attribute) {
714                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
715                 if (XMLHelper::isNodeNamed(attribute,NULL,MAJORVERSION)) {
716                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
717                         throw UnmarshallingException("Response has invalid major version.");
718                 }
719                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
720                 PROC_ID_ATTRIB(ResponseID,RESPONSEID,NULL);
721                 PROC_STRING_ATTRIB(InResponseTo,INRESPONSETO,NULL);
722                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
723                 PROC_STRING_ATTRIB(Recipient,RECIPIENT,NULL);
724             }
725         };
726
727         class SAML_DLLLOCAL ResponseImpl : public virtual Response, public ResponseAbstractTypeImpl
728         {
729             void init() {
730                 m_children.push_back(NULL);
731                 m_Status=NULL;
732                 m_pos_Status=m_pos_Signature;
733                 ++m_pos_Status;
734             }
735         public:
736             virtual ~ResponseImpl() {}
737     
738             ResponseImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
739                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
740                 init();
741             }
742                 
743             ResponseImpl(const ResponseImpl& src) : AbstractXMLObject(src), ResponseAbstractTypeImpl(src) {
744                 init();
745                 if (src.getStatus())
746                     setStatus(src.getStatus()->cloneStatus());
747                 VectorOf(Assertion) v=getAssertions();
748                 for (vector<Assertion*>::const_iterator i=src.m_Assertions.begin(); i!=src.m_Assertions.end(); i++) {
749                     if (*i) {
750                         v.push_back((*i)->cloneAssertion());
751                     }
752                 }
753             }
754             
755             IMPL_XMLOBJECT_CLONE(Response);
756             ResponseAbstractType* cloneResponseAbstractType() const {
757                 return cloneResponse();
758             }
759             IMPL_TYPED_CHILD(Status);
760             IMPL_TYPED_CHILDREN(Assertion, m_children.end());
761     
762         protected:
763             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
764                 PROC_TYPED_CHILD(Status,SAML1P_NS,false);
765                 PROC_TYPED_CHILDREN(Assertion,SAML1_NS,true);
766                 ResponseAbstractTypeImpl::processChildElement(childXMLObject,root);
767             }
768         };
769
770     };
771 };
772
773 #if defined (_MSC_VER)
774     #pragma warning( pop )
775 #endif
776
777 // Builder Implementations
778
779 IMPL_XMLOBJECTBUILDER(AssertionArtifact);
780 IMPL_XMLOBJECTBUILDER(AttributeQuery);
781 IMPL_XMLOBJECTBUILDER(AuthenticationQuery);
782 IMPL_XMLOBJECTBUILDER(AuthorizationDecisionQuery);
783 IMPL_XMLOBJECTBUILDER(Request);
784 IMPL_XMLOBJECTBUILDER(RespondWith);
785 IMPL_XMLOBJECTBUILDER(Response);
786 IMPL_XMLOBJECTBUILDER(Status);
787 IMPL_XMLOBJECTBUILDER(StatusCode);
788 IMPL_XMLOBJECTBUILDER(StatusDetail);
789 IMPL_XMLOBJECTBUILDER(StatusMessage);
790
791 // Unicode literals
792 const XMLCh RequestAbstractType::LOCAL_NAME[] =             {chNull};
793 const XMLCh RequestAbstractType::TYPE_NAME[] =              UNICODE_LITERAL_19(R,e,q,u,e,s,t,A,b,s,t,r,a,c,t,T,y,p,e);
794 const XMLCh RequestAbstractType::MINORVERSION_ATTRIB_NAME[] =   UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
795 const XMLCh RequestAbstractType::REQUESTID_ATTRIB_NAME[] =      UNICODE_LITERAL_9(R,e,q,u,e,s,t,I,D);
796 const XMLCh RequestAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =   UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
797 const XMLCh ResponseAbstractType::LOCAL_NAME[] =            {chNull};
798 const XMLCh ResponseAbstractType::TYPE_NAME[] =             UNICODE_LITERAL_20(R,e,s,p,o,n,s,e,A,b,s,t,r,a,c,t,T,y,p,e);
799 const XMLCh ResponseAbstractType::MINORVERSION_ATTRIB_NAME[] =  UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
800 const XMLCh ResponseAbstractType::RESPONSEID_ATTRIB_NAME[] =    UNICODE_LITERAL_10(R,e,s,p,o,n,s,e,I,D);
801 const XMLCh ResponseAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
802 const XMLCh ResponseAbstractType::INRESPONSETO_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,n,R,e,s,p,o,n,s,e,T,o);
803 const XMLCh ResponseAbstractType::RECIPIENT_ATTRIB_NAME[] =     UNICODE_LITERAL_9(R,e,c,i,p,i,e,n,t);
804 const XMLCh AssertionArtifact::LOCAL_NAME[] =               UNICODE_LITERAL_17(A,s,s,e,r,t,i,o,n,A,r,t,i,f,a,c,t);
805 const XMLCh AttributeQuery::LOCAL_NAME[] =                  UNICODE_LITERAL_14(A,t,t,r,i,b,u,t,e,Q,u,e,r,y);
806 const XMLCh AttributeQuery::TYPE_NAME[] =                   UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,Q,u,e,r,y,T,y,p,e);
807 const XMLCh AttributeQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
808 const XMLCh AuthenticationQuery::LOCAL_NAME[] =             UNICODE_LITERAL_19(A,u,t,h,e,n,t,i,c,a,t,i,o,n,Q,u,e,r,y);
809 const XMLCh AuthenticationQuery::TYPE_NAME[] =              UNICODE_LITERAL_23(A,u,t,h,e,n,t,i,c,a,t,i,o,n,Q,u,e,r,y,T,y,p,e);
810 const XMLCh AuthenticationQuery::AUTHENTICATIONMETHOD_ATTRIB_NAME[] =   UNICODE_LITERAL_20(A,u,t,h,e,n,t,i,c,a,t,i,o,n,M,e,t,h,o,d);
811 const XMLCh AuthorizationDecisionQuery::LOCAL_NAME[] =      UNICODE_LITERAL_26(A,u,t,h,o,r,i,z,a,t,i,o,n,D,e,c,i,s,i,o,n,Q,u,e,r,y);
812 const XMLCh AuthorizationDecisionQuery::TYPE_NAME[] =       UNICODE_LITERAL_30(A,u,t,h,o,r,i,z,a,t,i,o,n,D,e,c,i,s,i,o,n,Q,u,e,r,y,T,y,p,e);
813 const XMLCh AuthorizationDecisionQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
814 const XMLCh Query::LOCAL_NAME[] =                           UNICODE_LITERAL_5(Q,u,e,r,y);
815 const XMLCh Request::LOCAL_NAME[] =                         UNICODE_LITERAL_7(R,e,q,u,e,s,t);
816 const XMLCh Request::TYPE_NAME[] =                          UNICODE_LITERAL_11(R,e,q,u,e,s,t,T,y,p,e);
817 const XMLCh RespondWith::LOCAL_NAME[] =                     UNICODE_LITERAL_11(R,e,s,p,o,n,d,W,i,t,h);
818 const XMLCh Response::LOCAL_NAME[] =                        UNICODE_LITERAL_8(R,e,s,p,o,n,s,e);
819 const XMLCh Response::TYPE_NAME[] =                         UNICODE_LITERAL_12(R,e,s,p,o,n,s,e,T,y,p,e);
820 const XMLCh Status::LOCAL_NAME[] =                          UNICODE_LITERAL_6(S,t,a,t,u,s);
821 const XMLCh Status::TYPE_NAME[] =                           UNICODE_LITERAL_10(S,t,a,t,u,s,T,y,p,e);
822 const XMLCh StatusCode::LOCAL_NAME[] =                      UNICODE_LITERAL_10(S,t,a,t,u,s,C,o,d,e);
823 const XMLCh StatusCode::TYPE_NAME[] =                       UNICODE_LITERAL_14(S,t,a,t,u,s,C,o,d,e,T,y,p,e);
824 const XMLCh StatusCode::VALUE_ATTRIB_NAME[] =               UNICODE_LITERAL_5(V,a,l,u,e);
825 const XMLCh StatusDetail::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,t,a,t,u,s,D,e,t,a,i,l);
826 const XMLCh StatusDetail::TYPE_NAME[] =                     UNICODE_LITERAL_16(S,t,a,t,u,s,D,e,t,a,i,l,T,y,p,e);
827 const XMLCh StatusMessage::LOCAL_NAME[] =                   UNICODE_LITERAL_13(S,t,a,t,u,s,M,e,s,s,a,g,e);
828 const XMLCh SubjectQuery::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,u,b,j,e,c,t,Q,u,e,r,y);
829
830 #define XCH(ch) chLatin_##ch
831 #define XNUM(d) chDigit_##d
832
833 const XMLCh _SUCCESS[] =                                    UNICODE_LITERAL_7(S,u,c,c,e,s,s);
834 const XMLCh _REQUESTER[] =                                  UNICODE_LITERAL_9(R,e,q,u,e,s,t,e,r);
835 const XMLCh _RESPONDER[] =                                  UNICODE_LITERAL_9(R,e,s,p,o,n,d,e,r);
836 const XMLCh _VERSIONMISMATCH[] =                            UNICODE_LITERAL_15(V,e,r,s,i,o,n,M,i,s,m,a,t,c,h);
837  
838 QName StatusCode::SUCCESS(SAML1P_NS,_SUCCESS,SAML1P_PREFIX);
839 QName StatusCode::REQUESTER(SAML1P_NS,_REQUESTER,SAML1P_PREFIX);
840 QName StatusCode::RESPONDER(SAML1P_NS,_RESPONDER,SAML1P_PREFIX);
841 QName StatusCode::VERSIONMISMATCH(SAML1P_NS,_VERSIONMISMATCH,SAML1P_PREFIX);