File: saml.h

package info (click to toggle)
opensaml 1.1a-2%2Betch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 2,364 kB
  • ctags: 1,771
  • sloc: cpp: 10,614; sh: 8,329; makefile: 199; ansic: 23
file content (2112 lines) | stat: -rw-r--r-- 87,441 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
/*
 *  Copyright 2001-2005 Internet2
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* saml.h - OpenSAML header file

   Scott Cantor
   5/7/02

   $History:$
*/

#ifndef __saml_h__
#define __saml_h__

#include <xercesc/dom/DOM.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/sax/InputSource.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/enc/XSECKeyInfoResolver.hpp>

#ifdef WIN32
# include <windows.h>
# ifndef SAML_EXPORTS
#  define SAML_EXPORTS __declspec(dllimport)
# endif
# pragma warning(disable : 4786 4231 4250 4251 4503 4661)
#else
# define __stdcall
# define __cdecl
# define SAML_EXPORTS
#endif

/* Xerces defines its own macro for wide literals, but on platforms without 16 bit wchar_t
   it defines away the L"" and assumes the ASCII literal is usable, which is never true.
   I convert L"foo" to L(foo) so that the macro handles the reference to the static constant,
   while the code stays somewhat similar.
 */
#define L(s) saml::XML::Literals::s
#define L_QNAME(p,s) saml::XML::Literals::p##_##s

/* Implement a class name mechanism for use with logging. */
# define RTTI(type) _RTTI(#type)

// STL headers
#include <map>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <iostream>
#include <exception>

#if defined (_MSC_VER) || defined(__BORLANDC__)
# include <saml/config_pub_win32.h>
#else
# include <saml/config_pub.h>
#endif

using namespace xercesc;

#include <saml/hresult.h>
#include <saml/SAMLDateTime.h>

namespace saml
{
#ifdef HAVE_GOOD_STL
    // A dynamic widestring that works across platforms
    typedef std::basic_string<XMLCh> xstring;
#endif

    // Wraps a UTF-8 transcoder (both directions).
    SAML_EXPORTS char* toUTF8(const XMLCh* src);
    SAML_EXPORTS XMLCh* fromUTF8(const char* src);

    // These are NOT full auto_ptrs, they're just useful for simple cases.
    // The difference is they free memory allocated by the Xerces memory mgr.
    class SAML_EXPORTS auto_ptr_char
    {
    public:
        auto_ptr_char(const XMLCh* src, bool trim=true) : m_buf(XMLString::transcode(src)) {if (trim && m_buf) XMLString::trim(m_buf);}
        auto_ptr_char(const char* src, bool trim=true) : m_buf(XMLString::replicate(src)) {if (trim && m_buf) XMLString::trim(m_buf);}
        ~auto_ptr_char() { XMLString::release(&m_buf); }
        const char* get() const { return m_buf; }
        char* release() { char* temp=m_buf; m_buf=NULL; return temp; }

    private:
        char* m_buf;
    };

    class SAML_EXPORTS auto_ptr_XMLCh
    {
    public:
        auto_ptr_XMLCh(const char* src, bool trim=true) : m_buf(XMLString::transcode(src)) {if (trim && m_buf) XMLString::trim(m_buf);}
        auto_ptr_XMLCh(const XMLCh* src, bool trim=true) : m_buf(XMLString::replicate(src)) {if (trim && m_buf) XMLString::trim(m_buf);}
        ~auto_ptr_XMLCh() { XMLString::release(&m_buf); }
        const XMLCh* get() const { return m_buf; }
        XMLCh* release() { XMLCh* temp=m_buf; m_buf=NULL; return temp; }

    private:
        XMLCh* m_buf;
    };

    // Java-style Iterator interfaces
    template<class T> class Iterator
    {
    public:
        Iterator();
        Iterator(const std::vector<T>& v) : m_vector(v) { m_iter=m_vector.begin(); }
        Iterator(const Iterator<T>& i) : m_vector(i.m_vector) { m_iter=m_vector.begin(); }
        std::vector<T> clone() const;
        bool hasNext() const { return m_iter!=m_vector.end(); }
        const T& next() const { return *(m_iter++); }
        size_t size() const { return m_vector.size(); }
        const T& at(size_t i) const { return m_vector[i]; }
        const T& operator[](size_t i) const { return m_vector[i]; }
        void reset() const { m_iter=m_vector.begin(); }

    protected:
        const std::vector<T>& m_vector;
        mutable typename std::vector<T>::const_iterator m_iter;

    private:
        static std::vector<T> m_empty_vector;
    };

    template<class T> class ArrayIterator : public Iterator<T>
    {
    public:
        ArrayIterator(T v[], size_t s);
        ArrayIterator(const ArrayIterator<T>& a);

    protected:
        std::vector<T> m_real_vector;
    };

    #define EMPTY(T) saml::Iterator<T>()

    template<class T> std::vector<T> Iterator<T>::m_empty_vector;

    template<class T> Iterator<T>::Iterator() : m_vector(m_empty_vector)
    {
        m_iter=m_vector.begin();
    }

    template<class T> ArrayIterator<T>::ArrayIterator(T v[], size_t s) : Iterator<T>(m_real_vector)
    {
        for (size_t i=0; v && i<s; i++)
            m_real_vector.push_back(v[i]);
        this->m_iter=this->m_vector.begin();
    }

    template<class T> ArrayIterator<T>::ArrayIterator(const ArrayIterator<T>& a) : Iterator<T>(m_real_vector)
    {
        this->m_real_vector=a.m_real_vector;
        this->m_iter=this->m_vector.begin();
    }

#ifdef SAML_INSTANTIATE
    class QName;
    class SAMLAdvice;
    class SAMLArtifact;
    class SAMLAttribute;
    class SAMLAttributeDesignator;
    class SAMLAuthorityBinding;
    class SAMLStatement;
    class SAMLCondition;
    class SAMLAssertion;
    class SAMLAction;
    class SAMLEvidence;

#ifdef HAVE_GOOD_STL
    template class SAML_EXPORTS saml::Iterator<xstring>;
    template class SAML_EXPORTS saml::ArrayIterator<xstring>;
#endif
    template class SAML_EXPORTS saml::Iterator<std::string>;
    template class SAML_EXPORTS saml::ArrayIterator<std::string>;
    template class SAML_EXPORTS saml::Iterator<const char*>;
    template class SAML_EXPORTS saml::ArrayIterator<const char*>;
    template class SAML_EXPORTS saml::Iterator<const XMLCh*>;
    template class SAML_EXPORTS saml::ArrayIterator<const XMLCh*>;
    template class SAML_EXPORTS saml::Iterator<const DOMElement*>;
    template class SAML_EXPORTS saml::ArrayIterator<const DOMElement*>;
    template class SAML_EXPORTS saml::Iterator<DOMElement*>;
    template class SAML_EXPORTS saml::ArrayIterator<DOMElement*>;
    template class SAML_EXPORTS saml::Iterator<saml::QName>;
    template class SAML_EXPORTS saml::ArrayIterator<saml::QName>;
    template class SAML_EXPORTS saml::Iterator<XSECCryptoX509*>;
    template class SAML_EXPORTS saml::ArrayIterator<XSECCryptoX509*>;
    template class SAML_EXPORTS saml::Iterator<SAMLArtifact*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLArtifact*>;
    template class SAML_EXPORTS saml::Iterator<SAMLAttribute*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLAttribute*>;
    template class SAML_EXPORTS saml::Iterator<SAMLAttributeDesignator*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLAttributeDesignator*>;
    template class SAML_EXPORTS saml::Iterator<SAMLAuthorityBinding*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLAuthorityBinding*>;
    template class SAML_EXPORTS saml::Iterator<SAMLStatement*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLStatement*>;
    template class SAML_EXPORTS saml::Iterator<SAMLCondition*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLCondition*>;
    template class SAML_EXPORTS saml::Iterator<SAMLAssertion*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLAssertion*>;
    template class SAML_EXPORTS saml::Iterator<SAMLAction*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLAction*>;
    template class SAML_EXPORTS saml::Iterator<SAMLEvidence*>;
    template class SAML_EXPORTS saml::ArrayIterator<SAMLEvidence*>;
#endif

    // Abstract handling of diagnostic context for logging
    class SAML_EXPORTS NDC
    {
    public:
        NDC();
        NDC(const char* context);
        NDC(std::string& context);
        ~NDC();
    };

    // Abstracts handling of XML QNames, including namespace prefix traversal
    class SAML_EXPORTS QName
    {
    public:
        QName(const XMLCh* nsURI=NULL, const XMLCh* localName=NULL);
        ~QName();

        static QName* getQNameAttribute(DOMElement* e, const XMLCh* nsURI, const XMLCh* localName);
        static QName* getQNameTextNode(DOMText* t);
        static const XMLCh* getNamespaceForQName(const XMLCh* qname, DOMElement* e);
        static const XMLCh* getNamespaceForPrefix(const XMLCh* prefix, DOMElement* e);

#ifdef HAVE_GOOD_STL
        const XMLCh* getNamespaceURI() const {return m_namespace.c_str();}
        const XMLCh* getLocalName() const {return m_localName.c_str();}

    private:
        xstring m_namespace;
        xstring m_localName;
#else
        QName(const QName& src);
        QName& operator=(const QName& src);

        const XMLCh* getNamespaceURI() const {return m_namespace;}
        const XMLCh* getLocalName() const {return m_localName;}

    private:
        XMLCh* m_namespace;
        XMLCh* m_localName;
#endif
    };

    // Needed to allow QNames in sorted STL containers
    SAML_EXPORTS bool operator<(const saml::QName& op1, const saml::QName& op2);
#ifndef HAVE_GOOD_STL
    SAML_EXPORTS bool operator==(const saml::QName& op1, const saml::QName& op2);
#endif
    
    // Wraps pseudorandom identifier generation for SAML objects
    class SAML_EXPORTS SAMLIdentifier
    {
    public:
        SAMLIdentifier();
        ~SAMLIdentifier();
        operator const XMLCh*() {return m_buffer;}

    static void generateRandomBytes(void* buf, unsigned int len);
    static void generateRandomBytes(std::string& buf, unsigned int len);

    private:
        SAMLIdentifier(const SAMLIdentifier&) {}
        SAMLIdentifier& operator=(const SAMLIdentifier&) {return *this;}
        XMLCh* m_buffer;
    };

    // Wraps basic XML handling and wide constants (ugly, but fast)
    class SAML_EXPORTS XML
    {
    public:
        // URI constants
        static const XMLCh OPENSAML_NS[];
        static const XMLCh SAML_NS[];
        static const XMLCh SAML_SCHEMA_ID[];
        static const XMLCh SAML11_SCHEMA_ID[];
        static const XMLCh SAMLP_NS[];
        static const XMLCh SAMLP_SCHEMA_ID[];
        static const XMLCh SAMLP11_SCHEMA_ID[];
        static const XMLCh SOAP11ENV_NS[];
        static const XMLCh SOAP11ENV_SCHEMA_ID[];
        static const XMLCh XMLSIG_NS[];
        static const XMLCh XMLSIG_SCHEMA_ID[];
        static const XMLCh XMLNS_NS[];
        static const XMLCh XML_NS[];
        static const XMLCh XML_SCHEMA_ID[];
        static const XMLCh XSD_NS[];
        static const XMLCh XSI_NS[];

        // SAML2->1 metadata profile protocol indicators
#define SAML10_PROTOCOL_ENUM SAMLP_NS
        static const XMLCh SAML11_PROTOCOL_ENUM[];
        static const XMLCh SAML_ARTIFACT_SOURCEID[];
        
        // Helper functions and whitespace skippers
        static bool isEmpty(const XMLCh* src) {return (!src || !*src);}
        static XMLCh* assign(const XMLCh* src, bool trim=true); // replicates and trims source
        static bool isElementNamed(const DOMElement* e, const XMLCh* ns, const XMLCh* localName);
        static DOMElement* getFirstChildElement(const DOMNode* n);
        static DOMElement* getLastChildElement(const DOMNode* n);
        static DOMElement* getNextSiblingElement(const DOMNode* n);
        static DOMElement* getPreviousSiblingElement(const DOMNode* n);
        static DOMElement* getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName);
        static DOMElement* getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName);
        static DOMElement* getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName);
        static DOMElement* getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName);

        struct SAML_EXPORTS Literals
        {
            // SAML vocabulary
            static const XMLCh Action[];
            static const XMLCh Advice[];
            static const XMLCh Assertion[];
            static const XMLCh AssertionArtifact[];
            static const XMLCh AssertionID[];
            static const XMLCh AssertionIDReference[];
            static const XMLCh saml_AssertionIDReference[];
            static const XMLCh Attribute[];
            static const XMLCh AttributeDesignator[];
            static const XMLCh AttributeName[];
            static const XMLCh AttributeNamespace[];
            static const XMLCh AttributeQuery[];
            static const XMLCh AttributeQueryType[];
            static const XMLCh AttributeStatement[];
            static const XMLCh AttributeStatementType[];
            static const XMLCh AttributeValue[];
            static const XMLCh Audience[];
            static const XMLCh AudienceRestrictionCondition[];
            static const XMLCh AudienceRestrictionConditionType[];
            static const XMLCh AuthenticationInstant[];
            static const XMLCh AuthenticationMethod[];
            static const XMLCh AuthenticationQuery[];
            static const XMLCh AuthenticationQueryType[];
            static const XMLCh AuthenticationStatement[];
            static const XMLCh AuthenticationStatementType[];
            static const XMLCh AuthorityBinding[];
            static const XMLCh AuthorityKind[];
            static const XMLCh AuthorizationDecisionQuery[];
            static const XMLCh AuthorizationDecisionQueryType[];
            static const XMLCh AuthorizationDecisionStatement[];
            static const XMLCh AuthorizationDecisionStatementType[];
            static const XMLCh Binding[];
            static const XMLCh Client[];
            static const XMLCh Condition[];
            static const XMLCh Conditions[];
            static const XMLCh ConfirmationMethod[];
            static const XMLCh Decision[];
            static const XMLCh DNSAddress[];
            static const XMLCh DoNotCacheCondition[];
            static const XMLCh DoNotCacheConditionType[];
            static const XMLCh Evidence[];
            static const XMLCh Format[];
            static const XMLCh InResponseTo[];
            static const XMLCh IPAddress[];
            static const XMLCh Issuer[];
            static const XMLCh IssueInstant[];
            static const XMLCh Location[];
            static const XMLCh MajorVersion[];
            static const XMLCh MinorVersion[];
            static const XMLCh MustUnderstand[];
            static const XMLCh NameIdentifier[];
            static const XMLCh NameQualifier[];
            static const XMLCh Namespace[];
            static const XMLCh NotBefore[];
            static const XMLCh NotOnOrAfter[];
            static const XMLCh Query[];
            static const XMLCh Recipient[];
            static const XMLCh Request[];
            static const XMLCh Requester[];
            static const XMLCh RequestID[];
            static const XMLCh Resource[];
            static const XMLCh Responder[];
            static const XMLCh samlp_Responder[];
            static const XMLCh RespondWith[];
            static const XMLCh Response[];
            static const XMLCh ResponseID[];
            static const XMLCh Server[];
            static const XMLCh Statement[];
            static const XMLCh Status[];
            static const XMLCh StatusMessage[];
            static const XMLCh StatusCode[];
            static const XMLCh StatusDetail[];
            static const XMLCh Subject[];
            static const XMLCh saml_Subject[];
            static const XMLCh SubjectConfirmation[];
            static const XMLCh SubjectConfirmationData[];
            static const XMLCh SubjectLocality[];
            static const XMLCh SubjectQuery[];
            static const XMLCh SubjectStatement[];
            static const XMLCh Success[];
            static const XMLCh Value[];
            static const XMLCh VersionMismatch[];

            // SOAP vocabulary
            static const XMLCh Body[];
            static const XMLCh Envelope[];
            static const XMLCh Fault[];
            static const XMLCh faultcode[];
            static const XMLCh faultstring[];
            static const XMLCh Header[];
            static const XMLCh mustUnderstand[];

            // Signature vocabulary
            static const XMLCh Digest[];
            static const XMLCh KeyInfo[];
            static const XMLCh Signature[];
            static const XMLCh X509Data[];
            static const XMLCh X509Certificate[];

            // XML vocabulary
            static const XMLCh lang[];
            static const XMLCh saml[];
            static const XMLCh samlp[];
            static const XMLCh soap[];
            static const XMLCh type[];
            static const XMLCh xml[];
            static const XMLCh xmlns[];
            static const XMLCh xsd[];
            static const XMLCh xsi[];
            static const XMLCh xmlns_xsd[];
            static const XMLCh xmlns_xsi[];
            static const XMLCh xmlns_saml[];
            static const XMLCh xmlns_samlp[];
            static const XMLCh xmlns_soap[];
            static const XMLCh xmlns_code[];
            static const XMLCh xmlns_kind[];
            static const XMLCh xmlns_rw[];
            static const XMLCh xmlns_typens[];
            static const XMLCh xmlns_opensaml[];
            static const XMLCh typens[];
            static const XMLCh xsi_type[];
            
            // OpenSAML vocabulary
            static const XMLCh Code[];
            static const XMLCh ExceptionClass[];
            static const XMLCh Name[];
            static const XMLCh Param[];
            static const XMLCh opensaml_Code[];
            static const XMLCh opensaml_ExceptionClass[];
            static const XMLCh opensaml_Param[];
        };

        static void registerSchema(
            const XMLCh* xmlns,
            const XMLCh* systemId,
            DOMEntityResolver* resolver=NULL,
            bool compatModePool=true    // register the schema in all pools?
            );

        class SAML_EXPORTS ParserPool : public DOMEntityResolver, DOMErrorHandler
        {
        public:
            ParserPool();
            ~ParserPool();

            DOMBuilder* get(bool validating=true);
            void put(DOMBuilder* p);

            void registerSchema(const XMLCh* xmlns, const XMLCh* systemId, DOMEntityResolver* resolver=NULL);

            DOMInputSource* resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const baseURI);
            bool handleError(const DOMError& e);

        private:
#ifdef HAVE_GOOD_STL
            typedef std::map<xstring,xstring> SchemaLocationMap;
            typedef std::map<xstring,DOMEntityResolver*> ResolverMap;
            xstring m_schemaLocations;
#else
            typedef std::map<std::string,std::string> SchemaLocationMap;
            typedef std::map<std::string,DOMEntityResolver*> ResolverMap;
            std::string m_schemaLocations;
#endif
            SchemaLocationMap m_SchemaLocMap;
            ResolverMap m_ResolverMap;
            std::stack<DOMBuilder*> m_pool;
            void* m_lock;
        };

        class SAML_EXPORTS Parser
        {
        public:
            Parser();
            Parser(int minor);
            ~Parser();
            DOMDocument* parse(DOMInputSource& domsrc)
            {
                DOMDocument* doc=m_parser->parse(domsrc);
                m_parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument,true);
                return doc;
            }

        private:
            Parser(const Parser&) {}
            Parser& operator=(const Parser&) { return *this; }
            DOMBuilder* m_parser;
            int m_minor;
        };

        class SAML_EXPORTS StreamInputSource : public InputSource
        {
        public:
            StreamInputSource(std::istream& is, const char* systemId=NULL) : InputSource(systemId), m_is(is) {}
            virtual BinInputStream* makeStream() const { return new StreamBinInputStream(m_is); }

        private:
            std::istream& m_is;

            class SAML_EXPORTS StreamBinInputStream : public BinInputStream
            {
            public:
                StreamBinInputStream(std::istream& is) : m_is(is), m_pos(0) {}
                virtual unsigned int curPos() const { return m_pos; }
                virtual unsigned int readBytes(XMLByte* const toFill, const unsigned int maxToRead);
            private:
                std::istream& m_is;
                unsigned int m_pos;
            };
        };
    };

    // Artifacts in SAML 1.x are references to assertions issued in the Browser/Artifact
    // profile. If you use them for any other purpose, you're defining your own profile.
    // The C++ string class is used to manage raw byte sequences. Unless specified,
    // you MUST NOT treat the contents as printable strings and there could be embedded nulls.
    class SAML_EXPORTS SAMLArtifact;
    extern "C" { typedef SAMLArtifact* SAMLArtifactFactory(const char*); }

    class SAML_EXPORTS SAMLArtifact
    {
    public:
        virtual ~SAMLArtifact() {}

        // Access the artifact components as byte sequences. Do not assume null-termination
        // unless specified. Actual structure of RemainingArtifact depends on the artifact type.
        virtual std::string getBytes() const {return m_raw;}                    // raw binary artifact
        virtual std::string getTypeCode() const {return m_raw.substr(0,2);}     // first two bytes
        virtual std::string getRemainingArtifact() const {return m_raw.substr(2);}    // all but first two bytes
        
        // Returns the artifact encoded into null-terminated base64 for transmission.
        virtual std::string encode() const;
        
        // Build a duplicate, independent object of the same type.
        virtual SAMLArtifact* clone() const=0;
        
        // Parses a base64-encoded null-terminated string into an artifact.
        static SAMLArtifact* parse(const char* s);
        static SAMLArtifact* parse(const XMLCh* s);
        
        // Debugging function to help print out hex-encoded binary data.
        static std::string toHex(const std::string& s);
        
        // Register implementation classes based on type code.
        static void regFactory(std::string& typecode, SAMLArtifactFactory* factory)
            {m_map.insert(SAMLArtifactFactoryMap::value_type(typecode,factory));}
        static void unregFactory(std::string& typecode) {m_map.erase(typecode);}
    protected:
        SAMLArtifact() {}
        SAMLArtifact(const char* s);    // Base64 decodes s into m_raw
        std::string m_raw;

    private:
        typedef std::map<std::string,SAMLArtifactFactory*> SAMLArtifactFactoryMap;
        static SAMLArtifactFactoryMap m_map;
    };
    
    class SAML_EXPORTS SAMLArtifactType0001 : public SAMLArtifact
    {
    public:
        // null-terminated base64 encoded artifact
        SAMLArtifactType0001(const char* s);
        
        // SOURCEID_LENGTH bytes of binary data, handle is randomly generated
        SAMLArtifactType0001(const std::string& sourceid);
        
        // SOURCEID_LENGTH bytes of binary data and HANDLE_LENGTH bytes of binary data
        SAMLArtifactType0001(const std::string& sourceid, const std::string& handle);

        virtual ~SAMLArtifactType0001() {}
        virtual SAMLArtifact* clone() const;
    
        std::string getSourceID() const {return m_raw.substr(2,20);}            // bytes 3-22
        std::string getAssertionHandle() const {return m_raw.substr(22,20);}    // bytes 23-42
    
        static const int SOURCEID_LENGTH;
        static const int HANDLE_LENGTH;
        
        // Hashes the input string into a 20-byte SourceID value.
        static std::string generateSourceId(const char* s);
    };

    class SAML_EXPORTS SAMLArtifactType0002 : public SAMLArtifact
    {
    public:
        // null-terminated base64 encoded artifact
        SAMLArtifactType0002(const char* s);
        
        // sourceLocation as a URI endpoint, handle is randomly generated
        SAMLArtifactType0002(const std::string& sourceLocation);
        
        // sourceLocation as a URI endpoint and HANDLE_LENGTH bytes of binary data
        SAMLArtifactType0002(const std::string& sourceLocation, const std::string& handle);

        virtual ~SAMLArtifactType0002() {}
        virtual SAMLArtifact* clone() const;
    
        std::string getAssertionHandle() const {return m_raw.substr(2,20);} // bytes 3-22
        const char* getSourceLocation() const {return m_raw.c_str() + 22;}  // bytes 23-terminating null
    
        static const int HANDLE_LENGTH;
    };

    // Most of the rest of the classes implement SAML constructs. The root
    // object provides a framework for serialization/deserialization and memory
    // management that is tied to the XML parser's behavior and assumptions.
    // Extension classes should always inherit from SAMLObject and use the
    // built-in classes as examples of how to code new types.

    class SAML_EXPORTS SAMLObject
    {
    public:
        virtual ~SAMLObject();
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
        XMLByte* toBase64(unsigned int* outputLength) const;
        virtual void checkValidity() const {}
        SAMLObject* setParent(SAMLObject* parent);
        SAMLObject* getParent() const {return m_parent;}
        virtual SAMLObject* clone() const=0;
        const char* classname() const {return m_classname.c_str();}
        DOMDocument* setDocument(DOMDocument* doc) {DOMDocument* ret=m_document; m_document=doc; return ret;}

    protected:
        SAMLObject();
        SAMLObject(std::istream& in);
        SAMLObject(std::istream& in, int minor);
        SAMLObject(const SAMLObject& src) : m_classname(src.m_classname),
            m_root(NULL), m_document(NULL), m_parent(NULL),
            m_bDirty(true), m_bOwnStrings(true), m_log(NULL) {}
        SAMLObject& operator=(const SAMLObject&) { return *this; }

        virtual void setDirty();
        void setClean() const { m_bDirty=false; }
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const {return NULL;}
        virtual void ownStrings() {} // transfers ownership of object's string members to object from DOM
        DOMNode* plantRoot();
        void _RTTI(const char* classname);

        friend SAML_EXPORTS std::ostream& operator<<(std::ostream& ostr, const SAMLObject& obj);

        mutable DOMNode* m_root;                // no memory management on DOM itself
        mutable DOMDocument* m_document;        // DOM built manually is freed with "document->release()"
        SAMLObject* m_parent;                   // Back-pointer to SAML parent object
        mutable bool m_bDirty;                  // Dirty bit triggers recreation of DOM
        bool m_bOwnStrings;                     // Does this SAML object own its component fields?
        void* m_log;                            // Logging object, does not expose the implementation
        std::string m_classname;
    };

    // Serialization of objects and wide strings (eventually will use EXC-C14N)
    SAML_EXPORTS std::ostream& operator<<(std::ostream& ostr, const DOMNode& node);
    SAML_EXPORTS std::ostream& operator<<(std::ostream& ostr, const SAMLObject& obj);
    SAML_EXPORTS std::ostream& xmlout(std::ostream& target, const XMLCh* s);

    // vararg wrappers
    class SAML_EXPORTS params {
    public:
        params() {}
        params(int count,...);      // any number of const char*
        Iterator<const char*> get() const {return v;}
    protected:
        std::vector<const char*> v;
    };
    
    class SAML_EXPORTS namedparams : public params {
    public:
        namedparams() {}
        namedparams(int count,...); // any even number of const char*
    };

    // Wraps all internal library errors and reflects SAML status structure
    class SAML_EXPORTS SAMLException;
    extern "C" { typedef SAMLException* SAMLExceptionFactory(DOMElement*); }

    class SAML_EXPORTS SAMLException : public std::exception, public SAMLObject
    {
    public:
        static saml::QName SUCCESS;
        static saml::QName REQUESTER;
        static saml::QName RESPONDER;
        static saml::QName VERSIONMISMATCH;

        static SAMLException* getInstance(DOMElement* e);
        static SAMLException* getInstance(std::istream& in);
        static void regFactory(const char* exceptionClass, SAMLExceptionFactory* factory);
        static void unregFactory(const char* exceptionClass);

        // The first four forms accept a message, optional positional or named message parameters,
        // and optional SAML StatusCodes and StatusDetail information (rarely used).
        SAMLException(
            const char* msg,
            const params& p=params(),
            const Iterator<saml::QName>& codes=EMPTY(saml::QName),
            DOMElement* detail=NULL
            );
        SAMLException(
            const char* msg,
            const namedparams& p,
            const Iterator<saml::QName>& codes=EMPTY(saml::QName),
            DOMElement* detail=NULL
            );
        SAMLException(
            const std::string& msg,
            const params& p=params(),
            const Iterator<saml::QName>& codes=EMPTY(saml::QName),
            DOMElement* detail=NULL
            );
        SAMLException(
            const std::string& msg,
            const namedparams& p,
            const Iterator<saml::QName>& codes=EMPTY(saml::QName),
            DOMElement* detail=NULL
            );
        
        // The second four are the same, except they require a single SAML StatusCode first.
        SAMLException(const saml::QName& code, const char* msg, const params& p=params(), DOMElement* detail=NULL);
        SAMLException(const saml::QName& code, const char* msg, const namedparams& p, DOMElement* detail=NULL);
        SAMLException(const saml::QName& code, const std::string& msg, const params& p=params(), DOMElement* detail=NULL);
        SAMLException(const saml::QName& code, const std::string& msg, const namedparams& p, DOMElement* detail=NULL);
        
        // The third four are for non-SAML protocol use internally and support HRESULT codes.
        // Most error handling is exception driven, but a status code facility is
        // also utilized to compactly communicate specific errors without defining a
        // separate exception type for every condition. The code block is defined
        // within the Win32 HRESULT ITF facility for application use.
        SAMLException(HRESULT code, const char* msg, const params& p=params(), DOMElement* detail=NULL);
        SAMLException(HRESULT code, const char* msg, const namedparams& p, DOMElement* detail=NULL);
        SAMLException(HRESULT code, const std::string& msg, const params& p=params(), DOMElement* detail=NULL);
        SAMLException(HRESULT code, const std::string& msg, const namedparams& p, DOMElement* detail=NULL);
        
        SAMLException(const SAMLException&);
        SAMLException& operator=(const SAMLException&);
        virtual ~SAMLException() throw ();

        virtual const char* what() const throw () {return getMessage();}
        virtual const char* getMessage() const;
        HRESULT getStatus() const {return m_hr;}
        Iterator<saml::QName> getCodes() const {return m_codes;}
        DOMElement* getDetail() const {return m_detail;}

        void setMessage(const char* msg);
        void setStatus(HRESULT hr);
        void setCodes(const Iterator<saml::QName>& codes=EMPTY(saml::QName));
        void addCode(const saml::QName& code);
        void removeCode(unsigned long index);
        void setDetail(DOMElement* detail);

        void addProperty(const char* value) {addProperties(params(1,value));}
        void addProperty(const char* name, const char* value) {addProperties(namedparams(1,name,value));}
        void addProperties(const params& p);
        void addProperties(const namedparams& p);
        const char* getProperty(unsigned int index) const;
        const char* getProperty(const char* name) const;

        virtual void raise() const {throw *this;}
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
        virtual SAMLObject* clone() const;
        
    protected:
        SAMLException(DOMElement* e);
        SAMLException(std::istream& in);
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;

    private:
        HRESULT m_hr;
        std::vector<saml::QName> m_codes;
        std::map<std::string,std::string> m_params;
        std::string m_msg;
        mutable std::string m_processedmsg;
        mutable DOMElement* m_detail;
        DOMDocument* m_scratch;

        typedef std::map<std::string,SAMLExceptionFactory*> SAMLExceptionFactoryMap;
        static SAMLExceptionFactoryMap m_map;
    };

    // Simplify derivation of exception types
    #define DECLARE_SAML_EXCEPTION(exportspec,name,base) \
    class exportspec name : public saml::base \
    { \
    public: \
        name(const char* msg, const saml::params& p=saml::params(), const saml::Iterator<saml::QName>& codes=EMPTY(saml::QName), DOMElement* detail=NULL) \
            : saml::base(msg,p,codes,detail) {RTTI(name);} \
        name(const char* msg, const saml::namedparams& p, const saml::Iterator<saml::QName>& codes=EMPTY(saml::QName), DOMElement* detail=NULL) \
            : saml::base(msg,p,codes,detail) {RTTI(name);} \
        name(const std::string& msg, const saml::params& p=saml::params(), const saml::Iterator<saml::QName>& codes=EMPTY(saml::QName), DOMElement* detail=NULL) \
            : saml::base(msg,p,codes,detail) {RTTI(name);} \
        name(const std::string& msg, const saml::namedparams& p, const saml::Iterator<saml::QName>& codes=EMPTY(saml::QName), DOMElement* detail=NULL) \
            : saml::base(msg,p,codes,detail) {RTTI(name);} \
        name(const saml::QName& code, const char* msg, const saml::params& p=saml::params(), DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(const saml::QName& code, const char* msg, const saml::namedparams& p, DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(const saml::QName& code, const std::string& msg, const saml::params& p=saml::params(), DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(const saml::QName& code, const std::string& msg, const saml::namedparams& p, DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(HRESULT code, const char* msg, const saml::params& p=saml::params(), DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(HRESULT code, const char* msg, const saml::namedparams& p, DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(HRESULT code, const std::string& msg, const saml::params& p=saml::params(), DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(HRESULT code, const std::string& msg, const saml::namedparams& p, DOMElement* detail=NULL) \
            : saml::base(code,msg,p,detail) {RTTI(name);} \
        name(DOMElement* e) : saml::base(e) {RTTI(name);} \
        name(std::istream& in) : saml::base(in) {RTTI(name);} \
        virtual ~name() throw() {} \
        saml::SAMLObject* clone() const {return new name(*this);} \
        void raise() const {throw *this;} \
    }
    
    #define SAML_EXCEPTION_FACTORY(name) \
        extern "C" SAMLException* name##Factory(DOMElement* e) \
        { \
            return new name(e); \
        }
    
    #define REGISTER_EXCEPTION_FACTORY(name) SAMLException::regFactory("org.opensaml."#name,name##Factory)

    // Core-level Errors
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,MalformedException,SAMLException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,UnsupportedExtensionException,SAMLException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,InvalidCryptoException,SAMLException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,TrustException,InvalidCryptoException);

    // Binding-level Errors
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,BindingException,SAMLException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,SOAPException,BindingException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,HTTPException,BindingException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,ContentTypeException,HTTPException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,UnknownAssertionException,BindingException);

    // Profile-level Errors
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,ProfileException,SAMLException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,FatalProfileException,ProfileException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,RetryableProfileException,ProfileException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,UnsupportedProfileException,FatalProfileException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,ExpiredAssertionException,FatalProfileException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,InvalidAssertionException,FatalProfileException);
    DECLARE_SAML_EXCEPTION(SAML_EXPORTS,ReplayedAssertionException,RetryableProfileException);

    class SAML_EXPORTS SAMLSignedObject : public SAMLObject
    {
    public:
        virtual ~SAMLSignedObject();

        const XMLCh* getId() const {return m_id;}
        virtual void setId(const XMLCh* id);
        virtual void sign(
            XSECCryptoKey* k,
            const Iterator<XSECCryptoX509*>& certs=EMPTY(XSECCryptoX509*),
            const char* signatureAlg=URI_ID_RSA_SHA1,
            const char* digestAlg=URI_ID_SHA1
            );
        virtual void unsign();
        virtual void verify(XSECCryptoKey* k=NULL) const;
        virtual void verify(XSECCryptoX509& cert) const;
        virtual void verify(XSECKeyInfoResolver* r) const;
        virtual unsigned int getX509CertificateCount() const;
        virtual const XMLCh* getX509Certificate(unsigned int index) const;
        virtual const char* getSignatureAlgorithm() const;
        virtual const char* getDigestAlgorithm() const;
        virtual bool isSigned() const;

    protected:
        SAMLSignedObject(std::istream& in);
        SAMLSignedObject(std::istream& in, int minor);
        SAMLSignedObject() : m_id(NULL), m_signature(NULL), m_sigElement(NULL) { RTTI(SAMLSignedObject); }
        virtual void setDirty();
        virtual void ownStrings();
        virtual void insertSignature()=0;
        DOMElement* getSignatureElement() { return m_sigElement; }

        mutable XMLCh* m_id;
        mutable safeBuffer m_safebuf;
        DSIGSignature* m_signature;
        DOMElement* m_sigElement;
    };

    class SAML_EXPORTS SAMLNameIdentifier;
    extern "C" { typedef SAMLNameIdentifier* SAMLNameIdentifierFactory(DOMElement*); }

    class SAML_EXPORTS SAMLNameIdentifier : public SAMLObject
    {
    public:
        SAMLNameIdentifier(const XMLCh* name=NULL, const XMLCh* nameQualifier=NULL, const XMLCh* format=NULL);
        SAMLNameIdentifier(DOMElement* e);
        SAMLNameIdentifier(std::istream& in);
        virtual ~SAMLNameIdentifier();

        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        const XMLCh* getName() const {return m_name;}
        const XMLCh* getNameQualifier() const {return m_nameQualifier;}
        const XMLCh* getFormat() const {return m_format;}
        void setName(const XMLCh* name);
        void setNameQualifier(const XMLCh* nq=NULL);
        void setFormat(const XMLCh* format=NULL);

        static const XMLCh UNSPECIFIED[];
        static const XMLCh EMAIL[];
        static const XMLCh X509[];
        static const XMLCh WINDOWS[];

#ifdef HAVE_GOOD_STL
        static void regFactory(const xstring& format, SAMLNameIdentifierFactory* factory) {
        	m_map.insert(SAMLNameIdentifierFactoryMap::value_type(format,factory));
        }
        static void unregFactory(const xstring& format) {m_map.erase(format);}
#else
        static void regFactory(const std::string& format, SAMLNameIdentifierFactory* factory) {
        	m_map.insert(SAMLNameIdentifierFactoryMap::value_type(format,factory));
        }
        static void unregFactory(const std::string& format) {m_map.erase(format);}
#endif
        static SAMLNameIdentifier* getInstance(DOMElement* e);
        static SAMLNameIdentifier* getInstance(std::istream& in);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        XMLCh* m_name;
        XMLCh* m_nameQualifier;
        XMLCh* m_format;

    private:
        SAMLNameIdentifier(const SAMLNameIdentifier&) {}
        SAMLNameIdentifier& operator=(const SAMLNameIdentifier&) {return *this;}

#ifdef HAVE_GOOD_STL
        typedef std::map<xstring,SAMLNameIdentifierFactory*> SAMLNameIdentifierFactoryMap;
#else
        typedef std::map<std::string,SAMLNameIdentifierFactory*> SAMLNameIdentifierFactoryMap;
#endif
        static SAMLNameIdentifierFactoryMap m_map;
    };

    class SAML_EXPORTS SAMLSubject : public SAMLObject
    {
    public:
        SAMLSubject(
            SAMLNameIdentifier* name=NULL,
            const Iterator<const XMLCh*>& confirmationMethods=EMPTY(const XMLCh*),
            DOMElement* confirmationData=NULL,
            DOMElement* keyInfo=NULL
            );
        SAMLSubject(DOMElement* e);
        SAMLSubject(std::istream& in);
        virtual ~SAMLSubject();

        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        SAMLNameIdentifier* getNameIdentifier() const {return m_name;}
        Iterator<const XMLCh*> getConfirmationMethods() const {return m_confirmationMethods;}
        DOMElement* getConfirmationData() const {return m_confirmationData;}
        DOMElement* getKeyInfo() const {return m_keyInfo;}
        void setNameIdentifier(SAMLNameIdentifier* name=NULL);
        void setConfirmationMethods(const Iterator<const XMLCh*>& methods=EMPTY(const XMLCh*));
        void addConfirmationMethod(const XMLCh* method);
        void removeConfirmationMethod(unsigned long index);
        void setConfirmationData(DOMElement* data=NULL);
        void setKeyInfo(DOMElement* keyInfo=NULL);
        
        static const XMLCh CONF_ARTIFACT01[];
        static const XMLCh CONF_ARTIFACT[];
        static const XMLCh CONF_BEARER[];
        static const XMLCh CONF_HOLDER_KEY[];
        static const XMLCh CONF_SENDER_VOUCHES[];

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        SAMLNameIdentifier* m_name;
        std::vector<const XMLCh*> m_confirmationMethods;
        mutable DOMElement* m_confirmationData;
        mutable DOMElement* m_keyInfo;

    private:
        DOMDocument* m_scratch;
        SAMLSubject(const SAMLSubject&) {}
        SAMLSubject& operator=(const SAMLSubject&) {return *this;}
    };

    class SAML_EXPORTS SAMLAttributeDesignator : public SAMLObject
    {
    public:
        SAMLAttributeDesignator(const XMLCh* name=NULL, const XMLCh* ns=NULL);
        SAMLAttributeDesignator(DOMElement* e);
        SAMLAttributeDesignator(std::istream& in);
        virtual ~SAMLAttributeDesignator();
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        virtual const XMLCh* getName() const {return m_name;}
        virtual const XMLCh* getNamespace() const {return m_namespace;}
        virtual void setName(const XMLCh* name);
        virtual void setNamespace(const XMLCh* ns);

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        XMLCh* m_name;
        XMLCh* m_namespace;

    private:
        SAMLAttributeDesignator(const SAMLAttributeDesignator&) {}
        SAMLAttributeDesignator& operator=(const SAMLAttributeDesignator&) {return *this;}
    };

    class SAML_EXPORTS SAMLAttribute;
    extern "C" { typedef SAMLAttribute* SAMLAttributeFactory(DOMElement* e); }

    class SAML_EXPORTS SAMLAttribute : public SAMLObject
    {
    public:
        SAMLAttribute(
            const XMLCh* name=NULL,
            const XMLCh* ns=NULL,
            const saml::QName* type=NULL,
            long lifetime=0,
            const Iterator<const XMLCh*>& values=EMPTY(const XMLCh*)
            );
        SAMLAttribute(DOMElement* e, bool processDOM=true);
        SAMLAttribute(std::istream& in, bool processDOM=true);
        virtual ~SAMLAttribute();
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        virtual const XMLCh* getName() const {return m_name;}
        virtual const XMLCh* getNamespace() const {return m_namespace;}
        virtual const QName* getType() const {return m_type;}
        virtual long getLifetime() const {return m_lifetime;}

        virtual void setName(const XMLCh* name);
        virtual void setNamespace(const XMLCh* ns);
        virtual void setType(const QName* type);
        virtual void setLifetime(long lifetime);

        virtual Iterator<const XMLCh*> getValues() const {return m_values;}
        virtual Iterator<std::string> getSingleByteValues() const;
        virtual DOMNodeList* getValueElements() const;
        virtual void setValues(const Iterator<const XMLCh*>& values=EMPTY(const XMLCh*));
        virtual void addValue(const XMLCh* value);
        virtual void removeValue(unsigned long index);
        
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        static SAMLAttributeFactory* setFactory(SAMLAttributeFactory* factory);
        static SAMLAttribute* getInstance(DOMElement* e);
        static SAMLAttribute* getInstance(std::istream& in);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
        virtual void valueToDOM(unsigned int index, DOMElement* e) const;
        virtual void valueFromDOM(DOMElement* e);
        virtual XMLCh* computeTypeDecl(DOMElement* e) const;

        XMLCh* m_name;
        XMLCh* m_namespace;
        QName* m_type;
        long m_lifetime;
        mutable std::vector<const XMLCh*> m_values;
        mutable std::vector<std::string> m_sbValues;

    private:
        SAMLAttribute(const SAMLAttribute&) {}
        SAMLAttribute& operator=(const SAMLAttribute&) {return *this;}

        static SAMLAttributeFactory* m_factory;
    };

    class SAML_EXPORTS SAMLAuthorityBinding : public SAMLObject
    {
    public:
        SAMLAuthorityBinding(const saml::QName* kind=NULL, const XMLCh* binding=NULL, const XMLCh* location=NULL);
        SAMLAuthorityBinding(DOMElement* e);
        SAMLAuthorityBinding(std::istream& in);
        virtual ~SAMLAuthorityBinding();
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        const saml::QName* getAuthorityKind() const {return m_kind;}
        const XMLCh* getBinding() const {return m_binding;}
        const XMLCh* getLocation() const {return m_location;}
        
        void setAuthorityKind(saml::QName& kind);
        void setBinding(const XMLCh* binding);
        void setLocation(const XMLCh* location);

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        saml::QName* m_kind;
        XMLCh* m_binding;
        XMLCh* m_location;

    private:
        SAMLAuthorityBinding(const SAMLAuthorityBinding&) {}
        SAMLAuthorityBinding& operator=(const SAMLAuthorityBinding&) {return *this;}
    };

    class SAML_EXPORTS SAMLCondition;
    extern "C" { typedef SAMLCondition* SAMLConditionFactory(DOMElement*); }

    class SAML_EXPORTS SAMLCondition : public SAMLObject
    {
    public:
        virtual ~SAMLCondition() {}

        static void regFactory(saml::QName& type, SAMLConditionFactory* factory) {m_map.insert(SAMLConditionFactoryMap::value_type(type,factory));}
        static void unregFactory(saml::QName& type) {m_map.erase(type);}
        static SAMLCondition* getInstance(DOMElement* e);
        static SAMLCondition* getInstance(std::istream& in);

    protected:
        SAMLCondition() { RTTI(SAMLCondition); }
        SAMLCondition(std::istream& in) : SAMLObject(in) { RTTI(SAMLCondition); }

    private:
        SAMLCondition(const SAMLCondition&) {}
        SAMLCondition& operator=(const SAMLCondition&) {return *this;}

        typedef std::map<saml::QName,SAMLConditionFactory*> SAMLConditionFactoryMap;
        static SAMLConditionFactoryMap m_map;
    };

    class SAML_EXPORTS SAMLAudienceRestrictionCondition : public SAMLCondition
    {
    public:
        SAMLAudienceRestrictionCondition(const Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*));
        SAMLAudienceRestrictionCondition(DOMElement* e);
        SAMLAudienceRestrictionCondition(std::istream& in);
        virtual ~SAMLAudienceRestrictionCondition();
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        saml::Iterator<const XMLCh*> getAudiences() {return m_audiences;}
        void setAudiences(const Iterator<const XMLCh*>& audiences);
        void addAudience(const XMLCh* audience);
        void removeAudience(unsigned long index);

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        bool eval(const Iterator<const XMLCh*>& audiences) const;
#ifdef HAVE_GOOD_STL
        bool eval(const Iterator<xstring>& audiences) const;
#endif

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
        std::vector<const XMLCh*> m_audiences;

    private:
        SAMLAudienceRestrictionCondition(const SAMLAudienceRestrictionCondition&) {}
        SAMLAudienceRestrictionCondition& operator=(const SAMLAudienceRestrictionCondition&) {return *this;}
    };

    class SAML_EXPORTS SAMLDoNotCacheCondition : public SAMLCondition
    {
    public:
        SAMLDoNotCacheCondition();
        SAMLDoNotCacheCondition(DOMElement* e);
        SAMLDoNotCacheCondition(std::istream& in);
        virtual ~SAMLDoNotCacheCondition() {}
        virtual SAMLObject* clone() const;

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;

    private:
        SAMLDoNotCacheCondition(const SAMLDoNotCacheCondition&) {}
        SAMLDoNotCacheCondition& operator=(const SAMLDoNotCacheCondition&) {return *this;}
    };

    class SAML_EXPORTS SAMLStatement;
    extern "C" { typedef SAMLStatement* SAMLStatementFactory(DOMElement*); }

    class SAML_EXPORTS SAMLStatement : public SAMLObject
    {
    public:
        virtual ~SAMLStatement() {}

        static void regFactory(saml::QName& type, SAMLStatementFactory* factory) {m_map.insert(SAMLStatementFactoryMap::value_type(type,factory));}
        static void unregFactory(saml::QName& type) {m_map.erase(type);}
        static SAMLStatement* getInstance(DOMElement* e);
        static SAMLStatement* getInstance(std::istream& in);

    protected:
        SAMLStatement() { RTTI(SAMLStatement); }
        SAMLStatement(std::istream& in) : SAMLObject(in) { RTTI(SAMLStatement); }

    private:
        SAMLStatement(const SAMLStatement&) {}
        SAMLStatement& operator=(const SAMLStatement&) {return *this;}

        typedef std::map<saml::QName,SAMLStatementFactory*> SAMLStatementFactoryMap;
        static SAMLStatementFactoryMap m_map;
    };

    class SAML_EXPORTS SAMLAssertion : public SAMLSignedObject
    {
    public:
        SAMLAssertion(
            const XMLCh* issuer=NULL,
            const SAMLDateTime* notBefore=NULL,
            const SAMLDateTime* notOnOrAfter=NULL,
            const Iterator<SAMLCondition*>& conditions=EMPTY(SAMLCondition*),
            const Iterator<SAMLStatement*>& statements=EMPTY(SAMLStatement*),
            const Iterator<const XMLCh*>& adviceRefs=EMPTY(const XMLCh*),
            const Iterator<SAMLAssertion*>& adviceAssertions=EMPTY(SAMLAssertion*),
            const Iterator<DOMElement*>& adviceElements=EMPTY(DOMElement*),
            const XMLCh* id=NULL,
            const SAMLDateTime* issueInstant=NULL
            );
        SAMLAssertion(DOMElement* e);
        SAMLAssertion(std::istream& in);
        SAMLAssertion(std::istream& in, int minor);
        virtual ~SAMLAssertion();
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        int getMinorVersion() const {return m_minor;}
        const XMLCh* getIssuer() const {return m_issuer;}
        const SAMLDateTime* getIssueInstant() const {return m_issueInstant;}
        const SAMLDateTime* getNotBefore() const {return m_notBefore;}
        const SAMLDateTime* getNotOnOrAfter() const {return m_notOnOrAfter;}
        Iterator<SAMLCondition*> getConditions() const {return m_conditions;}
        Iterator<SAMLStatement*> getStatements() const {return m_statements;}
        Iterator<const XMLCh*> getAdviceRefs() const {return m_adviceRefs;}
        Iterator<SAMLAssertion*> getAdviceAssertions() const {return m_adviceAssertions;}
        Iterator<DOMElement*> getAdviceElements() const {return m_adviceElements;}

        void setMinorVersion(int minor);
        void setIssuer(const XMLCh* issuer);
        void setIssueInstant(const SAMLDateTime* instant=NULL);
        void setNotBefore(const SAMLDateTime* notBefore=NULL);
        void setNotOnOrAfter(const SAMLDateTime* notOnOrAfter=NULL);
        void setConditions(const Iterator<SAMLCondition*>& conditions);
        void addCondition(SAMLCondition* condition);
        void removeCondition(unsigned long index);
        void setStatements(const Iterator<SAMLStatement*>& statements);
        void addStatement(SAMLStatement* statement);
        void removeStatement(unsigned long index);
        void setAdvice(const Iterator<const XMLCh*>& advice=EMPTY(const XMLCh*));
        void setAdvice(const Iterator<SAMLAssertion*>& advice=EMPTY(SAMLAssertion*));
        void setAdvice(const Iterator<DOMElement*>& advice=EMPTY(DOMElement*));
        void addAdvice(const XMLCh* advice);
        void addAdvice(SAMLAssertion* advice);
        void addAdvice(DOMElement* advice);
        void removeAdviceRef(unsigned long index);
        void removeAdviceAssertion(unsigned long index);
        void removeAdviceElement(unsigned long index);
        
    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
        virtual void insertSignature();

        int m_minor;
        XMLCh* m_issuer;
        mutable SAMLDateTime* m_issueInstant;
        SAMLDateTime* m_notBefore;
        SAMLDateTime* m_notOnOrAfter;
        std::vector<SAMLCondition*> m_conditions;
        std::vector<SAMLStatement*> m_statements;
        std::vector<const XMLCh*> m_adviceRefs;
        std::vector<SAMLAssertion*> m_adviceAssertions;
        mutable std::vector<DOMElement*> m_adviceElements;

    private:
        DOMDocument* m_scratch;
        SAMLAssertion(const SAMLAssertion&) {}
        SAMLAssertion& operator=(const SAMLAssertion&) {return *this;}
    };

    class SAML_EXPORTS SAMLSubjectStatement : public SAMLStatement
    {
    public:
        virtual ~SAMLSubjectStatement();
        virtual void checkValidity() const;

        SAMLSubject* getSubject() const {return m_subject;}
        void setSubject(SAMLSubject* subject);

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
    protected:
        SAMLSubjectStatement() {RTTI(SAMLSubjectStatement);}
        SAMLSubjectStatement(SAMLSubject* subject);
        SAMLSubjectStatement(DOMElement* e);
        SAMLSubjectStatement(std::istream& in);
        virtual void fromDOM(DOMElement* e);
        SAMLSubject* m_subject;

    private:
        SAMLSubjectStatement(const SAMLSubjectStatement&) {}
        SAMLSubjectStatement& operator=(const SAMLSubjectStatement&) {return *this;}
    };

    class SAML_EXPORTS SAMLAttributeStatement : public SAMLSubjectStatement
    {
    public:
        SAMLAttributeStatement(SAMLSubject* subject=NULL, const Iterator<SAMLAttribute*>& attributes=EMPTY(SAMLAttribute*));
        SAMLAttributeStatement(DOMElement* e);
        SAMLAttributeStatement(std::istream& in);
        virtual ~SAMLAttributeStatement();
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        Iterator<SAMLAttribute*> getAttributes() const {return m_attributes;}
        void setAttributes(const Iterator<SAMLAttribute*>& attributes);
        void addAttribute(SAMLAttribute* attribute);
        void removeAttribute(unsigned long index);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        std::vector<SAMLAttribute*> m_attributes;

    private:
        SAMLAttributeStatement(const SAMLAttributeStatement&) {}
        SAMLAttributeStatement& operator=(const SAMLAttributeStatement&) {return *this;}
    };

    class SAML_EXPORTS SAMLAuthenticationStatement : public SAMLSubjectStatement
    {
    public:
        SAMLAuthenticationStatement(
            SAMLSubject* subject=NULL,
            const XMLCh* authMethod=NULL,
            const SAMLDateTime* authInstant=NULL,
            const XMLCh* subjectIP=NULL,
            const XMLCh* subjectDNS=NULL,
            const Iterator<SAMLAuthorityBinding*>& bindings=EMPTY(SAMLAuthorityBinding*)
            );
        SAMLAuthenticationStatement(DOMElement* e);
        SAMLAuthenticationStatement(std::istream& in);
        virtual ~SAMLAuthenticationStatement();

        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        const XMLCh* getAuthMethod() const {return m_authMethod;}
        const SAMLDateTime* getAuthInstant() const {return m_authInstant;}
        const XMLCh* getSubjectIP() const {return m_subjectIP;}
        const XMLCh* getSubjectDNS() const {return m_subjectDNS;}
        Iterator<SAMLAuthorityBinding*> getBindings() const {return m_bindings;}
        
        void setAuthMethod(const XMLCh* authMethod);
        void setAuthInstant(const SAMLDateTime* authInstant);
        void setSubjectIP(const XMLCh* subjectIP=NULL);
        void setSubjectDNS(const XMLCh* subjectDNS=NULL);
        void setBindings(const Iterator<SAMLAuthorityBinding*>& bindings=EMPTY(SAMLAuthorityBinding*));
        void addBinding(SAMLAuthorityBinding* binding);
        void removeBinding(unsigned long index);
        
    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        XMLCh* m_subjectIP;
        XMLCh* m_subjectDNS;
        XMLCh* m_authMethod;
        SAMLDateTime* m_authInstant;
        std::vector<SAMLAuthorityBinding*> m_bindings;

    private:
        SAMLAuthenticationStatement(const SAMLAuthenticationStatement&) {}
        SAMLAuthenticationStatement& operator=(const SAMLAuthenticationStatement&) {return *this;}
    };

    class SAML_EXPORTS SAMLAction : public SAMLObject
    {
    public:
        SAMLAction(const XMLCh* data=NULL, const XMLCh* nsURI=NULL);
        SAMLAction(DOMElement* e);
        SAMLAction(std::istream& in);
        virtual ~SAMLAction();
    
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        static const XMLCh SAML_ACTION_NAMESPACE_RWEDC_NEG[];
        static const XMLCh SAML_ACTION_NAMESPACE_RWEDC[];
        static const XMLCh SAML_ACTION_NAMESPACE_GHPP[];
        static const XMLCh SAML_ACTION_NAMESPACE_UNIX[];
    
        const XMLCh* getNamespace() const {return m_namespace ? m_namespace : SAML_ACTION_NAMESPACE_RWEDC_NEG;}
        const XMLCh* getData() const {return m_data;}
        void setNamespace(const XMLCh* ns=NULL);
        void setData(const XMLCh* data);
    
    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
    
        XMLCh* m_namespace;
        XMLCh* m_data;

    private:
        SAMLAction(const SAMLAction&) {}
        SAMLAction& operator=(const SAMLAction&) {return *this;}
    };

    class SAML_EXPORTS SAMLEvidence : public SAMLObject
    {
    public:
        SAMLEvidence(
            const Iterator<SAMLAssertion*>& assertions=EMPTY(SAMLAssertion*),
            const Iterator<const XMLCh*>& assertionIDRefs=EMPTY(const XMLCh*)
            );
        SAMLEvidence(const Iterator<const XMLCh*>& assertionIDRefs);
        SAMLEvidence(DOMElement* e);
        SAMLEvidence(std::istream& in);
        virtual ~SAMLEvidence();
    
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
    
        Iterator<SAMLAssertion*> getAssertions() const {return m_assertions;}
        Iterator<const XMLCh*> getAssertionIDRefs() const {return m_assertionIDRefs;}
        
        void setAssertions(const Iterator<SAMLAssertion*>& assertions=EMPTY(SAMLAssertion*));
        void addAssertion(SAMLAssertion* assertion);
        void removeAssertion(unsigned long index);
        void setAssertionIDRefs(const Iterator<const XMLCh*>& assertionIDRefs=EMPTY(const XMLCh*));
        void addAssertionIDRef(const XMLCh* ref);
        void removeAssertionIDRef(unsigned long index);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
    
        std::vector<SAMLAssertion*> m_assertions;
        std::vector<const XMLCh*> m_assertionIDRefs;

    private:
        void init(const Iterator<SAMLAssertion*>& assertions, const Iterator<const XMLCh*>& assertionIDRefs);

        SAMLEvidence(const SAMLEvidence&) {}
        SAMLEvidence& operator=(const SAMLEvidence&) {return *this;}
    };

    class SAML_EXPORTS SAMLDecision
    {
    public:
        static const XMLCh Permit[];
        static const XMLCh Deny[];
        static const XMLCh Indeterminate[];
    };

    class SAML_EXPORTS SAMLAuthorizationDecisionStatement : public SAMLSubjectStatement
    {
    public:
        SAMLAuthorizationDecisionStatement(
            SAMLSubject* subject=NULL,
            const XMLCh* resource=NULL,
            const XMLCh* decision=NULL,
            const Iterator<SAMLAction*>& actions=EMPTY(SAMLAction*),
            SAMLEvidence* evidence=NULL
            );
        SAMLAuthorizationDecisionStatement(DOMElement* e);
        SAMLAuthorizationDecisionStatement(std::istream& in);
        virtual ~SAMLAuthorizationDecisionStatement();
    
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
    
        const XMLCh* getResource() const {return m_resource;}
        const XMLCh* getDecision() const {return m_decision;}
        Iterator<SAMLAction*> getActions() const {return m_actions;}
        SAMLEvidence* getEvidence() const {return m_evidence;}
        
        void setResource(const XMLCh* resource);
        void setDecision(const XMLCh* decision);
        void setActions(const Iterator<SAMLAction*>& actions);
        void addAction(SAMLAction* action);
        void removeAction(unsigned long index);
        void setEvidence(SAMLEvidence* evidence=NULL);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        XMLCh* m_resource;
        XMLCh* m_decision;
        std::vector<SAMLAction*> m_actions;
        SAMLEvidence* m_evidence;

    private:
        SAMLAuthorizationDecisionStatement(const SAMLAuthorizationDecisionStatement&) {}
        SAMLAuthorizationDecisionStatement& operator=(const SAMLAuthorizationDecisionStatement&) {return *this;}
    };

    class SAML_EXPORTS SAMLQuery;
    extern "C" { typedef SAMLQuery* SAMLQueryFactory(DOMElement*); }

    class SAML_EXPORTS SAMLQuery : public SAMLObject
    {
    public:
        virtual ~SAMLQuery() {}

        static void regFactory(saml::QName& type, SAMLQueryFactory* factory) {m_map.insert(SAMLQueryFactoryMap::value_type(type,factory));}
        static void unregFactory(saml::QName& type) {m_map.erase(type);}
        static SAMLQuery* getInstance(DOMElement* e);
        static SAMLQuery* getInstance(std::istream& in);

    protected:
        SAMLQuery() { RTTI(SAMLQuery); }
        SAMLQuery(std::istream& in) : SAMLObject(in) { RTTI(SAMLQuery); }

    private:
        SAMLQuery(const SAMLQuery&) {}
        SAMLQuery& operator=(const SAMLQuery&) {return *this;}

        typedef std::map<saml::QName,SAMLQueryFactory*> SAMLQueryFactoryMap;
        static SAMLQueryFactoryMap m_map;
    };

    class SAML_EXPORTS SAMLSubjectQuery : public SAMLQuery
    {
    public:
        virtual ~SAMLSubjectQuery();
        virtual void checkValidity() const;

        SAMLSubject* getSubject() const {return m_subject;}
        void setSubject(SAMLSubject* subject);

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

    protected:
        SAMLSubjectQuery() {RTTI(SAMLSubjectQuery);}
        SAMLSubjectQuery(SAMLSubject* subject);
        SAMLSubjectQuery(DOMElement* e);
        SAMLSubjectQuery(std::istream& in);
        virtual void fromDOM(DOMElement* e);
        SAMLSubject* m_subject;

    private:
        SAMLSubjectQuery(const SAMLSubjectQuery&) {}
        SAMLSubjectQuery& operator=(const SAMLSubjectQuery&) {return *this;}
    };

    class SAML_EXPORTS SAMLAttributeQuery : public SAMLSubjectQuery
    {
    public:
        SAMLAttributeQuery(
            SAMLSubject* subject=NULL,
            const XMLCh* resource=NULL,
            const Iterator<SAMLAttributeDesignator*>& designators=EMPTY(SAMLAttributeDesignator*)
            );
        SAMLAttributeQuery(DOMElement* e);
        SAMLAttributeQuery(std::istream& in);
        virtual ~SAMLAttributeQuery();
        virtual SAMLObject* clone() const;

        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        const XMLCh* getResource() const {return m_resource;}
        Iterator<SAMLAttributeDesignator*> getDesignators() const {return m_designators;}
        
        void setResource(const XMLCh* resource=NULL);
        void setDesignators(const Iterator<SAMLAttributeDesignator*>& designators=EMPTY(SAMLAttributeDesignator*));
        void addDesignator(SAMLAttributeDesignator* designator);
        void removeDesignator(unsigned long index);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();

        XMLCh* m_resource;
        std::vector<SAMLAttributeDesignator*> m_designators;

    private:
        SAMLAttributeQuery(const SAMLAttributeQuery&) {}
        SAMLAttributeQuery& operator=(const SAMLAttributeQuery&) {return *this;}
    };

    class SAML_EXPORTS SAMLAuthenticationQuery : public SAMLSubjectQuery
    {
    public:
        SAMLAuthenticationQuery(SAMLSubject* subject=NULL, const XMLCh* authMethod=NULL);
        SAMLAuthenticationQuery(DOMElement* e);
        SAMLAuthenticationQuery(std::istream& in);
        virtual ~SAMLAuthenticationQuery();
    
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
    
        const XMLCh* getAuthMethod() const {return m_authMethod;}
        void setAuthMethod(const XMLCh* authMethod=NULL);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
    
        XMLCh* m_authMethod;

    private:
        SAMLAuthenticationQuery(const SAMLAuthenticationQuery&) {}
        SAMLAuthenticationQuery& operator=(const SAMLAuthenticationQuery&) {return *this;}
    };

    class SAML_EXPORTS SAMLAuthorizationDecisionQuery : public SAMLSubjectQuery
    {
    public:
        SAMLAuthorizationDecisionQuery(
            SAMLSubject* subject=NULL,
            const XMLCh* resource=NULL,
            const Iterator<SAMLAction*>& actions=EMPTY(SAMLAction*),
            SAMLEvidence* evidence=NULL
            );
        SAMLAuthorizationDecisionQuery(DOMElement* e);
        SAMLAuthorizationDecisionQuery(std::istream& in);
        virtual ~SAMLAuthorizationDecisionQuery();
    
        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
    
        const XMLCh* getResource() const {return m_resource;}
        Iterator<SAMLAction*> getActions() const {return m_actions;}
        SAMLEvidence* getEvidence() const {return m_evidence;}

        void setResource(const XMLCh* resource);
        void setActions(const Iterator<SAMLAction*>& actions);
        void addAction(SAMLAction* action);
        void removeAction(unsigned long index);
        void setEvidence(SAMLEvidence* evidence=NULL);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
    
        XMLCh* m_resource;
        std::vector<SAMLAction*> m_actions;
        SAMLEvidence* m_evidence;

    private:
        SAMLAuthorizationDecisionQuery(const SAMLAuthorizationDecisionQuery&) {}
        SAMLAuthorizationDecisionQuery& operator=(const SAMLAuthorizationDecisionQuery&) {return *this;}
    };

    class SAML_EXPORTS SAMLRequest : public SAMLSignedObject
    {
    public:
        SAMLRequest(
            SAMLQuery* query=NULL,
            const Iterator<saml::QName>& respondWiths=EMPTY(saml::QName),
            const XMLCh* id=NULL,
            const SAMLDateTime* issueInstant=NULL
            );
        SAMLRequest(
            const Iterator<const XMLCh*>& assertionIDRefs,
            const Iterator<saml::QName>& respondWiths=EMPTY(saml::QName),
            const XMLCh* id=NULL,
            const SAMLDateTime* issueInstant=NULL
            );
        SAMLRequest(
            const Iterator<SAMLArtifact*>& artifacts,
            const Iterator<saml::QName>& respondWiths=EMPTY(saml::QName),
            const XMLCh* id=NULL,
            const SAMLDateTime* issueInstant=NULL
            );
        SAMLRequest(DOMElement* e);
        SAMLRequest(std::istream& in);
        SAMLRequest(std::istream& in, int minor);
        virtual ~SAMLRequest();

        virtual void checkValidity() const;
        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        int getMinorVersion() const {return m_minor;}
        const SAMLDateTime* getIssueInstant() const {return m_issueInstant;}
        Iterator<saml::QName> getRespondWiths() const {return m_respondWiths;}
        SAMLQuery* getQuery() const {return m_query;}
        Iterator<const XMLCh*> getAssertionIdRefs() const {return m_assertionIDRefs;}
        Iterator<SAMLArtifact*> getArtifacts() const {return m_artifacts;}
        
        void setMinorVersion(int minor);
        void setIssueInstant(const SAMLDateTime* issueInstant=NULL);
        void setRespondWiths(const Iterator<saml::QName>& respondWiths=EMPTY(saml::QName));
        void addRespondWith(const saml::QName& rw);
        void removeRespondWith(unsigned long index);
        void setQuery(SAMLQuery* query);
        void setAssertionIDRefs(const Iterator<const XMLCh*>& assertionIDRefs=EMPTY(const XMLCh*));
        void addAssertionIDRef(const XMLCh* ref);
        void removeAssertionIDRef(unsigned long index);
        void setArtifacts(const Iterator<SAMLArtifact*>& artifacts=EMPTY(SAMLArtifact*));
        void addArtifact(SAMLArtifact* artifact);
        void removeArtifact(unsigned long index);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
        virtual void insertSignature();

        int m_minor;
        mutable SAMLDateTime* m_issueInstant;
        std::vector<saml::QName> m_respondWiths;
        SAMLQuery* m_query;
        std::vector<const XMLCh*> m_assertionIDRefs;
        std::vector<SAMLArtifact*> m_artifacts;

    private:
        SAMLRequest(const SAMLRequest&) {}
        SAMLRequest& operator=(const SAMLRequest&) {return *this;}
    };

    class SAML_EXPORTS SAMLResponse : public SAMLSignedObject
    {
    public:
        SAMLResponse(
            const XMLCh* inResponseTo=NULL,
            const XMLCh* recipient=NULL,
            const Iterator<SAMLAssertion*>& assertions=EMPTY(SAMLAssertion*),
            SAMLException* e=NULL,
            const XMLCh* id=NULL,
            const SAMLDateTime* issueInstant=NULL
            );
        SAMLResponse(DOMElement* e);
        SAMLResponse(std::istream& in);
        SAMLResponse(std::istream& in, int minor);
        virtual ~SAMLResponse();

        virtual SAMLObject* clone() const;
        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;

        int getMinorVersion() const {return m_minor;}
        const XMLCh* getInResponseTo() const {return m_inResponseTo;}
        const SAMLDateTime* getIssueInstant() const {return m_issueInstant;}
        const XMLCh* getRecipient() const {return m_recipient;}
        Iterator<SAMLAssertion*> getAssertions() const {return m_assertions;}
        SAMLException* getStatus() const {return m_exception;}

        void setMinorVersion(int minor);
        void setInResponseTo(const XMLCh* inResponseTo=NULL);
        void setIssueInstant(const SAMLDateTime* issueInstant=NULL);
        void setRecipient(const XMLCh* recipient=NULL);
        void setAssertions(const Iterator<SAMLAssertion*>& assertions=EMPTY(SAMLAssertion*));
        void addAssertion(SAMLAssertion* assertion);
        void removeAssertion(unsigned long index);
        void setStatus(SAMLException* e=NULL);

    protected:
        virtual void fromDOM(DOMElement* e);
        virtual DOMElement* buildRoot(DOMDocument* doc, bool xmlns=true) const;
        virtual void ownStrings();
        virtual void insertSignature();

        int m_minor;
        XMLCh* m_inResponseTo;
        mutable SAMLDateTime* m_issueInstant;
        XMLCh* m_recipient;
        std::vector<SAMLAssertion*> m_assertions;
        SAMLException* m_exception;

    private:
        SAMLResponse(const SAMLResponse&) {}
        SAMLResponse& operator=(const SAMLResponse&) {return *this;}
    };

    // The final classes support SAML binding and profile implementations that
    // use the SAML objects to do useful things.

    // Manages pluggable implementations of interfaces
    // Would prefer this to be a template, but the Windows STL isn't DLL-safe.

    struct SAML_EXPORTS IPlugIn
    {
        virtual ~IPlugIn() {}
    };

    // Manages dynamic class creation using a string-based type map and a factory
    // interface that supports DOMElement and XMLCh-qualified DOMElement constructors.
    class SAML_EXPORTS PlugManager
    {
    public:
        PlugManager() {}
        ~PlugManager() {}

        typedef IPlugIn* Factory(const DOMElement* e);
        typedef IPlugIn* XMLChFactory(const XMLCh* qualifier, const DOMElement* e);
        void regFactory(const char* type, Factory* factory);
        void regFactory(const char* type, XMLChFactory* factory);
        void unregFactory(const char* type);
        IPlugIn* newPlugin(const char* type, const DOMElement* e);
        IPlugIn* newPlugin(const char* type, const XMLCh* qualifier, const DOMElement* e);

    private:
        typedef std::map<std::string, Factory*> FactoryMap;
        typedef std::map<std::string, XMLChFactory*> XMLChFactoryMap;
        FactoryMap m_map;
        XMLChFactoryMap m_XMLCh_map;
    };

    // Various interfaces inherit from this to support locking
    struct SAML_EXPORTS ILockable
    {
        virtual void lock()=0;
        virtual void unlock()=0;
        virtual ~ILockable() {}
    };        

    class SAML_EXPORTS Locker
    {
    public:
        Locker(ILockable* lockee) : m_lockee(lockee) {m_lockee->lock();}
        ~Locker() {if (m_lockee) m_lockee->unlock();}
        
    private:
        Locker(const Locker&);
        void operator=(const Locker&);
        ILockable* m_lockee;
    };

    // Wraps a ds:KeyInfo resolver plugin for the security library
    class SAML_EXPORTS KeyInfoResolver : public virtual IPlugIn
    {
    public:
        virtual ~KeyInfoResolver() {delete m_resolver;}

        operator XSECKeyInfoResolver*() const {return m_resolver;}
        virtual XSECCryptoX509* resolveCert(DSIGKeyInfoList* klist)=0;
        
        // factories
        static KeyInfoResolver* getInstance(const DOMElement* e=NULL);
        static KeyInfoResolver* getInstance(const char* type, const DOMElement* e=NULL);
        
    protected:
        XSECKeyInfoResolver* m_resolver;
    };

    // Generic "synchronous" binding interface
    struct SAML_EXPORTS SAMLBinding : public virtual IPlugIn
    {
        virtual ~SAMLBinding() {}

        virtual SAMLResponse* send(const XMLCh* endpoint, SAMLRequest& req, void* callCtx=NULL) const=0;
        virtual SAMLRequest* receive(void* reqContext, void* callCtx=NULL, int minorVersion=1) const=0;
        virtual void respond(void* respContext, SAMLResponse* response, SAMLException* e=NULL, void* callCtx=NULL) const=0;

        // Binding URIs
        static const XMLCh SOAP[];
        
        // Factory methods
        static SAMLBinding* getInstance(const XMLCh* binding, const DOMElement* e=NULL);
        static SAMLBinding* getInstance(const XMLCh* binding, const char* type, const DOMElement* e=NULL);
    };
    
    // Base class for SOAP bindings
    class SAML_EXPORTS SAMLSOAPBinding : public virtual SAMLBinding
    {
    public:
        // Hook interface provided by caller
        struct SAML_EXPORTS SOAPHook {
            virtual ~SOAPHook() {}
            virtual bool incoming(DOMElement* envelope, void* globalCtx, void* callCtx) {return true;}
            virtual bool outgoing(DOMElement* envelope, void* globalCtx, void* callCtx) {return true;}
        };
        SAMLSOAPBinding() {}
        virtual ~SAMLSOAPBinding() {}
        virtual void addHook(SOAPHook* h, void* globalCtx=NULL);

        virtual DOMElement* sendRequest(SAMLRequest& request, void* callCtx=NULL) const;
        virtual DOMElement* sendResponse(SAMLResponse* response, SAMLException* e=NULL, void* callCtx=NULL) const;
        virtual SAMLRequest* recvRequest(DOMElement* envelope, void* callCtx=NULL) const;
        virtual SAMLResponse* recvResponse(DOMElement* envelope, void* callCtx=NULL) const;
    
        static saml::QName CLIENT;
        static saml::QName SERVER;
        static saml::QName MUSTUNDERSTAND;
        static saml::QName VERSIONMISMATCH;
    
    private:
        std::vector<std::pair<SOAPHook*,void*> > m_soapHooks;
    };

    // Interfaces for HTTP hooks to access/manipulate HTTP connection/information
    struct SAML_EXPORTS HTTPClient
    {
        virtual ~HTTPClient() {}

        enum auth_t {
            auth_none = 0,
            auth_basic = 1,
            auth_digest = 2,
            auth_ntlm = 3,
            auth_gss = 4,
        };
        
        virtual bool setConnectTimeout(long timeout)=0;
        virtual bool setTimeout(long timeout)=0;
        virtual bool setAuth(auth_t authType, const char* username=NULL, const char* password=NULL)=0;
        virtual bool setRequestHeader(const char* name, const char* val)=0;
        virtual Iterator<std::string> getResponseHeader(const char* val) const=0;
        typedef bool (*ssl_ctx_callback_fn)(void* ssl_ctx, void* userptr);
        virtual bool setSSLCallback(ssl_ctx_callback_fn fn, void* userptr=NULL)=0;
    };

    // Currently this is unimplemented...
    struct SAML_EXPORTS HTTPServer
    {
        virtual ~HTTPServer() {}
        virtual const char* getRemoteUser() const=0;
        virtual const char* getRemoteAddr() const=0;
        virtual Iterator<std::string> getRequestHeader(const char* val) const=0;
        virtual bool setResponseHeader(const char* name, const char* val)=0;
        virtual Iterator<XSECCryptoX509*> getClientCertificateChain() const=0;
    };

    // Interface for SOAP/HTTP binding implementations
    struct SAML_EXPORTS SAMLSOAPHTTPBinding : public virtual SAMLSOAPBinding
    {
        // Hook interface provided by caller
        struct SAML_EXPORTS HTTPHook {
            virtual ~HTTPHook() {}
            virtual bool incoming(HTTPClient* conn, void* globalCtx=NULL, void* callCtx=NULL) {return true;}
            virtual bool outgoing(HTTPClient* conn, void* globalCtx=NULL, void* callCtx=NULL) {return true;}
            virtual bool incoming(HTTPServer* conn, void* globalCtx=NULL, void* callCtx=NULL) {return true;}
            virtual bool outgoing(HTTPServer* conn, void* globalCtx=NULL, void* callCtx=NULL) {return true;}
        };
        virtual ~SAMLSOAPHTTPBinding() {}
        virtual void addHook(HTTPHook* h, void* globalCtx=NULL)=0;
    };

    // Handle replay detection for assertions, artifacts, etc.
    struct SAML_EXPORTS IReplayCache : public virtual IPlugIn
    {
        virtual ~IReplayCache() {}
        virtual void thread_init()=0;
        virtual void thread_end()=0;
        virtual bool check(const char*, time_t)=0;
        
        // factories
        static IReplayCache* getInstance(const DOMElement* e=NULL);
        static IReplayCache* getInstance(const char* type, const DOMElement* e=NULL);
    };
    
    // SAML browser profiles address only the receiving end, new POST/artifact support
    // is revised to reflect this. Both profiles take a pluggable replay cache instance.
    // Leave callback parameter empty for POST-only processing. Specific profiles can
    // be disabled by omitting them from the supportedProfiles mask parameter.
    struct SAML_EXPORTS SAMLBrowserProfile : public virtual IPlugIn
    {
        virtual ~SAMLBrowserProfile() {}

        enum profiles_t {
           Artifact=1,
           Post=2
        };
        
        struct SAML_EXPORTS ArtifactMapper {
            virtual ~ArtifactMapper() {}
            virtual SAMLResponse* resolve(SAMLRequest* request)=0;
        };
        
        struct SAML_EXPORTS BrowserProfileResponse {
            BrowserProfileResponse() : response(NULL), assertion(NULL), authnStatement(NULL) {}
            SAMLResponse* response;
            SAMLAssertion* assertion;
            SAMLAuthenticationStatement* authnStatement;
            std::string TARGET;
            profiles_t profile;
            void clear() { delete response; response=NULL; assertion=NULL; authnStatement=NULL;}
        };

        // Can process a posted form response, or initiate a callback with artifacts.
        virtual BrowserProfileResponse receive(
            const char* packet,
            const XMLCh* recipient,
            int supportedProfiles,
            IReplayCache* replayCache=NULL,
            ArtifactMapper* artifactMapper=NULL,
            int minorVersion=1
            ) const=0;
        
        static const XMLCh BROWSER_POST[];
        static const XMLCh BROWSER_ARTIFACT[];

        // factories
        static SAMLBrowserProfile* getInstance(const DOMElement* e=NULL);
        static SAMLBrowserProfile* getInstance(const char* type, const DOMElement* e=NULL);
    };

    // Captures global configuration data that must be provided by library client
    class SAML_EXPORTS SAMLConfig
    {
    public:
        SAMLConfig() : compatibility_mode(false), strict_dom_checking(true), clock_skew_secs(300), conn_pool_max(256) {}

        // enables runtime and clients to access global configuration object
        static SAMLConfig& getConfig();

        // global per-process setup and shutdown of runtime
        virtual bool init()=0;
        virtual void term()=0;

    /* start of externally supplied configuration */
        bool compatibility_mode;
        std::string schema_dir;
        std::string log_config;
        std::string alg_config;
        std::string inclusive_namespace_prefixes;
        bool strict_dom_checking;
        time_t clock_skew_secs;
        long conn_pool_max;
        long timeout;
        long conn_timeout;
        std::string ssl_certfile;
        std::string ssl_certtype;
        std::string ssl_keyfile;
        std::string ssl_keytype;
        std::string ssl_keypass;
        std::string ssl_calist;
        std::string ssl_cadir;
        HTTPClient::ssl_ctx_callback_fn ssl_ctx_callback;
        void* ssl_ctx_data;
    /* end of externally supplied configuration */

        // global mutex available to library applications
        virtual void saml_lock() const=0;
        virtual void saml_unlock() const=0;

        // cross-platform extension library loader
        // extensions must provide:
        //      extern "C" int saml_extension_init(void* context);
        //      extern "C" void saml_extension_term();
        virtual void saml_register_extension(const char* path, void* context=NULL) const=0;

        // mangages pluggable interfaces requiring DOM-based configuration
        virtual PlugManager& getPlugMgr()=0;
        virtual const char* getDefaultBindingProvider(const XMLCh* binding) const=0;
        virtual void setDefaultBindingProvider(const XMLCh* binding, const char* type)=0;
    };
}

#endif