2 * Copyright 2010 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * DiscoverableMetadataProvider.cpp
20 * A metadata provider that provides a JSON feed of IdP discovery information.
24 #include "binding/SAMLArtifact.h"
25 #include "saml2/metadata/Metadata.h"
26 #include "saml2/metadata/DiscoverableMetadataProvider.h"
30 #include <xmltooling/logging.h>
31 #include <xmltooling/XMLToolingConfig.h>
33 using namespace opensaml::saml2md;
34 using namespace xmltooling;
37 DiscoverableMetadataProvider::DiscoverableMetadataProvider(const DOMElement* e) : MetadataProvider(e), m_legacyOrgNames(false)
39 static const XMLCh legacyOrgNames[] = UNICODE_LITERAL_14(l,e,g,a,c,y,O,r,g,N,a,m,e,s);
40 m_legacyOrgNames = XMLHelper::getAttrBool(e, false, legacyOrgNames);
43 DiscoverableMetadataProvider::~DiscoverableMetadataProvider()
47 void DiscoverableMetadataProvider::generateFeed()
50 const XMLObject* object = getMetadata();
51 disco(m_feed, dynamic_cast<const EntitiesDescriptor*>(object), first);
52 disco(m_feed, dynamic_cast<const EntityDescriptor*>(object), first);
54 SAMLConfig::getConfig().generateRandomBytes(m_feedTag, 4);
55 m_feedTag = SAMLArtifact::toHex(m_feedTag);
58 string DiscoverableMetadataProvider::getCacheTag() const
63 void DiscoverableMetadataProvider::outputFeed(ostream& os, bool& first, bool wrapArray) const
67 if (!m_feed.empty()) {
78 static string& json_safe(string& s, const char* buf)
109 void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* entity, bool& first) const
111 time_t now = time(nullptr);
112 if (entity && entity->isValid(now)) {
113 const vector<IDPSSODescriptor*>& idps = entity->getIDPSSODescriptors();
115 auto_ptr_char entityid(entity->getEntityID());
116 // Open a struct and output id: entityID.
121 s += "\n{\n \"entityID\": \"";
122 json_safe(s, entityid.get());
124 bool extFound = false;
125 for (vector<IDPSSODescriptor*>::const_iterator idp = idps.begin(); !extFound && idp != idps.end(); ++idp) {
126 if ((*idp)->isValid(now) && (*idp)->getExtensions()) {
127 const vector<XMLObject*>& exts = const_cast<const Extensions*>((*idp)->getExtensions())->getUnknownXMLObjects();
128 for (vector<XMLObject*>::const_iterator ext = exts.begin(); !extFound && ext != exts.end(); ++ext) {
129 const UIInfo* info = dynamic_cast<UIInfo*>(*ext);
132 const vector<DisplayName*>& dispnames = info->getDisplayNames();
133 if (!dispnames.empty()) {
134 s += ",\n \"DisplayNames\": [";
135 for (vector<DisplayName*>::const_iterator dispname = dispnames.begin(); dispname != dispnames.end(); ++dispname) {
136 if (dispname != dispnames.begin())
138 auto_arrayptr<char> val(toUTF8((*dispname)->getName()));
139 auto_ptr_char lang((*dispname)->getLang());
140 s += "\n {\n \"value\": \"";
141 json_safe(s, val.get());
142 s += "\",\n \"lang\": \"";
149 const vector<Description*>& descs = info->getDescriptions();
150 if (!descs.empty()) {
151 s += ",\n \"Descriptions\": [";
152 for (vector<Description*>::const_iterator desc = descs.begin(); desc != descs.end(); ++desc) {
153 if (desc != descs.begin())
155 auto_arrayptr<char> val(toUTF8((*desc)->getDescription()));
156 auto_ptr_char lang((*desc)->getLang());
157 s += "\n {\n \"value\": \"";
158 json_safe(s, val.get());
159 s += "\",\n \"lang\": \"";
166 const vector<InformationURL*>& infurls = info->getInformationURLs();
167 if (!infurls.empty()) {
168 s += ",\n \"InformationURLs\": [";
169 for (vector<InformationURL*>::const_iterator infurl = infurls.begin(); infurl != infurls.end(); ++infurl) {
170 if (infurl != infurls.begin())
172 auto_ptr_char val((*infurl)->getURL());
173 auto_ptr_char lang((*infurl)->getLang());
174 s += "\n {\n \"value\": \"";
175 json_safe(s, val.get());
176 s += "\",\n \"lang\": \"";
183 const vector<PrivacyStatementURL*>& privs = info->getPrivacyStatementURLs();
184 if (!privs.empty()) {
185 s += ",\n \"PrivacyStatementURLs\": [";
186 for (vector<PrivacyStatementURL*>::const_iterator priv = privs.begin(); priv != privs.end(); ++priv) {
187 if (priv != privs.begin())
189 auto_ptr_char val((*priv)->getURL());
190 auto_ptr_char lang((*priv)->getLang());
191 s += "\n {\n \"value\": \"";
192 json_safe(s, val.get());
193 s += "\",\n \"lang\": \"";
200 const vector<Logo*>& logos = info->getLogos();
201 if (!logos.empty()) {
202 s += ",\n \"Logos\": [";
203 for (vector<Logo*>::const_iterator logo = logos.begin(); logo != logos.end(); ++logo) {
204 if (logo != logos.begin())
207 auto_ptr_char val((*logo)->getURL());
208 s += " \"value\": \"";
209 json_safe(s, val.get());
211 ht << (*logo)->getHeight().second;
212 s += "\",\n \"height\": \"";
215 ht << (*logo)->getWidth().second;
216 s += "\",\n \"width\": \"";
219 if ((*logo)->getLang()) {
220 auto_ptr_char lang((*logo)->getLang());
221 s += ",\n \"lang\": \"";
234 if (m_legacyOrgNames && !extFound) {
235 const Organization* org = nullptr;
236 for (vector<IDPSSODescriptor*>::const_iterator idp = idps.begin(); !org && idp != idps.end(); ++idp) {
237 if ((*idp)->isValid(now))
238 org = (*idp)->getOrganization();
241 org = entity->getOrganization();
243 const vector<OrganizationDisplayName*>& odns = org->getOrganizationDisplayNames();
245 s += ",\n \"DisplayNames\": [";
246 for (vector<OrganizationDisplayName*>::const_iterator dispname = odns.begin(); dispname != odns.end(); ++dispname) {
247 if (dispname != odns.begin())
249 auto_arrayptr<char> val(toUTF8((*dispname)->getName()));
250 auto_ptr_char lang((*dispname)->getLang());
251 s += "\n {\n \"value\": \"";
252 json_safe(s, val.get());
253 s += "\",\n \"lang\": \"";
268 void DiscoverableMetadataProvider::disco(string& s, const EntitiesDescriptor* group, bool& first) const
271 const vector<EntitiesDescriptor*>& groups = group->getEntitiesDescriptors();
272 for (vector<EntitiesDescriptor*>::const_iterator i = groups.begin(); i != groups.end(); ++i)
275 const vector<EntityDescriptor*>& sites = group->getEntityDescriptors();
276 for (vector<EntityDescriptor*>::const_iterator j = sites.begin(); j != sites.end(); ++j)