5274446e1aecfc96d6cf520ff2160b35433dad12
[shibboleth/cpp-opensaml.git] / saml / saml2 / metadata / impl / DiscoverableMetadataProvider.cpp
1 /*
2  *  Copyright 2010 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  * DiscoverableMetadataProvider.cpp
19  *
20  * A metadata provider that provides a JSON feed of IdP discovery information.
21  */
22
23 #include "internal.h"
24 #include "binding/SAMLArtifact.h"
25 #include "saml2/metadata/Metadata.h"
26 #include "saml2/metadata/DiscoverableMetadataProvider.h"
27
28 #include <fstream>
29 #include <sstream>
30 #include <xmltooling/logging.h>
31 #include <xmltooling/XMLToolingConfig.h>
32
33 using namespace opensaml::saml2md;
34 using namespace xmltooling;
35 using namespace std;
36
37 namespace {
38     void disco(string& s, const EntityDescriptor* entity, bool first) {
39         if (entity) {
40             const vector<IDPSSODescriptor*>& idps = entity->getIDPSSODescriptors();
41             if (!idps.empty()) {
42                 auto_ptr_char entityid(entity->getEntityID());
43                 // Open a struct and output id: entityID.
44                 if (first)
45                     first = false;
46                 else
47                     s += ',';
48                 s += "\n{\n \"entityID\": \"";
49                 s += entityid.get();
50                 s += '\"';
51                 for (vector<IDPSSODescriptor*>::const_iterator idp = idps.begin(); idp != idps.end(); ++idp) {
52                     if ((*idp)->getExtensions()) {
53                         const vector<XMLObject*>& exts =  const_cast<const Extensions*>((*idp)->getExtensions())->getUnknownXMLObjects();
54                         for (vector<XMLObject*>::const_iterator ext = exts.begin(); ext != exts.end(); ++ext) {
55                             const UIInfo* info = dynamic_cast<UIInfo*>(*ext);
56                             if (info) {
57                                 const vector<DisplayName*>& dispnames = info->getDisplayNames();
58                                 if (!dispnames.empty()) {
59                                     s += ",\n \"DisplayNames\": [";
60                                     for (vector<DisplayName*>::const_iterator dispname = dispnames.begin(); dispname != dispnames.end(); ++dispname) {
61                                         if (dispname != dispnames.begin())
62                                             s += ',';
63                                         auto_ptr_char val((*dispname)->getName());
64                                         auto_ptr_char lang((*dispname)->getLang());
65                                         s += "\n  {\n  \"value\": \"";
66                                         s += val.get();
67                                         s += "\",\n  \"lang\": \"";
68                                         s += lang.get();
69                                         s += "\"\n  }";
70                                     }
71                                     s += "\n ]";
72                                 }
73
74                                 const vector<Description*>& descs = info->getDescriptions();
75                                 if (!descs.empty()) {
76                                     s += ",\n \"Descriptions\": [";
77                                     for (vector<Description*>::const_iterator desc = descs.begin(); desc != descs.end(); ++desc) {
78                                         if (desc != descs.begin())
79                                             s += ',';
80                                         auto_ptr_char val((*desc)->getDescription());
81                                         auto_ptr_char lang((*desc)->getLang());
82                                         s += "\n  {\n  \"value\": \"";
83                                         s += val.get();
84                                         s += "\",\n  \"lang\": \"";
85                                         s += lang.get();
86                                         s += "\"\n  }";
87                                     }
88                                     s += "\n ]";
89                                 }
90
91                                 const vector<InformationURL*>& infurls = info->getInformationURLs();
92                                 if (!infurls.empty()) {
93                                     s += ",\n \"InformationURLs\": [";
94                                     for (vector<InformationURL*>::const_iterator infurl = infurls.begin(); infurl != infurls.end(); ++infurl) {
95                                         if (infurl != infurls.begin())
96                                             s += ',';
97                                         auto_ptr_char val((*infurl)->getURL());
98                                         auto_ptr_char lang((*infurl)->getLang());
99                                         s += "\n  {\n  \"value\": \"";
100                                         s += val.get();
101                                         s += "\",\n  \"lang\": \"";
102                                         s += lang.get();
103                                         s += "\"\n  }";
104                                     }
105                                     s += "\n ]";
106                                 }
107
108                                 const vector<PrivacyStatementURL*>& privs = info->getPrivacyStatementURLs();
109                                 if (!privs.empty()) {
110                                     s += ",\n \"PrivacyStatementURLs\": [";
111                                     for (vector<PrivacyStatementURL*>::const_iterator priv = privs.begin(); priv != privs.end(); ++priv) {
112                                         if (priv != privs.begin())
113                                             s += ',';
114                                         auto_ptr_char val((*priv)->getURL());
115                                         auto_ptr_char lang((*priv)->getLang());
116                                         s += "\n  {\n  \"value\": \"";
117                                         s += val.get();
118                                         s += "\",\n  \"lang\": \"";
119                                         s += lang.get();
120                                         s += "\"\n  }";
121                                     }
122                                     s += "\n ]";
123                                 }
124
125                                 const vector<Logo*>& logos = info->getLogos();
126                                 if (!logos.empty()) {
127                                     s += ",\n \"Logos\": [";
128                                     for (vector<Logo*>::const_iterator logo = logos.begin(); logo != logos.end(); ++logo) {
129                                         if (logo != logos.begin())
130                                             s += ',';
131                                         s += "\n  {\n";
132                                         auto_ptr_char val((*logo)->getURL());
133                                         s += "  \"value\": \"";
134                                         s += val.get();
135                                         ostringstream ht;
136                                         ht << (*logo)->getHeight().second;
137                                         s += "\",\n  \"height\": \"";
138                                         s += ht.str();
139                                         ht.clear();
140                                         ht << (*logo)->getWidth().second;
141                                         s += "\",\n  \"width\": \"";
142                                         s += ht.str();
143                                         s += '\"';
144                                         if ((*logo)->getLang()) {
145                                             auto_ptr_char lang((*logo)->getLang());
146                                             s += ",\n  \"lang\": \"";
147                                             s += lang.get();
148                                             s += '\"';
149                                         }
150                                         s += "\n  }";
151                                     }
152                                     s += "\n ]";
153                                 }
154                             }
155                         }
156                     }
157                 }
158                 // Close the struct;
159                 s += "\n}";
160             }
161         }
162     }
163
164     void disco(string& s, const EntitiesDescriptor* group, bool first) {
165         if (group) {
166             const vector<EntitiesDescriptor*>& groups = group->getEntitiesDescriptors();
167             for (vector<EntitiesDescriptor*>::const_iterator i = groups.begin(); i != groups.end(); ++i)
168                 disco(s, *i, first);
169
170             const vector<EntityDescriptor*>& sites = group->getEntityDescriptors();
171             for (vector<EntityDescriptor*>::const_iterator j = sites.begin(); j != sites.end(); ++j)
172                 disco(s, *j, first);
173         }
174     }
175 }
176
177 DiscoverableMetadataProvider::DiscoverableMetadataProvider()
178 {
179 }
180
181 DiscoverableMetadataProvider::~DiscoverableMetadataProvider()
182 {
183 }
184
185 void DiscoverableMetadataProvider::generateFeed()
186 {
187     bool first = true;
188     m_feed = "[";
189     const XMLObject* object = getMetadata();
190     disco(m_feed, dynamic_cast<const EntitiesDescriptor*>(object), first);
191     disco(m_feed, dynamic_cast<const EntityDescriptor*>(object), first);
192     m_feed += "\n]\n";
193
194     SAMLConfig::getConfig().generateRandomBytes(m_feedTag, 4);
195     m_feedTag = SAMLArtifact::toHex(m_feedTag);
196 }
197
198 string DiscoverableMetadataProvider::getCacheTag() const
199 {
200     return m_feedTag;
201 }
202
203 ostream& DiscoverableMetadataProvider::outputFeed(ostream& os) const
204 {
205     return os << m_feed;
206 }