2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
22 * DiscoverableMetadataProvider.cpp
24 * A metadata provider that provides a JSON feed of IdP discovery information.
28 #include "binding/SAMLArtifact.h"
29 #include "saml2/metadata/Metadata.h"
30 #include "saml2/metadata/DiscoverableMetadataProvider.h"
34 #include <xmltooling/logging.h>
35 #include <xmltooling/XMLToolingConfig.h>
37 using namespace opensaml::saml2md;
38 using namespace xmltooling;
41 DiscoverableMetadataProvider::DiscoverableMetadataProvider(const DOMElement* e) : MetadataProvider(e), m_legacyOrgNames(false)
43 static const XMLCh legacyOrgNames[] = UNICODE_LITERAL_14(l,e,g,a,c,y,O,r,g,N,a,m,e,s);
44 m_legacyOrgNames = XMLHelper::getAttrBool(e, false, legacyOrgNames);
47 DiscoverableMetadataProvider::~DiscoverableMetadataProvider()
51 void DiscoverableMetadataProvider::generateFeed()
55 const XMLObject* object = getMetadata();
56 disco(m_feed, dynamic_cast<const EntitiesDescriptor*>(object), first);
57 disco(m_feed, dynamic_cast<const EntityDescriptor*>(object), first);
59 SAMLConfig::getConfig().generateRandomBytes(m_feedTag, 4);
60 m_feedTag = SAMLArtifact::toHex(m_feedTag);
63 string DiscoverableMetadataProvider::getCacheTag() const
68 void DiscoverableMetadataProvider::outputFeed(ostream& os, bool& first, bool wrapArray) const
72 if (!m_feed.empty()) {
83 static string& json_safe(string& s, const char* buf)
114 void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* entity, bool& first) const
116 time_t now = time(nullptr);
117 if (entity && entity->isValid(now)) {
118 const vector<IDPSSODescriptor*>& idps = entity->getIDPSSODescriptors();
120 auto_ptr_char entityid(entity->getEntityID());
121 // Open a struct and output id: entityID.
126 s += "\n{\n \"entityID\": \"";
127 json_safe(s, entityid.get());
129 bool extFound = false;
130 for (vector<IDPSSODescriptor*>::const_iterator idp = idps.begin(); !extFound && idp != idps.end(); ++idp) {
131 if ((*idp)->isValid(now) && (*idp)->getExtensions()) {
132 const vector<XMLObject*>& exts = const_cast<const Extensions*>((*idp)->getExtensions())->getUnknownXMLObjects();
133 for (vector<XMLObject*>::const_iterator ext = exts.begin(); !extFound && ext != exts.end(); ++ext) {
134 const UIInfo* info = dynamic_cast<UIInfo*>(*ext);
137 const vector<DisplayName*>& dispnames = info->getDisplayNames();
138 if (!dispnames.empty()) {
139 s += ",\n \"DisplayNames\": [";
140 for (vector<DisplayName*>::const_iterator dispname = dispnames.begin(); dispname != dispnames.end(); ++dispname) {
141 if (dispname != dispnames.begin())
143 auto_arrayptr<char> val(toUTF8((*dispname)->getName()));
144 auto_ptr_char lang((*dispname)->getLang());
145 s += "\n {\n \"value\": \"";
146 json_safe(s, val.get());
147 s += "\",\n \"lang\": \"";
154 const vector<Description*>& descs = info->getDescriptions();
155 if (!descs.empty()) {
156 s += ",\n \"Descriptions\": [";
157 for (vector<Description*>::const_iterator desc = descs.begin(); desc != descs.end(); ++desc) {
158 if (desc != descs.begin())
160 auto_arrayptr<char> val(toUTF8((*desc)->getDescription()));
161 auto_ptr_char lang((*desc)->getLang());
162 s += "\n {\n \"value\": \"";
163 json_safe(s, val.get());
164 s += "\",\n \"lang\": \"";
171 const vector<Keywords*>& keywords = info->getKeywordss();
172 if (!keywords.empty()) {
173 s += ",\n \"Keywords\": [";
174 for (vector<Keywords*>::const_iterator words = keywords.begin(); words != keywords.end(); ++words) {
175 if (words != keywords.begin())
177 auto_arrayptr<char> val(toUTF8((*words)->getValues()));
178 auto_ptr_char lang((*words)->getLang());
179 s += "\n {\n \"value\": \"";
180 json_safe(s, val.get());
181 s += "\",\n \"lang\": \"";
188 const vector<InformationURL*>& infurls = info->getInformationURLs();
189 if (!infurls.empty()) {
190 s += ",\n \"InformationURLs\": [";
191 for (vector<InformationURL*>::const_iterator infurl = infurls.begin(); infurl != infurls.end(); ++infurl) {
192 if (infurl != infurls.begin())
194 auto_ptr_char val((*infurl)->getURL());
195 auto_ptr_char lang((*infurl)->getLang());
196 s += "\n {\n \"value\": \"";
197 json_safe(s, val.get());
198 s += "\",\n \"lang\": \"";
205 const vector<PrivacyStatementURL*>& privs = info->getPrivacyStatementURLs();
206 if (!privs.empty()) {
207 s += ",\n \"PrivacyStatementURLs\": [";
208 for (vector<PrivacyStatementURL*>::const_iterator priv = privs.begin(); priv != privs.end(); ++priv) {
209 if (priv != privs.begin())
211 auto_ptr_char val((*priv)->getURL());
212 auto_ptr_char lang((*priv)->getLang());
213 s += "\n {\n \"value\": \"";
214 json_safe(s, val.get());
215 s += "\",\n \"lang\": \"";
222 const vector<Logo*>& logos = info->getLogos();
223 if (!logos.empty()) {
224 s += ",\n \"Logos\": [";
225 for (vector<Logo*>::const_iterator logo = logos.begin(); logo != logos.end(); ++logo) {
226 if (logo != logos.begin())
229 auto_ptr_char val((*logo)->getURL());
230 s += " \"value\": \"";
231 json_safe(s, val.get());
233 ht << (*logo)->getHeight().second;
234 s += "\",\n \"height\": \"";
237 wt << (*logo)->getWidth().second;
238 s += "\",\n \"width\": \"";
241 if ((*logo)->getLang()) {
242 auto_ptr_char lang((*logo)->getLang());
243 s += ",\n \"lang\": \"";
256 if (m_legacyOrgNames && !extFound) {
257 const Organization* org = nullptr;
258 for (vector<IDPSSODescriptor*>::const_iterator idp = idps.begin(); !org && idp != idps.end(); ++idp) {
259 if ((*idp)->isValid(now))
260 org = (*idp)->getOrganization();
263 org = entity->getOrganization();
265 const vector<OrganizationDisplayName*>& odns = org->getOrganizationDisplayNames();
267 s += ",\n \"DisplayNames\": [";
268 for (vector<OrganizationDisplayName*>::const_iterator dispname = odns.begin(); dispname != odns.end(); ++dispname) {
269 if (dispname != odns.begin())
271 auto_arrayptr<char> val(toUTF8((*dispname)->getName()));
272 auto_ptr_char lang((*dispname)->getLang());
273 s += "\n {\n \"value\": \"";
274 json_safe(s, val.get());
275 s += "\",\n \"lang\": \"";
290 void DiscoverableMetadataProvider::disco(string& s, const EntitiesDescriptor* group, bool& first) const
293 const vector<EntitiesDescriptor*>& groups = group->getEntitiesDescriptors();
294 for (vector<EntitiesDescriptor*>::const_iterator i = groups.begin(); i != groups.end(); ++i)
297 const vector<EntityDescriptor*>& sites = group->getEntityDescriptors();
298 for (vector<EntityDescriptor*>::const_iterator j = sites.begin(); j != sites.end(); ++j)