An extractor for keys in metadata, and a decoder for KeyInfo-valued attributes.
authorScott Cantor <cantor.2@osu.edu>
Fri, 17 Apr 2009 22:02:21 +0000 (22:02 +0000)
committerScott Cantor <cantor.2@osu.edu>
Fri, 17 Apr 2009 22:02:21 +0000 (22:02 +0000)
.cproject
shibsp/Makefile.am
shibsp/attribute/Attribute.cpp
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/KeyInfoAttributeDecoder.cpp [new file with mode: 0644]
shibsp/attribute/resolver/AttributeExtractor.h
shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp [new file with mode: 0644]
shibsp/shibsp.vcproj

index 3f1b396..68d69c0 100644 (file)
--- a/.cproject
+++ b/.cproject
@@ -20,7 +20,7 @@
 \r
 <storageModule moduleId="org.eclipse.cdt.core.pathentry">\r
 <pathentry include="C:/log4shib-1.0/include" kind="inc" path="" system="true"/>\r
-<pathentry include="C:/xerces-c_2_8_0-x86-windows-vc_8_0/include" kind="inc" path="" system="true"/>\r
+<pathentry include="C:/xerces-c-3.0.1-x86-windows-vc-9.0/include" kind="inc" path="" system="true"/>\r
 <pathentry base-path="cpp-xmltooling" include="" kind="inc" path="" system="true"/>\r
 <pathentry base-path="cpp-opensaml2" include="" kind="inc" path="" system="true"/>\r
 <pathentry base-path="cpp-sp" include="shibsp" kind="inc" path="" system="true"/>\r
index cf9de7c..40c4a3f 100644 (file)
@@ -155,6 +155,7 @@ libshibsp_lite_la_SOURCES = \
 
 libshibsp_la_SOURCES = \
        ${common_sources} \
+       attribute/KeyInfoAttributeDecoder.cpp \
        attribute/NameIDAttributeDecoder.cpp \
        attribute/NameIDFromScopedAttributeDecoder.cpp \
        attribute/ScopedAttributeDecoder.cpp \
@@ -185,6 +186,7 @@ libshibsp_la_SOURCES = \
        attribute/resolver/impl/QueryAttributeResolver.cpp \
        attribute/resolver/impl/ChainingAttributeExtractor.cpp \
        attribute/resolver/impl/DelegationAttributeExtractor.cpp \
+       attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp \
        attribute/resolver/impl/XMLAttributeExtractor.cpp \
        binding/impl/ArtifactResolver.cpp \
        binding/impl/SOAPClient.cpp \
index feffbd3..8c4a16a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,11 +60,13 @@ namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
 
     static const XMLCh _StringAttributeDecoder[] = UNICODE_LITERAL_22(S,t,r,i,n,g,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _ScopedAttributeDecoder[] = UNICODE_LITERAL_22(S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _NameIDAttributeDecoder[] = UNICODE_LITERAL_22(N,a,m,e,I,D,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _NameIDFromScopedAttributeDecoder[] = UNICODE_LITERAL_32(N,a,m,e,I,D,F,r,o,m,S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    static const XMLCh _KeyInfoAttributeDecoder[] = UNICODE_LITERAL_23(K,e,y,I,n,f,o,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
 
     static const XMLCh caseSensitive[] =           UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
 #endif
@@ -75,6 +77,7 @@ xmltooling::QName shibsp::StringAttributeDecoderType(shibspconstants::SHIB2ATTRI
 xmltooling::QName shibsp::ScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _ScopedAttributeDecoder);
 xmltooling::QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDAttributeDecoder);
 xmltooling::QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
+xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
 
 void shibsp::registerAttributeDecoders()
 {
@@ -83,6 +86,7 @@ void shibsp::registerAttributeDecoders()
     conf.AttributeDecoderManager.registerFactory(ScopedAttributeDecoderType, ScopedAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(NameIDAttributeDecoderType, NameIDAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(NameIDFromScopedAttributeDecoderType, NameIDFromScopedAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
 }
 
 AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true)
index 7063ceb..9a3bb8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -78,6 +78,9 @@ namespace shibsp {
     /** Decodes scoped attributes into a NameIDAttribute. */
     extern SHIBSP_API xmltooling::QName NameIDFromScopedAttributeDecoderType;
 
+    /** Decodes KeyInfo information into a SimpleAttribute. */
+    extern SHIBSP_API xmltooling::QName KeyInfoAttributeDecoderType;
+
     /** Registers built-in AttributeDecoders into the runtime. */
     void registerAttributeDecoders();
 };
diff --git a/shibsp/attribute/KeyInfoAttributeDecoder.cpp b/shibsp/attribute/KeyInfoAttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..d1a3e9d
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+ *  Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * KeyInfoAttributeDecoder.cpp\r
+ *\r
+ * Decodes KeyInfo information into a SimpleAttribute.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "attribute/AttributeDecoder.h"\r
+#include "attribute/SimpleAttribute.h"\r
+\r
+#include <saml/saml1/core/Assertions.h>\r
+#include <saml/saml2/core/Assertions.h>\r
+#include <xmltooling/security/SecurityHelper.h>\r
+#include <xmltooling/signature/KeyInfo.h>\r
+\r
+using namespace shibsp;\r
+using namespace opensaml;\r
+using namespace xmlsignature;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder\r
+    {\r
+    public:\r
+        KeyInfoAttributeDecoder(const DOMElement* e);\r
+        ~KeyInfoAttributeDecoder() {\r
+            delete m_keyInfoResolver;\r
+        }\r
+\r
+        Attribute* decode(\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            ) const;\r
+\r
+    private:\r
+        void extract(const KeyInfo* k, vector<string>& dest) const {\r
+            auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));\r
+            if (cred.get()) {\r
+                dest.push_back(string());\r
+                dest.back() = SecurityHelper::getDEREncoding(*cred.get());\r
+                if (dest.back().empty())\r
+                    dest.pop_back();\r
+            }\r
+        }\r
+\r
+        const KeyInfoResolver* getKeyInfoResolver() const {\r
+            return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();\r
+        }\r
+\r
+        KeyInfoResolver* m_keyInfoResolver;\r
+    };\r
+\r
+    AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)\r
+    {\r
+        return new KeyInfoAttributeDecoder(e);\r
+    }\r
+\r
+    static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);\r
+    static const XMLCh type[] =             UNICODE_LITERAL_4(t,y,p,e);\r
+};\r
+\r
+KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_keyInfoResolver(NULL) {\r
+    e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;\r
+    if (e) {\r
+        auto_ptr_char t(e->getAttributeNS(NULL,type));\r
+        if (t.get() && *t.get())\r
+            m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);\r
+        else\r
+            throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");\r
+    }\r
+}\r
+\r
+Attribute* KeyInfoAttributeDecoder::decode(\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    ) const\r
+{\r
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");\r
+\r
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
+        log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
+        return NULL;\r
+    }\r
+\r
+    auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));\r
+    vector<string>& dest = attr->getValues();\r
+    vector<XMLObject*>::const_iterator v,stop;\r
+\r
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
+    if (saml2attr) {\r
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
+        v = values.begin();\r
+        stop = values.end();\r
+        if (log.isDebugEnabled()) {\r
+            auto_ptr_char n(saml2attr->getName());\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
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
+        if (saml1attr) {\r
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
+            v = values.begin();\r
+            stop = values.end();\r
+            if (log.isDebugEnabled()) {\r
+                auto_ptr_char n(saml1attr->getAttributeName());\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
+            log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
+            return NULL;\r
+        }\r
+    }\r
+\r
+    for (; v!=stop; ++v) {\r
+        const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);\r
+        if (k)\r
+            extract(k, dest);\r
+        else if ((*v)->hasChildren()) {\r
+            const list<XMLObject*>& children = (*v)->getOrderedChildren();\r
+            for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {\r
+                if (k=dynamic_cast<const KeyInfo*>(*vv))\r
+                    extract(k, dest);\r
+                else\r
+                    log.warn("skipping AttributeValue without a recognizable KeyInfo");\r
+            }\r
+        }\r
+    }\r
+\r
+    return dest.empty() ? NULL : attr.release();\r
+}\r
index 0438296..63644ca 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2009 Internet2
- * 
+ *
  * 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
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/attribute/resolver/AttributeExtractor.h
- * 
+ *
  * A service that extracts and decodes attributes from XML objects.
  */
 
@@ -45,12 +45,12 @@ namespace shibsp {
 
         /**
          * Extracts the attributes found in an XMLObject.
-         * 
+         *
          * @param application   Application performing the extraction
          * @param issuer        source of object, if known
          * @param xmlObject     object to extract
          * @param attributes    an array to populate with the extracted attributes
-         * 
+         *
          * @throws AttributeExtractionException thrown if there is a problem extracting attributes
          */
         virtual void extractAttributes(
@@ -79,6 +79,9 @@ namespace shibsp {
     /** AttributeExtractor for DelegationRestriction information. */
     #define DELEGATION_ATTRIBUTE_EXTRACTOR "Delegation"
 
+    /** AttributeExtractor for KeyInfo information. */
+    #define KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR "KeyDescriptor"
+
     /** AttributeExtractor based on chaining together other extractors. */
     #define CHAINING_ATTRIBUTE_EXTRACTOR "Chaining"
 };
index 95bda8a..523cdc3 100644 (file)
@@ -71,8 +71,9 @@ namespace shibsp {
     static const XMLCh _AttributeExtractor[] =  UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
     static const XMLCh _type[] =                UNICODE_LITERAL_4(t,y,p,e);
 
-    SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory XMLAttributeExtractorFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory DelegationAttributeExtractorFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory KeyDescriptorAttributeExtractorFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory XMLAttributeExtractorFactory;
     AttributeExtractor* SHIBSP_DLLLOCAL ChainingExtractorFactory(const DOMElement* const & e)
     {
         return new ChainingAttributeExtractor(e);
@@ -82,6 +83,7 @@ namespace shibsp {
 void SHIBSP_API shibsp::registerAttributeExtractors()
 {
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(DELEGATION_ATTRIBUTE_EXTRACTOR, DelegationAttributeExtractorFactory);
+    SPConfig::getConfig().AttributeExtractorManager.registerFactory(KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR, KeyDescriptorAttributeExtractorFactory);
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(XML_ATTRIBUTE_EXTRACTOR, XMLAttributeExtractorFactory);
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory);
 }
diff --git a/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
new file mode 100644 (file)
index 0000000..50aa8f8
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * 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
+ *
+ *     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.
+ */
+
+/**
+ * KeyDescriptorAttributeExtractor.cpp
+ *
+ * AttributeExtractor for KeyDescriptor information.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+#include "attribute/resolver/AttributeExtractor.h"
+
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 )
+#endif
+
+    class KeyDescriptorExtractor : public AttributeExtractor
+    {
+    public:
+        KeyDescriptorExtractor(const DOMElement* e);
+        ~KeyDescriptorExtractor() {}
+
+        Lockable* lock() {
+            return this;
+        }
+
+        void unlock() {
+        }
+
+        void extractAttributes(
+            const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+            ) const;
+
+        void getAttributeIds(std::vector<std::string>& attributes) const {
+            if (!m_signingId.empty())
+                attributes.push_back(m_signingId.front());
+            if (!m_encryptionId.empty())
+                attributes.push_back(m_encryptionId.front());
+        }
+
+    private:
+        vector<string> m_signingId;
+        vector<string> m_encryptionId;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+    AttributeExtractor* SHIBSP_DLLLOCAL KeyDescriptorAttributeExtractorFactory(const DOMElement* const & e)
+    {
+        return new KeyDescriptorExtractor(e);
+    }
+
+    static const XMLCh encryptionId[] = UNICODE_LITERAL_12(e,n,c,r,y,p,t,i,o,n,I,d);
+    static const XMLCh signingId[] =    UNICODE_LITERAL_9(s,i,g,n,i,n,g,I,d);
+};
+
+KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e)
+{
+    if (e) {
+        const XMLCh* a = e->getAttributeNS(NULL, signingId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_signingId.push_back(temp.get());
+        }
+        a = e->getAttributeNS(NULL, encryptionId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_encryptionId.push_back(temp.get());
+        }
+    }
+    if (m_signingId.empty() && m_encryptionId.empty())
+        throw ConfigurationException("KeyDescriptor AttributeExtractor requires signingId or encryptionId property.");
+}
+
+void KeyDescriptorExtractor::extractAttributes(
+    const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+    ) const
+{
+    const EntityDescriptor* entity = dynamic_cast<const EntityDescriptor*>(&xmlObject);
+    if (!entity || !issuer)
+        return;
+
+    vector<const Credential*> creds;
+    MetadataCredentialCriteria mcc(*issuer);
+
+    if (!m_signingId.empty()) {
+        mcc.setUsage(Credential::SIGNING_CREDENTIAL);
+        if (application.getMetadataProvider()->resolve(creds, &mcc)) {
+            auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_signingId));
+            vector<string>& vals = attr->getValues();
+            for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                if (vals.empty() || !vals.back().empty())
+                    vals.push_back(string());
+                vals.back() = SecurityHelper::getDEREncoding(*(*c));
+            }
+            if (vals.back().empty())
+                vals.pop_back();
+            if (!vals.empty())
+                attributes.push_back(attr.release());
+            creds.clear();
+        }
+    }
+
+    if (!m_encryptionId.empty()) {
+        mcc.setUsage(Credential::ENCRYPTION_CREDENTIAL);
+        if (application.getMetadataProvider()->resolve(creds, &mcc)) {
+            auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_encryptionId));
+            vector<string>& vals = attr->getValues();
+            for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
+                if (vals.empty() || !vals.back().empty())
+                    vals.push_back(string());
+                vals.back() = SecurityHelper::getDEREncoding(*(*c));
+            }
+            if (vals.back().empty())
+                vals.pop_back();
+            if (!vals.empty())
+                attributes.push_back(attr.release());
+        }
+    }
+}
index 87279c0..a99c34e 100644 (file)
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\KeyInfoAttributeDecoder.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\attribute\resolver\impl\KeyDescriptorAttributeExtractor.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\attribute\resolver\impl\QueryAttributeResolver.cpp"\r
                                                        >\r
                                                </File>\r