Collapse feeds to a single array, sanitize JSON strings.
authorScott Cantor <cantor.2@osu.edu>
Sat, 6 Nov 2010 19:20:00 +0000 (19:20 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sat, 6 Nov 2010 19:20:00 +0000 (19:20 +0000)
saml/saml2/metadata/DiscoverableMetadataProvider.h
saml/saml2/metadata/impl/ChainingMetadataProvider.cpp
saml/saml2/metadata/impl/DiscoverableMetadataProvider.cpp

index daa78fe..d86513a 100644 (file)
@@ -75,10 +75,12 @@ namespace opensaml {
              * 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. */
index ef2a3ec..0ba3c0e 100644 (file)
@@ -72,20 +72,19 @@ namespace opensaml {
                 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 {
index fafce23..e3f8925 100644 (file)
@@ -47,11 +47,9 @@ DiscoverableMetadataProvider::~DiscoverableMetadataProvider()
 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);
@@ -62,9 +60,50 @@ string DiscoverableMetadataProvider::getCacheTag() const
     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
@@ -80,7 +119,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
             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) {
@@ -99,7 +138,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
                                     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  }";
@@ -116,7 +155,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
                                     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  }";
@@ -133,7 +172,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
                                     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  }";
@@ -150,7 +189,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
                                     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  }";
@@ -167,7 +206,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
                                     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\": \"";
@@ -210,7 +249,7 @@ void DiscoverableMetadataProvider::disco(string& s, const EntityDescriptor* enti
                             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  }";