Wrap rest of KeyInfo, add support for exposing object pairs.
[shibboleth/cpp-xmltooling.git] / xmltooling / signature / impl / KeyInfoImpl.cpp
1 /*
2 *  Copyright 2001-2006 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  * KeyInfoImpl.cpp
19  * 
20  * Implementation classes for KeyInfo schema
21  */
22
23 #include "internal.h"
24 #include "AbstractElementProxy.h"
25 #include "exceptions.h"
26 #include "io/AbstractXMLObjectMarshaller.h"
27 #include "io/AbstractXMLObjectUnmarshaller.h"
28 #include "signature/KeyInfo.h"
29 #include "util/XMLHelper.h"
30 #include "validation/AbstractValidatingXMLObject.h"
31
32 #include <xercesc/util/XMLUniDefs.hpp>
33
34 using namespace xmlsignature;
35 using namespace xmltooling;
36 using namespace std;
37
38 #if defined (_MSC_VER)
39     #pragma warning( push )
40     #pragma warning( disable : 4250 4251 )
41 #endif
42
43 namespace xmlsignature {
44     
45     class XMLTOOL_DLLLOCAL DSAKeyValueImpl : public DSAKeyValue,
46         public AbstractDOMCachingXMLObject,
47         public AbstractValidatingXMLObject,
48         public AbstractXMLObjectMarshaller,
49         public AbstractXMLObjectUnmarshaller
50     {
51     public:
52         virtual ~DSAKeyValueImpl() {}
53
54         DSAKeyValueImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
55             : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
56             init();
57         }
58             
59         DSAKeyValueImpl(const DSAKeyValueImpl& src)
60                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
61             init();
62             if (src.getP())
63                 setP(src.getP()->cloneP());
64             if (src.getQ())
65                 setQ(src.getQ()->cloneQ());
66             if (src.getG())
67                 setG(src.getG()->cloneG());
68             if (src.getY())
69                 setY(src.getY()->cloneY());
70             if (src.getJ())
71                 setJ(src.getJ()->cloneJ());
72             if (src.getSeed())
73                 setSeed(src.getSeed()->cloneSeed());
74             if (src.getPgenCounter())
75                 setPgenCounter(src.getPgenCounter()->clonePgenCounter());
76         }
77         
78         void init() {
79             m_P=NULL;
80             m_Q=NULL;
81             m_G=NULL;
82             m_Y=NULL;
83             m_J=NULL;
84             m_Seed=NULL;
85             m_PgenCounter=NULL;
86             m_children.push_back(NULL);
87             m_children.push_back(NULL);
88             m_children.push_back(NULL);
89             m_children.push_back(NULL);
90             m_children.push_back(NULL);
91             m_children.push_back(NULL);
92             m_children.push_back(NULL);
93             m_pos_P=m_children.begin();
94             m_pos_Q=m_pos_P;
95             ++m_pos_Q;
96             m_pos_G=m_pos_Q;
97             ++m_pos_G;
98             m_pos_Y=m_pos_G;
99             ++m_pos_Y;
100             m_pos_J=m_pos_Y;
101             ++m_pos_J;
102             m_pos_Seed=m_pos_J;
103             ++m_pos_Seed;
104             m_pos_PgenCounter=m_pos_Seed;
105             ++m_pos_PgenCounter;
106         }
107         
108         IMPL_XMLOBJECT_CLONE(DSAKeyValue);
109         IMPL_XMLOBJECT_CHILD(P);
110         IMPL_XMLOBJECT_CHILD(Q);
111         IMPL_XMLOBJECT_CHILD(G);
112         IMPL_XMLOBJECT_CHILD(Y);
113         IMPL_XMLOBJECT_CHILD(J);
114         IMPL_XMLOBJECT_CHILD(Seed);
115         IMPL_XMLOBJECT_CHILD(PgenCounter);
116
117     protected:
118         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
119             PROC_XMLOBJECT_CHILD(P,XMLConstants::XMLSIG_NS);
120             PROC_XMLOBJECT_CHILD(Q,XMLConstants::XMLSIG_NS);
121             PROC_XMLOBJECT_CHILD(G,XMLConstants::XMLSIG_NS);
122             PROC_XMLOBJECT_CHILD(Y,XMLConstants::XMLSIG_NS);
123             PROC_XMLOBJECT_CHILD(J,XMLConstants::XMLSIG_NS);
124             PROC_XMLOBJECT_CHILD(Seed,XMLConstants::XMLSIG_NS);
125             PROC_XMLOBJECT_CHILD(PgenCounter,XMLConstants::XMLSIG_NS);
126             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
127         }
128     };
129
130     class XMLTOOL_DLLLOCAL RSAKeyValueImpl : public RSAKeyValue,
131         public AbstractDOMCachingXMLObject,
132         public AbstractValidatingXMLObject,
133         public AbstractXMLObjectMarshaller,
134         public AbstractXMLObjectUnmarshaller
135     {
136     public:
137         virtual ~RSAKeyValueImpl() {}
138
139         RSAKeyValueImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
140                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
141             init();
142         }
143             
144         RSAKeyValueImpl(const RSAKeyValueImpl& src)
145                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
146             init();
147             if (src.getModulus())
148                 setModulus(src.getModulus()->cloneModulus());
149             if (src.getExponent())
150                 setExponent(src.getExponent()->cloneExponent());
151         }
152         
153         void init() {
154             m_Modulus=NULL;
155             m_Exponent=NULL;
156             m_children.push_back(NULL);
157             m_children.push_back(NULL);
158             m_pos_Modulus=m_children.begin();
159             m_pos_Exponent=m_pos_Modulus;
160             ++m_pos_Exponent;
161         }
162         
163         IMPL_XMLOBJECT_CLONE(RSAKeyValue);
164         IMPL_XMLOBJECT_CHILD(Modulus);
165         IMPL_XMLOBJECT_CHILD(Exponent);
166
167     protected:
168         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
169             PROC_XMLOBJECT_CHILD(Modulus,XMLConstants::XMLSIG_NS);
170             PROC_XMLOBJECT_CHILD(Exponent,XMLConstants::XMLSIG_NS);
171             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
172         }
173     };
174
175     class XMLTOOL_DLLLOCAL KeyValueImpl : public KeyValue,
176         public AbstractDOMCachingXMLObject,
177         public AbstractValidatingXMLObject,
178         public AbstractXMLObjectMarshaller,
179         public AbstractXMLObjectUnmarshaller
180     {
181     public:
182         virtual ~KeyValueImpl() {}
183
184         KeyValueImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
185                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
186             init();
187         }
188             
189         KeyValueImpl(const KeyValueImpl& src)
190                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
191             init();
192             if (src.getDSAKeyValue())
193                 setDSAKeyValue(src.getDSAKeyValue()->cloneDSAKeyValue());
194             if (src.getRSAKeyValue())
195                 setRSAKeyValue(src.getRSAKeyValue()->cloneRSAKeyValue());
196             if (src.getXMLObject())
197                 setXMLObject(src.getXMLObject()->clone());
198             setTextContent(src.getTextContent());
199         }
200         
201         void init() {
202             m_TextContent=NULL;
203             m_DSAKeyValue=NULL;
204             m_RSAKeyValue=NULL;
205             m_XMLObject=NULL;
206             m_children.push_back(NULL);
207             m_children.push_back(NULL);
208             m_children.push_back(NULL);
209             m_pos_DSAKeyValue=m_children.begin();
210             m_pos_RSAKeyValue=m_pos_DSAKeyValue;
211             ++m_pos_RSAKeyValue;
212             m_pos_XMLObject=m_pos_RSAKeyValue;
213             ++m_pos_XMLObject;
214         }
215         
216         IMPL_XMLOBJECT_CLONE(KeyValue);
217         IMPL_XMLOBJECT_CHILD(DSAKeyValue);
218         IMPL_XMLOBJECT_CHILD(RSAKeyValue);
219         IMPL_XMLOBJECT_CHILD(XMLObject);
220         IMPL_XMLOBJECT_CONTENT(TextContent);
221
222     protected:
223         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
224             PROC_XMLOBJECT_CHILD(DSAKeyValue,XMLConstants::XMLSIG_NS);
225             PROC_XMLOBJECT_CHILD(RSAKeyValue,XMLConstants::XMLSIG_NS);
226             
227             // Unknown child.
228             const XMLCh* nsURI=root->getNamespaceURI();
229             if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) && nsURI && *nsURI)
230                 setXMLObject(childXMLObject);
231             
232             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
233         }
234     };
235
236     class XMLTOOL_DLLLOCAL TransformImpl : public Transform,
237         public AbstractDOMCachingXMLObject,
238         public AbstractElementProxy,
239         public AbstractValidatingXMLObject,
240         public AbstractXMLObjectMarshaller,
241         public AbstractXMLObjectUnmarshaller
242     {
243     public:
244         virtual ~TransformImpl() {}
245
246         TransformImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
247             : AbstractXMLObject(nsURI, localName, prefix, schemaType), m_Algorithm(NULL) {
248         }
249             
250         TransformImpl(const TransformImpl& src)
251                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractElementProxy(src),
252                     AbstractValidatingXMLObject(src), m_Algorithm(XMLString::replicate(src.m_Algorithm)) {
253             for (list<XMLObject*>::const_iterator i=src.m_children.begin(); i!=src.m_children.end(); i++) {
254                 if (*i) {
255                     XPath* x=dynamic_cast<XPath*>(*i);
256                     if (x) {
257                         getXPaths().push_back(x->cloneXPath());
258                         continue;
259                     }
260                     getXMLObjects().push_back((*i)->clone());
261                 }
262             }
263         }
264         
265         IMPL_XMLOBJECT_CLONE(Transform);
266         IMPL_XMLOBJECT_ATTRIB(Algorithm);
267         IMPL_XMLOBJECT_CHILDREN(XPath,m_children.end());
268
269     protected:
270         void marshallAttributes(DOMElement* domElement) const {
271             MARSHALL_XMLOBJECT_ATTRIB(Algorithm,ALGORITHM,NULL);
272         }
273
274         void marshallElementContent(DOMElement* domElement) const {
275             if(getTextContent()) {
276                 domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent()));
277             }
278         }
279
280         void processElementContent(const XMLCh* elementContent) {
281             setTextContent(elementContent);
282         }
283
284         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
285             PROC_XMLOBJECT_CHILDREN(XPath,XMLConstants::XMLSIG_NS);
286             
287             // Unknown child.
288             const XMLCh* nsURI=root->getNamespaceURI();
289             if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) && nsURI && *nsURI)
290                 getXMLObjects().push_back(childXMLObject);
291             
292             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
293         }
294
295         void processAttribute(const DOMAttr* attribute) {
296             PROC_XMLOBJECT_ATTRIB(Algorithm,ALGORITHM,NULL);
297         }
298     };
299
300     class XMLTOOL_DLLLOCAL TransformsImpl : public Transforms,
301         public AbstractDOMCachingXMLObject,
302         public AbstractValidatingXMLObject,
303         public AbstractXMLObjectMarshaller,
304         public AbstractXMLObjectUnmarshaller
305     {
306     public:
307         virtual ~TransformsImpl() {}
308
309         TransformsImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
310             : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
311         }
312             
313         TransformsImpl(const TransformsImpl& src)
314                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
315             VectorOf(Transform) v=getTransforms();
316             for (vector<Transform*>::const_iterator i=src.m_Transforms.begin(); i!=src.m_Transforms.end(); i++) {
317                 if (*i) {
318                     v.push_back((*i)->cloneTransform());
319                 }
320             }
321         }
322         
323         IMPL_XMLOBJECT_CLONE(Transforms);
324         IMPL_XMLOBJECT_CHILDREN(Transform,m_children.end());
325
326     protected:
327         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
328             PROC_XMLOBJECT_CHILDREN(Transform,XMLConstants::XMLSIG_NS);
329             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
330         }
331     };
332
333     class XMLTOOL_DLLLOCAL RetrievalMethodImpl : public RetrievalMethod,
334         public AbstractDOMCachingXMLObject,
335         public AbstractValidatingXMLObject,
336         public AbstractXMLObjectMarshaller,
337         public AbstractXMLObjectUnmarshaller
338     {
339     public:
340         virtual ~RetrievalMethodImpl() {}
341
342         RetrievalMethodImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
343             : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
344             init();
345         }
346             
347         RetrievalMethodImpl(const RetrievalMethodImpl& src)
348                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
349             init();
350             setURI(getURI());
351             setType(getType());
352             if (src.getTransforms())
353                 setTransforms(src.getTransforms()->cloneTransforms());
354         }
355         
356         void init() {
357             m_URI=m_Type=NULL;
358             m_Transforms=NULL;
359             m_children.push_back(NULL);
360             m_pos_Transforms=m_children.begin();
361         }
362         
363         IMPL_XMLOBJECT_CLONE(RetrievalMethod);
364         IMPL_XMLOBJECT_ATTRIB(URI);
365         IMPL_XMLOBJECT_ATTRIB(Type);
366         IMPL_XMLOBJECT_CHILD(Transforms);
367
368     protected:
369         void marshallAttributes(DOMElement* domElement) const {
370             MARSHALL_XMLOBJECT_ATTRIB(URI,URI,NULL);
371             MARSHALL_XMLOBJECT_ATTRIB(Type,TYPE,NULL);
372         }
373
374         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
375             PROC_XMLOBJECT_CHILD(Transforms,XMLConstants::XMLSIG_NS);
376             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
377         }
378
379         void processAttribute(const DOMAttr* attribute) {
380             PROC_XMLOBJECT_ATTRIB(URI,URI,NULL);
381             PROC_XMLOBJECT_ATTRIB(Type,TYPE,NULL);
382         }
383     };
384
385     class XMLTOOL_DLLLOCAL X509IssuerSerialImpl : public X509IssuerSerial,
386         public AbstractDOMCachingXMLObject,
387         public AbstractValidatingXMLObject,
388         public AbstractXMLObjectMarshaller,
389         public AbstractXMLObjectUnmarshaller
390     {
391     public:
392         virtual ~X509IssuerSerialImpl() {}
393
394         X509IssuerSerialImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
395                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
396             init();
397         }
398             
399         X509IssuerSerialImpl(const X509IssuerSerialImpl& src)
400                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
401             init();
402             if (src.getX509IssuerName())
403                 setX509IssuerName(src.getX509IssuerName()->cloneX509IssuerName());
404             if (src.getX509SerialNumber())
405                 setX509SerialNumber(src.getX509SerialNumber()->cloneX509SerialNumber());
406         }
407         
408         void init() {
409             m_X509IssuerName=NULL;
410             m_X509SerialNumber=NULL;
411             m_children.push_back(NULL);
412             m_children.push_back(NULL);
413             m_pos_X509IssuerName=m_children.begin();
414             m_pos_X509SerialNumber=m_pos_X509IssuerName;
415             ++m_pos_X509SerialNumber;
416         }
417         
418         IMPL_XMLOBJECT_CLONE(X509IssuerSerial);
419         IMPL_XMLOBJECT_CHILD(X509IssuerName);
420         IMPL_XMLOBJECT_CHILD(X509SerialNumber);
421
422     protected:
423         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
424             PROC_XMLOBJECT_CHILD(X509IssuerName,XMLConstants::XMLSIG_NS);
425             PROC_XMLOBJECT_CHILD(X509SerialNumber,XMLConstants::XMLSIG_NS);
426             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
427         }
428     };
429
430     class XMLTOOL_DLLLOCAL X509DataImpl : public X509Data,
431         public AbstractDOMCachingXMLObject,
432         public AbstractValidatingXMLObject,
433         public AbstractXMLObjectMarshaller,
434         public AbstractXMLObjectUnmarshaller
435     {
436     public:
437         virtual ~X509DataImpl() {}
438
439         X509DataImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
440             : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
441         }
442             
443         X509DataImpl(const X509DataImpl& src)
444                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
445             for (list<XMLObject*>::const_iterator i=src.m_children.begin(); i!=src.m_children.end(); i++) {
446                 if (*i) {
447                     X509Certificate* xcert=dynamic_cast<X509Certificate*>(*i);
448                     if (xcert) {
449                         getX509Certificates().push_back(xcert->cloneX509Certificate());
450                         continue;
451                     }
452
453                     X509CRL* xcrl=dynamic_cast<X509CRL*>(*i);
454                     if (xcrl) {
455                         getX509CRLs().push_back(xcrl->cloneX509CRL());
456                         continue;
457                     }
458
459                     X509SubjectName* xsn=dynamic_cast<X509SubjectName*>(*i);
460                     if (xsn) {
461                         getX509SubjectNames().push_back(xsn->cloneX509SubjectName());
462                         continue;
463                     }
464
465                     X509IssuerSerial* xis=dynamic_cast<X509IssuerSerial*>(*i);
466                     if (xis) {
467                         getX509IssuerSerials().push_back(xis->cloneX509IssuerSerial());
468                         continue;
469                     }
470
471                     X509SKI* xski=dynamic_cast<X509SKI*>(*i);
472                     if (xski) {
473                         getX509SKIs().push_back(xski->cloneX509SKI());
474                         continue;
475                     }
476
477                     getXMLObjects().push_back((*i)->clone());
478                 }
479             }
480         }
481         
482         IMPL_XMLOBJECT_CLONE(X509Data);
483         IMPL_XMLOBJECT_CHILDREN(X509IssuerSerial,m_children.end());
484         IMPL_XMLOBJECT_CHILDREN(X509SKI,m_children.end());
485         IMPL_XMLOBJECT_CHILDREN(X509SubjectName,m_children.end());
486         IMPL_XMLOBJECT_CHILDREN(X509Certificate,m_children.end());
487         IMPL_XMLOBJECT_CHILDREN(X509CRL,m_children.end());
488         IMPL_XMLOBJECT_CHILDREN(XMLObject,m_children.end());
489
490     protected:
491         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
492             PROC_XMLOBJECT_CHILDREN(X509IssuerSerial,XMLConstants::XMLSIG_NS);
493             PROC_XMLOBJECT_CHILDREN(X509SKI,XMLConstants::XMLSIG_NS);
494             PROC_XMLOBJECT_CHILDREN(X509SubjectName,XMLConstants::XMLSIG_NS);
495             PROC_XMLOBJECT_CHILDREN(X509Certificate,XMLConstants::XMLSIG_NS);
496             PROC_XMLOBJECT_CHILDREN(X509CRL,XMLConstants::XMLSIG_NS);
497             
498             // Unknown child.
499             const XMLCh* nsURI=root->getNamespaceURI();
500             if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) && nsURI && *nsURI)
501                 getXMLObjects().push_back(childXMLObject);
502             
503             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
504         }
505     };
506
507     class XMLTOOL_DLLLOCAL SPKIDataImpl : public SPKIData,
508         public AbstractDOMCachingXMLObject,
509         public AbstractValidatingXMLObject,
510         public AbstractXMLObjectMarshaller,
511         public AbstractXMLObjectUnmarshaller
512     {
513     public:
514         virtual ~SPKIDataImpl() {}
515
516         SPKIDataImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
517             : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
518         }
519             
520         SPKIDataImpl(const SPKIDataImpl& src)
521                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
522             VectorOfPairs(SPKISexp,XMLObject) v=getSPKISexps();
523             for (vector< pair<SPKISexp*,XMLObject*> >::const_iterator i=src.m_SPKISexps.begin(); i!=src.m_SPKISexps.end(); i++) {
524                 if (i->first) {
525                     v.push_back(make_pair(i->first->cloneSPKISexp(),(i->second ? i->second->clone() : (XMLObject*)NULL)));
526                 }
527             }
528         }
529         
530         IMPL_XMLOBJECT_CLONE(SPKIData);
531
532     private:
533         vector< pair<SPKISexp*,XMLObject*> > m_SPKISexps;
534
535     public:
536         VectorOfPairs(SPKISexp,XMLObject) getSPKISexps() {
537             return VectorOfPairs(SPKISexp,XMLObject)(this, m_SPKISexps, &m_children, m_children.end());
538         }
539         
540         const vector< pair<SPKISexp*,XMLObject*> >& getSPKISexps() const {
541             return m_SPKISexps;
542         }
543         
544     protected:
545         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
546             if (XMLHelper::isNodeNamed(root,XMLConstants::XMLSIG_NS,SPKISexp::LOCAL_NAME)) {
547                 SPKISexp* typesafe=dynamic_cast<SPKISexp*>(childXMLObject);
548                 if (typesafe) {
549                     getSPKISexps().push_back(make_pair(typesafe,(XMLObject*)NULL));
550                     return;
551                 }
552             }
553
554             // Unknown child (has to be paired with the last SPKISexp processed.
555             const XMLCh* nsURI=root->getNamespaceURI();
556             if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) && nsURI && *nsURI) {
557                 // Update second half of pair in vector, then add to master list.
558                 if (m_SPKISexps.back().second==NULL) {
559                     m_SPKISexps.back().second=childXMLObject;
560                     m_children.push_back(childXMLObject);
561                 }
562                 else
563                     throw UnmarshallingException("Extension element must follow ds:SPKISexp element.");
564             }
565             
566             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
567         }
568     };
569
570     class XMLTOOL_DLLLOCAL PGPDataImpl : public PGPData,
571         public AbstractDOMCachingXMLObject,
572         public AbstractValidatingXMLObject,
573         public AbstractXMLObjectMarshaller,
574         public AbstractXMLObjectUnmarshaller
575     {
576     public:
577         virtual ~PGPDataImpl() {}
578
579         PGPDataImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
580                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
581             init();
582         }
583             
584         PGPDataImpl(const PGPDataImpl& src)
585                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractValidatingXMLObject(src) {
586             init();
587             if (src.getPGPKeyID())
588                 setPGPKeyID(src.getPGPKeyID()->clonePGPKeyID());
589             if (src.getPGPKeyPacket())
590                 setPGPKeyPacket(src.getPGPKeyPacket()->clonePGPKeyPacket());
591             VectorOf(XMLObject) v=getXMLObjects();
592             for (vector<XMLObject*>::const_iterator i=src.m_XMLObjects.begin(); i!=src.m_XMLObjects.end(); i++) {
593                 if (*i) {
594                     v.push_back((*i)->clone());
595                 }
596             }
597         }
598         
599         void init() {
600             m_PGPKeyID=NULL;
601             m_PGPKeyPacket=NULL;
602             m_children.push_back(NULL);
603             m_children.push_back(NULL);
604             m_pos_PGPKeyID=m_children.begin();
605             m_pos_PGPKeyPacket=m_pos_PGPKeyID;
606             ++m_pos_PGPKeyPacket;
607         }
608         
609         IMPL_XMLOBJECT_CLONE(PGPData);
610         IMPL_XMLOBJECT_CHILD(PGPKeyID);
611         IMPL_XMLOBJECT_CHILD(PGPKeyPacket);
612         IMPL_XMLOBJECT_CHILDREN(XMLObject,m_children.end());
613
614     protected:
615         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
616             PROC_XMLOBJECT_CHILD(PGPKeyID,XMLConstants::XMLSIG_NS);
617             PROC_XMLOBJECT_CHILD(PGPKeyPacket,XMLConstants::XMLSIG_NS);
618
619             // Unknown child.
620             const XMLCh* nsURI=root->getNamespaceURI();
621             if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) && nsURI && *nsURI)
622                 getXMLObjects().push_back(childXMLObject);
623
624             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
625         }
626     };
627
628     class XMLTOOL_DLLLOCAL KeyInfoImpl : public KeyInfo,
629         public AbstractDOMCachingXMLObject,
630         public AbstractElementProxy,
631         public AbstractValidatingXMLObject,
632         public AbstractXMLObjectMarshaller,
633         public AbstractXMLObjectUnmarshaller
634     {
635     public:
636         virtual ~KeyInfoImpl() {}
637
638         KeyInfoImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
639             : AbstractXMLObject(nsURI, localName, prefix, schemaType), m_Id(NULL) {
640         }
641             
642         KeyInfoImpl(const KeyInfoImpl& src)
643                 : AbstractXMLObject(src), AbstractDOMCachingXMLObject(src), AbstractElementProxy(src),
644                     AbstractValidatingXMLObject(src), m_Id(XMLString::replicate(src.m_Id)) {
645             for (list<XMLObject*>::const_iterator i=src.m_children.begin(); i!=src.m_children.end(); i++) {
646                 if (*i) {
647                     X509Data* xd=dynamic_cast<X509Data*>(*i);
648                     if (xd) {
649                         getX509Datas().push_back(xd->cloneX509Data());
650                         continue;
651                     }
652
653                     KeyName* kn=dynamic_cast<KeyName*>(*i);
654                     if (kn) {
655                         getKeyNames().push_back(kn->cloneKeyName());
656                         continue;
657                     }
658
659                     KeyValue* kv=dynamic_cast<KeyValue*>(*i);
660                     if (kv) {
661                         getKeyValues().push_back(kv->cloneKeyValue());
662                         continue;
663                     }
664
665                     RetrievalMethod* rm=dynamic_cast<RetrievalMethod*>(*i);
666                     if (rm) {
667                         getRetrievalMethods().push_back(rm->cloneRetrievalMethod());
668                         continue;
669                     }
670
671                     MgmtData* md=dynamic_cast<MgmtData*>(*i);
672                     if (md) {
673                         getMgmtDatas().push_back(md->cloneMgmtData());
674                         continue;
675                     }
676
677                     SPKIData* sd=dynamic_cast<SPKIData*>(*i);
678                     if (sd) {
679                         getSPKIDatas().push_back(sd->cloneSPKIData());
680                         continue;
681                     }
682
683                     PGPData* pd=dynamic_cast<PGPData*>(*i);
684                     if (pd) {
685                         getPGPDatas().push_back(pd->clonePGPData());
686                         continue;
687                     }
688
689                     getXMLObjects().push_back((*i)->clone());
690                 }
691             }
692         }
693         
694         IMPL_XMLOBJECT_CLONE(KeyInfo);
695         IMPL_XMLOBJECT_ATTRIB(Id);
696         IMPL_XMLOBJECT_CHILDREN(KeyName,m_children.end());
697         IMPL_XMLOBJECT_CHILDREN(KeyValue,m_children.end());
698         IMPL_XMLOBJECT_CHILDREN(RetrievalMethod,m_children.end());
699         IMPL_XMLOBJECT_CHILDREN(X509Data,m_children.end());
700         IMPL_XMLOBJECT_CHILDREN(MgmtData,m_children.end());
701         IMPL_XMLOBJECT_CHILDREN(SPKIData,m_children.end());
702         IMPL_XMLOBJECT_CHILDREN(PGPData,m_children.end());
703
704     protected:
705         void marshallAttributes(DOMElement* domElement) const {
706             MARSHALL_XMLOBJECT_ID_ATTRIB(Id,ID,NULL);
707         }
708
709         void marshallElementContent(DOMElement* domElement) const {
710             if(getTextContent()) {
711                 domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent()));
712             }
713         }
714
715         void processElementContent(const XMLCh* elementContent) {
716             setTextContent(elementContent);
717         }
718
719         void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
720             PROC_XMLOBJECT_CHILDREN(X509Data,XMLConstants::XMLSIG_NS);
721             PROC_XMLOBJECT_CHILDREN(KeyName,XMLConstants::XMLSIG_NS);
722             PROC_XMLOBJECT_CHILDREN(KeyValue,XMLConstants::XMLSIG_NS);
723             PROC_XMLOBJECT_CHILDREN(RetrievalMethod,XMLConstants::XMLSIG_NS);
724             PROC_XMLOBJECT_CHILDREN(MgmtData,XMLConstants::XMLSIG_NS);
725             PROC_XMLOBJECT_CHILDREN(SPKIData,XMLConstants::XMLSIG_NS);
726             PROC_XMLOBJECT_CHILDREN(PGPData,XMLConstants::XMLSIG_NS);
727             
728             // Unknown child.
729             const XMLCh* nsURI=root->getNamespaceURI();
730             if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) && nsURI && *nsURI)
731                 getXMLObjects().push_back(childXMLObject);
732             
733             throw UnmarshallingException("Invalid child element: $1",params(1,childXMLObject->getElementQName().toString().c_str()));
734         }
735
736         void processAttribute(const DOMAttr* attribute) {
737             PROC_XMLOBJECT_ID_ATTRIB(Id,ID,NULL);
738         }
739     };
740     
741     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,KeyName,Name);
742     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,MgmtData,Data);
743     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,Modulus,Value);
744     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,Exponent,Value);
745     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,Seed,Value);
746     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,PgenCounter,Value);
747     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,P,Value);
748     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,Q,Value);
749     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,G,Value);
750     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,Y,Value);
751     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,J,Value);
752     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,XPath,Expression);
753     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,X509IssuerName,Name);
754     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,X509SerialNumber,SerialNumber);
755     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,X509SKI,Value);
756     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,X509SubjectName,Name);
757     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,X509Certificate,Value);
758     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,X509CRL,Value);
759     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,SPKISexp,Value);
760     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,PGPKeyID,ID);
761     DECL_XMLOBJECTIMPL_SIMPLE(XMLTOOL_DLLLOCAL,PGPKeyPacket,Packet);
762 };
763
764 #if defined (_MSC_VER)
765     #pragma warning( pop )
766 #endif
767
768 // Builder Implementations
769
770 IMPL_XMLOBJECTBUILDER(X509IssuerSerial);
771 IMPL_XMLOBJECTBUILDER(X509IssuerName);
772 IMPL_XMLOBJECTBUILDER(X509SerialNumber);
773 IMPL_XMLOBJECTBUILDER(X509SKI);
774 IMPL_XMLOBJECTBUILDER(X509SubjectName);
775 IMPL_XMLOBJECTBUILDER(X509Certificate);
776 IMPL_XMLOBJECTBUILDER(X509CRL);
777 IMPL_XMLOBJECTBUILDER(X509Data);
778 IMPL_XMLOBJECTBUILDER(XPath);
779 IMPL_XMLOBJECTBUILDER(Transform);
780 IMPL_XMLOBJECTBUILDER(Transforms);
781 IMPL_XMLOBJECTBUILDER(RetrievalMethod);
782 IMPL_XMLOBJECTBUILDER(KeyName);
783 IMPL_XMLOBJECTBUILDER(MgmtData);
784 IMPL_XMLOBJECTBUILDER(Modulus);
785 IMPL_XMLOBJECTBUILDER(Exponent);
786 IMPL_XMLOBJECTBUILDER(Seed);
787 IMPL_XMLOBJECTBUILDER(PgenCounter);
788 IMPL_XMLOBJECTBUILDER(P);
789 IMPL_XMLOBJECTBUILDER(Q);
790 IMPL_XMLOBJECTBUILDER(G);
791 IMPL_XMLOBJECTBUILDER(Y);
792 IMPL_XMLOBJECTBUILDER(J);
793 IMPL_XMLOBJECTBUILDER(DSAKeyValue);
794 IMPL_XMLOBJECTBUILDER(RSAKeyValue);
795 IMPL_XMLOBJECTBUILDER(KeyValue);
796 IMPL_XMLOBJECTBUILDER(KeyInfo);
797 IMPL_XMLOBJECTBUILDER(SPKISexp);
798 IMPL_XMLOBJECTBUILDER(SPKIData);
799 IMPL_XMLOBJECTBUILDER(PGPKeyID);
800 IMPL_XMLOBJECTBUILDER(PGPKeyPacket);
801 IMPL_XMLOBJECTBUILDER(PGPData);
802
803 // Unicode literals
804
805 const XMLCh KeyInfo::LOCAL_NAME[] =             UNICODE_LITERAL_7(K,e,y,I,n,f,o);
806 const XMLCh KeyInfo::TYPE_NAME[] =              UNICODE_LITERAL_11(K,e,y,I,n,f,o,T,y,p,e);
807 const XMLCh KeyInfo::ID_ATTRIB_NAME[] =         UNICODE_LITERAL_2(I,d);
808 const XMLCh KeyValue::LOCAL_NAME[] =            UNICODE_LITERAL_8(K,e,y,V,a,l,u,e);
809 const XMLCh KeyValue::TYPE_NAME[] =             UNICODE_LITERAL_12(K,e,y,V,a,l,u,e,T,y,p,e);
810 const XMLCh DSAKeyValue::LOCAL_NAME[] =         UNICODE_LITERAL_11(D,S,A,K,e,y,V,a,l,u,e);
811 const XMLCh DSAKeyValue::TYPE_NAME[] =          UNICODE_LITERAL_15(D,S,A,K,e,y,V,a,l,u,e,T,y,p,e);
812 const XMLCh RSAKeyValue::LOCAL_NAME[] =         UNICODE_LITERAL_11(R,S,A,K,e,y,V,a,l,u,e);
813 const XMLCh RSAKeyValue::TYPE_NAME[] =          UNICODE_LITERAL_15(R,S,A,K,e,y,V,a,l,u,e,T,y,p,e);
814 const XMLCh MgmtData::LOCAL_NAME[] =            UNICODE_LITERAL_8(M,g,m,t,D,a,t,a);
815 const XMLCh KeyName::LOCAL_NAME[] =             UNICODE_LITERAL_7(K,e,y,N,a,m,e);
816 const XMLCh Modulus::LOCAL_NAME[] =             UNICODE_LITERAL_7(M,o,d,u,l,u,s);
817 const XMLCh Exponent::LOCAL_NAME[] =            UNICODE_LITERAL_8(E,x,p,o,n,e,n,t);
818 const XMLCh Seed::LOCAL_NAME[] =                UNICODE_LITERAL_4(S,e,e,d);
819 const XMLCh PgenCounter::LOCAL_NAME[] =         UNICODE_LITERAL_11(P,g,e,n,C,o,u,n,t,e,r);
820 const XMLCh P::LOCAL_NAME[] =                   UNICODE_LITERAL_1(P);
821 const XMLCh Q::LOCAL_NAME[] =                   UNICODE_LITERAL_1(Q);
822 const XMLCh G::LOCAL_NAME[] =                   UNICODE_LITERAL_1(G);
823 const XMLCh Y::LOCAL_NAME[] =                   UNICODE_LITERAL_1(Y);
824 const XMLCh J::LOCAL_NAME[] =                   UNICODE_LITERAL_1(J);
825 const XMLCh XPath::LOCAL_NAME[] =               UNICODE_LITERAL_5(X,P,a,t,h);
826 const XMLCh Transform::LOCAL_NAME[] =           UNICODE_LITERAL_9(T,r,a,n,s,f,o,r,m);
827 const XMLCh Transform::TYPE_NAME[] =            UNICODE_LITERAL_13(T,r,a,n,s,f,o,r,m,T,y,p,e);
828 const XMLCh Transform::ALGORITHM_ATTRIB_NAME[] = UNICODE_LITERAL_9(A,l,g,o,r,i,t,h,m);
829 const XMLCh Transforms::LOCAL_NAME[] =          UNICODE_LITERAL_10(T,r,a,n,s,f,o,r,m,s);
830 const XMLCh Transforms::TYPE_NAME[] =           UNICODE_LITERAL_14(T,r,a,n,s,f,o,r,m,s,T,y,p,e);
831 const XMLCh RetrievalMethod::LOCAL_NAME[] =     UNICODE_LITERAL_15(R,e,t,r,i,e,v,a,l,M,e,t,h,o,d);
832 const XMLCh RetrievalMethod::TYPE_NAME[] =      UNICODE_LITERAL_19(R,e,t,r,i,e,v,a,l,M,e,t,h,o,d,T,y,p,e);
833 const XMLCh RetrievalMethod::URI_ATTRIB_NAME[] = UNICODE_LITERAL_3(U,R,I);
834 const XMLCh RetrievalMethod::TYPE_ATTRIB_NAME[] = UNICODE_LITERAL_4(T,y,p,e);
835 const XMLCh SPKISexp::LOCAL_NAME[] =            UNICODE_LITERAL_8(S,P,K,I,S,e,x,p);
836 const XMLCh SPKIData::LOCAL_NAME[] =            UNICODE_LITERAL_8(S,P,K,I,D,a,t,a);
837 const XMLCh SPKIData::TYPE_NAME[] =             UNICODE_LITERAL_12(S,P,K,I,D,a,t,a,T,y,p,e);
838 const XMLCh PGPKeyID::LOCAL_NAME[] =            UNICODE_LITERAL_8(P,G,P,K,e,y,I,D);
839 const XMLCh PGPKeyPacket::LOCAL_NAME[] =        UNICODE_LITERAL_12(P,G,P,K,e,y,P,a,c,k,e,t);
840 const XMLCh PGPData::LOCAL_NAME[] =             UNICODE_LITERAL_7(P,G,P,D,a,t,a);
841 const XMLCh PGPData::TYPE_NAME[] =              UNICODE_LITERAL_11(P,G,P,D,a,t,a,T,y,p,e);
842
843 #define XCH(ch) chLatin_##ch
844 #define XNUM(d) chDigit_##d
845
846 const XMLCh X509Data::LOCAL_NAME[] = {
847     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(D), XCH(a), XCH(t), XCH(a), chNull
848     };
849 const XMLCh X509Data::TYPE_NAME[] = {
850     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(D), XCH(a), XCH(t), XCH(a), XCH(T), XCH(y), XCH(p), XCH(e), chNull
851     };
852 const XMLCh X509IssuerSerial::LOCAL_NAME[] = {
853     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(I), XCH(s), XCH(s), XCH(u), XCH(e), XCH(r),
854     XCH(S), XCH(e), XCH(r), XCH(i), XCH(a), XCH(l), chNull
855     };
856 const XMLCh X509IssuerSerial::TYPE_NAME[] = {
857     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(I), XCH(s), XCH(s), XCH(u), XCH(e), XCH(r),
858     XCH(S), XCH(e), XCH(r), XCH(i), XCH(a), XCH(l), XCH(T), XCH(y), XCH(p), XCH(e), chNull
859     };
860 const XMLCh X509IssuerName::LOCAL_NAME[] = {
861     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(I), XCH(s), XCH(s), XCH(u), XCH(e), XCH(r),
862     XCH(N), XCH(a), XCH(m), XCH(e), chNull
863     };
864 const XMLCh X509SerialNumber::LOCAL_NAME[] = {
865     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(S), XCH(e), XCH(r), XCH(i), XCH(a), XCH(l),
866     XCH(N), XCH(u), XCH(m), XCH(b), XCH(e), XCH(r), chNull
867     };
868 const XMLCh X509SKI::LOCAL_NAME[] = { XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(S), XCH(K), XCH(I), chNull };
869 const XMLCh X509SubjectName::LOCAL_NAME[] = {
870     XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(S), XCH(u), XCH(b), XCH(j), XCH(e), XCH(c), XCH(t),
871     XCH(N), XCH(a), XCH(m), XCH(e), chNull
872     };
873 const XMLCh X509Certificate::LOCAL_NAME[] = {
874     XCH(X), XNUM(5), XNUM(0), XNUM(9),
875     XCH(C), XCH(e), XCH(r), XCH(t), XCH(i), XCH(f), XCH(i), XCH(c), XCH(a), XCH(t), XCH(e), chNull
876     };
877 const XMLCh X509CRL::LOCAL_NAME[] = { XCH(X), XNUM(5), XNUM(0), XNUM(9), XCH(C), XCH(R), XCH(L), chNull };
878