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