Reducing header overuse, non-inlining selected methods (CPPOST-35).
[shibboleth/cpp-opensaml.git] / saml / binding / impl / SAMLArtifact.cpp
1 /*
2  *  Copyright 2001-2009 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * SAMLArtifact.cpp
19  * 
20  * Base class for SAML 1.x and 2.0 artifacts.
21  */
22
23 #include "internal.h"
24 #include "binding/SAMLArtifact.h"
25
26 #include <xercesc/util/Base64.hpp>
27 #include <xsec/framework/XSECDefs.hpp>
28 #include <xmltooling/unicode.h>
29
30 using namespace opensaml;
31 using namespace xmltooling;
32 using namespace std;
33
34 namespace opensaml {
35     namespace saml1p {
36         SAML_DLLLOCAL PluginManager<SAMLArtifact,string,const char*>::Factory SAMLArtifactType0001Factory; 
37         SAML_DLLLOCAL PluginManager<SAMLArtifact,string,const char*>::Factory SAMLArtifactType0002Factory; 
38     };
39
40     namespace saml2p {
41         SAML_DLLLOCAL PluginManager<SAMLArtifact,string,const char*>::Factory SAML2ArtifactType0004Factory; 
42     };
43 };
44
45 void SAML_API opensaml::registerSAMLArtifacts()
46 {
47     SAMLConfig& conf=SAMLConfig::getConfig();
48
49     string typecode;
50     typecode+=(char)0x0;
51     typecode+=(char)0x1;
52     conf.SAMLArtifactManager.registerFactory(typecode, saml1p::SAMLArtifactType0001Factory);
53     typecode[1]=(char)0x2;
54     conf.SAMLArtifactManager.registerFactory(typecode, saml1p::SAMLArtifactType0002Factory);
55     typecode[1]=(char)0x4;
56     conf.SAMLArtifactManager.registerFactory(typecode, saml2p::SAML2ArtifactType0004Factory);
57 }
58
59 const unsigned int SAMLArtifact::TYPECODE_LENGTH = 2;
60
61 SAMLArtifact::SAMLArtifact()
62 {
63 }
64
65 SAMLArtifact::~SAMLArtifact()
66 {
67 }
68
69 SAMLArtifact::SAMLArtifact(const SAMLArtifact& src) : m_raw(src.m_raw)
70 {
71 }
72
73 // Basic constructor just decodes the string and saves it off.
74 // Subclasses will handle pulling it apart.
75
76 SAMLArtifact::SAMLArtifact(const char* s)
77 {
78     xsecsize_t len=0;
79     XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(s),&len);
80     if (!decoded)
81         throw ArtifactException("Unable to decode base64 artifact.");
82     XMLByte* ptr=decoded;
83     while (len--)
84         m_raw+= *ptr++;
85 #ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE
86     XMLString::release(&decoded);
87 #else
88     XMLString::release((char**)&decoded);
89 #endif
90 }
91
92 string SAMLArtifact::getBytes() const
93 {
94     return m_raw;
95 }
96
97 string SAMLArtifact::getTypeCode() const
98 {
99     return m_raw.substr(0,TYPECODE_LENGTH);
100 }
101
102 string SAMLArtifact::getRemainingArtifact() const
103 {
104     return m_raw.substr(TYPECODE_LENGTH);
105 }
106
107 string SAMLArtifact::encode() const
108 {
109     xsecsize_t len=0;
110     XMLByte* out=Base64::encode(reinterpret_cast<const XMLByte*>(m_raw.data()),m_raw.size(),&len);
111     if (out) {
112         string ret(reinterpret_cast<char*>(out),len);
113 #ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE
114         XMLString::release(&out);
115 #else
116         XMLString::release((char**)&out);
117 #endif
118         return ret;
119     }
120     return string();
121 }
122
123 SAMLArtifact* SAMLArtifact::parse(const char* s)
124 {
125     // Decode and extract the type code first.
126     xsecsize_t len=0;
127     XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(s),&len);
128     if (!decoded)
129         throw ArtifactException("Artifact parser unable to decode base64-encoded artifact.");
130     
131     string type;
132     type+= decoded[0];
133     type+= decoded[1];
134 #ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE
135     XMLString::release(&decoded);
136 #else
137     XMLString::release((char**)&decoded);
138 #endif
139     
140     return SAMLConfig::getConfig().SAMLArtifactManager.newPlugin(type,s);
141 }
142
143 SAMLArtifact* SAMLArtifact::parse(const XMLCh* s)
144 {
145     auto_ptr_char temp(s);
146     return parse(temp.get());
147 }
148
149 string SAMLArtifact::toHex(const string& s)
150 {
151     static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
152     string::size_type len = s.length();
153     string ret;
154     
155     // two characters form the hex value.
156     for (string::size_type i=0; i < len; i++) {
157         ret+=(DIGITS[((unsigned char)(0xF0 & s[i])) >> 4 ]);
158         ret+=(DIGITS[0x0F & s[i]]);
159     }
160     return ret;
161 }