https://issues.shibboleth.net/jira/browse/SSPCPP-472
[shibboleth/sp.git] / shibsp / attribute / ExtensibleAttribute.cpp
index e2e1a0c..2d4fe54 100644 (file)
@@ -1,17 +1,21 @@
-/*
- *  Copyright 2009 Internet2
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
  */
 
 /**
 #include "attribute/ExtensibleAttribute.h"
 #include "util/SPConstants.h"
 
+#include <boost/algorithm/string/trim.hpp>
+
 using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
 
+namespace shibsp {
+    SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
+        return new ExtensibleAttribute(in);
+    }
+};
+
+ExtensibleAttribute::ExtensibleAttribute(const vector<string>& ids, const char* formatter) : Attribute(ids)
+{
+    m_obj = Attribute::marshall();
+    m_obj.name("Extensible");
+    m_obj.addmember("_formatter").string(formatter);
+}
+
+ExtensibleAttribute::ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy())
+{
+}
+
+ExtensibleAttribute::~ExtensibleAttribute()
+{
+    m_obj.destroy();
+}
+
+DDF ExtensibleAttribute::getValues()
+{
+    return m_obj.first();
+}
+
+size_t ExtensibleAttribute::valueCount() const
+{
+    return m_obj.first().integer();
+}
+
+void ExtensibleAttribute::clearSerializedValues()
+{
+    m_serialized.clear();
+}
+
+const char* ExtensibleAttribute::getString(size_t index) const
+{
+    return m_obj.first()[static_cast<unsigned long>(index)].string();
+}
+
+const char* ExtensibleAttribute::getScope(size_t index) const
+{
+    return nullptr;
+}
+
+void ExtensibleAttribute::removeValue(size_t index)
+{
+    Attribute::removeValue(index);
+    DDF vals = m_obj.first();
+    if (index < static_cast<size_t>(vals.integer()))
+        vals[static_cast<unsigned long>(index)].remove().destroy();
+}
 
 const vector<string>& ExtensibleAttribute::getSerializedValues() const
 {
@@ -39,26 +99,26 @@ const vector<string>& ExtensibleAttribute::getSerializedValues() const
             DDF val = m_obj.first().first();
             while (!val.isnull()) {
 
-                static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_.";
+                static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-.[]";
 
                 m_serialized.push_back(string());
                 string& processed = m_serialized.back();
 
                 string::size_type i=0,start=0;
-                while (start!=string::npos && start<msg.length() && (i=msg.find("$",start))!=string::npos) {
+                while (start != string::npos && start < msg.length() && (i = msg.find("$",start)) != string::npos) {
                     if (i>start)
-                        processed += msg.substr(start,i-start); // append everything in between
-                    start=i+1;                                  // move start to the beginning of the token name
-                    i=msg.find_first_not_of(legal,start);       // find token delimiter
-                    if (i==start) {                             // append a non legal character
-                       processed+=msg[start++];
+                        processed += msg.substr(start, i-start);    // append everything in between
+                    start = i+1;                                    // move start to the beginning of the token name
+                    i = msg.find_first_not_of(legal, start);        // find token delimiter
+                    if (i == start) {                               // append a non legal character
+                       processed += msg[start++];
                        continue;
                     }
                     
-                    string tag = msg.substr(start,(i==string::npos) ? i : i-start);
+                    string tag = msg.substr(start, (i==string::npos) ? i : i-start);
                     if (tag == "_string" && val.string()) {
                         processed += val.string();
-                        start=i;
+                        start = i;
                     }
                     else {
                         DDF child = val.getmember(tag.c_str());
@@ -66,11 +126,12 @@ const vector<string>& ExtensibleAttribute::getSerializedValues() const
                             processed += child.string();
                         else if (child.isstruct() && child["_string"].string())
                             processed += child["_string"].string();
-                        start=i;
+                        start = i;
                     }
                 }
-                if (start!=string::npos && start<msg.length())
+                if (start != string::npos && start < msg.length())
                     processed += msg.substr(start,i);    // append rest of string
+                boost::trim(processed);
 
                 val = m_obj.first().next();
             }
@@ -78,3 +139,17 @@ const vector<string>& ExtensibleAttribute::getSerializedValues() const
     }
     return Attribute::getSerializedValues();
 }
+
+DDF ExtensibleAttribute::marshall() const
+{
+    DDF ddf = Attribute::marshall();
+    ddf.name("Extensible");
+    ddf.addmember("_formatter").string(m_obj["_formatter"].string());
+    DDF val = m_obj.first().first();
+    while (!val.isnull()) {
+        DDF dup = val.copy();
+        ddf.first().add(dup);
+        val = m_obj.first().next();
+    }
+    return ddf;
+}