Add back alias support for attributes.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 6 Aug 2007 02:17:10 +0000 (02:17 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 6 Aug 2007 02:17:10 +0000 (02:17 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2386 cb58f699-b61c-0410-a6fe-9272a202ed29

12 files changed:
schemas/shibboleth-2.0-attribute-map.xsd
shibsp/attribute/Attribute.h
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/NameIDAttribute.h
shibsp/attribute/NameIDAttributeDecoder.cpp
shibsp/attribute/ScopedAttribute.h
shibsp/attribute/ScopedAttributeDecoder.cpp
shibsp/attribute/SimpleAttribute.h
shibsp/attribute/StringAttributeDecoder.cpp
shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
shibsp/impl/RemotedSessionCache.cpp
shibsp/impl/StorageServiceSessionCache.cpp

index 1e4fb20..7f88ac1 100644 (file)
             <minLength value="1"/>
         </restriction>
     </simpleType>
+
+    <simpleType name="listOfStrings">
+        <list itemType="am:string"/>
+    </simpleType>
     
     <element name="Attributes">
         <annotation>
                 <documentation>The internal attribute ID to which this SAML attribute maps.</documentation>
             </annotation>
         </attribute>
+        <attribute name="aliases" type="am:listOfStrings">
+            <annotation>
+                <documentation>Optional aliases for the internal attribute to which this SAML attribute maps.</documentation>
+            </annotation>
+        </attribute>
         <attribute name="name" type="am:string" use="required">
             <annotation>
                 <documentation>The SAML 1 AttributeName or SAML 2 Name of the attribute.</documentation>
index 4b0e474..c8ff978 100644 (file)
@@ -57,9 +57,9 @@ namespace shibsp {
         /**
          * Constructor
          * 
-         * @param id    Attribute identifier 
+         * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        Attribute(const char* id) : m_id(id ? id : ""), m_caseSensitive(true) {
+        Attribute(const std::vector<std::string>& ids) : m_id(ids), m_caseSensitive(true) {
         }
 
         /**
@@ -74,12 +74,19 @@ namespace shibsp {
         Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()) {
             const char* id = in.first().name();
             if (id && *id)
-                m_id = id;
+                m_id.push_back(id);
             else
                 throw AttributeException("No id found in marshalled attribute content.");
+            DDF aliases = in["aliases"];
+            if (aliases.islist()) {
+                DDF alias = aliases.first();
+                while (alias.isstring()) {
+                    m_id.push_back(alias.string());
+                    alias = aliases.next();
+                }
+            }
         }
         
-
         /**
          * Maintains a copy of serialized attribute values, when possible.
          * 
@@ -93,10 +100,19 @@ namespace shibsp {
         /**
          * Returns the Attribute identifier.
          * 
-         * @return Attribute identifier
+         * @return the Attribute identifier
          */
         const char* getId() const {
-            return m_id.c_str();
+            return m_id.front().c_str();
+        }
+
+        /**
+         * Returns all of the effective names for the Attribute.
+         *
+         * @return immutable array of identifiers, with the primary ID in the first position
+         */
+        const std::vector<std::string>& getAliases() const {
+            return m_id;
         }
 
         /**
@@ -181,9 +197,17 @@ namespace shibsp {
          */
         virtual DDF marshall() const {
             DDF ddf(NULL);
-            ddf.structure().addmember(m_id.c_str()).list();
+            ddf.structure().addmember(m_id.front().c_str()).list();
             if (!m_caseSensitive)
                 ddf.addmember("case_insensitive");
+            if (m_id.size() > 1) {
+                DDF alias;
+                DDF aliases = ddf.addmember("aliases").list();
+                for (std::vector<std::string>::const_iterator a = m_id.begin() + 1; a != m_id.end(); ++a) {
+                    alias = DDF(NULL).string(a->c_str());
+                    aliases.add(alias);
+                }
+            }
             return ddf;
         }
         
@@ -226,7 +250,7 @@ namespace shibsp {
         
     private:
         static std::map<std::string,AttributeFactory*> m_factoryMap;
-        std::string m_id;
+        std::vector<std::string> m_id;
         bool m_caseSensitive;
     };
 
index dd16148..4d0fe94 100644 (file)
@@ -51,14 +51,17 @@ namespace shibsp {
         /**
          * Decodes an XMLObject into a resolved Attribute.
          * 
-         * @param id                ID of resolved attribute
+         * @param ids               array containing primary identifier in first position, followed by any aliases
          * @param xmlObject         XMLObject to decode
          * @param assertingParty    name of the party asserting the attribute
          * @param relyingParty      name of the party relying on the attribute
          * @return a resolved Attribute, or NULL
          */
         virtual Attribute* decode(
-            const char* id, const xmltooling::XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            const std::vector<std::string>& ids,
+            const xmltooling::XMLObject* xmlObject,
+            const char* assertingParty=NULL,
+            const char* relyingParty=NULL
             ) const=0;
     };
 
index 3b674aa..d508ef2 100644 (file)
@@ -43,12 +43,12 @@ namespace shibsp {
     {
     public:
         /**
-         * Constructor
+         * Constructor.
          * 
-         * @param id    Attribute identifier
+         * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        NameIDAttribute(const char* id, const char* formatter=DEFAULT_NAMEID_FORMATTER)
-            : Attribute(id), m_formatter(formatter) {
+        NameIDAttribute(const std::vector<std::string>& ids, const char* formatter=DEFAULT_NAMEID_FORMATTER)
+            : Attribute(ids), m_formatter(formatter) {
         }
 
         /**
index 19ea010..e813bc1 100644 (file)
@@ -43,7 +43,7 @@ namespace shibsp {
         ~NameIDAttributeDecoder() {}\r
 \r
         shibsp::Attribute* decode(\r
-            const char* id, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
             ) const;\r
 \r
     private:\r
@@ -63,11 +63,11 @@ namespace shibsp {
 };\r
 \r
 shibsp::Attribute* NameIDAttributeDecoder::decode(\r
-    const char* id, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
     ) const\r
 {\r
     auto_ptr<NameIDAttribute> nameid(\r
-        new NameIDAttribute(id, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)\r
+        new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)\r
         );\r
     nameid->setCaseSensitive(m_caseSensitive);\r
     vector<NameIDAttribute::Value>& dest = nameid->getValues();\r
@@ -83,7 +83,10 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
             stop = values.end();\r
             if (log.isDebugEnabled()) {\r
                 auto_ptr_char n(saml2attr->getName());\r
-                log.debug("decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
+                log.debug(\r
+                    "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
             }\r
         }\r
         else {\r
@@ -94,7 +97,10 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
                 stop = values.end();\r
                 if (log.isDebugEnabled()) {\r
                     auto_ptr_char n(saml1attr->getAttributeName());\r
-                    log.debug("decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
+                    log.debug(\r
+                        "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                        ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                        );\r
                 }\r
             }\r
             else {\r
@@ -132,7 +138,7 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
     if (saml2name) {\r
         if (log.isDebugEnabled()) {\r
             auto_ptr_char f(saml2name->getFormat());\r
-            log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
+            log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
         }\r
         extract(saml2name, dest);\r
     }\r
@@ -141,7 +147,10 @@ shibsp::Attribute* NameIDAttributeDecoder::decode(
         if (saml1name) {\r
             if (log.isDebugEnabled()) {\r
                 auto_ptr_char f(saml1name->getFormat());\r
-                log.debug("decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
+                log.debug(\r
+                    "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
+                    );\r
             }\r
             extract(saml1name, dest);\r
         }\r
index 0e79398..5c87fe8 100644 (file)
@@ -46,12 +46,14 @@ namespace shibsp {
     {
     public:
         /**
-         * Constructor
+         * Constructor.
          * 
-         * @param id        Attribute identifier
+         * @param ids   array with primary identifier in first position, followed by any aliases
          * @param delimeter value/scope delimeter when serializing
          */
-        ScopedAttribute(const char* id, char delimeter='@') : Attribute(id), m_delimeter(delimeter) {}
+        ScopedAttribute(const std::vector<std::string>& ids, char delimeter='@')
+            : Attribute(ids), m_delimeter(delimeter) {
+        }
 
         /**
          * Constructs based on a remoted ScopedAttribute.
index 587d346..c194896 100644 (file)
@@ -51,7 +51,7 @@ namespace shibsp {
         ~ScopedAttributeDecoder() {}\r
 \r
         shibsp::Attribute* decode(\r
-            const char* id, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
             ) const;\r
 \r
     private:\r
@@ -65,14 +65,14 @@ namespace shibsp {
 };\r
 \r
 shibsp::Attribute* ScopedAttributeDecoder::decode(\r
-    const char* id, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
     ) const\r
 {\r
     char* val;\r
     char* scope;\r
     const XMLCh* xmlscope;\r
     QName scopeqname(NULL,Scope);\r
-    auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(id,m_delimeter));\r
+    auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(ids, m_delimeter));\r
     scoped->setCaseSensitive(m_caseSensitive);\r
     vector< pair<string,string> >& dest = scoped->getValues();\r
     vector<XMLObject*>::const_iterator v,stop;\r
@@ -87,7 +87,10 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
             stop = values.end();\r
             if (log.isDebugEnabled()) {\r
                 auto_ptr_char n(saml2attr->getName());\r
-                log.debug("decoding ScopedAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
+                log.debug(\r
+                    "decoding ScopedAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
             }\r
         }\r
         else {\r
@@ -98,7 +101,10 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
                 stop = values.end();\r
                 if (log.isDebugEnabled()) {\r
                     auto_ptr_char n(saml1attr->getAttributeName());\r
-                    log.debug("decoding ScopedAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
+                    log.debug(\r
+                        "decoding ScopedAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                        ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                        );\r
                 }\r
             }\r
             else {\r
@@ -149,7 +155,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
     if (saml2name) {\r
         if (log.isDebugEnabled()) {\r
             auto_ptr_char f(saml2name->getFormat());\r
-            log.debug("decoding ScopedAttribute (%s) from SAML 2 NameID with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
+            log.debug("decoding ScopedAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
         }\r
         val = toUTF8(saml2name->getName());\r
     }\r
@@ -158,7 +164,10 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
         if (saml1name) {\r
             if (log.isDebugEnabled()) {\r
                 auto_ptr_char f(saml1name->getFormat());\r
-                log.debug("decoding ScopedAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
+                log.debug(\r
+                    "decoding ScopedAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
+                    );\r
             }\r
             val = toUTF8(saml1name->getName());\r
         }\r
index 452beaf..39f869c 100644 (file)
@@ -34,11 +34,11 @@ namespace shibsp {
     {
     public:
         /**
-         * Constructor
+         * Constructor.
          * 
-         * @param id    Attribute identifier
+         * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        SimpleAttribute(const char* id) : Attribute(id) {}
+        SimpleAttribute(const std::vector<std::string>& ids) : Attribute(ids) {}
 
         /**
          * Constructs based on a remoted SimpleAttribute.
index b652ee0..0e075dd 100644 (file)
@@ -41,7 +41,7 @@ namespace shibsp {
         ~StringAttributeDecoder() {}\r
 \r
         shibsp::Attribute* decode(\r
-            const char* id, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
             ) const;\r
     };\r
 \r
@@ -52,11 +52,11 @@ namespace shibsp {
 };\r
 \r
 shibsp::Attribute* StringAttributeDecoder::decode(\r
-    const char* id, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
     ) const\r
 {\r
     char* val;\r
-    auto_ptr<SimpleAttribute> simple(new SimpleAttribute(id));\r
+    auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));\r
     simple->setCaseSensitive(m_caseSensitive);\r
     vector<string>& dest = simple->getValues();\r
     vector<XMLObject*>::const_iterator v,stop;\r
@@ -71,7 +71,10 @@ shibsp::Attribute* StringAttributeDecoder::decode(
             stop = values.end();\r
             if (log.isDebugEnabled()) {\r
                 auto_ptr_char n(saml2attr->getName());\r
-                log.debug("decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
+                log.debug(\r
+                    "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
             }\r
         }\r
         else {\r
@@ -82,7 +85,10 @@ shibsp::Attribute* StringAttributeDecoder::decode(
                 stop = values.end();\r
                 if (log.isDebugEnabled()) {\r
                     auto_ptr_char n(saml1attr->getAttributeName());\r
-                    log.debug("decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size());\r
+                log.debug(\r
+                    "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
                 }\r
             }\r
             else {\r
@@ -112,7 +118,7 @@ shibsp::Attribute* StringAttributeDecoder::decode(
     if (saml2name) {\r
         if (log.isDebugEnabled()) {\r
             auto_ptr_char f(saml2name->getFormat());\r
-            log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
+            log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
         }\r
         val = toUTF8(saml2name->getName());\r
     }\r
@@ -121,7 +127,10 @@ shibsp::Attribute* StringAttributeDecoder::decode(
         if (saml1name) {\r
             if (log.isDebugEnabled()) {\r
                 auto_ptr_char f(saml1name->getFormat());\r
-                log.debug("decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", id, f.get() ? f.get() : "unspecified");\r
+                log.debug(\r
+                    "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
+                    );\r
             }\r
             val = toUTF8(saml1name->getName());\r
         }\r
index e0942e2..e7915c4 100644 (file)
@@ -87,9 +87,9 @@ namespace shibsp {
         Category& m_log;
         DOMDocument* m_document;
 #ifdef HAVE_GOOD_STL
-        typedef map< pair<xstring,xstring>,pair<AttributeDecoder*,string> > attrmap_t;
+        typedef map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > > attrmap_t;
 #else
-        typedef map< pair<string,string>,pair<AttributeDecoder*,string> > attrmap_t;
+        typedef map< pair<string,string>,pair< AttributeDecoder*,vector<string> > > attrmap_t;
 #endif
         attrmap_t m_attrMap;
         vector<string> m_attributeIds;
@@ -133,6 +133,7 @@ namespace shibsp {
     static const XMLCh _AttributeDecoder[] =    UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh Attributes[] =           UNICODE_LITERAL_10(A,t,t,r,i,b,u,t,e,s);
     static const XMLCh _id[] =                  UNICODE_LITERAL_2(i,d);
+    static const XMLCh _aliases[] =             UNICODE_LITERAL_7(a,l,i,a,s,e,s);
     static const XMLCh _name[] =                UNICODE_LITERAL_4(n,a,m,e);
     static const XMLCh nameFormat[] =           UNICODE_LITERAL_10(n,a,m,e,F,o,r,m,a,t);
 };
@@ -201,11 +202,11 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(l
 
         // Fetch/create the map entry and see if it's a duplicate rule.
 #ifdef HAVE_GOOD_STL
-        pair<AttributeDecoder*,string>& decl = m_attrMap[make_pair(name,format)];
+        pair< AttributeDecoder*,vector<string> >& decl = m_attrMap[make_pair(name,format)];
 #else
         auto_ptr_char n(name);
         auto_ptr_char f(format);
-        pair<AttributeDecoder*,string>& decl = m_attrMap[make_pair(n.get(),f.get())];
+        pair< AttributeDecoder*,vector<string> >& decl = m_attrMap[make_pair(n.get(),f.get())];
 #endif
         if (decl.first) {
             m_log.warn("skipping duplicate Attribute mapping (same name and nameFormat)");
@@ -223,8 +224,32 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(l
         }
         
         decl.first = decoder;
-        decl.second = id.get();
+        decl.second.push_back(id.get());
         m_attributeIds.push_back(id.get());
+
+        name = child->getAttributeNS(NULL, _aliases);
+        if (name && *name) {
+            auto_ptr_char aliases(name);
+            char* pos;
+            char* start = const_cast<char*>(aliases.get());
+            while (start && *start) {
+                while (*start && isspace(*start))
+                    start++;
+                if (!*start)
+                    break;
+                pos = strchr(start,' ');
+                if (pos)
+                    *pos=0;
+                if (strcmp(start, "REMOTE_USER")) {
+                    decl.second.push_back(start);
+                    m_attributeIds.push_back(start);
+                }
+                else {
+                    m_log.warn("skipping alias, REMOTE_USER is a reserved name");
+                }
+                start = pos ? pos+1 : NULL;
+            }
+        }
         
         child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
     }
@@ -235,9 +260,9 @@ void XMLExtractorImpl::extractAttributes(
     ) const
 {
 #ifdef HAVE_GOOD_STL
-    map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #else
-    map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<string,string>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #endif
 
     const XMLCh* format = nameid.getFormat();
@@ -249,7 +274,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp(format);
     if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, application.getString("entityID").second);
         if (a)
             attributes.push_back(a);
     }
@@ -260,9 +285,9 @@ void XMLExtractorImpl::extractAttributes(
     ) const
 {
 #ifdef HAVE_GOOD_STL
-    map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #else
-    map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<string,string>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #endif
 
     const XMLCh* format = nameid.getFormat();
@@ -274,7 +299,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp(format);
     if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, application.getString("entityID").second);
         if (a)
             attributes.push_back(a);
     }
@@ -285,9 +310,9 @@ void XMLExtractorImpl::extractAttributes(
     ) const
 {
 #ifdef HAVE_GOOD_STL
-    map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #else
-    map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<string,string>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #endif
 
     const XMLCh* name = attr.getAttributeName();
@@ -303,7 +328,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp2(format);
     if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, application.getString("entityID").second);
         if (a)
             attributes.push_back(a);
     }
@@ -314,9 +339,9 @@ void XMLExtractorImpl::extractAttributes(
     ) const
 {
 #ifdef HAVE_GOOD_STL
-    map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #else
-    map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+    map< pair<string,string>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
 #endif
 
     const XMLCh* name = attr.getName();
@@ -334,7 +359,7 @@ void XMLExtractorImpl::extractAttributes(
     auto_ptr_char temp2(format);
     if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {
 #endif
-        Attribute* a = rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second);
+        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, application.getString("entityID").second);
         if (a)
             attributes.push_back(a);
     }
index e7bdbc9..48266ff 100644 (file)
@@ -105,8 +105,15 @@ namespace shibsp {
             return m_attributes;\r
         }\r
         const multimap<string,const Attribute*>& getIndexedAttributes() const {\r
-            if (m_attributes.empty())\r
-                unmarshallAttributes();\r
+            if (m_attributeIndex.empty()) {\r
+                if (m_attributes.empty())\r
+                    unmarshallAttributes();\r
+                for (vector<Attribute*>::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a) {\r
+                    const vector<string>& aliases = (*a)->getAliases();\r
+                    for (vector<string>::const_iterator alias = aliases.begin(); alias != aliases.end(); ++alias)\r
+                        m_attributeIndex.insert(make_pair(*alias, *a));\r
+                }\r
+            }\r
             return m_attributeIndex;\r
         }\r
         const vector<const char*>& getAssertionIDs() const {\r
@@ -177,7 +184,6 @@ void RemotedSession::unmarshallAttributes() const
         try {\r
             attribute = Attribute::unmarshall(attr);\r
             m_attributes.push_back(attribute);\r
-            m_attributeIndex.insert(make_pair(attribute->getId(),attribute));\r
             if (m_cache->m_log.isDebugEnabled())\r
                 m_cache->m_log.debug("unmarshalled attribute (ID: %s) with %d value%s",\r
                     attribute->getId(), attr.first().integer(), attr.first().integer()!=1 ? "s" : "");\r
index c1e7256..f310a55 100644 (file)
@@ -112,9 +112,16 @@ namespace shibsp {
             return m_attributes;
         }
         const multimap<string,const Attribute*>& getIndexedAttributes() const {
-            if (m_attributes.empty())
-                unmarshallAttributes();
-            return m_attributeIndex;
+            if (m_attributeIndex.empty()) {\r
+                if (m_attributes.empty())\r
+                    unmarshallAttributes();\r
+                for (vector<Attribute*>::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a) {\r
+                    const vector<string>& aliases = (*a)->getAliases();\r
+                    for (vector<string>::const_iterator alias = aliases.begin(); alias != aliases.end(); ++alias)\r
+                        m_attributeIndex.insert(make_pair(*alias, *a));\r
+                }\r
+            }\r
+            return m_attributeIndex;\r
         }
         const vector<const char*>& getAssertionIDs() const {
             if (m_ids.empty()) {