* Outputs the cached feed.
* <p>The provider <strong>MUST</strong> be locked.
*
- * @param os stream to output feed into
- * @return a reference to the output stream
+ * @param os stream to output feed into
+ * @param first on input, indicates if the feed is first in position,
+ * on output will be false if the feed was non-empty
+ * @param wrapArray true iff the feed array should be opened/closed by this provider
*/
- virtual std::ostream& outputFeed(std::ostream& os) const;
+ virtual void outputFeed(std::ostream& os, bool& first, bool wrapArray=true) const;
protected:
/** Storage for feed. */
return m_feedTag;
}
- ostream& outputFeed(ostream& os) const {
- os << "[\n";
+ void outputFeed(ostream& os, bool& first, bool wrapArray=true) const {
+ if (wrapArray)
+ os << '[';
// Lock each provider in turn and suck in its feed.
for (vector<MetadataProvider*>::const_iterator m = m_providers.begin(); m != m_providers.end(); ++m) {
- if (m != m_providers.begin())
- os << ",\n";
DiscoverableMetadataProvider* d = dynamic_cast<DiscoverableMetadataProvider*>(*m);
if (d) {
Locker locker(d);
- d->outputFeed(os);
+ d->outputFeed(os, first, false);
}
}
- os << ']';
- return os;
+ if (wrapArray)
+ os << "\n]";
}
void onEvent(const ObservableMetadataProvider& provider) const {
void DiscoverableMetadataProvider::generateFeed()
{
bool first = true;
- m_feed = "[";
const XMLObject* object = getMetadata();
disco(m_feed, dynamic_cast<const EntitiesDescriptor*>(object), first);
disco(m_feed, dynamic_cast<const EntityDescriptor*>(object), first);
- m_feed += "\n]";
SAMLConfig::getConfig().generateRandomBytes(m_feedTag, 4);
m_feedTag = SAMLArtifact::toHex(m_feedTag);
return m_feedTag;
}
-ostream& DiscoverableMetadataProvider::outputFeed(ostream& os) const
+void DiscoverableMetadataProvider::outputFeed(ostream& os, bool& first, bool wrapArray) const
{
- return os << m_feed;
+ if (wrapArray)
+ os << '[';
+ if (!m_feed.empty()) {
+ if (first)
+ first = false;
+ else
+ os << ",\n";
+ os << m_feed;
+ }
+ if (wrapArray)
+ os << "\n]";
+}
+
+static string& json_safe(string& s, const char* buf)
+{
+ for (; *buf; ++buf) {
+ switch (*buf) {
+ case '\\':
+ case '"':
+ s += '\\';
+ s += *buf;
+ break;
+ case '\b':
+ s += "\\b";
+ break;
+ case '\t':
+ s += "\\t";
+ break;
+ case '\n':
+ s += "\\n";
+ break;
+ case '\f':
+ s += "\\f";
+ break;
+ case '\r':
+ s += "\\r";
+ break;
+ default:
+ s += *buf;
+ }
+ }
+ return s;
}
void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* entity, bool& first) const
else
s += ',';
s += "\n{\n \"entityID\": \"";
- s += entityid.get();
+ json_safe(s, entityid.get());
s += '\"';
bool extFound = false;
for (vector<IDPSSODescriptor*>::const_iterator idp = idps.begin(); !extFound && idp != idps.end(); ++idp) {
auto_arrayptr<char> val(toUTF8((*dispname)->getName()));
auto_ptr_char lang((*dispname)->getLang());
s += "\n {\n \"value\": \"";
- s += val.get();
+ json_safe(s, val.get());
s += "\",\n \"lang\": \"";
s += lang.get();
s += "\"\n }";
auto_arrayptr<char> val(toUTF8((*desc)->getDescription()));
auto_ptr_char lang((*desc)->getLang());
s += "\n {\n \"value\": \"";
- s += val.get();
+ json_safe(s, val.get());
s += "\",\n \"lang\": \"";
s += lang.get();
s += "\"\n }";
auto_ptr_char val((*infurl)->getURL());
auto_ptr_char lang((*infurl)->getLang());
s += "\n {\n \"value\": \"";
- s += val.get();
+ json_safe(s, val.get());
s += "\",\n \"lang\": \"";
s += lang.get();
s += "\"\n }";
auto_ptr_char val((*priv)->getURL());
auto_ptr_char lang((*priv)->getLang());
s += "\n {\n \"value\": \"";
- s += val.get();
+ json_safe(s, val.get());
s += "\",\n \"lang\": \"";
s += lang.get();
s += "\"\n }";
s += "\n {\n";
auto_ptr_char val((*logo)->getURL());
s += " \"value\": \"";
- s += val.get();
+ json_safe(s, val.get());
ostringstream ht;
ht << (*logo)->getHeight().second;
s += "\",\n \"height\": \"";
auto_arrayptr<char> val(toUTF8((*dispname)->getName()));
auto_ptr_char lang((*dispname)->getLang());
s += "\n {\n \"value\": \"";
- s += val.get();
+ json_safe(s, val.get());
s += "\",\n \"lang\": \"";
s += lang.get();
s += "\"\n }";