Clean up svn props.
authorScott Cantor <cantor.2@osu.edu>
Sat, 31 Oct 2009 20:34:11 +0000 (20:34 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sat, 31 Oct 2009 20:34:11 +0000 (20:34 +0000)
31 files changed:
.cproject
.project
adfs/Makefile.am
adfs/resource.h
doc/CREDITS.txt [changed mode: 0755->0644]
doc/README.txt
doc/RELEASE.txt
fastcgi/Makefile.am
fastcgi/resource.h
fastcgi/shibauthorizer.cpp
fastcgi/shibresponder.cpp
memcache-store/Makefile.am
memcache-store/memcache-store.cpp
memcache-store/resource.h
odbc-store/resource.h
schemas/WS-Trust.xsd
schemas/shibboleth-2.0-afp.xsd
schemas/shibboleth-2.0-native-sp-config.xsd
shibd/shibd.cpp
shibd/shibd_win32.cpp
shibsp/attribute/DOMAttributeDecoder.cpp
shibsp/attribute/KeyInfoAttributeDecoder.cpp
shibsp/attribute/NameIDAttributeDecoder.cpp
shibsp/attribute/StringAttributeDecoder.cpp
shibsp/attribute/XMLAttributeDecoder.cpp
shibsp/impl/ChainingAccessControl.cpp
shibsp/impl/XMLAccessControl.cpp
shibsp/paths.h.in
shibsp/resource.h
shibsp/util/SPConstants.cpp
util/mdquery.cpp

index 0f46347..4d44992 100644 (file)
--- a/.cproject
+++ b/.cproject
 <?xml version="1.0" encoding="UTF-8"?><?fileVersion 4.0.0?><cproject>\r
 <storageModule moduleId="org.eclipse.cdt.core.settings">\r
-<cconfiguration id="converted.config.1630818620">\r
-\r
-<storageModule buildSystemId="org.eclipse.cdt.core.defaultConfigDataProvider" id="converted.config.1630818620" moduleId="org.eclipse.cdt.core.settings" name="convertedConfig">\r
+<cconfiguration id="org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450">\r
+<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450" moduleId="org.eclipse.cdt.core.settings" name="Build (GNU)">\r
 <externalSettings/>\r
 <extensions>\r
-<extension id="org.eclipse.cdt.core.domsourceindexer" point="org.eclipse.cdt.core.CIndexer"/>\r
-<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>\r
+<extension id="org.eclipse.linuxtools.cdt.autotools.AutotoolsScannerInfoProvider" point="org.eclipse.cdt.core.ScannerInfoProvider"/>\r
+<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
+<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
+<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
 </extensions>\r
 </storageModule>\r
 <storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>\r
-<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>\r
-\r
-\r
 <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>\r
-\r
+<storageModule moduleId="org.eclipse.cdt.core.pathentry">\r
+<pathentry include="C:/Program Files/Microsoft Visual Studio 9.0/VC/include" kind="inc" path="" system="true"/>\r
+<pathentry include="C:/log4shib-1.0.3/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 include="C:/xml-security-c-1.5.1/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
+<pathentry base-path="cpp-sp" include="" kind="inc" path="" system="true"/>\r
+<pathentry kind="mac" name="SHIBSP_API" path="" value=""/>\r
+<pathentry kind="mac" name="WIN32" path="" value=""/>\r
+<pathentry kind="mac" name="_MSC_VER" path="" value=""/>\r
+<pathentry kind="mac" name="SHIBSP_DLLLOCAL" path="" value=""/>\r
+<pathentry kind="mac" name="SHIBSP_LOGCAT" path="" value="&quot;Shibboleth&quot;"/>\r
+<pathentry kind="mac" name="XMLTOOLING_LOG4SHIB" path="" value=""/>\r
+<pathentry kind="out" path=""/>\r
+<pathentry excluding="util/|impl/|security/|metadata/|remoting/|remoting/impl/|attribute/|binding/|binding/impl/|attribute/resolver/|attribute/resolver/impl/|handler/|handler/impl/|attribute/filtering/|attribute/filtering/impl/|lite/" kind="src" path="shibsp"/>\r
+<pathentry excluding="resolver/|resolver/impl/|filtering/|filtering/impl/" kind="src" path="shibsp/attribute"/>\r
+<pathentry excluding="impl/" kind="src" path="shibsp/attribute/filtering"/>\r
+<pathentry kind="src" path="shibsp/attribute/filtering/impl"/>\r
+<pathentry excluding="impl/" kind="src" path="shibsp/attribute/resolver"/>\r
+<pathentry kind="src" path="shibsp/attribute/resolver/impl"/>\r
+<pathentry excluding="impl/" kind="src" path="shibsp/binding"/>\r
+<pathentry kind="src" path="shibsp/binding/impl"/>\r
+<pathentry excluding="impl/" kind="src" path="shibsp/handler"/>\r
+<pathentry kind="src" path="shibsp/handler/impl"/>\r
+<pathentry kind="src" path="shibsp/impl"/>\r
+<pathentry kind="src" path="shibsp/lite"/>\r
+<pathentry kind="src" path="shibsp/metadata"/>\r
+<pathentry excluding="impl/" kind="src" path="shibsp/remoting"/>\r
+<pathentry kind="src" path="shibsp/remoting/impl"/>\r
+<pathentry kind="src" path="shibsp/security"/>\r
+<pathentry kind="src" path="shibsp/util"/>\r
+<pathentry kind="src" path="shibd"/>\r
+<pathentry kind="src" path="apache"/>\r
+<pathentry kind="src" path="isapi_shib"/>\r
+<pathentry kind="src" path="nsapi_shib"/>\r
+<pathentry kind="src" path="odbc-store"/>\r
+<pathentry kind="src" path="memcache-store"/>\r
+<pathentry kind="src" path="util"/>\r
+<pathentry kind="src" path="adfs"/>\r
+<pathentry kind="src" path="fastcgi"/>\r
+<pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>\r
+</storageModule>\r
+<storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
+<configuration artifactName="cpp-sp" buildArtefactType="org.eclipse.linuxtools.cdt.autotools.buildArtefactType.autotools" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.linuxtools.cdt.autotools.buildArtefactType.autotools" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450" name="Build (GNU)" parent="org.eclipse.linuxtools.cdt.autotools.configuration.build">\r
+<folderInfo id="org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450." name="/" resourcePath="">\r
+<toolChain id="org.eclipse.linuxtools.cdt.autotools.toolChain.1841632347" name="GNU Autotools Toolchain" superClass="org.eclipse.linuxtools.cdt.autotools.toolChain">\r
+<targetPlatform id="org.eclipse.linuxtools.cdt.autotools.toolchain.targetPlatform.1692192358" isAbstract="false" name="GNU Autotools Target Platform" superClass="org.eclipse.linuxtools.cdt.autotools.toolchain.targetPlatform"/>\r
+<builder buildPath="${workspace_loc:/cpp-sp/build}" id="org.eclipse.linuxtools.cdt.autotools.toolchain.builder.1116584470" keepEnvironmentInBuildfile="false" name="Autotools Makefile Generator" superClass="org.eclipse.linuxtools.cdt.autotools.toolchain.builder"/>\r
+<tool id="org.eclipse.linuxtools.cdt.autotools.gnu.toolchain.tool.configure.1723135584" name="configure" superClass="org.eclipse.linuxtools.cdt.autotools.gnu.toolchain.tool.configure">\r
+<option id="org.eclipse.linuxtools.cdt.autotools.option.configure.symbols.647371647" name="symbols" superClass="org.eclipse.linuxtools.cdt.autotools.option.configure.symbols" valueType="definedSymbols">\r
+<listOptionValue builtIn="false" value="SHIBSP_API"/>\r
+<listOptionValue builtIn="false" value="SHIBSP_DLLLOCAL"/>\r
+</option>\r
+<option id="org.eclipse.linuxtools.cdt.autotools.option.configure.includes.1925509387" name="includes" superClass="org.eclipse.linuxtools.cdt.autotools.option.configure.includes" valueType="includePath">\r
+<listOptionValue builtIn="false" value="&quot;${workspace_loc:/cpp-xmltooling}&quot;"/>\r
+<listOptionValue builtIn="false" value="&quot;${workspace_loc:/cpp-opensaml2}&quot;"/>\r
+<listOptionValue builtIn="false" value="&quot;C:\log4shib-1.0.3\include&quot;"/>\r
+<listOptionValue builtIn="false" value="&quot;C:\xerces-c-3.0.1-x86-windows-vc-9.0\include&quot;"/>\r
+<listOptionValue builtIn="false" value="&quot;C:\xml-security-c-1.5.1\include&quot;"/>\r
+</option>\r
+<inputType id="org.eclipse.linuxtools.cdt.autotools.inputType.configure.1698708407" superClass="org.eclipse.linuxtools.cdt.autotools.inputType.configure"/>\r
+<inputType id="org.eclipse.linuxtools.cdt.autotools.inputType.configure1.2095849049" superClass="org.eclipse.linuxtools.cdt.autotools.inputType.configure1"/>\r
+</tool>\r
+<tool id="org.eclipse.linuxtools.cdt.autotools.toolchain.tool.autogen.782580356" name="autogen.sh" superClass="org.eclipse.linuxtools.cdt.autotools.toolchain.tool.autogen"/>\r
+</toolChain>\r
+</folderInfo>\r
+<fileInfo id="org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450.560277989" name="LOG4CPP.LICENSE" rcbsApplicability="disable" resourcePath="doc/LOG4CPP.LICENSE" toolsToInvoke=""/>\r
+<sourceEntries>\r
+<entry excluding="fastcgi|isapi_shib|memcache-store|nsapi_shib|odbc-store|shibd|shibsp|util|apache|adfs|Debug/|Release/|x64/" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="adfs"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="apache"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="fastcgi"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="isapi_shib"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="memcache-store"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="nsapi_shib"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="odbc-store"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="shibd"/>\r
+<entry excluding="Debug/|Release/|shibsp-lite-Debug/|shibsp-lite-Release/|x64/" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="shibsp"/>\r
+<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="util"/>\r
+</sourceEntries>\r
+</configuration>\r
+</storageModule>\r
 <storageModule moduleId="scannerConfiguration">\r
 <autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>\r
 <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">\r
 <parser enabled="true"/>\r
 </scannerInfoProvider>\r
 </profile>\r
+<scannerConfigBuildInfo instanceId="org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450;org.eclipse.linuxtools.cdt.autotools.configuration.build.951860450.">\r
+<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"/>\r
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="makefileGenerator">\r
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+</scannerConfigBuildInfo>\r
 </storageModule>\r
-<storageModule moduleId="org.eclipse.cdt.core.pathentry">\r
-<pathentry include="C:/Program Files/Microsoft Visual Studio 9.0/VC/include" kind="inc" path="" system="true"/>\r
-<pathentry include="C:/log4shib-1.0.3/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 include="C:/xml-security-c-1.5.1/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
-<pathentry base-path="cpp-sp" include="" kind="inc" path="" system="true"/>\r
-<pathentry kind="mac" name="SHIBSP_API" path="" value=""/>\r
-<pathentry kind="mac" name="WIN32" path="" value=""/>\r
-<pathentry kind="mac" name="_MSC_VER" path="" value=""/>\r
-<pathentry kind="mac" name="SHIBSP_DLLLOCAL" path="" value=""/>\r
-<pathentry kind="mac" name="SHIBSP_LOGCAT" path="" value="&quot;Shibboleth&quot;"/>\r
-<pathentry kind="mac" name="XMLTOOLING_LOG4SHIB" path="" value=""/>\r
-<pathentry kind="out" path=""/>\r
-<pathentry excluding="util/|impl/|security/|metadata/|remoting/|remoting/impl/|attribute/|binding/|binding/impl/|attribute/resolver/|attribute/resolver/impl/|handler/|handler/impl/|attribute/filtering/|attribute/filtering/impl/|lite/" kind="src" path="shibsp"/>\r
-<pathentry excluding="resolver/|resolver/impl/|filtering/|filtering/impl/" kind="src" path="shibsp/attribute"/>\r
-<pathentry excluding="impl/" kind="src" path="shibsp/attribute/filtering"/>\r
-<pathentry kind="src" path="shibsp/attribute/filtering/impl"/>\r
-<pathentry excluding="impl/" kind="src" path="shibsp/attribute/resolver"/>\r
-<pathentry kind="src" path="shibsp/attribute/resolver/impl"/>\r
-<pathentry excluding="impl/" kind="src" path="shibsp/binding"/>\r
-<pathentry kind="src" path="shibsp/binding/impl"/>\r
-<pathentry excluding="impl/" kind="src" path="shibsp/handler"/>\r
-<pathentry kind="src" path="shibsp/handler/impl"/>\r
-<pathentry kind="src" path="shibsp/impl"/>\r
-<pathentry kind="src" path="shibsp/lite"/>\r
-<pathentry kind="src" path="shibsp/metadata"/>\r
-<pathentry excluding="impl/" kind="src" path="shibsp/remoting"/>\r
-<pathentry kind="src" path="shibsp/remoting/impl"/>\r
-<pathentry kind="src" path="shibsp/security"/>\r
-<pathentry kind="src" path="shibsp/util"/>\r
-<pathentry kind="src" path="shibd"/>\r
-<pathentry kind="src" path="apache"/>\r
-<pathentry kind="src" path="isapi_shib"/>\r
-<pathentry kind="src" path="nsapi_shib"/>\r
-<pathentry kind="src" path="odbc-store"/>\r
-<pathentry kind="src" path="memcache-store"/>\r
-<pathentry kind="src" path="util"/>\r
-<pathentry kind="src" path="adfs"/>\r
-<pathentry kind="src" path="fastcgi"/>\r
-<pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>\r
+<storageModule moduleId="org.eclipse.cdt.core.externalSettings">\r
+<externalSettings containerId="cpp-opensaml2;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"/>\r
+<externalSettings containerId="cpp-xmltooling;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"/>\r
 </storageModule>\r
 </cconfiguration>\r
 </storageModule>\r
+<storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
+<project id="cpp-sp.org.eclipse.linuxtools.cdt.autotools.projectType.1209493510" name="GNU Autotools" projectType="org.eclipse.linuxtools.cdt.autotools.projectType"/>\r
+</storageModule>\r
 </cproject>\r
index 4dea911..0579a7a 100644 (file)
--- a/.project
+++ b/.project
        <name>cpp-sp</name>
        <comment></comment>
        <projects>
+               <project>cpp-opensaml2</project>
+               <project>cpp-xmltooling</project>
        </projects>
        <buildSpec>
                <buildCommand>
-                       <name>org.eclipse.cdt.make.core.makeBuilder</name>
-                       <triggers></triggers>
+                       <name>org.eclipse.linuxtools.cdt.autotools.genmakebuilder</name>
                        <arguments>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.core.errorOutputParser</key>
-                                       <value>org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.VCErrorParser;</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.append_environment</key>
-                                       <value>true</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.autoBuildTarget</key>
-                                       <value>all</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.build.arguments</key>
-                                       <value></value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.build.command</key>
-                                       <value>nmake</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.build.location</key>
-                                       <value></value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.build.target.auto</key>
-                                       <value>all</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.build.target.clean</key>
-                                       <value></value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.build.target.inc</key>
-                                       <value>all</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.buildArguments</key>
-                                       <value></value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.buildCommand</key>
-                                       <value>nmake</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.buildLocation</key>
-                                       <value></value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
-                                       <value>false</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
-                                       <value>false</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.enableFullBuild</key>
-                                       <value>false</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>
-                                       <value>false</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.environment</key>
-                                       <value></value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.fullBuildTarget</key>
-                                       <value>clean all</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.incrementalBuildTarget</key>
-                                       <value>all</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.stopOnError</key>
-                                       <value>false</value>
-                               </dictionary>
-                               <dictionary>
-                                       <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
-                                       <value>false</value>
-                               </dictionary>
                        </arguments>
                </buildCommand>
                <buildCommand>
-                       <name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>
+                       <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
        </buildSpec>
        <natures>
                <nature>org.eclipse.cdt.core.cnature</nature>
-               <nature>org.eclipse.cdt.make.core.makeNature</nature>
                <nature>org.eclipse.cdt.core.ccnature</nature>
-               <nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+               <nature>org.eclipse.linuxtools.cdt.autotools.autotoolsNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
        </natures>
 </projectDescription>
index 82913b5..196504b 100644 (file)
@@ -1,25 +1,25 @@
-AUTOMAKE_OPTIONS = foreign\r
-\r
-plugindir = $(libdir)/@PACKAGE@\r
-plugin_LTLIBRARIES = adfs.la adfs-lite.la\r
-\r
-adfs_la_LIBADD = \\r
-       $(top_builddir)/shibsp/libshibsp.la\r
-\r
-adfs_la_SOURCES = \\r
-       adfs.cpp\r
-\r
-adfs_lite_la_LIBADD = \\r
-       $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-adfs_lite_la_SOURCES = \\r
-       adfs.cpp\r
-\r
-adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)\r
-adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS)\r
-adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE\r
-\r
-install-exec-hook:\r
-       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done\r
-\r
-EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc\r
+AUTOMAKE_OPTIONS = foreign
+
+plugindir = $(libdir)/@PACKAGE@
+plugin_LTLIBRARIES = adfs.la adfs-lite.la
+
+adfs_la_LIBADD = \
+       $(top_builddir)/shibsp/libshibsp.la
+
+adfs_la_SOURCES = \
+       adfs.cpp
+
+adfs_lite_la_LIBADD = \
+       $(top_builddir)/shibsp/libshibsp-lite.la
+
+adfs_lite_la_SOURCES = \
+       adfs.cpp
+
+adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)
+adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS)
+adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE
+
+install-exec-hook:
+       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done
+
+EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc
index 95f2c63..3ba1cce 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by adfs.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1000\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by adfs.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
old mode 100755 (executable)
new mode 100644 (file)
index 6443108..e21e018 100644 (file)
@@ -1,4 +1,4 @@
-Version 2.2.1
+Version 2.3
 
 Welcome to Internet2's Shibboleth
 
index 66ee2a7..51a97cc 100644 (file)
@@ -1,14 +1,14 @@
 Release Notes
 
 Shibboleth Native SP
-2.2.1
+2.3
 
 NOTE: The shibboleth2.xml configuration format in this release
 is fully compatible with the 2.1 release, but there are some small
 changes required to eliminate various warnings about deprecated options.
 
 List of issues addressed by this release:
-https://bugs.internet2.edu/jira/secure/IssueNavigator.jspa?reset=true&&pid=10011&fixfor=10232&status=5&status=6&sorter/field=issuekey&sorter/order=ASC
+https://bugs.internet2.edu/jira/browse/SSPCPP/fixforversion/10261
 
 Fully Supported
 
index f0bec65..1c4ba8c 100644 (file)
@@ -1,30 +1,30 @@
-AUTOMAKE_OPTIONS = foreign\r
-\r
-if BUILD_FASTCGI\r
-\r
-fastcgidir = $(libdir)/@PACKAGE@\r
-\r
-fastcgi_PROGRAMS = shibauthorizer shibresponder\r
-\r
-shibauthorizer_SOURCES = shibauthorizer.cpp\r
-shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE)\r
-shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)\r
-shibauthorizer_LDADD = \\r
-  $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-shibresponder_SOURCES = shibresponder.cpp\r
-shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE)\r
-shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)\r
-shibresponder_LDADD = \\r
-  $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-endif\r
-\r
-EXTRA_DIST = \\r
-    shibauthorizer.cpp \\r
-    shibauthorizer.vcproj \\r
-    shibauthorizer.rc \\r
-    shibresponder.cpp \\r
-    shibresponder.vcproj \\r
-    shibresponder.rc \\r
-    resource.h\r
+AUTOMAKE_OPTIONS = foreign
+
+if BUILD_FASTCGI
+
+fastcgidir = $(libdir)/@PACKAGE@
+
+fastcgi_PROGRAMS = shibauthorizer shibresponder
+
+shibauthorizer_SOURCES = shibauthorizer.cpp
+shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE)
+shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)
+shibauthorizer_LDADD = \
+  $(top_builddir)/shibsp/libshibsp-lite.la
+
+shibresponder_SOURCES = shibresponder.cpp
+shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE)
+shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)
+shibresponder_LDADD = \
+  $(top_builddir)/shibsp/libshibsp-lite.la
+
+endif
+
+EXTRA_DIST = \
+    shibauthorizer.cpp \
+    shibauthorizer.vcproj \
+    shibauthorizer.rc \
+    shibresponder.cpp \
+    shibresponder.vcproj \
+    shibresponder.rc \
+    resource.h
index 55162af..f3772c1 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by isapi_shib.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1000\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by isapi_shib.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
index 4d9a4e5..26eb501 100644 (file)
-/*\r
- *  Copyright 2001-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
-/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer\r
-\r
-   Andre Cruz\r
-*/\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _SCL_SECURE_NO_WARNINGS 1\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <stdexcept>\r
-#include <stdlib.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-# include <sys/mman.h>\r
-#endif\r
-#include <fcgio.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);\r
-static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-\r
-typedef enum {\r
-    SHIB_RETURN_OK,\r
-    SHIB_RETURN_KO,\r
-    SHIB_RETURN_DONE\r
-} shib_return_t;\r
-\r
-class ShibTargetFCGIAuth : public AbstractSPRequest\r
-{\r
-    FCGX_Request* m_req;\r
-    int m_port;\r
-    string m_scheme,m_hostname;\r
-    multimap<string,string> m_response_headers;\r
-public:\r
-    map<string,string> m_request_headers;\r
-\r
-    ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
-            : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {\r
-        const char* server_name_str = hostname;\r
-        if (!server_name_str || !*server_name_str)\r
-            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
-        m_hostname = server_name_str;\r
-\r
-        m_port = port;\r
-        if (!m_port) {\r
-            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);\r
-            m_port = strtol(server_port_str, &server_port_str, 10);\r
-            if (*server_port_str) {\r
-                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
-                throw runtime_error("Unable to determine server port.");\r
-            }\r
-        }\r
-\r
-        const char* server_scheme_str = scheme;\r
-        if (!server_scheme_str || !*server_scheme_str)\r
-            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
-        m_scheme = server_scheme_str;\r
-\r
-        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
-    }\r
-\r
-    ~ShibTargetFCGIAuth() { }\r
-\r
-    const char* getScheme() const {\r
-        return m_scheme.c_str();\r
-    }\r
-    const char* getHostname() const {\r
-        return m_hostname.c_str();\r
-    }\r
-    int getPort() const {\r
-        return m_port;\r
-    }\r
-    const char* getMethod() const {\r
-        return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
-    }\r
-    string getContentType() const {\r
-        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    long getContentLength() const {\r
-        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);\r
-        return s ? atol(s) : 0;\r
-    }\r
-    string getRemoteAddr() const {\r
-        string ret = AbstractSPRequest::getRemoteAddr();\r
-        if (!ret.empty())\r
-            return ret;\r
-        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    void log(SPLogLevel level, const string& msg) const {\r
-        AbstractSPRequest::log(level,msg);\r
-        if (level >= SPError)\r
-            cerr << "shib: " << msg;\r
-    }\r
-    void clearHeader(const char* rawname, const char* cginame) {\r
-        // No need, since we use environment variables.\r
-    }\r
-    void setHeader(const char* name, const char* value) {\r
-        if (value)\r
-            m_request_headers[name] = value;\r
-        else\r
-            m_request_headers.erase(name);\r
-    }\r
-    string getHeader(const char* name) const {\r
-        // Look in the local map first.\r
-        map<string,string>::const_iterator i = m_request_headers.find(name);\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        // Nothing set locally and this isn't a "secure" call, so check the request.\r
-        string hdr("HTTP_");\r
-        for (; *name; ++name) {\r
-            if (*name=='-')\r
-                hdr += '_';\r
-            else\r
-                hdr += toupper(*name);\r
-        }\r
-        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    string getSecureHeader(const char* name) const {\r
-        // Look in the local map only.\r
-        map<string,string>::const_iterator i = m_request_headers.find(name);\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        return "";\r
-    }\r
-    void setRemoteUser(const char* user) {\r
-        if (user)\r
-            m_request_headers["REMOTE_USER"] = user;\r
-        else\r
-            m_request_headers.erase("REMOTE_USER");\r
-    }\r
-    string getRemoteUser() const {\r
-        map<string,string>::const_iterator i = m_request_headers.find("REMOTE_USER");\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        else {\r
-            char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp);\r
-            if (remote_user)\r
-                return remote_user;\r
-        }\r
-        return "";\r
-    }\r
-    void setAuthType(const char* authtype) {\r
-        if (authtype)\r
-            m_request_headers["AUTH_TYPE"] = authtype;\r
-        else\r
-            m_request_headers.erase("AUTH_TYPE");\r
-    }\r
-    string getAuthType() const {\r
-        map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        else {\r
-            char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);\r
-            if (auth_type)\r
-                return auth_type;\r
-        }\r
-        return "";\r
-    }\r
-    void setResponseHeader(const char* name, const char* value) {\r
-        AbstractSPRequest::setResponseHeader(name, value);\r
-        // Set for later.\r
-        if (value)\r
-            m_response_headers.insert(make_pair(name,value));\r
-        else\r
-            m_response_headers.erase(name);\r
-    }\r
-    const char* getQueryString() const {\r
-        return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
-    }\r
-    const char* getRequestBody() const {\r
-        throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");\r
-    }\r
-\r
-    long sendResponse(istream& in, long status) {\r
-        string hdr = string("Connection: close\r\n");\r
-        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-\r
-        // We can't return 200 OK here or else the filter is bypassed\r
-        // so custom Shib errors will get turned into a generic page.\r
-        const char* codestr="Status: 500 Server Error";\r
-        switch (status) {\r
-            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;\r
-            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;\r
-            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;\r
-        }\r
-        cout << codestr << "\r\n" << hdr << "\r\n";\r
-        char buf[1024];\r
-        while (in) {\r
-            in.read(buf,1024);\r
-            cout.write(buf, in.gcount());\r
-        }\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long sendRedirect(const char* url) {\r
-        AbstractSPRequest::sendRedirect(url);\r
-        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
-          "Content-Type: text/html\r\n"\r
-          "Content-Length: 40\r\n"\r
-          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
-          "Cache-Control: private,no-store,no-cache\r\n";\r
-        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-        hdr += "\r\n";\r
-\r
-        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long returnDecline() {\r
-        return SHIB_RETURN_KO;\r
-    }\r
-\r
-    long returnOK() {\r
-        return SHIB_RETURN_OK;\r
-    }\r
-\r
-    const vector<string>& getClientCertificates() const {\r
-        static vector<string> g_NoCerts;\r
-        return g_NoCerts;\r
-    }\r
-};\r
-\r
-static void print_ok(const map<string,string>& headers)\r
-{\r
-    cout << "Status: 200 OK" << "\r\n";\r
-    for (map<string,string>::const_iterator iter = headers.begin(); iter != headers.end(); iter++) {\r
-        cout << "Variable-" << iter->first << ": " << iter->second << "\r\n";\r
-    }\r
-    cout << "\r\n";\r
-}\r
-\r
-static void print_error(const char* msg)\r
-{\r
-    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;\r
-}\r
-\r
-int main(void)\r
-{\r
-    SPConfig* g_Config=&SPConfig::getConfig();\r
-    g_Config->setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::RequestMapping |\r
-        SPConfig::InProcess |\r
-        SPConfig::Logging |\r
-        SPConfig::Handlers\r
-        );\r
-    if (!g_Config->init()) {\r
-        cerr << "failed to initialize Shibboleth libraries" << endl;\r
-        exit(1);\r
-    }\r
-\r
-    try {\r
-        if (!g_Config->instantiate(NULL, true))\r
-            throw runtime_error("unknown error");\r
-    }\r
-    catch (exception& ex) {\r
-        g_Config->term();\r
-        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;\r
-        exit(1);\r
-    }\r
-\r
-    string g_ServerScheme;\r
-    string g_ServerName;\r
-    int g_ServerPort=0;\r
-\r
-    // Load "authoritative" URL fields.\r
-    char* var = getenv("SHIBSP_SERVER_NAME");\r
-    if (var)\r
-        g_ServerName = var;\r
-    var = getenv("SHIBSP_SERVER_SCHEME");\r
-    if (var)\r
-        g_ServerScheme = var;\r
-    var = getenv("SHIBSP_SERVER_PORT");\r
-    if (var)\r
-        g_ServerPort = atoi(var);\r
-\r
-    streambuf* cout_streambuf = cout.rdbuf();\r
-    streambuf* cerr_streambuf = cerr.rdbuf();\r
-\r
-    FCGX_Request request;\r
-\r
-    FCGX_Init();\r
-    FCGX_InitRequest(&request, 0, 0);\r
-\r
-    cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
-    while (FCGX_Accept_r(&request) == 0)\r
-    {\r
-        // Note that the default bufsize (0) will cause the use of iostream\r
-        // methods that require positioning (such as peek(), seek(),\r
-        // unget() and putback()) to fail (in favour of more efficient IO).\r
-        fcgi_streambuf cout_fcgi_streambuf(request.out);\r
-        fcgi_streambuf cerr_fcgi_streambuf(request.err);\r
-\r
-        cout.rdbuf(&cout_fcgi_streambuf);\r
-        cerr.rdbuf(&cerr_fcgi_streambuf);\r
-\r
-        try {\r
-            xmltooling::NDC ndc("FastCGI shibauthorizer");\r
-            ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-\r
-            pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);\r
-            if (res.first) {\r
-                sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        continue;\r
-\r
-                    default:\r
-                        cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
-                        continue;\r
-                }\r
-            }\r
-\r
-            res = sta.getServiceProvider().doExport(sta);\r
-            if (res.first) {\r
-                sta.log(SPRequest::SPDebug, "shib: doExport handled request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        continue;\r
-\r
-                    default:\r
-                        cerr << "shib: doExport returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
-                        continue;\r
-                }\r
-            }\r
-\r
-            res = sta.getServiceProvider().doAuthorization(sta);\r
-            if (res.first) {\r
-                sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        continue;\r
-\r
-                    default:\r
-                        cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
-                        continue;\r
-                }\r
-            }\r
-\r
-            print_ok(sta.m_request_headers);\r
-\r
-        }\r
-        catch (exception& e) {\r
-            cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;\r
-            print_error("<html><body>FastCGI Shibboleth authorizer caught an exception, check log for details.</body></html>");\r
-        }\r
-\r
-        // If the output streambufs had non-zero bufsizes and\r
-        // were constructed outside of the accept loop (i.e.\r
-        // their destructor won't be called here), they would\r
-        // have to be flushed here.\r
-    }\r
-    cout << "Request loop ended." << endl;\r
-\r
-    cout.rdbuf(cout_streambuf);\r
-    cerr.rdbuf(cerr_streambuf);\r
-\r
-    if (g_Config)\r
-        g_Config->term();\r
-\r
-    return 0;\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer
+
+   Andre Cruz
+*/
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _SCL_SECURE_NO_WARNINGS 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <stdexcept>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+#include <fcgio.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);
+static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+
+typedef enum {
+    SHIB_RETURN_OK,
+    SHIB_RETURN_KO,
+    SHIB_RETURN_DONE
+} shib_return_t;
+
+class ShibTargetFCGIAuth : public AbstractSPRequest
+{
+    FCGX_Request* m_req;
+    int m_port;
+    string m_scheme,m_hostname;
+    multimap<string,string> m_response_headers;
+public:
+    map<string,string> m_request_headers;
+
+    ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)
+            : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {
+        const char* server_name_str = hostname;
+        if (!server_name_str || !*server_name_str)
+            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);
+        m_hostname = server_name_str;
+
+        m_port = port;
+        if (!m_port) {
+            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);
+            m_port = strtol(server_port_str, &server_port_str, 10);
+            if (*server_port_str) {
+                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;
+                throw runtime_error("Unable to determine server port.");
+            }
+        }
+
+        const char* server_scheme_str = scheme;
+        if (!server_scheme_str || !*server_scheme_str)
+            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";
+        m_scheme = server_scheme_str;
+
+        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));
+    }
+
+    ~ShibTargetFCGIAuth() { }
+
+    const char* getScheme() const {
+        return m_scheme.c_str();
+    }
+    const char* getHostname() const {
+        return m_hostname.c_str();
+    }
+    int getPort() const {
+        return m_port;
+    }
+    const char* getMethod() const {
+        return FCGX_GetParam("REQUEST_METHOD", m_req->envp);
+    }
+    string getContentType() const {
+        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);
+        return s ? s : "";
+    }
+    long getContentLength() const {
+        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);
+        return s ? atol(s) : 0;
+    }
+    string getRemoteAddr() const {
+        string ret = AbstractSPRequest::getRemoteAddr();
+        if (!ret.empty())
+            return ret;
+        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
+        return s ? s : "";
+    }
+    void log(SPLogLevel level, const string& msg) const {
+        AbstractSPRequest::log(level,msg);
+        if (level >= SPError)
+            cerr << "shib: " << msg;
+    }
+    void clearHeader(const char* rawname, const char* cginame) {
+        // No need, since we use environment variables.
+    }
+    void setHeader(const char* name, const char* value) {
+        if (value)
+            m_request_headers[name] = value;
+        else
+            m_request_headers.erase(name);
+    }
+    string getHeader(const char* name) const {
+        // Look in the local map first.
+        map<string,string>::const_iterator i = m_request_headers.find(name);
+        if (i != m_request_headers.end())
+            return i->second;
+        // Nothing set locally and this isn't a "secure" call, so check the request.
+        string hdr("HTTP_");
+        for (; *name; ++name) {
+            if (*name=='-')
+                hdr += '_';
+            else
+                hdr += toupper(*name);
+        }
+        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);
+        return s ? s : "";
+    }
+    string getSecureHeader(const char* name) const {
+        // Look in the local map only.
+        map<string,string>::const_iterator i = m_request_headers.find(name);
+        if (i != m_request_headers.end())
+            return i->second;
+        return "";
+    }
+    void setRemoteUser(const char* user) {
+        if (user)
+            m_request_headers["REMOTE_USER"] = user;
+        else
+            m_request_headers.erase("REMOTE_USER");
+    }
+    string getRemoteUser() const {
+        map<string,string>::const_iterator i = m_request_headers.find("REMOTE_USER");
+        if (i != m_request_headers.end())
+            return i->second;
+        else {
+            char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp);
+            if (remote_user)
+                return remote_user;
+        }
+        return "";
+    }
+    void setAuthType(const char* authtype) {
+        if (authtype)
+            m_request_headers["AUTH_TYPE"] = authtype;
+        else
+            m_request_headers.erase("AUTH_TYPE");
+    }
+    string getAuthType() const {
+        map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");
+        if (i != m_request_headers.end())
+            return i->second;
+        else {
+            char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);
+            if (auth_type)
+                return auth_type;
+        }
+        return "";
+    }
+    void setResponseHeader(const char* name, const char* value) {
+        AbstractSPRequest::setResponseHeader(name, value);
+        // Set for later.
+        if (value)
+            m_response_headers.insert(make_pair(name,value));
+        else
+            m_response_headers.erase(name);
+    }
+    const char* getQueryString() const {
+        return FCGX_GetParam("QUERY_STRING", m_req->envp);
+    }
+    const char* getRequestBody() const {
+        throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");
+    }
+
+    long sendResponse(istream& in, long status) {
+        string hdr = string("Connection: close\r\n");
+        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)
+            hdr += i->first + ": " + i->second + "\r\n";
+
+        // We can't return 200 OK here or else the filter is bypassed
+        // so custom Shib errors will get turned into a generic page.
+        const char* codestr="Status: 500 Server Error";
+        switch (status) {
+            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;
+            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;
+            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;
+        }
+        cout << codestr << "\r\n" << hdr << "\r\n";
+        char buf[1024];
+        while (in) {
+            in.read(buf,1024);
+            cout.write(buf, in.gcount());
+        }
+        return SHIB_RETURN_DONE;
+    }
+
+    long sendRedirect(const char* url) {
+        AbstractSPRequest::sendRedirect(url);
+        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
+          "Content-Type: text/html\r\n"
+          "Content-Length: 40\r\n"
+          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+          "Cache-Control: private,no-store,no-cache\r\n";
+        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)
+            hdr += i->first + ": " + i->second + "\r\n";
+        hdr += "\r\n";
+
+        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";
+        return SHIB_RETURN_DONE;
+    }
+
+    long returnDecline() {
+        return SHIB_RETURN_KO;
+    }
+
+    long returnOK() {
+        return SHIB_RETURN_OK;
+    }
+
+    const vector<string>& getClientCertificates() const {
+        static vector<string> g_NoCerts;
+        return g_NoCerts;
+    }
+};
+
+static void print_ok(const map<string,string>& headers)
+{
+    cout << "Status: 200 OK" << "\r\n";
+    for (map<string,string>::const_iterator iter = headers.begin(); iter != headers.end(); iter++) {
+        cout << "Variable-" << iter->first << ": " << iter->second << "\r\n";
+    }
+    cout << "\r\n";
+}
+
+static void print_error(const char* msg)
+{
+    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;
+}
+
+int main(void)
+{
+    SPConfig* g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging |
+        SPConfig::Handlers
+        );
+    if (!g_Config->init()) {
+        cerr << "failed to initialize Shibboleth libraries" << endl;
+        exit(1);
+    }
+
+    try {
+        if (!g_Config->instantiate(NULL, true))
+            throw runtime_error("unknown error");
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;
+        exit(1);
+    }
+
+    string g_ServerScheme;
+    string g_ServerName;
+    int g_ServerPort=0;
+
+    // Load "authoritative" URL fields.
+    char* var = getenv("SHIBSP_SERVER_NAME");
+    if (var)
+        g_ServerName = var;
+    var = getenv("SHIBSP_SERVER_SCHEME");
+    if (var)
+        g_ServerScheme = var;
+    var = getenv("SHIBSP_SERVER_PORT");
+    if (var)
+        g_ServerPort = atoi(var);
+
+    streambuf* cout_streambuf = cout.rdbuf();
+    streambuf* cerr_streambuf = cerr.rdbuf();
+
+    FCGX_Request request;
+
+    FCGX_Init();
+    FCGX_InitRequest(&request, 0, 0);
+
+    cout << "Shibboleth initialization complete. Starting request loop." << endl;
+    while (FCGX_Accept_r(&request) == 0)
+    {
+        // Note that the default bufsize (0) will cause the use of iostream
+        // methods that require positioning (such as peek(), seek(),
+        // unget() and putback()) to fail (in favour of more efficient IO).
+        fcgi_streambuf cout_fcgi_streambuf(request.out);
+        fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+        cout.rdbuf(&cout_fcgi_streambuf);
+        cerr.rdbuf(&cerr_fcgi_streambuf);
+
+        try {
+            xmltooling::NDC ndc("FastCGI shibauthorizer");
+            ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);
+
+            pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);
+            if (res.first) {
+                sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_KO:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_DONE:
+                        continue;
+
+                    default:
+                        cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+                        continue;
+                }
+            }
+
+            res = sta.getServiceProvider().doExport(sta);
+            if (res.first) {
+                sta.log(SPRequest::SPDebug, "shib: doExport handled request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_KO:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_DONE:
+                        continue;
+
+                    default:
+                        cerr << "shib: doExport returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+                        continue;
+                }
+            }
+
+            res = sta.getServiceProvider().doAuthorization(sta);
+            if (res.first) {
+                sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_KO:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_DONE:
+                        continue;
+
+                    default:
+                        cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+                        continue;
+                }
+            }
+
+            print_ok(sta.m_request_headers);
+
+        }
+        catch (exception& e) {
+            cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;
+            print_error("<html><body>FastCGI Shibboleth authorizer caught an exception, check log for details.</body></html>");
+        }
+
+        // If the output streambufs had non-zero bufsizes and
+        // were constructed outside of the accept loop (i.e.
+        // their destructor won't be called here), they would
+        // have to be flushed here.
+    }
+    cout << "Request loop ended." << endl;
+
+    cout.rdbuf(cout_streambuf);
+    cerr.rdbuf(cerr_streambuf);
+
+    if (g_Config)
+        g_Config->term();
+
+    return 0;
+}
index 78a3c9d..3c76ff7 100644 (file)
-/*\r
- *  Copyright 2001-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
-/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler\r
-\r
-   Andre Cruz\r
-*/\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _SCL_SECURE_NO_WARNINGS 1\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <stdexcept>\r
-#include <stdlib.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-# include <sys/mman.h>\r
-#endif\r
-#include <fcgio.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);\r
-static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-\r
-typedef enum {\r
-    SHIB_RETURN_OK,\r
-    SHIB_RETURN_KO,\r
-    SHIB_RETURN_DONE\r
-} shib_return_t;\r
-\r
-class ShibTargetFCGI : public AbstractSPRequest\r
-{\r
-    FCGX_Request* m_req;\r
-    const char* m_body;\r
-    multimap<string,string> m_headers;\r
-    int m_port;\r
-    string m_scheme,m_hostname;\r
-\r
-public:\r
-    ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
-        : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) {\r
-\r
-        const char* server_name_str = hostname;\r
-        if (!server_name_str || !*server_name_str)\r
-            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
-        m_hostname = server_name_str;\r
-\r
-        m_port = port;\r
-        if (!m_port) {\r
-            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);\r
-            m_port = strtol(server_port_str, &server_port_str, 10);\r
-            if (*server_port_str) {\r
-                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
-                throw runtime_error("Unable to determine server port.");\r
-            }\r
-        }\r
-\r
-        const char* server_scheme_str = scheme;\r
-        if (!server_scheme_str || !*server_scheme_str)\r
-            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
-        m_scheme = server_scheme_str;\r
-\r
-        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
-    }\r
-\r
-    ~ShibTargetFCGI() { }\r
-\r
-    const char* getScheme() const {\r
-        return m_scheme.c_str();\r
-    }\r
-    const char* getHostname() const {\r
-        return m_hostname.c_str();\r
-    }\r
-    int getPort() const {\r
-        return m_port;\r
-    }\r
-    const char* getMethod() const {\r
-        return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
-    }\r
-    string getContentType() const {\r
-        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    long getContentLength() const {\r
-        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);\r
-        return s ? atol(s) : 0;\r
-    }\r
-    string getRemoteUser() const {\r
-        const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    string getRemoteAddr() const {\r
-        string ret = AbstractSPRequest::getRemoteAddr();\r
-        if (!ret.empty())\r
-            return ret;\r
-        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    void log(SPLogLevel level, const string& msg) const {\r
-        AbstractSPRequest::log(level,msg);\r
-        if (level >= SPError)\r
-            cerr << "shib: " << msg;\r
-    }\r
-\r
-    string getHeader(const char* name) const {\r
-        string hdr("HTTP_");\r
-        for (; *name; ++name) {\r
-            if (*name=='-')\r
-                hdr += '_';\r
-            else\r
-                hdr += toupper(*name);\r
-        }\r
-        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-\r
-    void setResponseHeader(const char* name, const char* value) {\r
-        AbstractSPRequest::setResponseHeader(name, value);\r
-        // Set for later.\r
-        if (value)\r
-            m_headers.insert(make_pair(name,value));\r
-        else\r
-            m_headers.erase(name);\r
-    }\r
-\r
-    const char* getQueryString() const {\r
-        return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
-    }\r
-\r
-    const char* getRequestBody() const {\r
-        return m_body;\r
-    }\r
-\r
-    long sendResponse(istream& in, long status) {\r
-        string hdr = string("Connection: close\r\n");\r
-        for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-\r
-        const char* codestr="Status: 200 OK";\r
-        switch (status) {\r
-            case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="Status: 500 Server Error"; break;\r
-            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;\r
-            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;\r
-            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;\r
-        }\r
-        cout << codestr << "\r\n" << hdr << "\r\n";\r
-        char buf[1024];\r
-        while (in) {\r
-            in.read(buf,1024);\r
-            cout.write(buf, in.gcount());\r
-        }\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long sendRedirect(const char* url) {\r
-        AbstractSPRequest::sendRedirect(url);\r
-        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
-          "Content-Type: text/html\r\n"\r
-          "Content-Length: 40\r\n"\r
-          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
-          "Cache-Control: private,no-store,no-cache\r\n";\r
-        for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-        hdr += "\r\n";\r
-\r
-        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long returnDecline() {\r
-        return SHIB_RETURN_KO;\r
-    }\r
-    long returnOK() {\r
-        return SHIB_RETURN_OK;\r
-    }\r
-\r
-    const vector<string>& getClientCertificates() const {\r
-        static vector<string> g_NoCerts;\r
-        return g_NoCerts;\r
-    }\r
-\r
-    // Not used in the extension.\r
-\r
-    virtual void clearHeader(const char* rawname, const char* cginame) {\r
-        throw runtime_error("clearHeader not implemented by FastCGI responder.");\r
-    }\r
-\r
-    virtual void setHeader(const char* name, const char* value) {\r
-        throw runtime_error("setHeader not implemented by FastCGI responder.");\r
-    }\r
-\r
-    virtual void setRemoteUser(const char* user) {\r
-        throw runtime_error("setRemoteUser not implemented by FastCGI responder.");\r
-    }\r
-};\r
-\r
-// Maximum number of bytes allowed to be read from stdin\r
-static const unsigned long STDIN_MAX = 1000000;\r
-\r
-static long gstdin(FCGX_Request* request, char** content)\r
-{\r
-    char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);\r
-    unsigned long clen = STDIN_MAX;\r
-\r
-    if (clenstr) {\r
-        clen = strtol(clenstr, &clenstr, 10);\r
-        if (*clenstr) {\r
-            cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl;\r
-            clen = STDIN_MAX;\r
-        }\r
-\r
-        // *always* put a cap on the amount of data that will be read\r
-        if (clen > STDIN_MAX)\r
-            clen = STDIN_MAX;\r
-\r
-        *content = new char[clen];\r
-\r
-        cin.read(*content, clen);\r
-        clen = cin.gcount();\r
-    }\r
-    else {\r
-        // *never* read stdin when CONTENT_LENGTH is missing or unparsable\r
-        *content = 0;\r
-        clen = 0;\r
-    }\r
-\r
-    // Chew up any remaining stdin - this shouldn't be necessary\r
-    // but is because mod_fastcgi doesn't handle it correctly.\r
-\r
-    // ignore() doesn't set the eof bit in some versions of glibc++\r
-    // so use gcount() instead of eof()...\r
-    do cin.ignore(1024); while (cin.gcount() == 1024);\r
-\r
-    return clen;\r
-}\r
-\r
-static void print_ok() {\r
-    cout << "Status: 200 OK" << "\r\n\r\n";\r
-}\r
-\r
-static void print_error(const char* msg) {\r
-    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;\r
-}\r
-\r
-int main(void)\r
-{\r
-    SPConfig* g_Config=&SPConfig::getConfig();\r
-    g_Config->setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::RequestMapping |\r
-        SPConfig::InProcess |\r
-        SPConfig::Logging |\r
-        SPConfig::Handlers\r
-        );\r
-    if (!g_Config->init()) {\r
-        cerr << "failed to initialize Shibboleth libraries" << endl;\r
-        exit(1);\r
-    }\r
-\r
-    try {\r
-        if (!g_Config->instantiate(NULL, true))\r
-            throw runtime_error("unknown error");\r
-    }\r
-    catch (exception& ex) {\r
-        g_Config->term();\r
-        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;\r
-        exit(1);\r
-    }\r
-\r
-    string g_ServerScheme;\r
-    string g_ServerName;\r
-    int g_ServerPort=0;\r
-\r
-    // Load "authoritative" URL fields.\r
-    char* var = getenv("SHIBSP_SERVER_NAME");\r
-    if (var)\r
-        g_ServerName = var;\r
-    var = getenv("SHIBSP_SERVER_SCHEME");\r
-    if (var)\r
-        g_ServerScheme = var;\r
-    var = getenv("SHIBSP_SERVER_PORT");\r
-    if (var)\r
-        g_ServerPort = atoi(var);\r
-\r
-    streambuf* cin_streambuf  = cin.rdbuf();\r
-    streambuf* cout_streambuf = cout.rdbuf();\r
-    streambuf* cerr_streambuf = cerr.rdbuf();\r
-\r
-    FCGX_Request request;\r
-\r
-    FCGX_Init();\r
-    FCGX_InitRequest(&request, 0, 0);\r
-\r
-    cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
-    while (FCGX_Accept_r(&request) == 0) {\r
-        // Note that the default bufsize (0) will cause the use of iostream\r
-        // methods that require positioning (such as peek(), seek(),\r
-        // unget() and putback()) to fail (in favour of more efficient IO).\r
-        fcgi_streambuf cin_fcgi_streambuf(request.in);\r
-        fcgi_streambuf cout_fcgi_streambuf(request.out);\r
-        fcgi_streambuf cerr_fcgi_streambuf(request.err);\r
-\r
-        cin.rdbuf(&cin_fcgi_streambuf);\r
-        cout.rdbuf(&cout_fcgi_streambuf);\r
-        cerr.rdbuf(&cerr_fcgi_streambuf);\r
-\r
-        // Although FastCGI supports writing before reading,\r
-        // many http clients (browsers) don't support it (so\r
-        // the connection deadlocks until a timeout expires!).\r
-        char* content;\r
-        gstdin(&request, &content);\r
-\r
-        try {\r
-            xmltooling::NDC ndc("FastCGI shibresponder");\r
-            ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-\r
-            pair<bool,long> res = stf.getServiceProvider().doHandler(stf);\r
-            if (res.first) {\r
-                stf.log(SPRequest::SPDebug, "shib: doHandler handled the request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok();\r
-                        break;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        cerr << "shib: doHandler failed to handle the request" << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth responder should only be used for Shibboleth protocol requests.</body></html>");\r
-                        break;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        // response already handled\r
-                        break;\r
-\r
-                    default:\r
-                        cerr << "shib: doHandler returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth responder returned an unexpected result.</body></html>");\r
-                        break;\r
-                }\r
-            }\r
-            else {\r
-                cerr << "shib: doHandler failed to handle request." << endl;\r
-                print_error("<html><body>FastCGI Shibboleth responder failed to process request.</body></html>");\r
-            }\r
-\r
-        }\r
-        catch (exception& e) {\r
-            cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl;\r
-            print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");\r
-        }\r
-\r
-        delete[] content;\r
-\r
-        // If the output streambufs had non-zero bufsizes and\r
-        // were constructed outside of the accept loop (i.e.\r
-        // their destructor won't be called here), they would\r
-        // have to be flushed here.\r
-    }\r
-\r
-    cout << "Request loop ended." << endl;\r
-\r
-    cin.rdbuf(cin_streambuf);\r
-    cout.rdbuf(cout_streambuf);\r
-    cerr.rdbuf(cerr_streambuf);\r
-\r
-    if (g_Config)\r
-        g_Config->term();\r
-\r
-    return 0;\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler
+
+   Andre Cruz
+*/
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _SCL_SECURE_NO_WARNINGS 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <stdexcept>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+#include <fcgio.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);
+static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
+
+typedef enum {
+    SHIB_RETURN_OK,
+    SHIB_RETURN_KO,
+    SHIB_RETURN_DONE
+} shib_return_t;
+
+class ShibTargetFCGI : public AbstractSPRequest
+{
+    FCGX_Request* m_req;
+    const char* m_body;
+    multimap<string,string> m_headers;
+    int m_port;
+    string m_scheme,m_hostname;
+
+public:
+    ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0)
+        : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) {
+
+        const char* server_name_str = hostname;
+        if (!server_name_str || !*server_name_str)
+            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);
+        m_hostname = server_name_str;
+
+        m_port = port;
+        if (!m_port) {
+            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);
+            m_port = strtol(server_port_str, &server_port_str, 10);
+            if (*server_port_str) {
+                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;
+                throw runtime_error("Unable to determine server port.");
+            }
+        }
+
+        const char* server_scheme_str = scheme;
+        if (!server_scheme_str || !*server_scheme_str)
+            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";
+        m_scheme = server_scheme_str;
+
+        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));
+    }
+
+    ~ShibTargetFCGI() { }
+
+    const char* getScheme() const {
+        return m_scheme.c_str();
+    }
+    const char* getHostname() const {
+        return m_hostname.c_str();
+    }
+    int getPort() const {
+        return m_port;
+    }
+    const char* getMethod() const {
+        return FCGX_GetParam("REQUEST_METHOD", m_req->envp);
+    }
+    string getContentType() const {
+        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);
+        return s ? s : "";
+    }
+    long getContentLength() const {
+        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);
+        return s ? atol(s) : 0;
+    }
+    string getRemoteUser() const {
+        const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp);
+        return s ? s : "";
+    }
+    string getRemoteAddr() const {
+        string ret = AbstractSPRequest::getRemoteAddr();
+        if (!ret.empty())
+            return ret;
+        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
+        return s ? s : "";
+    }
+    void log(SPLogLevel level, const string& msg) const {
+        AbstractSPRequest::log(level,msg);
+        if (level >= SPError)
+            cerr << "shib: " << msg;
+    }
+
+    string getHeader(const char* name) const {
+        string hdr("HTTP_");
+        for (; *name; ++name) {
+            if (*name=='-')
+                hdr += '_';
+            else
+                hdr += toupper(*name);
+        }
+        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);
+        return s ? s : "";
+    }
+
+    void setResponseHeader(const char* name, const char* value) {
+        AbstractSPRequest::setResponseHeader(name, value);
+        // Set for later.
+        if (value)
+            m_headers.insert(make_pair(name,value));
+        else
+            m_headers.erase(name);
+    }
+
+    const char* getQueryString() const {
+        return FCGX_GetParam("QUERY_STRING", m_req->envp);
+    }
+
+    const char* getRequestBody() const {
+        return m_body;
+    }
+
+    long sendResponse(istream& in, long status) {
+        string hdr = string("Connection: close\r\n");
+        for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+            hdr += i->first + ": " + i->second + "\r\n";
+
+        const char* codestr="Status: 200 OK";
+        switch (status) {
+            case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="Status: 500 Server Error"; break;
+            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;
+            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;
+            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;
+        }
+        cout << codestr << "\r\n" << hdr << "\r\n";
+        char buf[1024];
+        while (in) {
+            in.read(buf,1024);
+            cout.write(buf, in.gcount());
+        }
+        return SHIB_RETURN_DONE;
+    }
+
+    long sendRedirect(const char* url) {
+        AbstractSPRequest::sendRedirect(url);
+        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
+          "Content-Type: text/html\r\n"
+          "Content-Length: 40\r\n"
+          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+          "Cache-Control: private,no-store,no-cache\r\n";
+        for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+            hdr += i->first + ": " + i->second + "\r\n";
+        hdr += "\r\n";
+
+        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";
+        return SHIB_RETURN_DONE;
+    }
+
+    long returnDecline() {
+        return SHIB_RETURN_KO;
+    }
+    long returnOK() {
+        return SHIB_RETURN_OK;
+    }
+
+    const vector<string>& getClientCertificates() const {
+        static vector<string> g_NoCerts;
+        return g_NoCerts;
+    }
+
+    // Not used in the extension.
+
+    virtual void clearHeader(const char* rawname, const char* cginame) {
+        throw runtime_error("clearHeader not implemented by FastCGI responder.");
+    }
+
+    virtual void setHeader(const char* name, const char* value) {
+        throw runtime_error("setHeader not implemented by FastCGI responder.");
+    }
+
+    virtual void setRemoteUser(const char* user) {
+        throw runtime_error("setRemoteUser not implemented by FastCGI responder.");
+    }
+};
+
+// Maximum number of bytes allowed to be read from stdin
+static const unsigned long STDIN_MAX = 1000000;
+
+static long gstdin(FCGX_Request* request, char** content)
+{
+    char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);
+    unsigned long clen = STDIN_MAX;
+
+    if (clenstr) {
+        clen = strtol(clenstr, &clenstr, 10);
+        if (*clenstr) {
+            cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl;
+            clen = STDIN_MAX;
+        }
+
+        // *always* put a cap on the amount of data that will be read
+        if (clen > STDIN_MAX)
+            clen = STDIN_MAX;
+
+        *content = new char[clen];
+
+        cin.read(*content, clen);
+        clen = cin.gcount();
+    }
+    else {
+        // *never* read stdin when CONTENT_LENGTH is missing or unparsable
+        *content = 0;
+        clen = 0;
+    }
+
+    // Chew up any remaining stdin - this shouldn't be necessary
+    // but is because mod_fastcgi doesn't handle it correctly.
+
+    // ignore() doesn't set the eof bit in some versions of glibc++
+    // so use gcount() instead of eof()...
+    do cin.ignore(1024); while (cin.gcount() == 1024);
+
+    return clen;
+}
+
+static void print_ok() {
+    cout << "Status: 200 OK" << "\r\n\r\n";
+}
+
+static void print_error(const char* msg) {
+    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;
+}
+
+int main(void)
+{
+    SPConfig* g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging |
+        SPConfig::Handlers
+        );
+    if (!g_Config->init()) {
+        cerr << "failed to initialize Shibboleth libraries" << endl;
+        exit(1);
+    }
+
+    try {
+        if (!g_Config->instantiate(NULL, true))
+            throw runtime_error("unknown error");
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;
+        exit(1);
+    }
+
+    string g_ServerScheme;
+    string g_ServerName;
+    int g_ServerPort=0;
+
+    // Load "authoritative" URL fields.
+    char* var = getenv("SHIBSP_SERVER_NAME");
+    if (var)
+        g_ServerName = var;
+    var = getenv("SHIBSP_SERVER_SCHEME");
+    if (var)
+        g_ServerScheme = var;
+    var = getenv("SHIBSP_SERVER_PORT");
+    if (var)
+        g_ServerPort = atoi(var);
+
+    streambuf* cin_streambuf  = cin.rdbuf();
+    streambuf* cout_streambuf = cout.rdbuf();
+    streambuf* cerr_streambuf = cerr.rdbuf();
+
+    FCGX_Request request;
+
+    FCGX_Init();
+    FCGX_InitRequest(&request, 0, 0);
+
+    cout << "Shibboleth initialization complete. Starting request loop." << endl;
+    while (FCGX_Accept_r(&request) == 0) {
+        // Note that the default bufsize (0) will cause the use of iostream
+        // methods that require positioning (such as peek(), seek(),
+        // unget() and putback()) to fail (in favour of more efficient IO).
+        fcgi_streambuf cin_fcgi_streambuf(request.in);
+        fcgi_streambuf cout_fcgi_streambuf(request.out);
+        fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+        cin.rdbuf(&cin_fcgi_streambuf);
+        cout.rdbuf(&cout_fcgi_streambuf);
+        cerr.rdbuf(&cerr_fcgi_streambuf);
+
+        // Although FastCGI supports writing before reading,
+        // many http clients (browsers) don't support it (so
+        // the connection deadlocks until a timeout expires!).
+        char* content;
+        gstdin(&request, &content);
+
+        try {
+            xmltooling::NDC ndc("FastCGI shibresponder");
+            ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);
+
+            pair<bool,long> res = stf.getServiceProvider().doHandler(stf);
+            if (res.first) {
+                stf.log(SPRequest::SPDebug, "shib: doHandler handled the request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok();
+                        break;
+
+                    case SHIB_RETURN_KO:
+                        cerr << "shib: doHandler failed to handle the request" << endl;
+                        print_error("<html><body>FastCGI Shibboleth responder should only be used for Shibboleth protocol requests.</body></html>");
+                        break;
+
+                    case SHIB_RETURN_DONE:
+                        // response already handled
+                        break;
+
+                    default:
+                        cerr << "shib: doHandler returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth responder returned an unexpected result.</body></html>");
+                        break;
+                }
+            }
+            else {
+                cerr << "shib: doHandler failed to handle request." << endl;
+                print_error("<html><body>FastCGI Shibboleth responder failed to process request.</body></html>");
+            }
+
+        }
+        catch (exception& e) {
+            cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl;
+            print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");
+        }
+
+        delete[] content;
+
+        // If the output streambufs had non-zero bufsizes and
+        // were constructed outside of the accept loop (i.e.
+        // their destructor won't be called here), they would
+        // have to be flushed here.
+    }
+
+    cout << "Request loop ended." << endl;
+
+    cin.rdbuf(cin_streambuf);
+    cout.rdbuf(cout_streambuf);
+    cerr.rdbuf(cerr_streambuf);
+
+    if (g_Config)
+        g_Config->term();
+
+    return 0;
+}
index 9d46119..fa11fd8 100644 (file)
@@ -1,20 +1,20 @@
-AUTOMAKE_OPTIONS = foreign\r
-\r
-plugindir = $(libdir)/@PACKAGE@\r
-plugin_LTLIBRARIES = memcache-store.la\r
-\r
-AM_CFLAGS = $(MEMCACHED_CFLAGS)\r
-AM_CXXFLAGS = $(MEMCACHED_CFLAGS)\r
-\r
-memcache_store_la_LIBADD = \\r
-       $(MEMCACHED_LIBS)\r
-\r
-memcache_store_la_SOURCES = \\r
-       memcache-store.cpp\r
-\r
-memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)\r
-\r
-install-exec-hook:\r
-       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done\r
-\r
-EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h\r
+AUTOMAKE_OPTIONS = foreign
+
+plugindir = $(libdir)/@PACKAGE@
+plugin_LTLIBRARIES = memcache-store.la
+
+AM_CFLAGS = $(MEMCACHED_CFLAGS)
+AM_CXXFLAGS = $(MEMCACHED_CFLAGS)
+
+memcache_store_la_LIBADD = \
+       $(MEMCACHED_LIBS)
+
+memcache_store_la_SOURCES = \
+       memcache-store.cpp
+
+memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)
+
+install-exec-hook:
+       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done
+
+EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h
index 6724232..49d238d 100644 (file)
-/*\r
- *  Copyright 2001-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
- * memcache-store.cpp\r
- *\r
- * Storage Service using memcache (pre memcache tags)\r
- */\r
-\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-# define MCEXT_EXPORTS __declspec(dllexport)\r
-#else\r
-# define MCEXT_EXPORTS\r
-#endif\r
-\r
-#include <xmltooling/base.h>\r
-\r
-#include <list>\r
-#include <iostream> \r
-#include <libmemcached/memcached.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <xmltooling/logging.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/StorageService.h>\r
-#include <xmltooling/util/Threads.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace xmltooling::logging;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-namespace xmltooling {\r
-  static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s);\r
-  static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x);\r
-  static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p);\r
-  static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t);\r
-  static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t);\r
-  static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t);\r
-  static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t);\r
-  static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t);\r
-  \r
-  class mc_record {\r
-  public:\r
-    string value;\r
-    time_t expiration;\r
-    mc_record(){};\r
-    mc_record(string _v, time_t _e) :\r
-      value(_v), expiration(_e)\r
-    {}\r
-  };\r
-\r
-  class MemcacheBase {\r
-  public:\r
-    MemcacheBase(const DOMElement* e);\r
-    ~MemcacheBase();\r
-        \r
-    bool addMemcache(const char *key,\r
-                     string &value,\r
-                     time_t timeout,\r
-                     uint32_t flags,\r
-                     bool use_prefix = true);\r
-    bool setMemcache(const char *key,\r
-                     string &value,\r
-                     time_t timeout,\r
-                     uint32_t flags,\r
-                     bool use_prefix = true);\r
-    bool replaceMemcache(const char *key,\r
-                         string &value,\r
-                         time_t timeout,\r
-                         uint32_t flags,\r
-                         bool use_prefix = true);\r
-    bool getMemcache(const char *key,\r
-                     string &dest,\r
-                     uint32_t *flags,\r
-                     bool use_prefix = true);\r
-    bool deleteMemcache(const char *key,\r
-                        time_t timeout,\r
-                        bool use_prefix = true);\r
-\r
-    void serialize(mc_record &source, string &dest);\r
-    void serialize(list<string> &source, string &dest);\r
-    void deserialize(string &source, mc_record &dest);\r
-    void deserialize(string &source, list<string> &dest);\r
-\r
-    bool addSessionToUser(string &key, string &user);\r
-    bool addLock(string what, bool use_prefix = true);\r
-    void deleteLock(string what, bool use_prefix = true);\r
-\r
-  protected:\r
-    const DOMElement* m_root; // can only use this during initialization\r
-    Category& log;\r
-    memcached_st *memc;\r
-    string m_prefix;\r
-    Mutex* m_lock;\r
-  };\r
-  \r
-  class MemcacheStorageService : public StorageService, public MemcacheBase {\r
-\r
-  public:\r
-    MemcacheStorageService(const DOMElement* e);\r
-    ~MemcacheStorageService();\r
-    \r
-    bool createString(const char* context, const char* key, const char* value, time_t expiration);\r
-    int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0);\r
-    int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0);\r
-    bool deleteString(const char* context, const char* key);\r
-    \r
-    bool createText(const char* context, const char* key, const char* value, time_t expiration) {\r
-      return createString(context, key, value, expiration);\r
-    }\r
-    int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) {\r
-      return readString(context, key, pvalue, pexpiration, version);\r
-    }\r
-    int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) {\r
-      return updateString(context, key, value, expiration, version);\r
-    }\r
-    bool deleteText(const char* context, const char* key) {\r
-      return deleteString(context, key);\r
-    }\r
-    \r
-    void reap(const char* context) {}\r
-\r
-    void updateContext(const char* context, time_t expiration);\r
-    void deleteContext(const char* context);\r
-\r
-    private:\r
-\r
-    Category& m_log;\r
-    bool m_buildMap;\r
-\r
-\r
-  };\r
-\r
-  StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) {\r
-    return new MemcacheStorageService(e);\r
-  }\r
-\r
-};\r
-\r
-bool MemcacheBase::addLock(string what, bool use_prefix) {\r
-  string lock_name = what + ":LOCK";\r
-  string set_val = "1";\r
-  unsigned tries = 5;\r
-  while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {\r
-    if (tries-- == 0) {\r
-      log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());\r
-      return false;\r
-    }\r
-    log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());\r
-    \r
-    // sleep 100ms\r
-#ifdef WIN32\r
-    Sleep(100);\r
-#else\r
-    struct timeval tv = { 0, 100000 };\r
-    select(0, 0, 0, 0, &tv);\r
-#endif\r
-  }\r
-  return true;\r
-}\r
-\r
-void MemcacheBase::deleteLock(string what, bool use_prefix) {\r
-\r
-  string lock_name = what + ":LOCK";\r
-  deleteMemcache(lock_name.c_str(), 0, use_prefix);\r
-  return;\r
-\r
-}  \r
-\r
-void MemcacheBase::deserialize(string &source, mc_record &dest) {\r
-  istringstream is(source, stringstream::in | stringstream::out);\r
-  is >> dest.expiration;\r
-  is.ignore(1); // ignore delimiter\r
-  dest.value = is.str().c_str() + is.tellg();\r
-}\r
-\r
-void MemcacheBase::deserialize(string &source, list<string> &dest) {\r
-  istringstream is(source, stringstream::in | stringstream::out);\r
-  while (!is.eof()) {\r
-    string s;\r
-    is >> s;\r
-    dest.push_back(s);\r
-  }  \r
-}\r
-\r
-void MemcacheBase::serialize(mc_record &source, string &dest) {\r
-  ostringstream os(stringstream::in | stringstream::out);\r
-  os << source.expiration;\r
-  os << "-"; // delimiter\r
-  os << source.value;\r
-  dest = os.str();\r
-}\r
-\r
-void MemcacheBase::serialize(list<string> &source, string &dest) {  \r
-  ostringstream os(stringstream::in | stringstream::out);\r
-  for(list<string>::iterator iter = source.begin(); iter != source.end(); iter++) {\r
-    if (iter != source.begin()) {\r
-      os << endl;\r
-    }\r
-    os << *iter;\r
-  }\r
-  dest = os.str();\r
-}\r
-\r
-bool MemcacheBase::addSessionToUser(string &key, string &user) {\r
-\r
-  if (! addLock(user, false)) {\r
-    return false;\r
-  }\r
-\r
-  // Aquired lock\r
-\r
-  string sessid = m_prefix + key; // add specific prefix to session\r
-  string delimiter = ";";\r
-  string user_key = "UDATA:";\r
-  user_key += user;\r
-  string user_val;\r
-  uint32_t flags;\r
-  bool result = getMemcache(user_key.c_str(), user_val, &flags, false);\r
-\r
-  if (result) {\r
-    bool already_there = false;\r
-    // skip delimiters at beginning.\r
-    string::size_type lastPos = user_val.find_first_not_of(delimiter, 0);\r
-    \r
-    // find first "non-delimiter".\r
-    string::size_type pos = user_val.find_first_of(delimiter, lastPos);\r
-    \r
-    while (string::npos != pos || string::npos != lastPos) {\r
-      // found a token, add it to the vector.\r
-      string session = user_val.substr(lastPos, pos - lastPos);\r
-      if (strcmp(session.c_str(), sessid.c_str()) == 0) {\r
-        already_there = true;\r
-        break;\r
-      }\r
-      \r
-      // skip delimiters.  Note the "not_of"\r
-      lastPos = user_val.find_first_not_of(delimiter, pos);\r
-      \r
-      // find next "non-delimiter"\r
-      pos = user_val.find_first_of(delimiter, lastPos);\r
-    }\r
-    \r
-    if (!already_there) {\r
-      user_val += delimiter + sessid;\r
-      replaceMemcache(user_key.c_str(), user_val, 0, 0, false);\r
-    }\r
-  } else {\r
-    addMemcache(user_key.c_str(), sessid, 0, 0, false);\r
-  }\r
-\r
-  deleteLock(user, false);\r
-  return true;\r
-  \r
-}\r
-\r
-bool MemcacheBase::deleteMemcache(const char *key,\r
-                                  time_t timeout,\r
-                                  bool use_prefix) {\r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTFOUND) {\r
-    // Key wasn't there... No biggie.\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));\r
-    log.error(error);\r
-    throw IOException(error);\r
-  } else {\r
-    string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv);\r
-    log.error(error);\r
-    throw IOException(error);\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::getMemcache(const char *key,\r
-                               string &dest,\r
-                               uint32_t *flags,\r
-                               bool use_prefix) {\r
-  memcached_return rv;\r
-  size_t len;\r
-  char *result;\r
-  string final_key;\r
-  bool success;\r
-  \r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    dest = result;\r
-    free(result);\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTFOUND) {\r
-    log.debug("Key %s not found in memcache...", key);\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));\r
-    log.error(error);\r
-    throw IOException(error);\r
-  } else {\r
-    string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv);\r
-    log.error(error);\r
-    throw IOException(error);\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::addMemcache(const char *key,\r
-                               string &value,\r
-                               time_t timeout,\r
-                               uint32_t flags,\r
-                               bool use_prefix) {\r
-\r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTSTORED) {\r
-    // already there\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));\r
-    log.error(error);\r
-    throw IOException(error);\r
-  } else {\r
-    string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv);\r
-    log.error(error);\r
-    throw IOException(error);\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::setMemcache(const char *key,\r
-                               string &value,\r
-                               time_t timeout,\r
-                               uint32_t flags,\r
-                               bool use_prefix) {\r
-\r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));\r
-    log.error(error);\r
-    throw IOException(error);\r
-  } else {\r
-    string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv);\r
-    log.error(error);\r
-    throw IOException(error);\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::replaceMemcache(const char *key,\r
-                                   string &value,\r
-                                   time_t timeout,\r
-                                   uint32_t flags,\r
-                                   bool use_prefix) {\r
-  \r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTSTORED) {\r
-    // not there\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));\r
-    log.error(error);\r
-    throw IOException(error);\r
-  } else {\r
-    string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv);\r
-    log.error(error);\r
-    throw IOException(error);\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") {\r
-\r
-  auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL);\r
-  if (p.get() && *p.get()) {\r
-    log.debug("INIT: GOT key prefix: %s", p.get());\r
-    m_prefix = p.get();\r
-  }\r
-\r
-  m_lock = Mutex::create();\r
-  log.debug("Lock created");\r
-\r
-  memc = memcached_create(NULL);\r
-  if (memc == NULL) {\r
-    throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");\r
-  }\r
-\r
-  log.debug("Memcache created");\r
-\r
-  unsigned int hash = MEMCACHED_HASH_CRC;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);\r
-  log.debug("CRC hash set");\r
-\r
-  int32_t send_timeout = 1000000;\r
-  const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;\r
-  if (tag && *tag) {\r
-    send_timeout = XMLString::parseInt(tag);\r
-  }\r
-  log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout);\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout);\r
-\r
-  int32_t recv_timeout = 1000000;\r
-  tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;\r
-  if (tag && *tag) {\r
-    recv_timeout = XMLString::parseInt(tag);\r
-  }\r
-  log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout);\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout);\r
-\r
-  int32_t poll_timeout = 1000;\r
-  tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL;\r
-  if (tag && *tag) {\r
-    poll_timeout = XMLString::parseInt(tag);\r
-  }\r
-  log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout);\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);\r
-\r
-  int32_t fail_limit = 5;\r
-  tag = e ? e->getAttributeNS(NULL, failLimit) : NULL;\r
-  if (tag && *tag) {\r
-    fail_limit = XMLString::parseInt(tag);\r
-  }\r
-  log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit);\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);\r
-\r
-  int32_t retry_timeout = 30;\r
-  tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL;\r
-  if (tag && *tag) {\r
-    retry_timeout = XMLString::parseInt(tag);\r
-  }\r
-  log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout);\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);\r
-\r
-  // Grab hosts from the configuration.\r
-  e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL;\r
-  if (!e || !e->hasChildNodes()) {\r
-    throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");\r
-  }\r
-  auto_ptr_char h(e->getFirstChild()->getNodeValue());\r
-  log.debug("INIT: GOT Hosts: %s", h.get());\r
-  memcached_server_st *servers;\r
-  servers = memcached_servers_parse(const_cast<char*>(h.get()));\r
-  log.debug("Got %u hosts.",  memcached_server_list_count(servers));\r
-  if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {\r
-    throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed");    \r
-  }\r
-  memcached_server_list_free(servers);\r
-\r
-  log.debug("Memcache object initialized");\r
-}\r
-\r
-MemcacheBase::~MemcacheBase() {\r
-  memcached_free(memc);\r
-  delete m_lock;\r
-  log.debug("Base object destroyed");\r
-}\r
-\r
-MemcacheStorageService::MemcacheStorageService(const DOMElement* e)\r
-  : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) {\r
-\r
-    const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL;\r
-    if (tag && *tag && XMLString::parseInt(tag) != 0) {\r
-        m_buildMap = true;\r
-        m_log.debug("Cache built with buildMap ON");\r
-    }\r
-\r
-}\r
-\r
-MemcacheStorageService::~MemcacheStorageService() {\r
-\r
-  \r
-}\r
-\r
-bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) {\r
-\r
-  log.debug("createString ctx: %s - key: %s", context, key);\r
-\r
-  string final_key = string(context) + ":" + string(key);\r
-\r
-  mc_record rec(value, expiration);\r
-  string final_value;\r
-  serialize(rec, final_value);\r
-\r
-  bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version\r
-\r
-  if (result && m_buildMap) {\r
-    log.debug("Got result, updating map");\r
-\r
-    string map_name = context;\r
-    // we need to update the context map\r
-    if (! addLock(map_name)) {\r
-      log.error("Unable to get lock for context %s!", context);\r
-      deleteMemcache(final_key.c_str(), 0);\r
-      return false;\r
-    }\r
-\r
-    string ser_arr;\r
-    uint32_t flags;\r
-    bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-    \r
-    list<string> contents;\r
-    if (result) {\r
-      log.debug("Match found. Parsing...");\r
-\r
-      deserialize(ser_arr, contents);\r
-      \r
-      log.debug("Iterating retrieved session map...");\r
-      list<string>::iterator iter;\r
-      for(iter = contents.begin(); \r
-          iter != contents.end();\r
-          iter++) {\r
-        log.debug("value = " + *iter);\r
-      }\r
-\r
-    } else {\r
-      log.debug("New context: %s", map_name.c_str());\r
-\r
-    }\r
-\r
-    contents.push_back(key);\r
-    serialize(contents, ser_arr);    \r
-    setMemcache(map_name.c_str(), ser_arr, expiration, 0);    \r
-    \r
-    deleteLock(map_name);\r
-  }\r
-\r
-  return result;  \r
-\r
-}\r
-\r
-int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) {\r
-\r
-  log.debug("readString ctx: %s - key: %s", context, key);\r
-\r
-  string final_key = string(context) + ":" + string(key);\r
-  uint32_t rec_version;\r
-  string value;\r
-\r
-  if (m_buildMap) {\r
-    log.debug("Checking context");\r
-\r
-    string map_name = context;\r
-    string ser_arr;\r
-    uint32_t flags;\r
-    bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-\r
-    if (!ctx_found) {\r
-      return 0;\r
-    }\r
-  }\r
-\r
-  bool found = getMemcache(final_key.c_str(), value, &rec_version);\r
-  if (!found) {\r
-    return 0;\r
-  }\r
-\r
-  if (version && rec_version <= (uint32_t)version) {\r
-    return version;\r
-  }\r
-\r
-  if (pexpiration || pvalue) {\r
-    mc_record rec;\r
-    deserialize(value, rec);\r
-    \r
-    if (pexpiration) {\r
-      *pexpiration = rec.expiration;\r
-    }\r
-    \r
-    if (pvalue) {\r
-      *pvalue = rec.value;\r
-    }\r
-  }\r
-  \r
-  return rec_version;\r
-\r
-}\r
-\r
-int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) {\r
-\r
-  log.debug("updateString ctx: %s - key: %s", context, key);\r
-\r
-  time_t final_exp = expiration;\r
-  time_t *want_expiration = NULL;\r
-  if (! final_exp) {\r
-    want_expiration = &final_exp;\r
-  }\r
-\r
-  int read_res = readString(context, key, NULL, want_expiration, version);\r
-\r
-  if (!read_res) {\r
-    // not found\r
-    return read_res;\r
-  }\r
-\r
-  if (version && version != read_res) {\r
-    // version incorrect\r
-    return -1;\r
-  }\r
-\r
-  // Proceding with update\r
-  string final_key = string(context) + ":" + string(key);\r
-  mc_record rec(value, final_exp);\r
-  string final_value;\r
-  serialize(rec, final_value);\r
-\r
-  replaceMemcache(final_key.c_str(), final_value, final_exp, ++version);\r
-  return version;\r
-\r
-}\r
-\r
-bool MemcacheStorageService::deleteString(const char* context, const char* key) {\r
-\r
-  log.debug("deleteString ctx: %s - key: %s", context, key);\r
-  \r
-  string final_key = string(context) + ":" + string(key);\r
-\r
-  // Not updating context map, if there is one. There is no need.\r
-\r
-  return deleteMemcache(final_key.c_str(), 0);\r
-\r
-}\r
-\r
-void MemcacheStorageService::updateContext(const char* context, time_t expiration) {\r
-\r
-  log.debug("updateContext ctx: %s", context);\r
-\r
-  if (!m_buildMap) {\r
-    log.error("updateContext invoked on a Storage with no context map built!");\r
-    return;\r
-  }\r
-\r
-  string map_name = context;\r
-  string ser_arr;\r
-  uint32_t flags;\r
-  bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-  \r
-  list<string> contents;\r
-  if (result) {\r
-    log.debug("Match found. Parsing...");\r
-    \r
-    deserialize(ser_arr, contents);\r
-    \r
-    log.debug("Iterating retrieved session map...");\r
-    list<string>::iterator iter;\r
-    for(iter = contents.begin(); \r
-        iter != contents.end();\r
-        iter++) {\r
-\r
-      // Update expiration times\r
-      string value;      \r
-      int read_res = readString(context, iter->c_str(), &value, NULL, 0);\r
-      \r
-      if (!read_res) {\r
-        // not found\r
-        continue;\r
-      }\r
-\r
-      updateString(context, iter->c_str(), value.c_str(), expiration, read_res);\r
-    }\r
-    replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);\r
-  }\r
-  \r
-}\r
-\r
-void MemcacheStorageService::deleteContext(const char* context) {\r
-\r
-  log.debug("deleteContext ctx: %s", context);\r
-\r
-  if (!m_buildMap) {\r
-    log.error("deleteContext invoked on a Storage with no context map built!");\r
-    return;\r
-  }\r
-\r
-  string map_name = context;\r
-  string ser_arr;\r
-  uint32_t flags;\r
-  bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-  \r
-  list<string> contents;\r
-  if (result) {\r
-    log.debug("Match found. Parsing...");\r
-    \r
-    deserialize(ser_arr, contents);\r
-    \r
-    log.debug("Iterating retrieved session map...");\r
-    list<string>::iterator iter;\r
-    for(iter = contents.begin(); \r
-        iter != contents.end();\r
-        iter++) {\r
-      string final_key = map_name + *iter;\r
-      deleteMemcache(final_key.c_str(), 0);\r
-    }\r
-    \r
-    deleteMemcache(map_name.c_str(), 0);\r
-  }\r
-  \r
-}\r
-\r
-extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {\r
-    // Register this SS type\r
-    XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);\r
-    return 0;\r
-}\r
-\r
-extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {\r
-    XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/**
+ * memcache-store.cpp
+ *
+ * Storage Service using memcache (pre memcache tags)
+ */
+
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+# define MCEXT_EXPORTS __declspec(dllexport)
+#else
+# define MCEXT_EXPORTS
+#endif
+
+#include <xmltooling/base.h>
+
+#include <list>
+#include <iostream> 
+#include <libmemcached/memcached.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <xmltooling/logging.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/StorageService.h>
+#include <xmltooling/util/Threads.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+namespace xmltooling {
+  static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s);
+  static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x);
+  static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p);
+  static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t);
+  static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t);
+  static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t);
+  static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t);
+  static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t);
+  
+  class mc_record {
+  public:
+    string value;
+    time_t expiration;
+    mc_record(){};
+    mc_record(string _v, time_t _e) :
+      value(_v), expiration(_e)
+    {}
+  };
+
+  class MemcacheBase {
+  public:
+    MemcacheBase(const DOMElement* e);
+    ~MemcacheBase();
+        
+    bool addMemcache(const char *key,
+                     string &value,
+                     time_t timeout,
+                     uint32_t flags,
+                     bool use_prefix = true);
+    bool setMemcache(const char *key,
+                     string &value,
+                     time_t timeout,
+                     uint32_t flags,
+                     bool use_prefix = true);
+    bool replaceMemcache(const char *key,
+                         string &value,
+                         time_t timeout,
+                         uint32_t flags,
+                         bool use_prefix = true);
+    bool getMemcache(const char *key,
+                     string &dest,
+                     uint32_t *flags,
+                     bool use_prefix = true);
+    bool deleteMemcache(const char *key,
+                        time_t timeout,
+                        bool use_prefix = true);
+
+    void serialize(mc_record &source, string &dest);
+    void serialize(list<string> &source, string &dest);
+    void deserialize(string &source, mc_record &dest);
+    void deserialize(string &source, list<string> &dest);
+
+    bool addSessionToUser(string &key, string &user);
+    bool addLock(string what, bool use_prefix = true);
+    void deleteLock(string what, bool use_prefix = true);
+
+  protected:
+    const DOMElement* m_root; // can only use this during initialization
+    Category& log;
+    memcached_st *memc;
+    string m_prefix;
+    Mutex* m_lock;
+  };
+  
+  class MemcacheStorageService : public StorageService, public MemcacheBase {
+
+  public:
+    MemcacheStorageService(const DOMElement* e);
+    ~MemcacheStorageService();
+    
+    bool createString(const char* context, const char* key, const char* value, time_t expiration);
+    int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0);
+    int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0);
+    bool deleteString(const char* context, const char* key);
+    
+    bool createText(const char* context, const char* key, const char* value, time_t expiration) {
+      return createString(context, key, value, expiration);
+    }
+    int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) {
+      return readString(context, key, pvalue, pexpiration, version);
+    }
+    int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) {
+      return updateString(context, key, value, expiration, version);
+    }
+    bool deleteText(const char* context, const char* key) {
+      return deleteString(context, key);
+    }
+    
+    void reap(const char* context) {}
+
+    void updateContext(const char* context, time_t expiration);
+    void deleteContext(const char* context);
+
+    private:
+
+    Category& m_log;
+    bool m_buildMap;
+
+
+  };
+
+  StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) {
+    return new MemcacheStorageService(e);
+  }
+
+};
+
+bool MemcacheBase::addLock(string what, bool use_prefix) {
+  string lock_name = what + ":LOCK";
+  string set_val = "1";
+  unsigned tries = 5;
+  while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {
+    if (tries-- == 0) {
+      log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());
+      return false;
+    }
+    log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());
+    
+    // sleep 100ms
+#ifdef WIN32
+    Sleep(100);
+#else
+    struct timeval tv = { 0, 100000 };
+    select(0, 0, 0, 0, &tv);
+#endif
+  }
+  return true;
+}
+
+void MemcacheBase::deleteLock(string what, bool use_prefix) {
+
+  string lock_name = what + ":LOCK";
+  deleteMemcache(lock_name.c_str(), 0, use_prefix);
+  return;
+
+}  
+
+void MemcacheBase::deserialize(string &source, mc_record &dest) {
+  istringstream is(source, stringstream::in | stringstream::out);
+  is >> dest.expiration;
+  is.ignore(1); // ignore delimiter
+  dest.value = is.str().c_str() + is.tellg();
+}
+
+void MemcacheBase::deserialize(string &source, list<string> &dest) {
+  istringstream is(source, stringstream::in | stringstream::out);
+  while (!is.eof()) {
+    string s;
+    is >> s;
+    dest.push_back(s);
+  }  
+}
+
+void MemcacheBase::serialize(mc_record &source, string &dest) {
+  ostringstream os(stringstream::in | stringstream::out);
+  os << source.expiration;
+  os << "-"; // delimiter
+  os << source.value;
+  dest = os.str();
+}
+
+void MemcacheBase::serialize(list<string> &source, string &dest) {  
+  ostringstream os(stringstream::in | stringstream::out);
+  for(list<string>::iterator iter = source.begin(); iter != source.end(); iter++) {
+    if (iter != source.begin()) {
+      os << endl;
+    }
+    os << *iter;
+  }
+  dest = os.str();
+}
+
+bool MemcacheBase::addSessionToUser(string &key, string &user) {
+
+  if (! addLock(user, false)) {
+    return false;
+  }
+
+  // Aquired lock
+
+  string sessid = m_prefix + key; // add specific prefix to session
+  string delimiter = ";";
+  string user_key = "UDATA:";
+  user_key += user;
+  string user_val;
+  uint32_t flags;
+  bool result = getMemcache(user_key.c_str(), user_val, &flags, false);
+
+  if (result) {
+    bool already_there = false;
+    // skip delimiters at beginning.
+    string::size_type lastPos = user_val.find_first_not_of(delimiter, 0);
+    
+    // find first "non-delimiter".
+    string::size_type pos = user_val.find_first_of(delimiter, lastPos);
+    
+    while (string::npos != pos || string::npos != lastPos) {
+      // found a token, add it to the vector.
+      string session = user_val.substr(lastPos, pos - lastPos);
+      if (strcmp(session.c_str(), sessid.c_str()) == 0) {
+        already_there = true;
+        break;
+      }
+      
+      // skip delimiters.  Note the "not_of"
+      lastPos = user_val.find_first_not_of(delimiter, pos);
+      
+      // find next "non-delimiter"
+      pos = user_val.find_first_of(delimiter, lastPos);
+    }
+    
+    if (!already_there) {
+      user_val += delimiter + sessid;
+      replaceMemcache(user_key.c_str(), user_val, 0, 0, false);
+    }
+  } else {
+    addMemcache(user_key.c_str(), sessid, 0, 0, false);
+  }
+
+  deleteLock(user, false);
+  return true;
+  
+}
+
+bool MemcacheBase::deleteMemcache(const char *key,
+                                  time_t timeout,
+                                  bool use_prefix) {
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_NOTFOUND) {
+    // Key wasn't there... No biggie.
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::getMemcache(const char *key,
+                               string &dest,
+                               uint32_t *flags,
+                               bool use_prefix) {
+  memcached_return rv;
+  size_t len;
+  char *result;
+  string final_key;
+  bool success;
+  
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    dest = result;
+    free(result);
+    success = true;
+  } else if (rv == MEMCACHED_NOTFOUND) {
+    log.debug("Key %s not found in memcache...", key);
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::addMemcache(const char *key,
+                               string &value,
+                               time_t timeout,
+                               uint32_t flags,
+                               bool use_prefix) {
+
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_NOTSTORED) {
+    // already there
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::setMemcache(const char *key,
+                               string &value,
+                               time_t timeout,
+                               uint32_t flags,
+                               bool use_prefix) {
+
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::replaceMemcache(const char *key,
+                                   string &value,
+                                   time_t timeout,
+                                   uint32_t flags,
+                                   bool use_prefix) {
+  
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_NOTSTORED) {
+    // not there
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") {
+
+  auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL);
+  if (p.get() && *p.get()) {
+    log.debug("INIT: GOT key prefix: %s", p.get());
+    m_prefix = p.get();
+  }
+
+  m_lock = Mutex::create();
+  log.debug("Lock created");
+
+  memc = memcached_create(NULL);
+  if (memc == NULL) {
+    throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");
+  }
+
+  log.debug("Memcache created");
+
+  unsigned int hash = MEMCACHED_HASH_CRC;
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);
+  log.debug("CRC hash set");
+
+  int32_t send_timeout = 1000000;
+  const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;
+  if (tag && *tag) {
+    send_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout);
+
+  int32_t recv_timeout = 1000000;
+  tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;
+  if (tag && *tag) {
+    recv_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout);
+
+  int32_t poll_timeout = 1000;
+  tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL;
+  if (tag && *tag) {
+    poll_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);
+
+  int32_t fail_limit = 5;
+  tag = e ? e->getAttributeNS(NULL, failLimit) : NULL;
+  if (tag && *tag) {
+    fail_limit = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);
+
+  int32_t retry_timeout = 30;
+  tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL;
+  if (tag && *tag) {
+    retry_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);
+
+  // Grab hosts from the configuration.
+  e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL;
+  if (!e || !e->hasChildNodes()) {
+    throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");
+  }
+  auto_ptr_char h(e->getFirstChild()->getNodeValue());
+  log.debug("INIT: GOT Hosts: %s", h.get());
+  memcached_server_st *servers;
+  servers = memcached_servers_parse(const_cast<char*>(h.get()));
+  log.debug("Got %u hosts.",  memcached_server_list_count(servers));
+  if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {
+    throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed");    
+  }
+  memcached_server_list_free(servers);
+
+  log.debug("Memcache object initialized");
+}
+
+MemcacheBase::~MemcacheBase() {
+  memcached_free(memc);
+  delete m_lock;
+  log.debug("Base object destroyed");
+}
+
+MemcacheStorageService::MemcacheStorageService(const DOMElement* e)
+  : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) {
+
+    const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL;
+    if (tag && *tag && XMLString::parseInt(tag) != 0) {
+        m_buildMap = true;
+        m_log.debug("Cache built with buildMap ON");
+    }
+
+}
+
+MemcacheStorageService::~MemcacheStorageService() {
+
+  
+}
+
+bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) {
+
+  log.debug("createString ctx: %s - key: %s", context, key);
+
+  string final_key = string(context) + ":" + string(key);
+
+  mc_record rec(value, expiration);
+  string final_value;
+  serialize(rec, final_value);
+
+  bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version
+
+  if (result && m_buildMap) {
+    log.debug("Got result, updating map");
+
+    string map_name = context;
+    // we need to update the context map
+    if (! addLock(map_name)) {
+      log.error("Unable to get lock for context %s!", context);
+      deleteMemcache(final_key.c_str(), 0);
+      return false;
+    }
+
+    string ser_arr;
+    uint32_t flags;
+    bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
+    
+    list<string> contents;
+    if (result) {
+      log.debug("Match found. Parsing...");
+
+      deserialize(ser_arr, contents);
+      
+      log.debug("Iterating retrieved session map...");
+      list<string>::iterator iter;
+      for(iter = contents.begin(); 
+          iter != contents.end();
+          iter++) {
+        log.debug("value = " + *iter);
+      }
+
+    } else {
+      log.debug("New context: %s", map_name.c_str());
+
+    }
+
+    contents.push_back(key);
+    serialize(contents, ser_arr);    
+    setMemcache(map_name.c_str(), ser_arr, expiration, 0);    
+    
+    deleteLock(map_name);
+  }
+
+  return result;  
+
+}
+
+int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) {
+
+  log.debug("readString ctx: %s - key: %s", context, key);
+
+  string final_key = string(context) + ":" + string(key);
+  uint32_t rec_version;
+  string value;
+
+  if (m_buildMap) {
+    log.debug("Checking context");
+
+    string map_name = context;
+    string ser_arr;
+    uint32_t flags;
+    bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);
+
+    if (!ctx_found) {
+      return 0;
+    }
+  }
+
+  bool found = getMemcache(final_key.c_str(), value, &rec_version);
+  if (!found) {
+    return 0;
+  }
+
+  if (version && rec_version <= (uint32_t)version) {
+    return version;
+  }
+
+  if (pexpiration || pvalue) {
+    mc_record rec;
+    deserialize(value, rec);
+    
+    if (pexpiration) {
+      *pexpiration = rec.expiration;
+    }
+    
+    if (pvalue) {
+      *pvalue = rec.value;
+    }
+  }
+  
+  return rec_version;
+
+}
+
+int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) {
+
+  log.debug("updateString ctx: %s - key: %s", context, key);
+
+  time_t final_exp = expiration;
+  time_t *want_expiration = NULL;
+  if (! final_exp) {
+    want_expiration = &final_exp;
+  }
+
+  int read_res = readString(context, key, NULL, want_expiration, version);
+
+  if (!read_res) {
+    // not found
+    return read_res;
+  }
+
+  if (version && version != read_res) {
+    // version incorrect
+    return -1;
+  }
+
+  // Proceding with update
+  string final_key = string(context) + ":" + string(key);
+  mc_record rec(value, final_exp);
+  string final_value;
+  serialize(rec, final_value);
+
+  replaceMemcache(final_key.c_str(), final_value, final_exp, ++version);
+  return version;
+
+}
+
+bool MemcacheStorageService::deleteString(const char* context, const char* key) {
+
+  log.debug("deleteString ctx: %s - key: %s", context, key);
+  
+  string final_key = string(context) + ":" + string(key);
+
+  // Not updating context map, if there is one. There is no need.
+
+  return deleteMemcache(final_key.c_str(), 0);
+
+}
+
+void MemcacheStorageService::updateContext(const char* context, time_t expiration) {
+
+  log.debug("updateContext ctx: %s", context);
+
+  if (!m_buildMap) {
+    log.error("updateContext invoked on a Storage with no context map built!");
+    return;
+  }
+
+  string map_name = context;
+  string ser_arr;
+  uint32_t flags;
+  bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
+  
+  list<string> contents;
+  if (result) {
+    log.debug("Match found. Parsing...");
+    
+    deserialize(ser_arr, contents);
+    
+    log.debug("Iterating retrieved session map...");
+    list<string>::iterator iter;
+    for(iter = contents.begin(); 
+        iter != contents.end();
+        iter++) {
+
+      // Update expiration times
+      string value;      
+      int read_res = readString(context, iter->c_str(), &value, NULL, 0);
+      
+      if (!read_res) {
+        // not found
+        continue;
+      }
+
+      updateString(context, iter->c_str(), value.c_str(), expiration, read_res);
+    }
+    replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);
+  }
+  
+}
+
+void MemcacheStorageService::deleteContext(const char* context) {
+
+  log.debug("deleteContext ctx: %s", context);
+
+  if (!m_buildMap) {
+    log.error("deleteContext invoked on a Storage with no context map built!");
+    return;
+  }
+
+  string map_name = context;
+  string ser_arr;
+  uint32_t flags;
+  bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
+  
+  list<string> contents;
+  if (result) {
+    log.debug("Match found. Parsing...");
+    
+    deserialize(ser_arr, contents);
+    
+    log.debug("Iterating retrieved session map...");
+    list<string>::iterator iter;
+    for(iter = contents.begin(); 
+        iter != contents.end();
+        iter++) {
+      string final_key = map_name + *iter;
+      deleteMemcache(final_key.c_str(), 0);
+    }
+    
+    deleteMemcache(map_name.c_str(), 0);
+  }
+  
+}
+
+extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {
+    // Register this SS type
+    XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);
+    return 0;
+}
+
+extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {
+    XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");
+}
index 42c4d44..bd4e56a 100644 (file)
@@ -1,14 +1,14 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by memcache-store.rc\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1001\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by memcache-store.rc
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
index 7a79a45..625d6ee 100644 (file)
@@ -1,14 +1,14 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by odbc-store.rc\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1001\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by odbc-store.rc
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
index 8c10883..d1e2a9f 100644 (file)
-<?xml version="1.0" encoding="utf-8"?>\r
-\r
-<!-- \r
-Modified copy of WS-Trust schema that only contains WS-Fed PRP-relevant content. \r
- -->\r
-\r
-<!--\r
-\r
-Copyright Notice\r
-\r
-(c) 2001-2005 Actional Corporation, BEA Systems, Inc., \r
-Computer Associates International, Inc., International Business Machines Corporation, \r
-Layer 7 Technologies, Microsoft Corporation, Netegrity, Inc., Oblix Inc.,\r
-OpenNetwork Technologies Inc., Ping Identity Corporation, Reactivity Inc., \r
-RSA Security Inc., and VeriSign Inc.\r
-All rights reserved. \r
-\r
-Permission to copy and display the WS-Trust Specification (the "Specification", which \r
-includes WSDL and schema documents), in any medium without fee or royalty \r
-is hereby granted, provided that you include the following on ALL copies of the \r
-Specification, that you make:\r
-\r
-1.  A link or URL to the Specification at one of the Authors' websites\r
-2. The copyright notice as shown in the Specification.\r
-\r
-IBM, Microsoft and Actional, BEA, Computer Associates, Layer 7, Netegrity, Oblix, \r
-OpenNetwork, Ping Identity, Reactivity, and Verisign (collectively, the "Authors") each \r
-agree to grant you a license, under royalty-free and otherwise reasonable, \r
-non-discriminatory terms and conditions, to their respective essential patent claims \r
-that they deem necessary to implement the Specification.\r
-\r
-THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE \r
-NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT \r
-NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A \r
-PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF \r
-THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE \r
-IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY \r
-PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.\r
-\r
-THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, \r
-INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY \r
-USE OR DISTRIBUTION OF THE SPECIFICATION.\r
-\r
-The name and trademarks of the Authors may NOT be used in any manner, \r
-including advertising or publicity pertaining to the Specification or \r
-its contents without specific, written prior permission. Title to \r
-copyright in the Specification will at all times remain with the Authors.\r
-\r
-No other rights are granted by implication, estoppel or otherwise.\r
-\r
--->\r
-<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'\r
-                  xmlns:wst='http://schemas.xmlsoap.org/ws/2005/02/trust'\r
-                  targetNamespace='http://schemas.xmlsoap.org/ws/2005/02/trust' \r
-                  elementFormDefault='qualified' >\r
-\r
-  <!-- WS-Trust Section 5.2 -->\r
-  <xs:element name='RequestSecurityTokenResponse' type='wst:RequestSecurityTokenResponseType' />\r
-  <xs:complexType name='RequestSecurityTokenResponseType' >\r
-       <xs:annotation>\r
-         <xs:documentation>\r
-               Actual content model is non-deterministic, hence wildcard. The following shows intended content model:\r
-\r
-               <xs:element ref='wst:TokenType' minOccurs='0' />\r
-               <xs:element ref='wst:RequestType' />\r
-               <xs:element ref='wst:RequestedSecurityToken'  minOccurs='0' />\r
-               <xs:element ref='wsp:AppliesTo' minOccurs='0' /> \r
-               <xs:element ref='wst:RequestedAttachedReference' minOccurs='0' />\r
-               <xs:element ref='wst:RequestedUnattachedReference' minOccurs='0' />\r
-               <xs:element ref='wst:RequestedProofToken' minOccurs='0' />\r
-               <xs:element ref='wst:Entropy' minOccurs='0' />\r
-               <xs:element ref='wst:Lifetime' minOccurs='0' />\r
-               <xs:element ref='wst:Status' minOccurs='0' />\r
-               <xs:element ref='wst:AllowPostdating' minOccurs='0' />\r
-               <xs:element ref='wst:Renewing' minOccurs='0' />\r
-               <xs:element ref='wst:OnBehalfOf' minOccurs='0' />\r
-               <xs:element ref='wst:Issuer' minOccurs='0' />\r
-               <xs:element ref='wst:AuthenticationType' minOccurs='0' />\r
-               <xs:element ref='wst:Authenticator' minOccurs='0' />\r
-               <xs:element ref='wst:KeyType' minOccurs='0' />\r
-               <xs:element ref='wst:KeySize' minOccurs='0' />\r
-               <xs:element ref='wst:SignatureAlgorithm' minOccurs='0' />\r
-               <xs:element ref='wst:Encryption' minOccurs='0' />\r
-               <xs:element ref='wst:EncryptionAlgorithm' minOccurs='0' />\r
-               <xs:element ref='wst:CanonicalizationAlgorithm' minOccurs='0' />\r
-               <xs:element ref='wst:ProofEncryption' minOccurs='0' />\r
-               <xs:element ref='wst:UseKey' minOccurs='0' />\r
-               <xs:element ref='wst:SignWith' minOccurs='0' />\r
-               <xs:element ref='wst:EncryptWith' minOccurs='0' />\r
-               <xs:element ref='wst:DelegateTo' minOccurs='0' />\r
-               <xs:element ref='wst:Forwardable' minOccurs='0' />\r
-               <xs:element ref='wst:Delegatable' minOccurs='0' />\r
-               <xs:element ref='wsp:Policy' minOccurs='0' />\r
-               <xs:element ref='wsp:PolicyReference' minOccurs='0' />\r
-               <xs:any namespace='##other' processContents='lax' minOccurs='0' maxOccurs='unbounded' />\r
-\r
-         </xs:documentation>\r
-       </xs:annotation>\r
-       <xs:sequence>\r
-         <xs:any namespace='##any' processContents='lax' minOccurs='0' maxOccurs='unbounded' />\r
-       </xs:sequence>\r
-       <xs:attribute name='Context' type='xs:anyURI' use='optional' />\r
-       <xs:anyAttribute namespace='##other' processContents='lax' />\r
-  </xs:complexType>\r
-\r
-  <xs:element name='RequestedSecurityToken' type='wst:RequestedSecurityTokenType' />\r
-  <xs:complexType name='RequestedSecurityTokenType' >\r
-       <xs:sequence>\r
-         <xs:any namespace='##any' processContents='lax' />\r
-       </xs:sequence>\r
-  </xs:complexType>\r
-\r
-</xs:schema>\r
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 
+Modified copy of WS-Trust schema that only contains WS-Fed PRP-relevant content. 
+ -->
+
+<!--
+
+Copyright Notice
+
+(c) 2001-2005 Actional Corporation, BEA Systems, Inc., 
+Computer Associates International, Inc., International Business Machines Corporation, 
+Layer 7 Technologies, Microsoft Corporation, Netegrity, Inc., Oblix Inc.,
+OpenNetwork Technologies Inc., Ping Identity Corporation, Reactivity Inc., 
+RSA Security Inc., and VeriSign Inc.
+All rights reserved. 
+
+Permission to copy and display the WS-Trust Specification (the "Specification", which 
+includes WSDL and schema documents), in any medium without fee or royalty 
+is hereby granted, provided that you include the following on ALL copies of the 
+Specification, that you make:
+
+1.  A link or URL to the Specification at one of the Authors' websites
+2. The copyright notice as shown in the Specification.
+
+IBM, Microsoft and Actional, BEA, Computer Associates, Layer 7, Netegrity, Oblix, 
+OpenNetwork, Ping Identity, Reactivity, and Verisign (collectively, the "Authors") each 
+agree to grant you a license, under royalty-free and otherwise reasonable, 
+non-discriminatory terms and conditions, to their respective essential patent claims 
+that they deem necessary to implement the Specification.
+
+THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE 
+NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT 
+NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF 
+THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE 
+IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY 
+PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, 
+INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY 
+USE OR DISTRIBUTION OF THE SPECIFICATION.
+
+The name and trademarks of the Authors may NOT be used in any manner, 
+including advertising or publicity pertaining to the Specification or 
+its contents without specific, written prior permission. Title to 
+copyright in the Specification will at all times remain with the Authors.
+
+No other rights are granted by implication, estoppel or otherwise.
+
+-->
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
+                  xmlns:wst='http://schemas.xmlsoap.org/ws/2005/02/trust'
+                  targetNamespace='http://schemas.xmlsoap.org/ws/2005/02/trust' 
+                  elementFormDefault='qualified' >
+
+  <!-- WS-Trust Section 5.2 -->
+  <xs:element name='RequestSecurityTokenResponse' type='wst:RequestSecurityTokenResponseType' />
+  <xs:complexType name='RequestSecurityTokenResponseType' >
+       <xs:annotation>
+         <xs:documentation>
+               Actual content model is non-deterministic, hence wildcard. The following shows intended content model:
+
+               <xs:element ref='wst:TokenType' minOccurs='0' />
+               <xs:element ref='wst:RequestType' />
+               <xs:element ref='wst:RequestedSecurityToken'  minOccurs='0' />
+               <xs:element ref='wsp:AppliesTo' minOccurs='0' /> 
+               <xs:element ref='wst:RequestedAttachedReference' minOccurs='0' />
+               <xs:element ref='wst:RequestedUnattachedReference' minOccurs='0' />
+               <xs:element ref='wst:RequestedProofToken' minOccurs='0' />
+               <xs:element ref='wst:Entropy' minOccurs='0' />
+               <xs:element ref='wst:Lifetime' minOccurs='0' />
+               <xs:element ref='wst:Status' minOccurs='0' />
+               <xs:element ref='wst:AllowPostdating' minOccurs='0' />
+               <xs:element ref='wst:Renewing' minOccurs='0' />
+               <xs:element ref='wst:OnBehalfOf' minOccurs='0' />
+               <xs:element ref='wst:Issuer' minOccurs='0' />
+               <xs:element ref='wst:AuthenticationType' minOccurs='0' />
+               <xs:element ref='wst:Authenticator' minOccurs='0' />
+               <xs:element ref='wst:KeyType' minOccurs='0' />
+               <xs:element ref='wst:KeySize' minOccurs='0' />
+               <xs:element ref='wst:SignatureAlgorithm' minOccurs='0' />
+               <xs:element ref='wst:Encryption' minOccurs='0' />
+               <xs:element ref='wst:EncryptionAlgorithm' minOccurs='0' />
+               <xs:element ref='wst:CanonicalizationAlgorithm' minOccurs='0' />
+               <xs:element ref='wst:ProofEncryption' minOccurs='0' />
+               <xs:element ref='wst:UseKey' minOccurs='0' />
+               <xs:element ref='wst:SignWith' minOccurs='0' />
+               <xs:element ref='wst:EncryptWith' minOccurs='0' />
+               <xs:element ref='wst:DelegateTo' minOccurs='0' />
+               <xs:element ref='wst:Forwardable' minOccurs='0' />
+               <xs:element ref='wst:Delegatable' minOccurs='0' />
+               <xs:element ref='wsp:Policy' minOccurs='0' />
+               <xs:element ref='wsp:PolicyReference' minOccurs='0' />
+               <xs:any namespace='##other' processContents='lax' minOccurs='0' maxOccurs='unbounded' />
+
+         </xs:documentation>
+       </xs:annotation>
+       <xs:sequence>
+         <xs:any namespace='##any' processContents='lax' minOccurs='0' maxOccurs='unbounded' />
+       </xs:sequence>
+       <xs:attribute name='Context' type='xs:anyURI' use='optional' />
+       <xs:anyAttribute namespace='##other' processContents='lax' />
+  </xs:complexType>
+
+  <xs:element name='RequestedSecurityToken' type='wst:RequestedSecurityTokenType' />
+  <xs:complexType name='RequestedSecurityTokenType' >
+       <xs:sequence>
+         <xs:any namespace='##any' processContents='lax' />
+       </xs:sequence>
+  </xs:complexType>
+
+</xs:schema>
index 675f41f..ded4423 100644 (file)
@@ -4,10 +4,10 @@
     xmlns="http://www.w3.org/2001/XMLSchema"
     xmlns:afp="urn:mace:shibboleth:2.0:afp"
     xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
-    elementFormDefault="qualified">\r
-\r
-    <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="classpath:/schema/xmldsig-core-schema.xsd" />\r
-\r
+    elementFormDefault="qualified">
+
+    <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="classpath:/schema/xmldsig-core-schema.xsd" />
+
     <annotation>
         <documentation>Schema for the attribute filter policies.</documentation>
     </annotation>
@@ -51,7 +51,7 @@
                                 Defines an attribute rule that may be reused across multiple filter policies.
                             </documentation>
                         </annotation>
-                    </element>\r
+                    </element>
                     <element ref="afp:AttributeFilterPolicy" minOccurs="0" maxOccurs="unbounded">
                         <annotation>
                             <documentation>
                                 such as a federation site, should be signed.
                             </documentation>
                         </annotation>
-                    </element>\r
-                </sequence>\r
+                    </element>
+                </sequence>
             </extension>
-        </complexContent>\r
+        </complexContent>
     </complexType>
 
     <element name="AttributeFilterPolicy" type="afp:AttributeFilterPolicyType">
                 </sequence>
             </extension>
         </complexContent>
-    </complexType>\r
-\r
+    </complexType>
+
     <element name="AttributeRule" type="afp:AttributeRuleType">
         <annotation>
             <documentation>A rule that describes how values of an attribute will be filtered.</documentation>
         </annotation>
-    </element>\r
+    </element>
     <complexType name="AttributeRuleType">
         <complexContent>
             <extension base="afp:IdentityType">
                     </annotation>
                 </attribute>
             </extension>
-        </complexContent>\r
+        </complexContent>
     </complexType>
 
     <element name="PolicyRequirementRule" type="afp:MatchFunctorType">
         </attribute>
     </complexType>
 
-</schema>
\ No newline at end of file
+</schema>
index 99c9be6..24a051e 100644 (file)
-<?xml version="1.0" encoding="US-ASCII"?>\r
-<schema targetNamespace="urn:mace:shibboleth:2.0:native:sp:config"\r
-       xmlns="http://www.w3.org/2001/XMLSchema"\r
-       xmlns:conf="urn:mace:shibboleth:2.0:native:sp:config"\r
-       xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"\r
-       xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"\r
-       xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"\r
-       elementFormDefault="qualified"\r
-       attributeFormDefault="unqualified"\r
-       blockDefault="substitution"\r
-       version="2.3">\r
-\r
-       <import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>\r
-       <import namespace="urn:oasis:names:tc:SAML:2.0:protocol" schemaLocation="saml-schema-protocol-2.0.xsd"/>\r
-       <import namespace="urn:oasis:names:tc:SAML:2.0:metadata" schemaLocation="saml-schema-metadata-2.0.xsd"/>\r
-\r
-       <annotation>\r
-               <documentation>\r
-               2.0 schema for XML-based configuration of Shibboleth Native SP instances.\r
-               First appearing in Shibboleth 2.0 release.\r
-               </documentation>\r
-       </annotation>\r
-\r
-       <simpleType name="string">\r
-               <restriction base="string">\r
-                       <minLength value="1"/>\r
-               </restriction>\r
-       </simpleType>\r
-\r
-       <simpleType name="listOfStrings">\r
-               <list itemType="conf:string"/>\r
-       </simpleType>\r
-\r
-       <simpleType name="listOfURIs">\r
-               <list itemType="anyURI"/>\r
-       </simpleType>\r
-\r
-       <simpleType name="bindingBoolean">\r
-               <restriction base="string">\r
-                       <enumeration value="true"/>\r
-                       <enumeration value="false"/>\r
-                       <enumeration value="front"/>\r
-                       <enumeration value="back"/>\r
-               </restriction>\r
-       </simpleType>\r
-       \r
-       <complexType name="PluggableType">\r
-               <sequence>\r
-                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-               </sequence>\r
-               <attribute name="type" type="conf:string" use="required"/>\r
-               <anyAttribute namespace="##any" processContents="lax"/>\r
-       </complexType>\r
-\r
-       <element name="SPConfig">\r
-               <complexType>\r
-                       <annotation>\r
-                               <documentation>Root of configuration</documentation>\r
-                       </annotation>\r
-                       <sequence>\r
-                               <element ref="conf:Extensions" minOccurs="0"/>\r
-                               <element ref="conf:OutOfProcess"/>\r
-                               <element ref="conf:InProcess"/>\r
-                <choice minOccurs="0">\r
-                    <element name="UnixListener">\r
-                        <complexType>\r
-                            <attribute name="address" type="conf:string" use="required"/>\r
-                        </complexType>\r
-                    </element>\r
-                    <element name="TCPListener">\r
-                        <complexType>\r
-                            <attribute name="address" type="conf:string" use="required"/>\r
-                            <attribute name="port" type="unsignedInt" use="required"/>\r
-                            <attribute name="acl" type="conf:listOfStrings"/>\r
-                        </complexType>\r
-                    </element>\r
-                    <element name="Listener" type="conf:PluggableType"/>\r
-                </choice>\r
-                <element ref="conf:StorageService" minOccurs="0" maxOccurs="unbounded"/>\r
-                <element ref="conf:SessionCache" minOccurs="0"/>\r
-                <element ref="conf:ReplayCache" minOccurs="0"/>\r
-                <element ref="conf:ArtifactMap" minOccurs="0"/>\r
-                <element name="RequestMapper" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element ref="conf:ApplicationDefaults"/>\r
-                               <element ref="conf:SecurityPolicies"/>\r
+<?xml version="1.0" encoding="US-ASCII"?>
+<schema targetNamespace="urn:mace:shibboleth:2.0:native:sp:config"
+       xmlns="http://www.w3.org/2001/XMLSchema"
+       xmlns:conf="urn:mace:shibboleth:2.0:native:sp:config"
+       xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+       xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+       xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
+       elementFormDefault="qualified"
+       attributeFormDefault="unqualified"
+       blockDefault="substitution"
+       version="2.3">
+
+       <import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>
+       <import namespace="urn:oasis:names:tc:SAML:2.0:protocol" schemaLocation="saml-schema-protocol-2.0.xsd"/>
+       <import namespace="urn:oasis:names:tc:SAML:2.0:metadata" schemaLocation="saml-schema-metadata-2.0.xsd"/>
+
+       <annotation>
+               <documentation>
+               2.0 schema for XML-based configuration of Shibboleth Native SP instances.
+               First appearing in Shibboleth 2.0 release.
+               </documentation>
+       </annotation>
+
+       <simpleType name="string">
+               <restriction base="string">
+                       <minLength value="1"/>
+               </restriction>
+       </simpleType>
+
+       <simpleType name="listOfStrings">
+               <list itemType="conf:string"/>
+       </simpleType>
+
+       <simpleType name="listOfURIs">
+               <list itemType="anyURI"/>
+       </simpleType>
+
+       <simpleType name="bindingBoolean">
+               <restriction base="string">
+                       <enumeration value="true"/>
+                       <enumeration value="false"/>
+                       <enumeration value="front"/>
+                       <enumeration value="back"/>
+               </restriction>
+       </simpleType>
+       
+       <complexType name="PluggableType">
+               <sequence>
+                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+               </sequence>
+               <attribute name="type" type="conf:string" use="required"/>
+               <anyAttribute namespace="##any" processContents="lax"/>
+       </complexType>
+
+       <element name="SPConfig">
+               <complexType>
+                       <annotation>
+                               <documentation>Root of configuration</documentation>
+                       </annotation>
+                       <sequence>
+                               <element ref="conf:Extensions" minOccurs="0"/>
+                               <element ref="conf:OutOfProcess"/>
+                               <element ref="conf:InProcess"/>
+                <choice minOccurs="0">
+                    <element name="UnixListener">
+                        <complexType>
+                            <attribute name="address" type="conf:string" use="required"/>
+                        </complexType>
+                    </element>
+                    <element name="TCPListener">
+                        <complexType>
+                            <attribute name="address" type="conf:string" use="required"/>
+                            <attribute name="port" type="unsignedInt" use="required"/>
+                            <attribute name="acl" type="conf:listOfStrings"/>
+                        </complexType>
+                    </element>
+                    <element name="Listener" type="conf:PluggableType"/>
+                </choice>
+                <element ref="conf:StorageService" minOccurs="0" maxOccurs="unbounded"/>
+                <element ref="conf:SessionCache" minOccurs="0"/>
+                <element ref="conf:ReplayCache" minOccurs="0"/>
+                <element ref="conf:ArtifactMap" minOccurs="0"/>
+                <element name="RequestMapper" type="conf:PluggableType" minOccurs="0"/>
+                               <element ref="conf:ApplicationDefaults"/>
+                               <element ref="conf:SecurityPolicies"/>
                 <element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>
-                       </sequence>\r
-                       <attribute name="logger" type="anyURI"/>\r
-                       <attribute name="clockSkew" type="unsignedInt"/>\r
+                       </sequence>
+                       <attribute name="logger" type="anyURI"/>
+                       <attribute name="clockSkew" type="unsignedInt"/>
             <attribute name="unsafeChars" type="conf:string"/>
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="Extensions">\r
-               <annotation>\r
-                       <documentation>Container for extension libraries and custom configuration</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <element name="Library" minOccurs="0" maxOccurs="unbounded">\r
-                                       <complexType>\r
-                                               <sequence>\r
-                                                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                                               </sequence>\r
-                                               <attribute name="path" type="anyURI" use="required"/>\r
-                                               <attribute name="fatal" type="boolean"/>\r
-                                               <anyAttribute namespace="##any" processContents="lax"/>\r
-                                       </complexType>\r
-                               </element>\r
-                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="StorageService">\r
-               <annotation>\r
-                       <documentation>References StorageService plugins</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <complexContent>\r
-                               <restriction base="conf:PluggableType">\r
-                                       <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                                       </sequence>\r
-                                       <attribute name="id" type="ID" use="required"/>\r
-                                       <attribute name="cleanupInterval" type="unsignedInt"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
-                               </restriction>\r
-                       </complexContent>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="SessionCache">\r
-               <annotation>\r
-                       <documentation>References SessionCache plugins</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <complexContent>\r
-                               <restriction base="conf:PluggableType">\r
-                                       <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                                       </sequence>\r
-                                       <attribute name="StorageService" type="IDREF"/>\r
-                                       <attribute name="cacheTimeout" type="unsignedInt"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
-                               </restriction>\r
-                       </complexContent>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="ReplayCache">\r
-               <annotation>\r
-                       <documentation>Ties ReplayCache to a custom StorageService</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence/>\r
-                       <attribute name="StorageService" type="IDREF" use="required"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="ArtifactMap">\r
-               <annotation>\r
-                       <documentation>Customizes an ArtifactMap</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence/>\r
-                       <attribute name="StorageService" type="IDREF"/>\r
-                       <attribute name="context" type="conf:string"/>\r
-                       <attribute name="artifactTTL" type="unsignedInt"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="OutOfProcess">\r
-               <annotation>\r
-                       <documentation>Container for out-of-process (shibd) configuration</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <element ref="conf:Extensions" minOccurs="0"/>\r
-                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-                       <attribute name="logger" type="anyURI"/>\r
-                   <attribute name="catchAll" type="boolean"/>\r
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="InProcess">\r
-               <annotation>\r
-                       <documentation>\r
-                       Container for configuration of locally integrated or platform-specific\r
-                       features (e.g. web server filters)\r
-                       </documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <element ref="conf:Extensions" minOccurs="0"/>\r
-                               <element ref="conf:ISAPI" minOccurs="0"/>\r
-                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-                       <attribute name="logger" type="anyURI"/>\r
-                       <attribute name="unsetHeaderValue" type="conf:string"/>\r
-                       <attribute name="checkSpoofing" type="boolean"/>\r
-                       <attribute name="spoofKey" type="conf:string"/>\r
-                       <attribute name="catchAll" type="boolean"/>\r
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="ISAPI">\r
-               <complexType>\r
-                       <sequence>\r
-                               <element name="Site" maxOccurs="unbounded">\r
-                                       <complexType>\r
-                                               <sequence>\r
-                                                       <element name="Alias" type="string" minOccurs="0" maxOccurs="unbounded"/>\r
-                                               </sequence>\r
-                                               <attribute name="id" type="unsignedInt" use="required"/>\r
-                                               <attribute name="name" type="conf:string" use="required"/>\r
-                                               <attribute name="port" type="unsignedInt"/>\r
-                                               <attribute name="sslport" type="unsignedInt"/>\r
-                                               <attribute name="scheme" type="conf:string"/>\r
-                                       </complexType>\r
-                               </element>\r
-                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-                       <attribute name="normalizeRequest" type="boolean"/>\r
-                       <attribute name="safeHeaderNames" type="boolean"/>\r
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="AccessControl" type="conf:UniOperatorType">\r
-               <annotation>\r
-                       <documentation>\r
-                       A simple example access policy language extension that supersedes Apache .htaccess\r
-                       </documentation>\r
-               </annotation>\r
-       </element>\r
-       <element name="OR" type="conf:MultiOperatorType"/>\r
-       <element name="AND" type="conf:MultiOperatorType"/>\r
-       <element name="NOT" type="conf:UniOperatorType"/>\r
-       <complexType name="UniOperatorType">\r
-               <choice>\r
-                       <element ref="conf:AND"/>\r
-                       <element ref="conf:OR"/>\r
-                       <element ref="conf:NOT"/>\r
-                       <element ref="conf:Rule"/>\r
-                   <element ref="conf:RuleRegex"/>\r
-               </choice>\r
-       </complexType>\r
-       <complexType name="MultiOperatorType">\r
-               <choice minOccurs="2" maxOccurs="unbounded">\r
-                       <element ref="conf:AND"/>\r
-                       <element ref="conf:OR"/>\r
-                       <element ref="conf:NOT"/>\r
-                       <element ref="conf:Rule"/>\r
-                   <element ref="conf:RuleRegex"/>\r
-               </choice>\r
-       </complexType>\r
-       <element name="Rule">\r
-               <complexType>\r
-                       <simpleContent>\r
-                               <extension base="conf:listOfStrings">\r
-                                       <attribute name="require" type="conf:string" use="required"/>\r
-                                   <attribute name="list" type="boolean"/>\r
-                               </extension>\r
-                       </simpleContent>\r
-               </complexType>\r
-       </element>\r
-    <element name="RuleRegex">\r
-        <complexType>\r
-            <simpleContent>\r
-                <extension base="conf:string">\r
-                    <attribute name="require" type="conf:string" use="required"/>\r
-                    <attribute name="ignoreCase" type="boolean"/>\r
-                </extension>\r
-            </simpleContent>\r
-        </complexType>\r
-    </element>\r
-       \r
-       <attributeGroup name="ContentSettings">\r
-               <attribute name="authType" type="conf:string"/>\r
-               <attribute name="requireSession" type="boolean"/>\r
-               <attribute name="requireSessionWith" type="conf:string"/>\r
-               <attribute name="exportAssertion" type="boolean"/>\r
-               <attribute name="redirectToSSL" type="unsignedInt"/>\r
-               <attribute name="entityID" type="anyURI"/>\r
-        <attribute name="discoveryURL" type="anyURI"/>\r
-               <attribute name="isPassive" type="boolean"/>\r
-               <attribute name="forceAuthn" type="boolean"/>\r
-               <attribute name="authnContextClassRef" type="anyURI"/>\r
-               <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
-        <attribute name="NameIDFormat" type="anyURI"/>\r
-        <attribute name="SPNameQualifier" type="conf:string"/>\r
-        <attribute name="redirectErrors" type="anyURI"/>\r
-               <attribute name="sessionError" type="anyURI"/>\r
-               <attribute name="metadataError" type="anyURI"/>\r
-               <attribute name="accessError" type="anyURI"/>\r
-               <attribute name="sslError" type="anyURI"/>\r
-        <attribute name="REMOTE_ADDR" type="conf:string"/>\r
-               <anyAttribute namespace="##other" processContents="lax"/>\r
-       </attributeGroup>\r
-       <element name="AccessControlProvider" type="conf:PluggableType"/>\r
-       <element name="htaccess" type="conf:PluggableType"/>\r
-\r
-    <element name="RequestMap">\r
-               <annotation>\r
-                       <documentation>\r
-                       Built-in request mapping syntax, decomposes URLs into Host/Path/Path/...\r
-                       </documentation>\r
-               </annotation>\r
-        <complexType>\r
-            <sequence>\r
-               <choice minOccurs="0">\r
-                       <element ref="conf:htaccess"/>\r
-                                       <element ref="conf:AccessControl"/>\r
-                       <element ref="conf:AccessControlProvider"/>\r
-                   </choice>\r
-               <choice minOccurs="0" maxOccurs="unbounded">\r
-                                       <element ref="conf:Host"/>\r
-                       <element ref="conf:HostRegex"/>\r
-               </choice>\r
-            </sequence>\r
-            <attribute name="applicationId" type="conf:string" fixed="default"/>\r
-               <attributeGroup ref="conf:ContentSettings"/>\r
-        </complexType>\r
-    </element>\r
-\r
-    <element name="Host">\r
-       <complexType>\r
-               <sequence>\r
-               <choice minOccurs="0">\r
-                       <element ref="conf:htaccess"/>\r
-                                       <element ref="conf:AccessControl"/>\r
-                       <element ref="conf:AccessControlProvider"/>\r
-                   </choice>\r
-                       <choice minOccurs="0" maxOccurs="unbounded">\r
-                               <element ref="conf:Path"/>\r
-                               <element ref="conf:PathRegex"/>\r
-                               <element ref="conf:Query"/>\r
-                       </choice>\r
-               </sequence>\r
-               <attribute name="scheme">\r
-                           <simpleType>\r
-                               <restriction base="conf:string">\r
-                                   <enumeration value="http"/>\r
-                                   <enumeration value="https"/>\r
-                                   <enumeration value="ftp"/>\r
-                                   <enumeration value="ldap"/>\r
-                                   <enumeration value="ldaps"/>\r
-                               </restriction>\r
-                           </simpleType>\r
-               </attribute>\r
-               <attribute name="name" type="conf:string" use="required"/>\r
-               <attribute name="port" type="unsignedInt"/>\r
-                       <attribute name="applicationId" type="conf:string"/>\r
-               <attributeGroup ref="conf:ContentSettings"/>\r
-       </complexType>\r
-    </element>\r
-       \r
-       <element name="HostRegex">\r
-               <complexType>\r
-                       <sequence>\r
-                               <choice minOccurs="0">\r
-                                       <element ref="conf:htaccess"/>\r
-                                       <element ref="conf:AccessControl"/>\r
-                                       <element ref="conf:AccessControlProvider"/>\r
-                               </choice>\r
-                               <choice minOccurs="0" maxOccurs="unbounded">\r
-                                       <element ref="conf:Path"/>\r
-                                       <element ref="conf:PathRegex"/>\r
-                                       <element ref="conf:Query"/>\r
-                               </choice>\r
-                       </sequence>\r
-                       <attribute name="regex" type="conf:string" use="required"/>\r
-                       <attribute name="ignoreCase" type="boolean"/>\r
-                       <attribute name="applicationId" type="conf:string"/>\r
-                       <attributeGroup ref="conf:ContentSettings"/>\r
-               </complexType>\r
-       </element>\r
-\r
-    <element name="Path">\r
-        <complexType>\r
-               <sequence>\r
-               <choice minOccurs="0">\r
-                       <element ref="conf:htaccess"/>\r
-                                       <element ref="conf:AccessControl"/>\r
-                       <element ref="conf:AccessControlProvider"/>\r
-                   </choice>\r
-                       <choice minOccurs="0" maxOccurs="unbounded">\r
-                               <element ref="conf:Path"/>\r
-                               <element ref="conf:PathRegex"/>\r
-                               <element ref="conf:Query"/>\r
-                       </choice>\r
-               </sequence>\r
-                       <attribute name="name" type="conf:string" use="required"/>\r
-                       <attribute name="applicationId" type="conf:string"/>\r
-                       <attributeGroup ref="conf:ContentSettings"/>\r
-        </complexType>\r
-    </element>\r
-\r
-       <element name="PathRegex">\r
-               <complexType>\r
-                       <sequence>\r
-                               <choice minOccurs="0">\r
-                                       <element ref="conf:htaccess"/>\r
-                                       <element ref="conf:AccessControl"/>\r
-                                       <element ref="conf:AccessControlProvider"/>\r
-                               </choice>\r
-                               <element ref="conf:Query" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-                       <attribute name="regex" type="conf:string" use="required"/>\r
-                       <attribute name="ignoreCase" type="boolean"/>\r
-                       <attribute name="applicationId" type="conf:string"/>\r
-                       <attributeGroup ref="conf:ContentSettings"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="Query">\r
-               <complexType>\r
-                       <sequence>\r
-                               <choice minOccurs="0">\r
-                                       <element ref="conf:htaccess"/>\r
-                                       <element ref="conf:AccessControl"/>\r
-                                       <element ref="conf:AccessControlProvider"/>\r
-                               </choice>\r
-                               <element ref="conf:Query" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-                       <attribute name="name" type="conf:string" use="required"/>\r
-                       <attribute name="regex" type="conf:string"/>\r
-                       <attributeGroup ref="conf:ContentSettings"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="ApplicationDefaults">\r
-               <annotation>\r
-                       <documentation>Container for default settings and application-specific overrides</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <element ref="conf:Sessions"/>\r
-                               <element ref="conf:Errors" minOccurs="0"/>\r
-                               <element ref="conf:RelyingParty" minOccurs="0" maxOccurs="unbounded"/>\r
-                               <element ref="conf:Notify" minOccurs="0" maxOccurs="unbounded"/>\r
-                               <element ref="saml:Audience" minOccurs="0" maxOccurs="unbounded"/>\r
-                <element name="MetadataProvider" type="conf:PluggableType"/>\r
-                               <element name="TrustEngine" type="conf:PluggableType"/>\r
-                               <element name="AttributeExtractor" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="AttributeResolver" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="AttributeFilter" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="CredentialResolver" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element ref="conf:ApplicationOverride" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-                       <attribute name="id" type="conf:string" fixed="default"/>\r
-                       <attribute name="entityID" type="anyURI" use="required"/>\r
-                       <attribute name="policyId" type="conf:string" use="required"/>\r
-                       <attributeGroup ref="conf:ApplicationGroup"/>\r
-                   <attributeGroup ref="conf:RelyingPartyGroup"/>\r
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="ApplicationOverride">\r
-               <annotation>\r
-                       <documentation>Container for application-specific overrides</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <element ref="conf:Sessions" minOccurs="0"/>\r
-                               <element ref="conf:Errors" minOccurs="0"/>\r
-                               <element ref="conf:RelyingParty" minOccurs="0" maxOccurs="unbounded"/>\r
-                               <element ref="conf:Notify" minOccurs="0" maxOccurs="unbounded"/>\r
-                               <element ref="saml:Audience" minOccurs="0" maxOccurs="unbounded"/>\r
-                               <element name="MetadataProvider" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="TrustEngine" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="AttributeExtractor" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="AttributeResolver" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="AttributeFilter" type="conf:PluggableType" minOccurs="0"/>\r
-                               <element name="CredentialResolver" type="conf:PluggableType" minOccurs="0"/>\r
-                       </sequence>\r
-                       <attribute name="id" type="conf:string" use="required"/>\r
-                       <attribute name="entityID" type="anyURI"/>\r
-                       <attribute name="policyId" type="conf:string"/>\r
-                       <attributeGroup ref="conf:ApplicationGroup"/>\r
-                   <attributeGroup ref="conf:RelyingPartyGroup"/>\r
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-\r
-       <attributeGroup name="ApplicationGroup">\r
-               <attribute name="homeURL" type="anyURI"/>\r
-               <attribute name="REMOTE_USER" type="conf:listOfStrings"/>\r
-               <attribute name="unsetHeaders" type="conf:listOfStrings"/>\r
-               <attribute name="metadataAttributePrefix" type="conf:string"/>\r
-           <attribute name="attributePrefix" type="conf:string"/>\r
-       </attributeGroup>\r
-\r
-    <attributeGroup name="RelyingPartyGroup">\r
-        <attribute name="authType" type="conf:string"/>\r
-        <attribute name="authUsername" type="conf:string"/>\r
-        <attribute name="authPassword" type="conf:string"/>\r
-        <attribute name="signing" type="conf:bindingBoolean"/>\r
-        <attribute name="signingAlg" type="anyURI"/>\r
-        <attribute name="digestAlg" type="anyURI"/>\r
-        <attribute name="encryption" type="conf:bindingBoolean"/>\r
-        <attribute name="encryptionAlg" type="anyURI"/>\r
-        <attribute name="keyName" type="conf:string"/>\r
-        <attribute name="artifactEndpointIndex" type="unsignedShort"/>\r
-        <attribute name="chunkedEncoding" type="boolean"/>\r
-        <attribute name="connectTimeout" type="unsignedShort"/>\r
-        <attribute name="timeout" type="unsignedShort"/>\r
-        <attribute name="requireConfidentiality" type="boolean"/>\r
-        <attribute name="requireTransportAuth" type="boolean"/>\r
-        <attribute name="requireSignedAssertions" type="boolean"/>\r
-    </attributeGroup>\r
-    \r
-       <element name="Sessions">\r
-               <annotation>\r
-                       <documentation>Container for specifying protocol handlers and session policy</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <choice minOccurs="0" maxOccurs="unbounded">\r
-                               <element ref="conf:SessionInitiator"/>\r
-                               <element ref="conf:LogoutInitiator"/>\r
-                               <element ref="md:AssertionConsumerService"/>\r
-                               <element ref="md:ArtifactResolutionService"/>\r
-                               <element ref="md:SingleLogoutService"/>\r
-                               <element ref="md:ManageNameIDService"/>\r
-                               <element name="Handler">\r
-                                       <complexType>\r
-                                               <complexContent>\r
-                                                       <restriction base="conf:PluggableType">\r
-                                                               <sequence>\r
-                                                                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                                                               </sequence>\r
-                                                               <attribute name="Location" type="anyURI" use="required"/>\r
-                                                           <attribute name="acl" type="conf:listOfStrings"/>\r
-                                                               <anyAttribute namespace="##any" processContents="lax"/>\r
-                                                       </restriction>\r
-                                               </complexContent>\r
-                                       </complexType>\r
-                               </element>\r
-                       </choice>\r
-                       <attribute name="handlerURL" type="anyURI" use="required"/>\r
-                       <attribute name="handlerSSL" type="boolean"/>\r
-                       <attribute name="exportLocation" type="conf:string"/>\r
-                       <attribute name="exportACL" type="conf:listOfStrings"/>\r
-                       <attribute name="cookieName" type="conf:string"/>\r
-                       <attribute name="cookieProps" type="conf:string"/>\r
-            <attribute name="cookieLifetime" type="unsignedInt"/>\r
-                       <attribute name="idpHistory" type="boolean"/>\r
-                       <attribute name="idpHistoryDays" type="unsignedInt"/>\r
-                       <attribute name="lifetime" type="unsignedInt"/>\r
-                       <attribute name="timeout" type="unsignedInt"/>\r
-                   <attribute name="maxTimeSinceAuthn" type="unsignedInt"/>\r
-                       <attribute name="checkAddress" type="boolean"/>\r
-                       <attribute name="consistentAddress" type="boolean"/>\r
-                       <attribute name="postData" type="conf:string"/>\r
-            <attribute name="postLimit" type="positiveInteger"/>\r
-                       <attribute name="postTemplate" type="conf:string"/>\r
-            <attribute name="postExpire" type="boolean"/>\r
-                       <anyAttribute namespace="##other" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-\r
-       <attribute name="policyId" type="conf:string">\r
-               <annotation>\r
-                       <documentation>Used to reference Policy elements from profile endpoints.</documentation>\r
-               </annotation>\r
-       </attribute>\r
-\r
-       <element name="SessionInitiator">\r
-               <annotation>\r
-                       <documentation>Used to specify handlers that can issue AuthnRequests or perform discovery</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <complexContent>\r
-                               <restriction base="conf:PluggableType">\r
-                                       <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                                       </sequence>\r
-                                       <attribute name="Location" type="anyURI"/>\r
-                                       <attribute name="id" type="conf:string"/>\r
-                                       <attribute name="isDefault" type="boolean"/>\r
-                                       <attribute name="relayState" type="conf:string"/>\r
-                                       <attribute name="entityIDParam" type="conf:string"/>\r
-                                       <attribute name="entityID" type="anyURI"/>\r
-                                       <attribute name="URL" type="anyURI"/>\r
-                                       <attribute name="outgoingBindings" type="conf:listOfURIs"/>\r
-                                       <attribute name="template" type="anyURI"/>\r
-                                       <attribute name="postArtifact" type="boolean"/>\r
-                                       <attribute name="acsByIndex" type="boolean"/>\r
-                    <attribute name="acsIndex" type="unsignedShort"/>\r
-                                       <attribute name="defaultACSIndex" type="unsignedShort"/>   <!-- deprecated -->\r
-                    <attribute name="isPassive" type="boolean"/>\r
-                    <attribute name="forceAuthn" type="boolean"/>\r
-                    <attribute name="authnContextClassRef" type="anyURI"/>\r
-                    <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
-                    <attribute name="NameIDFormat" type="anyURI"/>\r
-                    <attribute name="SPNameQualifier" type="conf:string"/>\r
-                    <attribute name="requestDelegation" type="boolean"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
-                               </restriction>\r
-                       </complexContent>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="LogoutInitiator">\r
-               <annotation>\r
-                       <documentation>Used to specify handlers that can issue LogoutRequests</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <complexContent>\r
-                               <restriction base="conf:PluggableType">\r
-                                       <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                                       </sequence>\r
-                                       <attribute name="Location" type="anyURI"/>\r
-                                   <attribute name="relayState" type="conf:string"/>\r
-                                       <attribute name="outgoingBindings" type="conf:listOfURIs"/>\r
-                                       <attribute name="template" type="anyURI"/>\r
-                                       <attribute name="postArtifact" type="boolean"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
-                               </restriction>\r
-                       </complexContent>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="Errors">\r
-               <annotation>\r
-                       <documentation>Container for error templates and associated details</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
-                       </sequence>\r
-            <attribute name="redirectErrors" type="anyURI"/>\r
-                       <attribute name="session" type="anyURI"/>\r
-                       <attribute name="metadata" type="anyURI"/>\r
-                       <attribute name="access" type="anyURI"/>\r
-                       <attribute name="ssl" type="anyURI"/>\r
-            <attribute name="localLogout" type="anyURI"/>\r
-            <attribute name="globalLogout" type="anyURI"/>\r
-            <attribute name="partialLogout" type="anyURI"/>\r
-                       <attribute name="supportContact" type="conf:string"/>\r
-                       <attribute name="logoLocation" type="anyURI"/>\r
-                       <attribute name="styleSheet" type="anyURI"/>\r
-                       <anyAttribute namespace="##any" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-\r
-    <element name="RelyingParty">\r
-        <annotation>\r
-            <documentation>Container for specifying settings to use with particular peers</documentation>\r
-        </annotation>\r
-        <complexType>\r
-            <sequence/>\r
-            <attribute name="Name" type="conf:string" use="required"/>\r
-            <attributeGroup ref="conf:RelyingPartyGroup"/>\r
-            <attribute name="entityID" type="anyURI"/>\r
-            <anyAttribute namespace="##other" processContents="lax"/>\r
-        </complexType>\r
-    </element>\r
-    \r
-       <element name="Notify">\r
-               <annotation>\r
-                       <documentation>Used to specify locations to receive application notifications</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence/>\r
-                       <attribute name="Channel" use="required">\r
-                               <simpleType>\r
-                                       <restriction base="string">\r
-                                               <enumeration value="front"/>\r
-                                               <enumeration value="back"/>\r
-                                       </restriction>\r
-                               </simpleType>\r
-                       </attribute>\r
-                       <attribute name="Location" type="anyURI" use="required"/>\r
-                       <anyAttribute namespace="##any" processContents="lax"/>\r
-               </complexType>\r
-       </element>\r
-       \r
-       <element name="SecurityPolicies">\r
-               <annotation>\r
-                       <documentation>Container for specifying sets of policy rules to apply to incoming messages</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <sequence>\r
-                               <element name="Policy" minOccurs="1" maxOccurs="unbounded">\r
-                                       <annotation>\r
-                                               <documentation>Specifies a set of SecurityPolicyRule plugins</documentation>\r
-                                       </annotation>\r
-                                       <complexType>\r
-                                               <choice>\r
-                                                       <element name="Rule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>\r
-                            <element name="PolicyRule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>\r
-                                               </choice>\r
-                                               <attribute name="id" type="conf:string" use="required"/>\r
-                                               <attribute name="validate" type="boolean"/>\r
-                                               <anyAttribute namespace="##any" processContents="lax"/>\r
-                                       </complexType>\r
-                               </element>\r
-                       </sequence>\r
-               </complexType>\r
-       </element>\r
-\r
-       <element name="TransportOption">\r
-               <annotation>\r
-                       <documentation>Implementation-specific option to pass to SOAPTransport provider.</documentation>\r
-               </annotation>\r
-               <complexType>\r
-                       <simpleContent>\r
-                               <extension base="anySimpleType">\r
-                                       <attribute name="provider" type="conf:string" use="required"/>\r
-                                       <attribute name="option" type="conf:string" use="required"/>\r
-                               </extension>\r
-                       </simpleContent>\r
-               </complexType>\r
-       </element>\r
-       \r
-</schema>\r
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+
+       <element name="Extensions">
+               <annotation>
+                       <documentation>Container for extension libraries and custom configuration</documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <element name="Library" minOccurs="0" maxOccurs="unbounded">
+                                       <complexType>
+                                               <sequence>
+                                                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                                               </sequence>
+                                               <attribute name="path" type="anyURI" use="required"/>
+                                               <attribute name="fatal" type="boolean"/>
+                                               <anyAttribute namespace="##any" processContents="lax"/>
+                                       </complexType>
+                               </element>
+                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+               </complexType>
+       </element>
+
+       <element name="StorageService">
+               <annotation>
+                       <documentation>References StorageService plugins</documentation>
+               </annotation>
+               <complexType>
+                       <complexContent>
+                               <restriction base="conf:PluggableType">
+                                       <sequence>
+                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                                       </sequence>
+                                       <attribute name="id" type="ID" use="required"/>
+                                       <attribute name="cleanupInterval" type="unsignedInt"/>
+                                       <anyAttribute namespace="##any" processContents="lax"/>
+                               </restriction>
+                       </complexContent>
+               </complexType>
+       </element>
+
+       <element name="SessionCache">
+               <annotation>
+                       <documentation>References SessionCache plugins</documentation>
+               </annotation>
+               <complexType>
+                       <complexContent>
+                               <restriction base="conf:PluggableType">
+                                       <sequence>
+                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                                       </sequence>
+                                       <attribute name="StorageService" type="IDREF"/>
+                                       <attribute name="cacheTimeout" type="unsignedInt"/>
+                                       <anyAttribute namespace="##any" processContents="lax"/>
+                               </restriction>
+                       </complexContent>
+               </complexType>
+       </element>
+       
+       <element name="ReplayCache">
+               <annotation>
+                       <documentation>Ties ReplayCache to a custom StorageService</documentation>
+               </annotation>
+               <complexType>
+                       <sequence/>
+                       <attribute name="StorageService" type="IDREF" use="required"/>
+               </complexType>
+       </element>
+       
+       <element name="ArtifactMap">
+               <annotation>
+                       <documentation>Customizes an ArtifactMap</documentation>
+               </annotation>
+               <complexType>
+                       <sequence/>
+                       <attribute name="StorageService" type="IDREF"/>
+                       <attribute name="context" type="conf:string"/>
+                       <attribute name="artifactTTL" type="unsignedInt"/>
+               </complexType>
+       </element>
+       
+       <element name="OutOfProcess">
+               <annotation>
+                       <documentation>Container for out-of-process (shibd) configuration</documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <element ref="conf:Extensions" minOccurs="0"/>
+                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+                       <attribute name="logger" type="anyURI"/>
+                   <attribute name="catchAll" type="boolean"/>
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+
+       <element name="InProcess">
+               <annotation>
+                       <documentation>
+                       Container for configuration of locally integrated or platform-specific
+                       features (e.g. web server filters)
+                       </documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <element ref="conf:Extensions" minOccurs="0"/>
+                               <element ref="conf:ISAPI" minOccurs="0"/>
+                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+                       <attribute name="logger" type="anyURI"/>
+                       <attribute name="unsetHeaderValue" type="conf:string"/>
+                       <attribute name="checkSpoofing" type="boolean"/>
+                       <attribute name="spoofKey" type="conf:string"/>
+                       <attribute name="catchAll" type="boolean"/>
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+       
+       <element name="ISAPI">
+               <complexType>
+                       <sequence>
+                               <element name="Site" maxOccurs="unbounded">
+                                       <complexType>
+                                               <sequence>
+                                                       <element name="Alias" type="string" minOccurs="0" maxOccurs="unbounded"/>
+                                               </sequence>
+                                               <attribute name="id" type="unsignedInt" use="required"/>
+                                               <attribute name="name" type="conf:string" use="required"/>
+                                               <attribute name="port" type="unsignedInt"/>
+                                               <attribute name="sslport" type="unsignedInt"/>
+                                               <attribute name="scheme" type="conf:string"/>
+                                       </complexType>
+                               </element>
+                               <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+                       <attribute name="normalizeRequest" type="boolean"/>
+                       <attribute name="safeHeaderNames" type="boolean"/>
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+
+       <element name="AccessControl" type="conf:UniOperatorType">
+               <annotation>
+                       <documentation>
+                       A simple example access policy language extension that supersedes Apache .htaccess
+                       </documentation>
+               </annotation>
+       </element>
+       <element name="OR" type="conf:MultiOperatorType"/>
+       <element name="AND" type="conf:MultiOperatorType"/>
+       <element name="NOT" type="conf:UniOperatorType"/>
+       <complexType name="UniOperatorType">
+               <choice>
+                       <element ref="conf:AND"/>
+                       <element ref="conf:OR"/>
+                       <element ref="conf:NOT"/>
+                       <element ref="conf:Rule"/>
+                   <element ref="conf:RuleRegex"/>
+               </choice>
+       </complexType>
+       <complexType name="MultiOperatorType">
+               <choice minOccurs="2" maxOccurs="unbounded">
+                       <element ref="conf:AND"/>
+                       <element ref="conf:OR"/>
+                       <element ref="conf:NOT"/>
+                       <element ref="conf:Rule"/>
+                   <element ref="conf:RuleRegex"/>
+               </choice>
+       </complexType>
+       <element name="Rule">
+               <complexType>
+                       <simpleContent>
+                               <extension base="conf:listOfStrings">
+                                       <attribute name="require" type="conf:string" use="required"/>
+                                   <attribute name="list" type="boolean"/>
+                               </extension>
+                       </simpleContent>
+               </complexType>
+       </element>
+    <element name="RuleRegex">
+        <complexType>
+            <simpleContent>
+                <extension base="conf:string">
+                    <attribute name="require" type="conf:string" use="required"/>
+                    <attribute name="ignoreCase" type="boolean"/>
+                </extension>
+            </simpleContent>
+        </complexType>
+    </element>
+       
+       <attributeGroup name="ContentSettings">
+               <attribute name="authType" type="conf:string"/>
+               <attribute name="requireSession" type="boolean"/>
+               <attribute name="requireSessionWith" type="conf:string"/>
+               <attribute name="exportAssertion" type="boolean"/>
+               <attribute name="redirectToSSL" type="unsignedInt"/>
+               <attribute name="entityID" type="anyURI"/>
+        <attribute name="discoveryURL" type="anyURI"/>
+               <attribute name="isPassive" type="boolean"/>
+               <attribute name="forceAuthn" type="boolean"/>
+               <attribute name="authnContextClassRef" type="anyURI"/>
+               <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
+        <attribute name="NameIDFormat" type="anyURI"/>
+        <attribute name="SPNameQualifier" type="conf:string"/>
+        <attribute name="redirectErrors" type="anyURI"/>
+               <attribute name="sessionError" type="anyURI"/>
+               <attribute name="metadataError" type="anyURI"/>
+               <attribute name="accessError" type="anyURI"/>
+               <attribute name="sslError" type="anyURI"/>
+        <attribute name="REMOTE_ADDR" type="conf:string"/>
+               <anyAttribute namespace="##other" processContents="lax"/>
+       </attributeGroup>
+       <element name="AccessControlProvider" type="conf:PluggableType"/>
+       <element name="htaccess" type="conf:PluggableType"/>
+
+    <element name="RequestMap">
+               <annotation>
+                       <documentation>
+                       Built-in request mapping syntax, decomposes URLs into Host/Path/Path/...
+                       </documentation>
+               </annotation>
+        <complexType>
+            <sequence>
+               <choice minOccurs="0">
+                       <element ref="conf:htaccess"/>
+                                       <element ref="conf:AccessControl"/>
+                       <element ref="conf:AccessControlProvider"/>
+                   </choice>
+               <choice minOccurs="0" maxOccurs="unbounded">
+                                       <element ref="conf:Host"/>
+                       <element ref="conf:HostRegex"/>
+               </choice>
+            </sequence>
+            <attribute name="applicationId" type="conf:string" fixed="default"/>
+               <attributeGroup ref="conf:ContentSettings"/>
+        </complexType>
+    </element>
+
+    <element name="Host">
+       <complexType>
+               <sequence>
+               <choice minOccurs="0">
+                       <element ref="conf:htaccess"/>
+                                       <element ref="conf:AccessControl"/>
+                       <element ref="conf:AccessControlProvider"/>
+                   </choice>
+                       <choice minOccurs="0" maxOccurs="unbounded">
+                               <element ref="conf:Path"/>
+                               <element ref="conf:PathRegex"/>
+                               <element ref="conf:Query"/>
+                       </choice>
+               </sequence>
+               <attribute name="scheme">
+                           <simpleType>
+                               <restriction base="conf:string">
+                                   <enumeration value="http"/>
+                                   <enumeration value="https"/>
+                                   <enumeration value="ftp"/>
+                                   <enumeration value="ldap"/>
+                                   <enumeration value="ldaps"/>
+                               </restriction>
+                           </simpleType>
+               </attribute>
+               <attribute name="name" type="conf:string" use="required"/>
+               <attribute name="port" type="unsignedInt"/>
+                       <attribute name="applicationId" type="conf:string"/>
+               <attributeGroup ref="conf:ContentSettings"/>
+       </complexType>
+    </element>
+       
+       <element name="HostRegex">
+               <complexType>
+                       <sequence>
+                               <choice minOccurs="0">
+                                       <element ref="conf:htaccess"/>
+                                       <element ref="conf:AccessControl"/>
+                                       <element ref="conf:AccessControlProvider"/>
+                               </choice>
+                               <choice minOccurs="0" maxOccurs="unbounded">
+                                       <element ref="conf:Path"/>
+                                       <element ref="conf:PathRegex"/>
+                                       <element ref="conf:Query"/>
+                               </choice>
+                       </sequence>
+                       <attribute name="regex" type="conf:string" use="required"/>
+                       <attribute name="ignoreCase" type="boolean"/>
+                       <attribute name="applicationId" type="conf:string"/>
+                       <attributeGroup ref="conf:ContentSettings"/>
+               </complexType>
+       </element>
+
+    <element name="Path">
+        <complexType>
+               <sequence>
+               <choice minOccurs="0">
+                       <element ref="conf:htaccess"/>
+                                       <element ref="conf:AccessControl"/>
+                       <element ref="conf:AccessControlProvider"/>
+                   </choice>
+                       <choice minOccurs="0" maxOccurs="unbounded">
+                               <element ref="conf:Path"/>
+                               <element ref="conf:PathRegex"/>
+                               <element ref="conf:Query"/>
+                       </choice>
+               </sequence>
+                       <attribute name="name" type="conf:string" use="required"/>
+                       <attribute name="applicationId" type="conf:string"/>
+                       <attributeGroup ref="conf:ContentSettings"/>
+        </complexType>
+    </element>
+
+       <element name="PathRegex">
+               <complexType>
+                       <sequence>
+                               <choice minOccurs="0">
+                                       <element ref="conf:htaccess"/>
+                                       <element ref="conf:AccessControl"/>
+                                       <element ref="conf:AccessControlProvider"/>
+                               </choice>
+                               <element ref="conf:Query" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+                       <attribute name="regex" type="conf:string" use="required"/>
+                       <attribute name="ignoreCase" type="boolean"/>
+                       <attribute name="applicationId" type="conf:string"/>
+                       <attributeGroup ref="conf:ContentSettings"/>
+               </complexType>
+       </element>
+       
+       <element name="Query">
+               <complexType>
+                       <sequence>
+                               <choice minOccurs="0">
+                                       <element ref="conf:htaccess"/>
+                                       <element ref="conf:AccessControl"/>
+                                       <element ref="conf:AccessControlProvider"/>
+                               </choice>
+                               <element ref="conf:Query" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+                       <attribute name="name" type="conf:string" use="required"/>
+                       <attribute name="regex" type="conf:string"/>
+                       <attributeGroup ref="conf:ContentSettings"/>
+               </complexType>
+       </element>
+       
+       <element name="ApplicationDefaults">
+               <annotation>
+                       <documentation>Container for default settings and application-specific overrides</documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <element ref="conf:Sessions"/>
+                               <element ref="conf:Errors" minOccurs="0"/>
+                               <element ref="conf:RelyingParty" minOccurs="0" maxOccurs="unbounded"/>
+                               <element ref="conf:Notify" minOccurs="0" maxOccurs="unbounded"/>
+                               <element ref="saml:Audience" minOccurs="0" maxOccurs="unbounded"/>
+                <element name="MetadataProvider" type="conf:PluggableType"/>
+                               <element name="TrustEngine" type="conf:PluggableType"/>
+                               <element name="AttributeExtractor" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="AttributeResolver" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="AttributeFilter" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="CredentialResolver" type="conf:PluggableType" minOccurs="0"/>
+                               <element ref="conf:ApplicationOverride" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+                       <attribute name="id" type="conf:string" fixed="default"/>
+                       <attribute name="entityID" type="anyURI" use="required"/>
+                       <attribute name="policyId" type="conf:string" use="required"/>
+                       <attributeGroup ref="conf:ApplicationGroup"/>
+                   <attributeGroup ref="conf:RelyingPartyGroup"/>
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+       
+       <element name="ApplicationOverride">
+               <annotation>
+                       <documentation>Container for application-specific overrides</documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <element ref="conf:Sessions" minOccurs="0"/>
+                               <element ref="conf:Errors" minOccurs="0"/>
+                               <element ref="conf:RelyingParty" minOccurs="0" maxOccurs="unbounded"/>
+                               <element ref="conf:Notify" minOccurs="0" maxOccurs="unbounded"/>
+                               <element ref="saml:Audience" minOccurs="0" maxOccurs="unbounded"/>
+                               <element name="MetadataProvider" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="TrustEngine" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="AttributeExtractor" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="AttributeResolver" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="AttributeFilter" type="conf:PluggableType" minOccurs="0"/>
+                               <element name="CredentialResolver" type="conf:PluggableType" minOccurs="0"/>
+                       </sequence>
+                       <attribute name="id" type="conf:string" use="required"/>
+                       <attribute name="entityID" type="anyURI"/>
+                       <attribute name="policyId" type="conf:string"/>
+                       <attributeGroup ref="conf:ApplicationGroup"/>
+                   <attributeGroup ref="conf:RelyingPartyGroup"/>
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+
+       <attributeGroup name="ApplicationGroup">
+               <attribute name="homeURL" type="anyURI"/>
+               <attribute name="REMOTE_USER" type="conf:listOfStrings"/>
+               <attribute name="unsetHeaders" type="conf:listOfStrings"/>
+               <attribute name="metadataAttributePrefix" type="conf:string"/>
+           <attribute name="attributePrefix" type="conf:string"/>
+       </attributeGroup>
+
+    <attributeGroup name="RelyingPartyGroup">
+        <attribute name="authType" type="conf:string"/>
+        <attribute name="authUsername" type="conf:string"/>
+        <attribute name="authPassword" type="conf:string"/>
+        <attribute name="signing" type="conf:bindingBoolean"/>
+        <attribute name="signingAlg" type="anyURI"/>
+        <attribute name="digestAlg" type="anyURI"/>
+        <attribute name="encryption" type="conf:bindingBoolean"/>
+        <attribute name="encryptionAlg" type="anyURI"/>
+        <attribute name="keyName" type="conf:string"/>
+        <attribute name="artifactEndpointIndex" type="unsignedShort"/>
+        <attribute name="chunkedEncoding" type="boolean"/>
+        <attribute name="connectTimeout" type="unsignedShort"/>
+        <attribute name="timeout" type="unsignedShort"/>
+        <attribute name="requireConfidentiality" type="boolean"/>
+        <attribute name="requireTransportAuth" type="boolean"/>
+        <attribute name="requireSignedAssertions" type="boolean"/>
+    </attributeGroup>
+    
+       <element name="Sessions">
+               <annotation>
+                       <documentation>Container for specifying protocol handlers and session policy</documentation>
+               </annotation>
+               <complexType>
+                       <choice minOccurs="0" maxOccurs="unbounded">
+                               <element ref="conf:SessionInitiator"/>
+                               <element ref="conf:LogoutInitiator"/>
+                               <element ref="md:AssertionConsumerService"/>
+                               <element ref="md:ArtifactResolutionService"/>
+                               <element ref="md:SingleLogoutService"/>
+                               <element ref="md:ManageNameIDService"/>
+                               <element name="Handler">
+                                       <complexType>
+                                               <complexContent>
+                                                       <restriction base="conf:PluggableType">
+                                                               <sequence>
+                                                                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                                                               </sequence>
+                                                               <attribute name="Location" type="anyURI" use="required"/>
+                                                           <attribute name="acl" type="conf:listOfStrings"/>
+                                                               <anyAttribute namespace="##any" processContents="lax"/>
+                                                       </restriction>
+                                               </complexContent>
+                                       </complexType>
+                               </element>
+                       </choice>
+                       <attribute name="handlerURL" type="anyURI" use="required"/>
+                       <attribute name="handlerSSL" type="boolean"/>
+                       <attribute name="exportLocation" type="conf:string"/>
+                       <attribute name="exportACL" type="conf:listOfStrings"/>
+                       <attribute name="cookieName" type="conf:string"/>
+                       <attribute name="cookieProps" type="conf:string"/>
+            <attribute name="cookieLifetime" type="unsignedInt"/>
+                       <attribute name="idpHistory" type="boolean"/>
+                       <attribute name="idpHistoryDays" type="unsignedInt"/>
+                       <attribute name="lifetime" type="unsignedInt"/>
+                       <attribute name="timeout" type="unsignedInt"/>
+                   <attribute name="maxTimeSinceAuthn" type="unsignedInt"/>
+                       <attribute name="checkAddress" type="boolean"/>
+                       <attribute name="consistentAddress" type="boolean"/>
+                       <attribute name="postData" type="conf:string"/>
+            <attribute name="postLimit" type="positiveInteger"/>
+                       <attribute name="postTemplate" type="conf:string"/>
+            <attribute name="postExpire" type="boolean"/>
+                       <anyAttribute namespace="##other" processContents="lax"/>
+               </complexType>
+       </element>
+
+       <attribute name="policyId" type="conf:string">
+               <annotation>
+                       <documentation>Used to reference Policy elements from profile endpoints.</documentation>
+               </annotation>
+       </attribute>
+
+       <element name="SessionInitiator">
+               <annotation>
+                       <documentation>Used to specify handlers that can issue AuthnRequests or perform discovery</documentation>
+               </annotation>
+               <complexType>
+                       <complexContent>
+                               <restriction base="conf:PluggableType">
+                                       <sequence>
+                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                                       </sequence>
+                                       <attribute name="Location" type="anyURI"/>
+                                       <attribute name="id" type="conf:string"/>
+                                       <attribute name="isDefault" type="boolean"/>
+                                       <attribute name="relayState" type="conf:string"/>
+                                       <attribute name="entityIDParam" type="conf:string"/>
+                                       <attribute name="entityID" type="anyURI"/>
+                                       <attribute name="URL" type="anyURI"/>
+                                       <attribute name="outgoingBindings" type="conf:listOfURIs"/>
+                                       <attribute name="template" type="anyURI"/>
+                                       <attribute name="postArtifact" type="boolean"/>
+                                       <attribute name="acsByIndex" type="boolean"/>
+                    <attribute name="acsIndex" type="unsignedShort"/>
+                                       <attribute name="defaultACSIndex" type="unsignedShort"/>   <!-- deprecated -->
+                    <attribute name="isPassive" type="boolean"/>
+                    <attribute name="forceAuthn" type="boolean"/>
+                    <attribute name="authnContextClassRef" type="anyURI"/>
+                    <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
+                    <attribute name="NameIDFormat" type="anyURI"/>
+                    <attribute name="SPNameQualifier" type="conf:string"/>
+                    <attribute name="requestDelegation" type="boolean"/>
+                                       <anyAttribute namespace="##any" processContents="lax"/>
+                               </restriction>
+                       </complexContent>
+               </complexType>
+       </element>
+
+       <element name="LogoutInitiator">
+               <annotation>
+                       <documentation>Used to specify handlers that can issue LogoutRequests</documentation>
+               </annotation>
+               <complexType>
+                       <complexContent>
+                               <restriction base="conf:PluggableType">
+                                       <sequence>
+                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                                       </sequence>
+                                       <attribute name="Location" type="anyURI"/>
+                                   <attribute name="relayState" type="conf:string"/>
+                                       <attribute name="outgoingBindings" type="conf:listOfURIs"/>
+                                       <attribute name="template" type="anyURI"/>
+                                       <attribute name="postArtifact" type="boolean"/>
+                                       <anyAttribute namespace="##any" processContents="lax"/>
+                               </restriction>
+                       </complexContent>
+               </complexType>
+       </element>
+       
+       <element name="Errors">
+               <annotation>
+                       <documentation>Container for error templates and associated details</documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+                       </sequence>
+            <attribute name="redirectErrors" type="anyURI"/>
+                       <attribute name="session" type="anyURI"/>
+                       <attribute name="metadata" type="anyURI"/>
+                       <attribute name="access" type="anyURI"/>
+                       <attribute name="ssl" type="anyURI"/>
+            <attribute name="localLogout" type="anyURI"/>
+            <attribute name="globalLogout" type="anyURI"/>
+            <attribute name="partialLogout" type="anyURI"/>
+                       <attribute name="supportContact" type="conf:string"/>
+                       <attribute name="logoLocation" type="anyURI"/>
+                       <attribute name="styleSheet" type="anyURI"/>
+                       <anyAttribute namespace="##any" processContents="lax"/>
+               </complexType>
+       </element>
+
+    <element name="RelyingParty">
+        <annotation>
+            <documentation>Container for specifying settings to use with particular peers</documentation>
+        </annotation>
+        <complexType>
+            <sequence/>
+            <attribute name="Name" type="conf:string" use="required"/>
+            <attributeGroup ref="conf:RelyingPartyGroup"/>
+            <attribute name="entityID" type="anyURI"/>
+            <anyAttribute namespace="##other" processContents="lax"/>
+        </complexType>
+    </element>
+    
+       <element name="Notify">
+               <annotation>
+                       <documentation>Used to specify locations to receive application notifications</documentation>
+               </annotation>
+               <complexType>
+                       <sequence/>
+                       <attribute name="Channel" use="required">
+                               <simpleType>
+                                       <restriction base="string">
+                                               <enumeration value="front"/>
+                                               <enumeration value="back"/>
+                                       </restriction>
+                               </simpleType>
+                       </attribute>
+                       <attribute name="Location" type="anyURI" use="required"/>
+                       <anyAttribute namespace="##any" processContents="lax"/>
+               </complexType>
+       </element>
+       
+       <element name="SecurityPolicies">
+               <annotation>
+                       <documentation>Container for specifying sets of policy rules to apply to incoming messages</documentation>
+               </annotation>
+               <complexType>
+                       <sequence>
+                               <element name="Policy" minOccurs="1" maxOccurs="unbounded">
+                                       <annotation>
+                                               <documentation>Specifies a set of SecurityPolicyRule plugins</documentation>
+                                       </annotation>
+                                       <complexType>
+                                               <choice>
+                                                       <element name="Rule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>
+                            <element name="PolicyRule" type="conf:PluggableType" minOccurs="1" maxOccurs="unbounded"/>
+                                               </choice>
+                                               <attribute name="id" type="conf:string" use="required"/>
+                                               <attribute name="validate" type="boolean"/>
+                                               <anyAttribute namespace="##any" processContents="lax"/>
+                                       </complexType>
+                               </element>
+                       </sequence>
+               </complexType>
+       </element>
+
+       <element name="TransportOption">
+               <annotation>
+                       <documentation>Implementation-specific option to pass to SOAPTransport provider.</documentation>
+               </annotation>
+               <complexType>
+                       <simpleContent>
+                               <extension base="anySimpleType">
+                                       <attribute name="provider" type="conf:string" use="required"/>
+                                       <attribute name="option" type="conf:string" use="required"/>
+                               </extension>
+                       </simpleContent>
+               </complexType>
+       </element>
+       
+</schema>
index 4c86dae..2ac256d 100644 (file)
-/*\r
- *  Copyright 2001-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
- * shar.cpp -- the shibd "main" code.  All the functionality is elsewhere\r
- *\r
- * Created By: Derek Atkins <derek@ihtfp.com>\r
- *\r
- * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $\r
- */\r
-\r
-\r
-// eventually we might be able to support autoconf via cygwin...\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/SPConfig.h>\r
-\r
-#ifdef HAVE_UNISTD_H\r
-#include <unistd.h>\r
-#include <sys/select.h>\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <signal.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/remoting/ListenerService.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-bool shibd_shutdown = false;\r
-const char* shar_config = NULL;\r
-const char* shar_schemadir = NULL;\r
-const char* shar_prefix = NULL;\r
-bool shar_checkonly = false;\r
-bool shar_version = false;\r
-static bool unlink_socket = false;\r
-const char* pidfile = NULL;\r
-\r
-#ifdef WIN32\r
-\r
-//#include <CRTDBG.H>\r
-\r
-#define nNoMansLandSize 4\r
-typedef struct _CrtMemBlockHeader\r
-{\r
-        struct _CrtMemBlockHeader * pBlockHeaderNext;\r
-        struct _CrtMemBlockHeader * pBlockHeaderPrev;\r
-        char *                      szFileName;\r
-        int                         nLine;\r
-        size_t                      nDataSize;\r
-        int                         nBlockUse;\r
-        long                        lRequest;\r
-        unsigned char               gap[nNoMansLandSize];\r
-        /* followed by:\r
-         *  unsigned char           data[nDataSize];\r
-         *  unsigned char           anotherGap[nNoMansLandSize];\r
-         */\r
-} _CrtMemBlockHeader;\r
-\r
-/*\r
-int MyAllocHook(int nAllocType, void *pvData,\r
-      size_t nSize, int nBlockUse, long lRequest,\r
-      const unsigned char * szFileName, int nLine)\r
-{\r
-    if ( nBlockUse == _CRT_BLOCK )\r
-      return( TRUE );\r
-    if (nAllocType == _HOOK_FREE) {\r
-        _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);\r
-        if (ptr->nDataSize == 8192)\r
-            fprintf(stderr,"free  request %u size %u\n", ptr->lRequest, ptr->nDataSize);\r
-    }\r
-    else if (nAllocType == _HOOK_ALLOC && nSize == 8192)\r
-        fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);\r
-    return (TRUE);\r
-}\r
-*/\r
-\r
-int real_main(int preinit)\r
-{\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    if (preinit) {\r
-\r
-        // Initialize the SP library.\r
-        conf.setFeatures(\r
-            SPConfig::Listener |\r
-            SPConfig::Caching |\r
-            SPConfig::Metadata |\r
-            SPConfig::Trust |\r
-            SPConfig::Credentials |\r
-            SPConfig::AttributeResolution |\r
-            SPConfig::Handlers |\r
-            SPConfig::OutOfProcess |\r
-            (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
-            );\r
-        if (!conf.init(shar_schemadir, shar_prefix)) {\r
-            fprintf(stderr, "configuration is invalid, see console for specific problems\n");\r
-            return -1;\r
-        }\r
-\r
-        if (!conf.instantiate(shar_config)) {\r
-            fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
-            conf.term();\r
-            return -2;\r
-        }\r
-\r
-        // If just a test run, bail.\r
-        if (shar_checkonly) {\r
-            fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");\r
-            return 0;\r
-        }\r
-    }\r
-    else {\r
-\r
-        //_CrtSetAllocHook(MyAllocHook);\r
-\r
-        if (!shar_checkonly) {\r
-            // Run the listener.\r
-            ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
-            if (!listener->init(unlink_socket)) {\r
-                fprintf(stderr, "listener failed to initialize\n");\r
-                conf.term();\r
-                return -3;\r
-            }\r
-            else if (!listener->run(&shibd_shutdown)) {\r
-                fprintf(stderr, "listener failed during service\n");\r
-                listener->term();\r
-                conf.term();\r
-                return -3;\r
-            }\r
-            listener->term();\r
-        }\r
-\r
-        conf.term();\r
-    }\r
-    return 0;\r
-}\r
-\r
-#else\r
-\r
-int daemon_wait = 3;\r
-bool shibd_running = false;\r
-bool daemonize = true;\r
-\r
-static void term_handler(int arg)\r
-{\r
-    shibd_shutdown = true;\r
-}\r
-\r
-static void run_handler(int arg)\r
-{\r
-    shibd_running = true;\r
-}\r
-\r
-static void child_handler(int arg)\r
-{\r
-    // Terminate the parent's wait/sleep if the newly born daemon dies early.\r
-}\r
-\r
-static int setup_signals(void)\r
-{\r
-    struct sigaction sa;\r
-    memset(&sa, 0, sizeof (sa));\r
-    sa.sa_handler = SIG_IGN;\r
-    sa.sa_flags = SA_RESTART;\r
-\r
-    if (sigaction(SIGPIPE, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-\r
-    memset(&sa, 0, sizeof (sa));\r
-    sa.sa_handler = term_handler;\r
-    sa.sa_flags = SA_RESTART;\r
-\r
-    if (sigaction(SIGHUP, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-    if (sigaction(SIGINT, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-    if (sigaction(SIGQUIT, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-    if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-\r
-    if (daemonize) {\r
-        memset(&sa, 0, sizeof (sa));\r
-        sa.sa_handler = run_handler;\r
-\r
-        if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
-            return -1;\r
-        }\r
-\r
-        memset(&sa, 0, sizeof (sa));\r
-        sa.sa_handler = child_handler;\r
-\r
-        if (sigaction(SIGCHLD, &sa, NULL) < 0) {\r
-            return -1;\r
-        }\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-static void usage(char* whoami)\r
-{\r
-    fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);\r
-    fprintf(stderr, "  -d\tinstallation prefix to use.\n");\r
-    fprintf(stderr, "  -c\tconfig file to use.\n");\r
-    fprintf(stderr, "  -x\tXML schema catalogs to use.\n");\r
-    fprintf(stderr, "  -t\ttest configuration file for problems.\n");\r
-    fprintf(stderr, "  -f\tforce removal of listener socket.\n");\r
-    fprintf(stderr, "  -F\tstay in the foreground.\n");\r
-    fprintf(stderr, "  -p\tpid file to use.\n");\r
-    fprintf(stderr, "  -w\tseconds to wait for successful daemonization.\n");\r
-    fprintf(stderr, "  -v\tprint software version.\n");\r
-    fprintf(stderr, "  -h\tprint this help message.\n");\r
-    exit(1);\r
-}\r
-\r
-static int parse_args(int argc, char* argv[])\r
-{\r
-    int opt;\r
-\r
-    while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {\r
-        switch (opt) {\r
-            case 'd':\r
-                shar_prefix=optarg;\r
-                break;\r
-            case 'c':\r
-                shar_config=optarg;\r
-                break;\r
-            case 'x':\r
-                shar_schemadir=optarg;\r
-                break;\r
-            case 'f':\r
-                unlink_socket = true;\r
-                break;\r
-            case 'F':\r
-                daemonize = false;\r
-                break;\r
-            case 't':\r
-                shar_checkonly=true;\r
-                daemonize=false;\r
-                break;\r
-            case 'v':\r
-                shar_version=true;\r
-                break;\r
-            case 'p':\r
-                pidfile=optarg;\r
-                break;\r
-            case 'w':\r
-                if (optarg)\r
-                    daemon_wait = atoi(optarg);\r
-                if (daemon_wait <= 0)\r
-                    daemon_wait = 3;\r
-                break;\r
-            default:\r
-                return -1;\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-    if (parse_args(argc, argv) != 0)\r
-        usage(argv[0]);\r
-    else if (shar_version) {\r
-        fprintf(stdout, PACKAGE_STRING"\n");\r
-        return 0;\r
-    }\r
-\r
-    if (setup_signals() != 0)\r
-        return -1;\r
-\r
-    // initialize the shib-target library\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::Metadata |\r
-        SPConfig::Trust |\r
-        SPConfig::Credentials |\r
-        SPConfig::AttributeResolution |\r
-        SPConfig::Handlers |\r
-        SPConfig::OutOfProcess |\r
-        (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
-        );\r
-    if (!conf.init(shar_schemadir, shar_prefix)) {\r
-        fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
-        return -1;\r
-    }\r
-\r
-    if (daemonize) {\r
-        // We must fork() early, while we're single threaded.\r
-        // StorageService cleanup thread is about to start.\r
-        switch (fork()) {\r
-            case 0:\r
-                break;\r
-            case -1:\r
-                perror("forking");\r
-                exit(EXIT_FAILURE);\r
-            default:\r
-                sleep(daemon_wait);\r
-                exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
-        }\r
-    }\r
-\r
-    if (!conf.instantiate(shar_config)) {\r
-        fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
-        conf.term();\r
-        return -2;\r
-    }\r
-\r
-    if (shar_checkonly)\r
-        fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
-    else {\r
-        // Init the listener.\r
-        ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
-        if (!listener->init(unlink_socket)) {\r
-            fprintf(stderr, "listener failed to initialize\n");\r
-            conf.term();\r
-            return -3;\r
-        }\r
-\r
-        if (daemonize) {\r
-            if (setsid() == -1) {\r
-                perror("setsid");\r
-                exit(EXIT_FAILURE);\r
-            }\r
-            if (chdir("/") == -1) {\r
-                perror("chdir to root");\r
-                exit(EXIT_FAILURE);\r
-            }\r
-\r
-            if (pidfile) {\r
-                FILE* pidf = fopen(pidfile, "w");\r
-                if (pidf) {\r
-                    fprintf(pidf, "%d\n", getpid());\r
-                    fclose(pidf);\r
-                }\r
-                else {\r
-                    perror(pidfile);\r
-                }\r
-            }\r
-\r
-            freopen("/dev/null", "r", stdin);\r
-            freopen("/dev/null", "w", stdout);\r
-            freopen("/dev/null", "w", stderr);\r
-\r
-            // Signal our parent that we are A-OK.\r
-            kill(getppid(), SIGUSR1);\r
-        }\r
-\r
-        // Run the listener.\r
-        if (!listener->run(&shibd_shutdown)) {\r
-            fprintf(stderr, "listener failure during service\n");\r
-            listener->term();\r
-            conf.term();\r
-            if (pidfile)\r
-                unlink(pidfile);\r
-            return -3;\r
-        }\r
-        listener->term();\r
-    }\r
-\r
-    conf.term();\r
-    if (pidfile)\r
-        unlink(pidfile);\r
-    return 0;\r
-}\r
-\r
-#endif\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/*
+ * shar.cpp -- the shibd "main" code.  All the functionality is elsewhere
+ *
+ * Created By: Derek Atkins <derek@ihtfp.com>
+ *
+ * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $
+ */
+
+
+// eventually we might be able to support autoconf via cygwin...
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <shibsp/SPConfig.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#include <sys/select.h>
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#include <shibsp/ServiceProvider.h>
+#include <shibsp/remoting/ListenerService.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+bool shibd_shutdown = false;
+const char* shar_config = NULL;
+const char* shar_schemadir = NULL;
+const char* shar_prefix = NULL;
+bool shar_checkonly = false;
+bool shar_version = false;
+static bool unlink_socket = false;
+const char* pidfile = NULL;
+
+#ifdef WIN32
+
+//#include <CRTDBG.H>
+
+#define nNoMansLandSize 4
+typedef struct _CrtMemBlockHeader
+{
+        struct _CrtMemBlockHeader * pBlockHeaderNext;
+        struct _CrtMemBlockHeader * pBlockHeaderPrev;
+        char *                      szFileName;
+        int                         nLine;
+        size_t                      nDataSize;
+        int                         nBlockUse;
+        long                        lRequest;
+        unsigned char               gap[nNoMansLandSize];
+        /* followed by:
+         *  unsigned char           data[nDataSize];
+         *  unsigned char           anotherGap[nNoMansLandSize];
+         */
+} _CrtMemBlockHeader;
+
+/*
+int MyAllocHook(int nAllocType, void *pvData,
+      size_t nSize, int nBlockUse, long lRequest,
+      const unsigned char * szFileName, int nLine)
+{
+    if ( nBlockUse == _CRT_BLOCK )
+      return( TRUE );
+    if (nAllocType == _HOOK_FREE) {
+        _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
+        if (ptr->nDataSize == 8192)
+            fprintf(stderr,"free  request %u size %u\n", ptr->lRequest, ptr->nDataSize);
+    }
+    else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
+        fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
+    return (TRUE);
+}
+*/
+
+int real_main(int preinit)
+{
+    SPConfig& conf=SPConfig::getConfig();
+    if (preinit) {
+
+        // Initialize the SP library.
+        conf.setFeatures(
+            SPConfig::Listener |
+            SPConfig::Caching |
+            SPConfig::Metadata |
+            SPConfig::Trust |
+            SPConfig::Credentials |
+            SPConfig::AttributeResolution |
+            SPConfig::Handlers |
+            SPConfig::OutOfProcess |
+            (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
+            );
+        if (!conf.init(shar_schemadir, shar_prefix)) {
+            fprintf(stderr, "configuration is invalid, see console for specific problems\n");
+            return -1;
+        }
+
+        if (!conf.instantiate(shar_config)) {
+            fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+            conf.term();
+            return -2;
+        }
+
+        // If just a test run, bail.
+        if (shar_checkonly) {
+            fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
+            return 0;
+        }
+    }
+    else {
+
+        //_CrtSetAllocHook(MyAllocHook);
+
+        if (!shar_checkonly) {
+            // Run the listener.
+            ListenerService* listener = conf.getServiceProvider()->getListenerService();
+            if (!listener->init(unlink_socket)) {
+                fprintf(stderr, "listener failed to initialize\n");
+                conf.term();
+                return -3;
+            }
+            else if (!listener->run(&shibd_shutdown)) {
+                fprintf(stderr, "listener failed during service\n");
+                listener->term();
+                conf.term();
+                return -3;
+            }
+            listener->term();
+        }
+
+        conf.term();
+    }
+    return 0;
+}
+
+#else
+
+int daemon_wait = 3;
+bool shibd_running = false;
+bool daemonize = true;
+
+static void term_handler(int arg)
+{
+    shibd_shutdown = true;
+}
+
+static void run_handler(int arg)
+{
+    shibd_running = true;
+}
+
+static void child_handler(int arg)
+{
+    // Terminate the parent's wait/sleep if the newly born daemon dies early.
+}
+
+static int setup_signals(void)
+{
+    struct sigaction sa;
+    memset(&sa, 0, sizeof (sa));
+    sa.sa_handler = SIG_IGN;
+    sa.sa_flags = SA_RESTART;
+
+    if (sigaction(SIGPIPE, &sa, NULL) < 0) {
+        return -1;
+    }
+
+    memset(&sa, 0, sizeof (sa));
+    sa.sa_handler = term_handler;
+    sa.sa_flags = SA_RESTART;
+
+    if (sigaction(SIGHUP, &sa, NULL) < 0) {
+        return -1;
+    }
+    if (sigaction(SIGINT, &sa, NULL) < 0) {
+        return -1;
+    }
+    if (sigaction(SIGQUIT, &sa, NULL) < 0) {
+        return -1;
+    }
+    if (sigaction(SIGTERM, &sa, NULL) < 0) {
+        return -1;
+    }
+
+    if (daemonize) {
+        memset(&sa, 0, sizeof (sa));
+        sa.sa_handler = run_handler;
+
+        if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+            return -1;
+        }
+
+        memset(&sa, 0, sizeof (sa));
+        sa.sa_handler = child_handler;
+
+        if (sigaction(SIGCHLD, &sa, NULL) < 0) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static void usage(char* whoami)
+{
+    fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);
+    fprintf(stderr, "  -d\tinstallation prefix to use.\n");
+    fprintf(stderr, "  -c\tconfig file to use.\n");
+    fprintf(stderr, "  -x\tXML schema catalogs to use.\n");
+    fprintf(stderr, "  -t\ttest configuration file for problems.\n");
+    fprintf(stderr, "  -f\tforce removal of listener socket.\n");
+    fprintf(stderr, "  -F\tstay in the foreground.\n");
+    fprintf(stderr, "  -p\tpid file to use.\n");
+    fprintf(stderr, "  -w\tseconds to wait for successful daemonization.\n");
+    fprintf(stderr, "  -v\tprint software version.\n");
+    fprintf(stderr, "  -h\tprint this help message.\n");
+    exit(1);
+}
+
+static int parse_args(int argc, char* argv[])
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {
+        switch (opt) {
+            case 'd':
+                shar_prefix=optarg;
+                break;
+            case 'c':
+                shar_config=optarg;
+                break;
+            case 'x':
+                shar_schemadir=optarg;
+                break;
+            case 'f':
+                unlink_socket = true;
+                break;
+            case 'F':
+                daemonize = false;
+                break;
+            case 't':
+                shar_checkonly=true;
+                daemonize=false;
+                break;
+            case 'v':
+                shar_version=true;
+                break;
+            case 'p':
+                pidfile=optarg;
+                break;
+            case 'w':
+                if (optarg)
+                    daemon_wait = atoi(optarg);
+                if (daemon_wait <= 0)
+                    daemon_wait = 3;
+                break;
+            default:
+                return -1;
+        }
+    }
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    if (parse_args(argc, argv) != 0)
+        usage(argv[0]);
+    else if (shar_version) {
+        fprintf(stdout, PACKAGE_STRING"\n");
+        return 0;
+    }
+
+    if (setup_signals() != 0)
+        return -1;
+
+    // initialize the shib-target library
+    SPConfig& conf=SPConfig::getConfig();
+    conf.setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::Metadata |
+        SPConfig::Trust |
+        SPConfig::Credentials |
+        SPConfig::AttributeResolution |
+        SPConfig::Handlers |
+        SPConfig::OutOfProcess |
+        (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
+        );
+    if (!conf.init(shar_schemadir, shar_prefix)) {
+        fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+        return -1;
+    }
+
+    if (daemonize) {
+        // We must fork() early, while we're single threaded.
+        // StorageService cleanup thread is about to start.
+        switch (fork()) {
+            case 0:
+                break;
+            case -1:
+                perror("forking");
+                exit(EXIT_FAILURE);
+            default:
+                sleep(daemon_wait);
+                exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
+        }
+    }
+
+    if (!conf.instantiate(shar_config)) {
+        fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+        conf.term();
+        return -2;
+    }
+
+    if (shar_checkonly)
+        fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
+    else {
+        // Init the listener.
+        ListenerService* listener = conf.getServiceProvider()->getListenerService();
+        if (!listener->init(unlink_socket)) {
+            fprintf(stderr, "listener failed to initialize\n");
+            conf.term();
+            return -3;
+        }
+
+        if (daemonize) {
+            if (setsid() == -1) {
+                perror("setsid");
+                exit(EXIT_FAILURE);
+            }
+            if (chdir("/") == -1) {
+                perror("chdir to root");
+                exit(EXIT_FAILURE);
+            }
+
+            if (pidfile) {
+                FILE* pidf = fopen(pidfile, "w");
+                if (pidf) {
+                    fprintf(pidf, "%d\n", getpid());
+                    fclose(pidf);
+                }
+                else {
+                    perror(pidfile);
+                }
+            }
+
+            freopen("/dev/null", "r", stdin);
+            freopen("/dev/null", "w", stdout);
+            freopen("/dev/null", "w", stderr);
+
+            // Signal our parent that we are A-OK.
+            kill(getppid(), SIGUSR1);
+        }
+
+        // Run the listener.
+        if (!listener->run(&shibd_shutdown)) {
+            fprintf(stderr, "listener failure during service\n");
+            listener->term();
+            conf.term();
+            if (pidfile)
+                unlink(pidfile);
+            return -3;
+        }
+        listener->term();
+    }
+
+    conf.term();
+    if (pidfile)
+        unlink(pidfile);
+    return 0;
+}
+
+#endif
index b196ea8..7a9a602 100644 (file)
-/*\r
- *  Copyright 2001-2007 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
- * shar_win32.cpp -- the SHAR "main" code on Win32\r
- *\r
- * Created By: Scott Cantor (cantor.2@osu.edu)\r
- *\r
- * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $\r
- */\r
-\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-\r
-#include <shibsp/base.h>\r
-#include <string>\r
-#include <windows.h>\r
-\r
-using namespace std;\r
-\r
-extern bool shibd_shutdown;                    // signals shutdown to Unix side\r
-extern const char* shar_schemadir;\r
-extern const char* shar_config;\r
-extern const char* shar_prefix;\r
-extern bool shar_checkonly;\r
-\r
-// internal variables\r
-SERVICE_STATUS          ssStatus;       // current status of the service\r
-SERVICE_STATUS_HANDLE   sshStatusHandle;\r
-DWORD                   dwErr = 0;\r
-BOOL                    bConsole = FALSE;\r
-char                    szErr[256];\r
-LPCSTR                  lpszInstall = NULL;\r
-LPCSTR                  lpszRemove = NULL;\r
-\r
-// internal function prototypes\r
-VOID WINAPI service_ctrl(DWORD dwCtrlCode);\r
-VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);\r
-VOID CmdInstallService(LPCSTR);\r
-VOID CmdRemoveService(LPCSTR);\r
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );\r
-\r
-BOOL LogEvent(\r
-    LPCTSTR  lpUNCServerName,\r
-    WORD  wType,\r
-    DWORD  dwEventID,\r
-    PSID  lpUserSid,\r
-    LPCTSTR  message);\r
-\r
-VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);\r
-VOID ServiceStop();\r
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);\r
-void AddToMessageLog(LPSTR lpszMsg);\r
-\r
-BOOL WINAPI BreakHandler(DWORD dwCtrlType)\r
-{\r
-   switch(dwCtrlType)\r
-    {\r
-        case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate\r
-        case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in console mode\r
-            ServiceStop();\r
-            return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-\r
-\r
-int real_main(int);  // The revised two-phase main() in shar.cpp\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-    int i=1;\r
-    while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))\r
-    {\r
-        if (_stricmp("install", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                lpszInstall = argv[i++];\r
-        }\r
-        else if (_stricmp("remove", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                lpszRemove = argv[i++];\r
-        }\r
-        else if (_stricmp( "console", argv[i]+1) == 0)\r
-        {\r
-            i++;\r
-            bConsole = TRUE;\r
-        }\r
-        else if (_stricmp( "check", argv[i]+1) == 0)\r
-        {\r
-            i++;\r
-            bConsole = TRUE;\r
-            shar_checkonly=true;\r
-        }\r
-        else if (_stricmp( "config", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                shar_config = argv[i++];\r
-        }\r
-        else if (_stricmp( "prefix", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                shar_prefix = argv[i++];\r
-        }\r
-        else if (_stricmp( "catalogs", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                shar_schemadir = argv[i++];\r
-        }\r
-        else\r
-        {\r
-            goto dispatch;\r
-        }\r
-    }\r
-    \r
-    if (bConsole)\r
-    {\r
-        // Install break handler, then run the C routine twice, once to setup, once to start running.\r
-        SetConsoleCtrlHandler(&BreakHandler,TRUE);\r
-        if ((i=real_main(1))!=0)\r
-        {\r
-            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
-            return i;\r
-        }\r
-        return real_main(0);\r
-    }\r
-    else if (lpszInstall)\r
-    {\r
-        CmdInstallService(lpszInstall);\r
-        return 0;\r
-    }\r
-    else if (lpszRemove)\r
-    {\r
-        CmdRemoveService(lpszRemove);\r
-        return 0;\r
-    }\r
-    \r
-\r
-    // if it doesn't match any of the above parameters\r
-    // the service control manager may be starting the service\r
-    // so we must call StartServiceCtrlDispatcher\r
-    dispatch:\r
-        // this is just to be friendly\r
-        printf("%s -install <name>   to install the named service\n", argv[0]);\r
-        printf("%s -remove <name>    to remove the named service\n", argv[0]);\r
-        printf("%s -console          to run as a console app for debugging\n", argv[0]);\r
-        printf("%s -check            to run as a console app and check configuration\n", argv[0]);\r
-        printf("\t-prefix <dir> to specify the installation directory\n");\r
-        printf("\t-config <file> to specify the config file to use\n");\r
-        printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\n");\r
-        printf("\nService starting.\nThis may take several seconds. Please wait.\n" );\r
-\r
-    SERVICE_TABLE_ENTRY dispatchTable[] =\r
-    {\r
-        { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },\r
-        { NULL, NULL }\r
-    };\r
-\r
-    if (!StartServiceCtrlDispatcher(dispatchTable))\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");\r
-    return 0;\r
-}\r
-\r
-//\r
-//  FUNCTION: ServiceStart\r
-//\r
-//  PURPOSE: Actual code of the service\r
-//          that does the work.\r
-//\r
-VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)\r
-{\r
-\r
-    if (real_main(1)!=0)\r
-    {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
-        return;\r
-    }\r
-\r
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");\r
-\r
-    if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))\r
-        return;\r
-\r
-    real_main(0);\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: ServiceStop\r
-//\r
-//   PURPOSE: Stops the service\r
-//\r
-VOID ServiceStop()\r
-{\r
-    if (!bConsole)\r
-        LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");\r
-    shibd_shutdown=true;\r
-}\r
-\r
-\r
-void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)\r
-{\r
-\r
-    // register our service control handler:\r
-    sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);\r
-    if (!sshStatusHandle)\r
-        goto cleanup;\r
-\r
-    // SERVICE_STATUS members that don't change in example\r
-    ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;\r
-    ssStatus.dwServiceSpecificExitCode = 0;\r
-\r
-\r
-    // report the status to the service control manager.\r
-    if (!ReportStatusToSCMgr(\r
-        SERVICE_START_PENDING, // service state\r
-        NO_ERROR,              // exit code\r
-        3000))                 // wait hint\r
-        goto cleanup;\r
-\r
-\r
-    ServiceStart(dwArgc, lpszArgv);\r
-\r
-cleanup:\r
-\r
-    // try to report the stopped status to the service control manager.\r
-    //\r
-    if (sshStatusHandle)\r
-        (VOID)ReportStatusToSCMgr(\r
-                            SERVICE_STOPPED,\r
-                            dwErr,\r
-                            0);\r
-\r
-    return;\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: service_ctrl\r
-//\r
-//  PURPOSE: This function is called by the SCM whenever\r
-//           ControlService() is called on this service.\r
-//\r
-//  PARAMETERS:\r
-//    dwCtrlCode - type of control requested\r
-//\r
-//  RETURN VALUE:\r
-//    none\r
-//\r
-VOID WINAPI service_ctrl(DWORD dwCtrlCode)\r
-{\r
-    // Handle the requested control code.\r
-    //\r
-    switch(dwCtrlCode)\r
-    {\r
-        // Stop the service.\r
-        //\r
-        case SERVICE_CONTROL_STOP:\r
-            ssStatus.dwCurrentState = SERVICE_STOP_PENDING;\r
-            ServiceStop();\r
-            break;\r
-\r
-        // Update the service status.\r
-        //\r
-        case SERVICE_CONTROL_INTERROGATE:\r
-            break;\r
-\r
-        // invalid control code\r
-        //\r
-        default:\r
-            break;\r
-\r
-    }\r
-\r
-    ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: ReportStatusToSCMgr()\r
-//\r
-//  PURPOSE: Sets the current status of the service and\r
-//           reports it to the Service Control Manager\r
-//\r
-//  PARAMETERS:\r
-//    dwCurrentState - the state of the service\r
-//    dwWin32ExitCode - error code to report\r
-//    dwWaitHint - worst case estimate to next checkpoint\r
-//\r
-//  RETURN VALUE:\r
-//    TRUE  - success\r
-//    FALSE - failure\r
-//\r
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState,\r
-                         DWORD dwWin32ExitCode,\r
-                         DWORD dwWaitHint)\r
-{\r
-    static DWORD dwCheckPoint = 1;\r
-    BOOL fResult = TRUE;\r
-\r
-\r
-    if (!bConsole) // when console we don't report to the SCM\r
-    {\r
-        if (dwCurrentState == SERVICE_START_PENDING)\r
-            ssStatus.dwControlsAccepted = 0;\r
-        else\r
-            ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;\r
-\r
-        ssStatus.dwCurrentState = dwCurrentState;\r
-        ssStatus.dwWin32ExitCode = dwWin32ExitCode;\r
-        ssStatus.dwWaitHint = dwWaitHint;\r
-\r
-        if ( ( dwCurrentState == SERVICE_RUNNING ) ||\r
-             ( dwCurrentState == SERVICE_STOPPED ) )\r
-            ssStatus.dwCheckPoint = 0;\r
-        else\r
-            ssStatus.dwCheckPoint = dwCheckPoint++;\r
-\r
-\r
-        // Report the status of the service to the service control manager.\r
-        //\r
-        if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))\r
-            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");\r
-    }\r
-    return fResult;\r
-}\r
-\r
-\r
-///////////////////////////////////////////////////////////////////\r
-//\r
-//  The following code handles service installation and removal\r
-//\r
-//\r
-void CmdInstallService(LPCSTR name)\r
-{\r
-    SC_HANDLE   schService;\r
-    SC_HANDLE   schSCManager;\r
-\r
-    char szPath[256];\r
-\r
-    if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )\r
-    {\r
-        printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));\r
-        return;\r
-    }\r
-    \r
-    string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")";\r
-    string realName = string("shibd_") + name;\r
-    string cmd(szPath);\r
-    if (shar_prefix)\r
-        cmd = cmd + " -prefix " + shar_prefix;\r
-    if (shar_config)\r
-        cmd = cmd + " -config " + shar_config;\r
-    if (shar_schemadir)\r
-        cmd = cmd + " -schemadir " + shar_schemadir;\r
-\r
-    schSCManager = OpenSCManager(\r
-                        NULL,                   // machine (NULL == local)\r
-                        NULL,                   // database (NULL == default)\r
-                        SC_MANAGER_ALL_ACCESS   // access required\r
-                        );\r
-    \r
-    \r
-    if ( schSCManager )\r
-    {\r
-        schService = CreateService(\r
-            schSCManager,               // SCManager database\r
-            realName.c_str(),           // name of service\r
-            dispName.c_str(),           // name to display\r
-            SERVICE_ALL_ACCESS,         // desired access\r
-            SERVICE_WIN32_OWN_PROCESS,  // service type\r
-            SERVICE_AUTO_START,         // start type\r
-            SERVICE_ERROR_NORMAL,       // error control type\r
-            cmd.c_str(),                // service's command line\r
-            NULL,                       // no load ordering group\r
-            NULL,                       // no tag identifier\r
-            NULL,                       // dependencies\r
-            NULL,                       // LocalSystem account\r
-            NULL);                      // no password\r
-\r
-        if ( schService )\r
-        {\r
-            printf("%s installed.\n", realName.c_str());\r
-            CloseServiceHandle(schService);\r
-        }\r
-        else\r
-        {\r
-            printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));\r
-        }\r
-\r
-        CloseServiceHandle(schSCManager);\r
-    }\r
-    else\r
-        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
-}\r
-\r
-void CmdRemoveService(LPCSTR name)\r
-{\r
-    SC_HANDLE   schService;\r
-    SC_HANDLE   schSCManager;\r
-    char        realName[512];\r
-\r
-    _snprintf(realName,sizeof(realName),"shibd_%s",name);\r
-\r
-    schSCManager = OpenSCManager(\r
-                        NULL,                   // machine (NULL == local)\r
-                        NULL,                   // database (NULL == default)\r
-                        SC_MANAGER_ALL_ACCESS   // access required\r
-                        );\r
-    if ( schSCManager )\r
-    {\r
-        schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);\r
-\r
-        if (schService)\r
-        {\r
-            // try to stop the service\r
-            if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )\r
-            {\r
-                printf("Stopping shibd (%s).", name);\r
-                Sleep( 1000 );\r
-\r
-                while( QueryServiceStatus( schService, &ssStatus ) )\r
-                {\r
-                    if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )\r
-                    {\r
-                        printf(".");\r
-                        Sleep( 1000 );\r
-                    }\r
-                    else\r
-                        break;\r
-                }\r
-\r
-                if ( ssStatus.dwCurrentState == SERVICE_STOPPED )\r
-                    printf("\n%s stopped.\n", realName);\r
-                else\r
-                    printf("\n%s failed to stop.\n", realName);\r
-\r
-            }\r
-\r
-            // now remove the service\r
-            if( DeleteService(schService) )\r
-                printf("%s removed.\n", realName);\r
-            else\r
-                printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));\r
-\r
-\r
-            CloseServiceHandle(schService);\r
-        }\r
-        else\r
-            printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));\r
-\r
-        CloseServiceHandle(schSCManager);\r
-    }\r
-    else\r
-        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: GetLastErrorText\r
-//\r
-//  PURPOSE: copies error message text to string\r
-//\r
-//  PARAMETERS:\r
-//    lpszBuf - destination buffer\r
-//    dwSize - size of buffer\r
-//\r
-//  RETURN VALUE:\r
-//    destination buffer\r
-//\r
-//  COMMENTS:\r
-//\r
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )\r
-{\r
-    DWORD dwRet;\r
-    LPSTR lpszTemp = NULL;\r
-\r
-    dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,\r
-                           NULL,\r
-                           GetLastError(),\r
-                           LANG_NEUTRAL,\r
-                           (LPSTR)&lpszTemp,\r
-                           0,\r
-                           NULL );\r
-\r
-    // supplied buffer is not long enough\r
-    if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )\r
-        lpszBuf[0] = '\0';\r
-    else\r
-    {\r
-        lpszTemp[lstrlen(lpszTemp)-2] = '\0';  //remove cr and newline character\r
-        sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );\r
-    }\r
-\r
-    if ( lpszTemp )\r
-        LocalFree((HLOCAL) lpszTemp );\r
-\r
-    return lpszBuf;\r
-}\r
-\r
-BOOL LogEvent(\r
-    LPCSTR  lpUNCServerName,\r
-    WORD  wType,\r
-    DWORD  dwEventID,\r
-    PSID  lpUserSid,\r
-    LPCSTR  message)\r
-{\r
-    LPCSTR  messages[] = {message, NULL};\r
-    \r
-    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");\r
-    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
-    return (DeregisterEventSource(hElog) && res);\r
-}\r
+/*
+ *  Copyright 2001-2007 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.
+ */
+
+/*
+ * shar_win32.cpp -- the SHAR "main" code on Win32
+ *
+ * Created By: Scott Cantor (cantor.2@osu.edu)
+ *
+ * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $
+ */
+
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <shibsp/base.h>
+#include <string>
+#include <windows.h>
+
+using namespace std;
+
+extern bool shibd_shutdown;                    // signals shutdown to Unix side
+extern const char* shar_schemadir;
+extern const char* shar_config;
+extern const char* shar_prefix;
+extern bool shar_checkonly;
+
+// internal variables
+SERVICE_STATUS          ssStatus;       // current status of the service
+SERVICE_STATUS_HANDLE   sshStatusHandle;
+DWORD                   dwErr = 0;
+BOOL                    bConsole = FALSE;
+char                    szErr[256];
+LPCSTR                  lpszInstall = NULL;
+LPCSTR                  lpszRemove = NULL;
+
+// internal function prototypes
+VOID WINAPI service_ctrl(DWORD dwCtrlCode);
+VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);
+VOID CmdInstallService(LPCSTR);
+VOID CmdRemoveService(LPCSTR);
+LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );
+
+BOOL LogEvent(
+    LPCTSTR  lpUNCServerName,
+    WORD  wType,
+    DWORD  dwEventID,
+    PSID  lpUserSid,
+    LPCTSTR  message);
+
+VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);
+VOID ServiceStop();
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
+void AddToMessageLog(LPSTR lpszMsg);
+
+BOOL WINAPI BreakHandler(DWORD dwCtrlType)
+{
+   switch(dwCtrlType)
+    {
+        case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
+        case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in console mode
+            ServiceStop();
+            return TRUE;
+    }
+    return FALSE;
+}
+
+
+int real_main(int);  // The revised two-phase main() in shar.cpp
+
+int main(int argc, char *argv[])
+{
+    int i=1;
+    while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))
+    {
+        if (_stricmp("install", argv[i]+1) == 0)
+        {
+            if (argc > ++i)
+                lpszInstall = argv[i++];
+        }
+        else if (_stricmp("remove", argv[i]+1) == 0)
+        {
+            if (argc > ++i)
+                lpszRemove = argv[i++];
+        }
+        else if (_stricmp( "console", argv[i]+1) == 0)
+        {
+            i++;
+            bConsole = TRUE;
+        }
+        else if (_stricmp( "check", argv[i]+1) == 0)
+        {
+            i++;
+            bConsole = TRUE;
+            shar_checkonly=true;
+        }
+        else if (_stricmp( "config", argv[i]+1) == 0)
+        {
+            if (argc > ++i)
+                shar_config = argv[i++];
+        }
+        else if (_stricmp( "prefix", argv[i]+1) == 0)
+        {
+            if (argc > ++i)
+                shar_prefix = argv[i++];
+        }
+        else if (_stricmp( "catalogs", argv[i]+1) == 0)
+        {
+            if (argc > ++i)
+                shar_schemadir = argv[i++];
+        }
+        else
+        {
+            goto dispatch;
+        }
+    }
+    
+    if (bConsole)
+    {
+        // Install break handler, then run the C routine twice, once to setup, once to start running.
+        SetConsoleCtrlHandler(&BreakHandler,TRUE);
+        if ((i=real_main(1))!=0)
+        {
+            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
+            return i;
+        }
+        return real_main(0);
+    }
+    else if (lpszInstall)
+    {
+        CmdInstallService(lpszInstall);
+        return 0;
+    }
+    else if (lpszRemove)
+    {
+        CmdRemoveService(lpszRemove);
+        return 0;
+    }
+    
+
+    // if it doesn't match any of the above parameters
+    // the service control manager may be starting the service
+    // so we must call StartServiceCtrlDispatcher
+    dispatch:
+        // this is just to be friendly
+        printf("%s -install <name>   to install the named service\n", argv[0]);
+        printf("%s -remove <name>    to remove the named service\n", argv[0]);
+        printf("%s -console          to run as a console app for debugging\n", argv[0]);
+        printf("%s -check            to run as a console app and check configuration\n", argv[0]);
+        printf("\t-prefix <dir> to specify the installation directory\n");
+        printf("\t-config <file> to specify the config file to use\n");
+        printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\n");
+        printf("\nService starting.\nThis may take several seconds. Please wait.\n" );
+
+    SERVICE_TABLE_ENTRY dispatchTable[] =
+    {
+        { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },
+        { NULL, NULL }
+    };
+
+    if (!StartServiceCtrlDispatcher(dispatchTable))
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");
+    return 0;
+}
+
+//
+//  FUNCTION: ServiceStart
+//
+//  PURPOSE: Actual code of the service
+//          that does the work.
+//
+VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)
+{
+
+    if (real_main(1)!=0)
+    {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
+        return;
+    }
+
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");
+
+    if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
+        return;
+
+    real_main(0);
+}
+
+
+//
+//  FUNCTION: ServiceStop
+//
+//   PURPOSE: Stops the service
+//
+VOID ServiceStop()
+{
+    if (!bConsole)
+        LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");
+    shibd_shutdown=true;
+}
+
+
+void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)
+{
+
+    // register our service control handler:
+    sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
+    if (!sshStatusHandle)
+        goto cleanup;
+
+    // SERVICE_STATUS members that don't change in example
+    ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    ssStatus.dwServiceSpecificExitCode = 0;
+
+
+    // report the status to the service control manager.
+    if (!ReportStatusToSCMgr(
+        SERVICE_START_PENDING, // service state
+        NO_ERROR,              // exit code
+        3000))                 // wait hint
+        goto cleanup;
+
+
+    ServiceStart(dwArgc, lpszArgv);
+
+cleanup:
+
+    // try to report the stopped status to the service control manager.
+    //
+    if (sshStatusHandle)
+        (VOID)ReportStatusToSCMgr(
+                            SERVICE_STOPPED,
+                            dwErr,
+                            0);
+
+    return;
+}
+
+
+//
+//  FUNCTION: service_ctrl
+//
+//  PURPOSE: This function is called by the SCM whenever
+//           ControlService() is called on this service.
+//
+//  PARAMETERS:
+//    dwCtrlCode - type of control requested
+//
+//  RETURN VALUE:
+//    none
+//
+VOID WINAPI service_ctrl(DWORD dwCtrlCode)
+{
+    // Handle the requested control code.
+    //
+    switch(dwCtrlCode)
+    {
+        // Stop the service.
+        //
+        case SERVICE_CONTROL_STOP:
+            ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
+            ServiceStop();
+            break;
+
+        // Update the service status.
+        //
+        case SERVICE_CONTROL_INTERROGATE:
+            break;
+
+        // invalid control code
+        //
+        default:
+            break;
+
+    }
+
+    ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
+}
+
+
+//
+//  FUNCTION: ReportStatusToSCMgr()
+//
+//  PURPOSE: Sets the current status of the service and
+//           reports it to the Service Control Manager
+//
+//  PARAMETERS:
+//    dwCurrentState - the state of the service
+//    dwWin32ExitCode - error code to report
+//    dwWaitHint - worst case estimate to next checkpoint
+//
+//  RETURN VALUE:
+//    TRUE  - success
+//    FALSE - failure
+//
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
+                         DWORD dwWin32ExitCode,
+                         DWORD dwWaitHint)
+{
+    static DWORD dwCheckPoint = 1;
+    BOOL fResult = TRUE;
+
+
+    if (!bConsole) // when console we don't report to the SCM
+    {
+        if (dwCurrentState == SERVICE_START_PENDING)
+            ssStatus.dwControlsAccepted = 0;
+        else
+            ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+        ssStatus.dwCurrentState = dwCurrentState;
+        ssStatus.dwWin32ExitCode = dwWin32ExitCode;
+        ssStatus.dwWaitHint = dwWaitHint;
+
+        if ( ( dwCurrentState == SERVICE_RUNNING ) ||
+             ( dwCurrentState == SERVICE_STOPPED ) )
+            ssStatus.dwCheckPoint = 0;
+        else
+            ssStatus.dwCheckPoint = dwCheckPoint++;
+
+
+        // Report the status of the service to the service control manager.
+        //
+        if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))
+            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");
+    }
+    return fResult;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+//  The following code handles service installation and removal
+//
+//
+void CmdInstallService(LPCSTR name)
+{
+    SC_HANDLE   schService;
+    SC_HANDLE   schSCManager;
+
+    char szPath[256];
+
+    if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )
+    {
+        printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
+        return;
+    }
+    
+    string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")";
+    string realName = string("shibd_") + name;
+    string cmd(szPath);
+    if (shar_prefix)
+        cmd = cmd + " -prefix " + shar_prefix;
+    if (shar_config)
+        cmd = cmd + " -config " + shar_config;
+    if (shar_schemadir)
+        cmd = cmd + " -schemadir " + shar_schemadir;
+
+    schSCManager = OpenSCManager(
+                        NULL,                   // machine (NULL == local)
+                        NULL,                   // database (NULL == default)
+                        SC_MANAGER_ALL_ACCESS   // access required
+                        );
+    
+    
+    if ( schSCManager )
+    {
+        schService = CreateService(
+            schSCManager,               // SCManager database
+            realName.c_str(),           // name of service
+            dispName.c_str(),           // name to display
+            SERVICE_ALL_ACCESS,         // desired access
+            SERVICE_WIN32_OWN_PROCESS,  // service type
+            SERVICE_AUTO_START,         // start type
+            SERVICE_ERROR_NORMAL,       // error control type
+            cmd.c_str(),                // service's command line
+            NULL,                       // no load ordering group
+            NULL,                       // no tag identifier
+            NULL,                       // dependencies
+            NULL,                       // LocalSystem account
+            NULL);                      // no password
+
+        if ( schService )
+        {
+            printf("%s installed.\n", realName.c_str());
+            CloseServiceHandle(schService);
+        }
+        else
+        {
+            printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));
+        }
+
+        CloseServiceHandle(schSCManager);
+    }
+    else
+        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
+}
+
+void CmdRemoveService(LPCSTR name)
+{
+    SC_HANDLE   schService;
+    SC_HANDLE   schSCManager;
+    char        realName[512];
+
+    _snprintf(realName,sizeof(realName),"shibd_%s",name);
+
+    schSCManager = OpenSCManager(
+                        NULL,                   // machine (NULL == local)
+                        NULL,                   // database (NULL == default)
+                        SC_MANAGER_ALL_ACCESS   // access required
+                        );
+    if ( schSCManager )
+    {
+        schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);
+
+        if (schService)
+        {
+            // try to stop the service
+            if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
+            {
+                printf("Stopping shibd (%s).", name);
+                Sleep( 1000 );
+
+                while( QueryServiceStatus( schService, &ssStatus ) )
+                {
+                    if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
+                    {
+                        printf(".");
+                        Sleep( 1000 );
+                    }
+                    else
+                        break;
+                }
+
+                if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
+                    printf("\n%s stopped.\n", realName);
+                else
+                    printf("\n%s failed to stop.\n", realName);
+
+            }
+
+            // now remove the service
+            if( DeleteService(schService) )
+                printf("%s removed.\n", realName);
+            else
+                printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));
+
+
+            CloseServiceHandle(schService);
+        }
+        else
+            printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));
+
+        CloseServiceHandle(schSCManager);
+    }
+    else
+        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
+}
+
+
+//
+//  FUNCTION: GetLastErrorText
+//
+//  PURPOSE: copies error message text to string
+//
+//  PARAMETERS:
+//    lpszBuf - destination buffer
+//    dwSize - size of buffer
+//
+//  RETURN VALUE:
+//    destination buffer
+//
+//  COMMENTS:
+//
+LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )
+{
+    DWORD dwRet;
+    LPSTR lpszTemp = NULL;
+
+    dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                           NULL,
+                           GetLastError(),
+                           LANG_NEUTRAL,
+                           (LPSTR)&lpszTemp,
+                           0,
+                           NULL );
+
+    // supplied buffer is not long enough
+    if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
+        lpszBuf[0] = '\0';
+    else
+    {
+        lpszTemp[lstrlen(lpszTemp)-2] = '\0';  //remove cr and newline character
+        sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );
+    }
+
+    if ( lpszTemp )
+        LocalFree((HLOCAL) lpszTemp );
+
+    return lpszBuf;
+}
+
+BOOL LogEvent(
+    LPCSTR  lpUNCServerName,
+    WORD  wType,
+    DWORD  dwEventID,
+    PSID  lpUserSid,
+    LPCSTR  message)
+{
+    LPCSTR  messages[] = {message, NULL};
+    
+    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");
+    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
+    return (DeregisterEventSource(hElog) && res);
+}
index 98cb87c..d996be3 100644 (file)
-/*\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
- * DOMAttributeDecoder.cpp\r
- *\r
- * Decodes a DOM into an ExtensibleAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/ExtensibleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        DOMAttributeDecoder(const DOMElement* e);\r
-        ~DOMAttributeDecoder() {}\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
-        DDF convert(DOMElement* e, bool nameit=true) const;\r
-        auto_ptr_char m_formatter;\r
-        map<pair<xstring,xstring>,string> m_tagMap;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new DOMAttributeDecoder(e);\r
-    }\r
-\r
-    static const XMLCh Mapping[] =  UNICODE_LITERAL_7(M,a,p,p,i,n,g);\r
-    static const XMLCh _from[] =    UNICODE_LITERAL_4(f,r,o,m);\r
-    static const XMLCh _to[] =      UNICODE_LITERAL_2(t,o);\r
-    static const XMLCh formatter[] =      UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
-};\r
-\r
-DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)\r
-    : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)\r
-{\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
-\r
-    e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;\r
-    while (e) {\r
-        if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {\r
-            auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));\r
-            auto_ptr_char t(e->getAttributeNS(NULL, _to));\r
-            if (f.get() && t.get() && *t.get()) {\r
-                if (log.isDebugEnabled())\r
-                    log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());\r
-                m_tagMap.insert(\r
-                    pair< const pair<xstring,xstring>,string>(\r
-                        pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),\r
-                        t.get()\r
-                        )\r
-                    );\r
-            }\r
-        }\r
-        e = XMLHelper::getNextSiblingElement(e, Mapping);\r
-    }\r
-}\r
-\r
-Attribute* DOMAttributeDecoder::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.DOM");\r
-\r
-    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
-        log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
-        return NULL;\r
-    }\r
-\r
-    auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));\r
-    DDF 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 ExtensibleAttribute (%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 ExtensibleAttribute (%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 DOMAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    for (; v!=stop; ++v) {\r
-        DOMElement* e = (*v)->getDOM();\r
-        if (e) {\r
-            DDF converted = convert(e, false);\r
-            if (!converted.isnull())\r
-                dest.add(converted);\r
-        }\r
-        else\r
-            log.warn("skipping AttributeValue without a backing DOM");\r
-    }\r
-\r
-    return dest.integer() ? _decode(attr.release()) : NULL;\r
-}\r
-\r
-DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const\r
-{\r
-    const XMLCh* nsURI;\r
-    const XMLCh* local;\r
-    map<pair<xstring,xstring>,string>::const_iterator mapping;\r
-    DDF obj = DDF(NULL).structure();\r
-\r
-    if (nameit) {\r
-        // Name this structure.\r
-        nsURI = e->getNamespaceURI();\r
-        local = e->getLocalName();\r
-        mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));\r
-        if (mapping == m_tagMap.end()) {\r
-            auto_ptr_char temp(local);\r
-            obj.name(temp.get());\r
-        }\r
-        else {\r
-            obj.name(mapping->second.c_str());\r
-        }\r
-    }\r
-\r
-    // Process non-xmlns attributes.\r
-    DOMNamedNodeMap* attrs = e->getAttributes();\r
-    for (XMLSize_t a = attrs->getLength(); a > 0; --a) {\r
-        DOMNode* attr = attrs->item(a-1);\r
-        nsURI = attr->getNamespaceURI();\r
-        if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))\r
-            continue;\r
-        local = attr->getLocalName();\r
-        mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));\r
-        if (mapping == m_tagMap.end()) {\r
-            auto_ptr_char temp(local);\r
-            obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);\r
-        }\r
-        else {\r
-            obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);\r
-        }\r
-    }\r
-\r
-    DOMElement* child = XMLHelper::getFirstChildElement(e);\r
-    if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {\r
-        // Attach a _text member if a text node is present.\r
-        obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);\r
-    }\r
-    else {\r
-        while (child) {\r
-            // Convert the child element.\r
-            DDF converted = convert(child);\r
-            if (!converted.isnull()) {\r
-                // Now identify it and attach it.\r
-                if (obj[converted.name()].isnull()) {\r
-                    // We're a new child, so just attach as a structure member.\r
-                    obj.add(converted);\r
-                }\r
-                else if (obj[converted.name()].islist()) {\r
-                    // We're already a repeating child, so add it to the list.\r
-                    obj[converted.name()].add(converted);\r
-                }\r
-                else if (obj[converted.name()].isstruct()) {\r
-                    // This is the complex case where we see a child for the second\r
-                    // time and have to convert a structure member into a named list.\r
-                    DDF newlist = DDF(converted.name()).list();\r
-                    newlist.add(obj[converted.name()].remove());\r
-                    newlist.add(converted);\r
-                    obj.add(newlist);\r
-                }\r
-            }\r
-            child = XMLHelper::getNextSiblingElement(child);\r
-        }\r
-    }\r
-\r
-    // If we're empty, just delete.\r
-    if (obj.integer() == 0)\r
-        obj.destroy();\r
-    return obj;\r
-}\r
+/*
+ *  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.
+ */
+
+/**
+ * DOMAttributeDecoder.cpp
+ *
+ * Decodes a DOM into an ExtensibleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/ExtensibleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        DOMAttributeDecoder(const DOMElement* e);
+        ~DOMAttributeDecoder() {}
+
+        Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        DDF convert(DOMElement* e, bool nameit=true) const;
+        auto_ptr_char m_formatter;
+        map<pair<xstring,xstring>,string> m_tagMap;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new DOMAttributeDecoder(e);
+    }
+
+    static const XMLCh Mapping[] =  UNICODE_LITERAL_7(M,a,p,p,i,n,g);
+    static const XMLCh _from[] =    UNICODE_LITERAL_4(f,r,o,m);
+    static const XMLCh _to[] =      UNICODE_LITERAL_2(t,o);
+    static const XMLCh formatter[] =      UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+};
+
+DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)
+    : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)
+{
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+    e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;
+    while (e) {
+        if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {
+            auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));
+            auto_ptr_char t(e->getAttributeNS(NULL, _to));
+            if (f.get() && t.get() && *t.get()) {
+                if (log.isDebugEnabled())
+                    log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());
+                m_tagMap.insert(
+                    pair< const pair<xstring,xstring>,string>(
+                        pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),
+                        t.get()
+                        )
+                    );
+            }
+        }
+        e = XMLHelper::getNextSiblingElement(e, Mapping);
+    }
+}
+
+Attribute* DOMAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+        log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+        return NULL;
+    }
+
+    auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));
+    DDF dest = attr->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+    if (saml2attr) {
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+        v = values.begin();
+        stop = values.end();
+        if (log.isDebugEnabled()) {
+            auto_ptr_char n(saml2attr->getName());
+            log.debug(
+                "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                );
+        }
+    }
+    else {
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+        if (saml1attr) {
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    for (; v!=stop; ++v) {
+        DOMElement* e = (*v)->getDOM();
+        if (e) {
+            DDF converted = convert(e, false);
+            if (!converted.isnull())
+                dest.add(converted);
+        }
+        else
+            log.warn("skipping AttributeValue without a backing DOM");
+    }
+
+    return dest.integer() ? _decode(attr.release()) : NULL;
+}
+
+DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const
+{
+    const XMLCh* nsURI;
+    const XMLCh* local;
+    map<pair<xstring,xstring>,string>::const_iterator mapping;
+    DDF obj = DDF(NULL).structure();
+
+    if (nameit) {
+        // Name this structure.
+        nsURI = e->getNamespaceURI();
+        local = e->getLocalName();
+        mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));
+        if (mapping == m_tagMap.end()) {
+            auto_ptr_char temp(local);
+            obj.name(temp.get());
+        }
+        else {
+            obj.name(mapping->second.c_str());
+        }
+    }
+
+    // Process non-xmlns attributes.
+    DOMNamedNodeMap* attrs = e->getAttributes();
+    for (XMLSize_t a = attrs->getLength(); a > 0; --a) {
+        DOMNode* attr = attrs->item(a-1);
+        nsURI = attr->getNamespaceURI();
+        if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))
+            continue;
+        local = attr->getLocalName();
+        mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));
+        if (mapping == m_tagMap.end()) {
+            auto_ptr_char temp(local);
+            obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);
+        }
+        else {
+            obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);
+        }
+    }
+
+    DOMElement* child = XMLHelper::getFirstChildElement(e);
+    if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {
+        // Attach a _text member if a text node is present.
+        obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);
+    }
+    else {
+        while (child) {
+            // Convert the child element.
+            DDF converted = convert(child);
+            if (!converted.isnull()) {
+                // Now identify it and attach it.
+                if (obj[converted.name()].isnull()) {
+                    // We're a new child, so just attach as a structure member.
+                    obj.add(converted);
+                }
+                else if (obj[converted.name()].islist()) {
+                    // We're already a repeating child, so add it to the list.
+                    obj[converted.name()].add(converted);
+                }
+                else if (obj[converted.name()].isstruct()) {
+                    // This is the complex case where we see a child for the second
+                    // time and have to convert a structure member into a named list.
+                    DDF newlist = DDF(converted.name()).list();
+                    newlist.add(obj[converted.name()].remove());
+                    newlist.add(converted);
+                    obj.add(newlist);
+                }
+            }
+            child = XMLHelper::getNextSiblingElement(child);
+        }
+    }
+
+    // If we're empty, just delete.
+    if (obj.integer() == 0)
+        obj.destroy();
+    return obj;
+}
index 5857952..17a4683 100644 (file)
-/*\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/XMLToolingConfig.h>\r
-#include <xmltooling/security/Credential.h>\r
-#include <xmltooling/security/KeyInfoResolver.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(), m_hash);\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
-        bool m_hash;\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 _hash[] =            UNICODE_LITERAL_4(h,a,s,h);\r
-    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);\r
-};\r
-\r
-KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) {\r
-    const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;\r
-    m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));\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 KeyInfo information (%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 KeyInfo information (%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 : _decode(attr.release());\r
-}\r
+/*
+ *  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.
+ */
+
+/**
+ * KeyInfoAttributeDecoder.cpp
+ *
+ * Decodes KeyInfo information into a SimpleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/Credential.h>
+#include <xmltooling/security/KeyInfoResolver.h>
+#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/signature/KeyInfo.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        KeyInfoAttributeDecoder(const DOMElement* e);
+        ~KeyInfoAttributeDecoder() {
+            delete m_keyInfoResolver;
+        }
+
+        Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        void extract(const KeyInfo* k, vector<string>& dest) const {
+            auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
+            if (cred.get()) {
+                dest.push_back(string());
+                dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash);
+                if (dest.back().empty())
+                    dest.pop_back();
+            }
+        }
+
+        const KeyInfoResolver* getKeyInfoResolver() const {
+            return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
+        }
+
+        bool m_hash;
+        KeyInfoResolver* m_keyInfoResolver;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new KeyInfoAttributeDecoder(e);
+    }
+
+    static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);
+    static const XMLCh _hash[] =            UNICODE_LITERAL_4(h,a,s,h);
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
+};
+
+KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) {
+    const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;
+    m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+    e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;
+    if (e) {
+        auto_ptr_char t(e->getAttributeNS(NULL, _type));
+        if (t.get() && *t.get())
+            m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);
+        else
+            throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
+    }
+}
+
+Attribute* KeyInfoAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");
+
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+        log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+        return NULL;
+    }
+
+    auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));
+    vector<string>& dest = attr->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+    if (saml2attr) {
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+        v = values.begin();
+        stop = values.end();
+        if (log.isDebugEnabled()) {
+            auto_ptr_char n(saml2attr->getName());
+            log.debug(
+                "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                );
+        }
+    }
+    else {
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+        if (saml1attr) {
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    for (; v!=stop; ++v) {
+        const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);
+        if (k)
+            extract(k, dest);
+        else if ((*v)->hasChildren()) {
+            const list<XMLObject*>& children = (*v)->getOrderedChildren();
+            for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {
+                if (k=dynamic_cast<const KeyInfo*>(*vv))
+                    extract(k, dest);
+                else
+                    log.warn("skipping AttributeValue without a recognizable KeyInfo");
+            }
+        }
+    }
+
+    return dest.empty() ? NULL : _decode(attr.release());
+}
index 903bc33..82ff313 100644 (file)
-/*\r
- *  Copyright 2001-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
- * NameIDAttributeDecoder.cpp\r
- *\r
- * Decodes SAML into NameIDAttributes\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/NameIDAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml1;\r
-using namespace opensaml::saml2;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
-    static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);\r
-\r
-    class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        NameIDAttributeDecoder(const DOMElement* e)\r
-                : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {\r
-            const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;\r
-            if (flag && (*flag == chLatin_t || *flag == chDigit_1))\r
-                m_defaultQualifiers = true;\r
-        }\r
-        ~NameIDAttributeDecoder() {}\r
-\r
-        shibsp::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(\r
-            const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-            ) const;\r
-        void extract(\r
-            const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-            ) const;\r
-        auto_ptr_char m_formatter;\r
-        bool m_defaultQualifiers;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new NameIDAttributeDecoder(e);\r
-    }\r
-};\r
-\r
-shibsp::Attribute* NameIDAttributeDecoder::decode(\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(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)\r
-        );\r
-    vector<NameIDAttribute::Value>& dest = nameid->getValues();\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID");\r
-\r
-    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
-        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::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 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
-            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::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 NameIDAttributeDecoder, no values returned");\r
-                return NULL;\r
-            }\r
-        }\r
-\r
-        for (; v!=stop; ++v) {\r
-            const NameIDType* n2 = dynamic_cast<const NameIDType*>(*v);\r
-            if (n2)\r
-                extract(n2, dest, assertingParty, relyingParty);\r
-            else {\r
-                const NameIdentifier* n1=dynamic_cast<const NameIdentifier*>(*v);\r
-                if (n1)\r
-                    extract(n1, dest, assertingParty, relyingParty);\r
-                else if ((*v)->hasChildren()) {\r
-                    const list<XMLObject*>& values = (*v)->getOrderedChildren();\r
-                    for (list<XMLObject*>::const_iterator vv = values.begin(); vv!=values.end(); ++vv) {\r
-                        if (n2=dynamic_cast<const NameIDType*>(*vv))\r
-                            extract(n2, dest, assertingParty, relyingParty);\r
-                        else if (n1=dynamic_cast<const NameIdentifier*>(*vv))\r
-                            extract(n1, dest, assertingParty, relyingParty);\r
-                        else\r
-                            log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier");\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        return dest.empty() ? NULL : _decode(nameid.release());\r
-    }\r
-\r
-    const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);\r
-    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)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
-        }\r
-        extract(saml2name, dest, assertingParty, relyingParty);\r
-    }\r
-    else {\r
-        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
-        if (saml1name) {\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char f(saml1name->getFormat());\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, assertingParty, relyingParty);\r
-        }\r
-        else {\r
-            log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    return dest.empty() ? NULL : _decode(nameid.release());\r
-}\r
-\r
-void NameIDAttributeDecoder::extract(\r
-    const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    auto_arrayptr<char> name(toUTF8(n->getName()));\r
-    if (name.get() && *name.get()) {\r
-        dest.push_back(NameIDAttribute::Value());\r
-        NameIDAttribute::Value& val = dest.back();\r
-        val.m_Name = name.get();\r
-        char* str = toUTF8(n->getFormat());\r
-        if (str) {\r
-            val.m_Format = str;\r
-            delete[] str;\r
-        }\r
-\r
-        str = toUTF8(n->getNameQualifier());\r
-        if (str && *str)\r
-            val.m_NameQualifier = str;\r
-        else if (m_defaultQualifiers && assertingParty)\r
-            val.m_NameQualifier = assertingParty;\r
-        delete[] str;\r
-\r
-        str = toUTF8(n->getSPNameQualifier());\r
-        if (str && *str)\r
-            val.m_SPNameQualifier = str;\r
-        else if (m_defaultQualifiers && relyingParty)\r
-            val.m_SPNameQualifier = relyingParty;\r
-        delete[] str;\r
-\r
-        str = toUTF8(n->getSPProvidedID());\r
-        if (str) {\r
-            val.m_SPProvidedID = str;\r
-            delete[] str;\r
-        }\r
-    }\r
-}\r
-\r
-void NameIDAttributeDecoder::extract(\r
-    const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    auto_arrayptr<char> name(toUTF8(n->getName()));\r
-    if (name.get() && *name.get()) {\r
-        dest.push_back(NameIDAttribute::Value());\r
-        NameIDAttribute::Value& val = dest.back();\r
-        val.m_Name = name.get();\r
-        char* str = toUTF8(n->getFormat());\r
-        if (str) {\r
-            val.m_Format = str;\r
-            delete[] str;\r
-        }\r
-\r
-        str = toUTF8(n->getNameQualifier());\r
-        if (str && *str)\r
-            val.m_NameQualifier = str;\r
-        else if (m_defaultQualifiers && assertingParty)\r
-            val.m_NameQualifier = assertingParty;\r
-        delete[] str;\r
-\r
-        if (m_defaultQualifiers && relyingParty)\r
-            val.m_SPNameQualifier = relyingParty;\r
-    }\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/**
+ * NameIDAttributeDecoder.cpp
+ *
+ * Decodes SAML into NameIDAttributes
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/NameIDAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+    static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);
+
+    class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        NameIDAttributeDecoder(const DOMElement* e)
+                : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {
+            const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;
+            if (flag && (*flag == chLatin_t || *flag == chDigit_1))
+                m_defaultQualifiers = true;
+        }
+        ~NameIDAttributeDecoder() {}
+
+        shibsp::Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        void extract(
+            const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+            ) const;
+        void extract(
+            const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+            ) const;
+        auto_ptr_char m_formatter;
+        bool m_defaultQualifiers;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new NameIDAttributeDecoder(e);
+    }
+};
+
+shibsp::Attribute* NameIDAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_ptr<NameIDAttribute> nameid(
+        new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)
+        );
+    vector<NameIDAttribute::Value>& dest = nameid->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID");
+
+    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+        if (saml2attr) {
+            const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml2attr->getName());
+                log.debug(
+                    "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+            if (saml1attr) {
+                const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+                v = values.begin();
+                stop = values.end();
+                if (log.isDebugEnabled()) {
+                    auto_ptr_char n(saml1attr->getAttributeName());
+                    log.debug(
+                        "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                        ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                        );
+                }
+            }
+            else {
+                log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");
+                return NULL;
+            }
+        }
+
+        for (; v!=stop; ++v) {
+            const NameIDType* n2 = dynamic_cast<const NameIDType*>(*v);
+            if (n2)
+                extract(n2, dest, assertingParty, relyingParty);
+            else {
+                const NameIdentifier* n1=dynamic_cast<const NameIdentifier*>(*v);
+                if (n1)
+                    extract(n1, dest, assertingParty, relyingParty);
+                else if ((*v)->hasChildren()) {
+                    const list<XMLObject*>& values = (*v)->getOrderedChildren();
+                    for (list<XMLObject*>::const_iterator vv = values.begin(); vv!=values.end(); ++vv) {
+                        if (n2=dynamic_cast<const NameIDType*>(*vv))
+                            extract(n2, dest, assertingParty, relyingParty);
+                        else if (n1=dynamic_cast<const NameIdentifier*>(*vv))
+                            extract(n1, dest, assertingParty, relyingParty);
+                        else
+                            log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier");
+                    }
+                }
+            }
+        }
+
+        return dest.empty() ? NULL : _decode(nameid.release());
+    }
+
+    const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);
+    if (saml2name) {
+        if (log.isDebugEnabled()) {
+            auto_ptr_char f(saml2name->getFormat());
+            log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+        }
+        extract(saml2name, dest, assertingParty, relyingParty);
+    }
+    else {
+        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+        if (saml1name) {
+            if (log.isDebugEnabled()) {
+                auto_ptr_char f(saml1name->getFormat());
+                log.debug(
+                    "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"
+                    );
+            }
+            extract(saml1name, dest, assertingParty, relyingParty);
+        }
+        else {
+            log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    return dest.empty() ? NULL : _decode(nameid.release());
+}
+
+void NameIDAttributeDecoder::extract(
+    const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_arrayptr<char> name(toUTF8(n->getName()));
+    if (name.get() && *name.get()) {
+        dest.push_back(NameIDAttribute::Value());
+        NameIDAttribute::Value& val = dest.back();
+        val.m_Name = name.get();
+        char* str = toUTF8(n->getFormat());
+        if (str) {
+            val.m_Format = str;
+            delete[] str;
+        }
+
+        str = toUTF8(n->getNameQualifier());
+        if (str && *str)
+            val.m_NameQualifier = str;
+        else if (m_defaultQualifiers && assertingParty)
+            val.m_NameQualifier = assertingParty;
+        delete[] str;
+
+        str = toUTF8(n->getSPNameQualifier());
+        if (str && *str)
+            val.m_SPNameQualifier = str;
+        else if (m_defaultQualifiers && relyingParty)
+            val.m_SPNameQualifier = relyingParty;
+        delete[] str;
+
+        str = toUTF8(n->getSPProvidedID());
+        if (str) {
+            val.m_SPProvidedID = str;
+            delete[] str;
+        }
+    }
+}
+
+void NameIDAttributeDecoder::extract(
+    const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_arrayptr<char> name(toUTF8(n->getName()));
+    if (name.get() && *name.get()) {
+        dest.push_back(NameIDAttribute::Value());
+        NameIDAttribute::Value& val = dest.back();
+        val.m_Name = name.get();
+        char* str = toUTF8(n->getFormat());
+        if (str) {
+            val.m_Format = str;
+            delete[] str;
+        }
+
+        str = toUTF8(n->getNameQualifier());
+        if (str && *str)
+            val.m_NameQualifier = str;
+        else if (m_defaultQualifiers && assertingParty)
+            val.m_NameQualifier = assertingParty;
+        delete[] str;
+
+        if (m_defaultQualifiers && relyingParty)
+            val.m_SPNameQualifier = relyingParty;
+    }
+}
index f2a9d6f..c19fc6b 100644 (file)
-/*\r
- *  Copyright 2001-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
- * StringAttributeDecoder.cpp\r
- *\r
- * Decodes SAML into SimpleAttributes\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
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml1;\r
-using namespace opensaml::saml2;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
-        ~StringAttributeDecoder() {}\r
-\r
-        shibsp::Attribute* decode(\r
-            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
-            ) const;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new StringAttributeDecoder(e);\r
-    }\r
-};\r
-\r
-shibsp::Attribute* StringAttributeDecoder::decode(\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(ids));\r
-    vector<string>& dest = simple->getValues();\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");\r
-\r
-    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
-        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::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 opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::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 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
-                log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
-                return NULL;\r
-            }\r
-        }\r
-\r
-        for (; v!=stop; ++v) {\r
-            if (!(*v)->hasChildren()) {\r
-                val = toUTF8((*v)->getTextContent());\r
-                if (val && *val)\r
-                    dest.push_back(val);\r
-                else\r
-                    log.warn("skipping empty AttributeValue");\r
-                delete[] val;\r
-            }\r
-            else {\r
-                log.warn("skipping complex AttributeValue");\r
-            }\r
-        }\r
-\r
-        return dest.empty() ? NULL : _decode(simple.release());\r
-    }\r
-\r
-    const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
-    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)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
-        }\r
-        val = toUTF8(saml2name->getName());\r
-    }\r
-    else {\r
-        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
-        if (saml1name) {\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char f(saml1name->getFormat());\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
-        else {\r
-            log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    if (val && *val)\r
-        dest.push_back(val);\r
-    else\r
-        log.warn("ignoring empty NameID");\r
-    delete[] val;\r
-    return dest.empty() ? NULL : _decode(simple.release());\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/**
+ * StringAttributeDecoder.cpp
+ *
+ * Decodes SAML into SimpleAttributes
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+        ~StringAttributeDecoder() {}
+
+        shibsp::Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new StringAttributeDecoder(e);
+    }
+};
+
+shibsp::Attribute* StringAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    char* val;
+    auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
+    vector<string>& dest = simple->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");
+
+    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+        if (saml2attr) {
+            const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml2attr->getName());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+            if (saml1attr) {
+                const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+                v = values.begin();
+                stop = values.end();
+                if (log.isDebugEnabled()) {
+                    auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+                }
+            }
+            else {
+                log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
+                return NULL;
+            }
+        }
+
+        for (; v!=stop; ++v) {
+            if (!(*v)->hasChildren()) {
+                val = toUTF8((*v)->getTextContent());
+                if (val && *val)
+                    dest.push_back(val);
+                else
+                    log.warn("skipping empty AttributeValue");
+                delete[] val;
+            }
+            else {
+                log.warn("skipping complex AttributeValue");
+            }
+        }
+
+        return dest.empty() ? NULL : _decode(simple.release());
+    }
+
+    const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
+    if (saml2name) {
+        if (log.isDebugEnabled()) {
+            auto_ptr_char f(saml2name->getFormat());
+            log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+        }
+        val = toUTF8(saml2name->getName());
+    }
+    else {
+        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+        if (saml1name) {
+            if (log.isDebugEnabled()) {
+                auto_ptr_char f(saml1name->getFormat());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"
+                    );
+            }
+            val = toUTF8(saml1name->getName());
+        }
+        else {
+            log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    if (val && *val)
+        dest.push_back(val);
+    else
+        log.warn("ignoring empty NameID");
+    delete[] val;
+    return dest.empty() ? NULL : _decode(simple.release());
+}
index 2d59528..4c99938 100644 (file)
-/*\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
- * XMLAttributeDecoder.cpp\r
- *\r
- * Decodes arbitrary XML into an XMLAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/XMLAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
-        ~XMLAttributeDecoder() {}\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
-        DDF convert(DOMElement* e, bool nameit=true) const;\r
-        auto_ptr_char m_formatter;\r
-        map<pair<xstring,xstring>,string> m_tagMap;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new XMLAttributeDecoder(e);\r
-    }\r
-};\r
-\r
-\r
-Attribute* XMLAttributeDecoder::decode(\r
-    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    if (!xmlObject)\r
-        return NULL;\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");\r
-\r
-    auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));\r
-    vector<string>& dest = attr->getValues();\r
-\r
-    // Handle any non-Attribute object directly.\r
-    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
-        DOMElement* e = xmlObject->getDOM();\r
-        if (e) {\r
-            if (log.isDebugEnabled()) {\r
-                log.debug(\r
-                    "decoding XMLAttribute (%s) from XMLObject (%s)",\r
-                    ids.front().c_str(),\r
-                    (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()\r
-                    );\r
-            }\r
-            dest.push_back(string());\r
-            XMLHelper::serialize(e, dest.back());\r
-        }\r
-        else {\r
-            log.warn("skipping XMLObject without a backing DOM");\r
-        }\r
-        return dest.empty() ? NULL : _decode(attr.release());\r
-    }\r
-\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 XMLAttribute (%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 XMLAttribute (%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 XMLAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    for (; v!=stop; ++v) {\r
-        DOMElement* e = (*v)->getDOM();\r
-        if (e) {\r
-            dest.push_back(string());\r
-            XMLHelper::serialize(e, dest.back());\r
-        }\r
-        else\r
-            log.warn("skipping AttributeValue without a backing DOM");\r
-    }\r
-\r
-    return dest.empty() ? NULL : _decode(attr.release());\r
-}\r
+/*
+ *  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.
+ */
+
+/**
+ * XMLAttributeDecoder.cpp
+ *
+ * Decodes arbitrary XML into an XMLAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/XMLAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+        ~XMLAttributeDecoder() {}
+
+        Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        DDF convert(DOMElement* e, bool nameit=true) const;
+        auto_ptr_char m_formatter;
+        map<pair<xstring,xstring>,string> m_tagMap;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new XMLAttributeDecoder(e);
+    }
+};
+
+
+Attribute* XMLAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    if (!xmlObject)
+        return NULL;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");
+
+    auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));
+    vector<string>& dest = attr->getValues();
+
+    // Handle any non-Attribute object directly.
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+        DOMElement* e = xmlObject->getDOM();
+        if (e) {
+            if (log.isDebugEnabled()) {
+                log.debug(
+                    "decoding XMLAttribute (%s) from XMLObject (%s)",
+                    ids.front().c_str(),
+                    (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()
+                    );
+            }
+            dest.push_back(string());
+            XMLHelper::serialize(e, dest.back());
+        }
+        else {
+            log.warn("skipping XMLObject without a backing DOM");
+        }
+        return dest.empty() ? NULL : _decode(attr.release());
+    }
+
+    vector<XMLObject*>::const_iterator v,stop;
+
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+    if (saml2attr) {
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+        v = values.begin();
+        stop = values.end();
+        if (log.isDebugEnabled()) {
+            auto_ptr_char n(saml2attr->getName());
+            log.debug(
+                "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                );
+        }
+    }
+    else {
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+        if (saml1attr) {
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    for (; v!=stop; ++v) {
+        DOMElement* e = (*v)->getDOM();
+        if (e) {
+            dest.push_back(string());
+            XMLHelper::serialize(e, dest.back());
+        }
+        else
+            log.warn("skipping AttributeValue without a backing DOM");
+    }
+
+    return dest.empty() ? NULL : _decode(attr.release());
+}
index 8f6e78c..6feafda 100644 (file)
-/*\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
- * ChainingAccessControl.cpp\r
- *\r
- * Access control plugin that combines other plugins.\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "AccessControl.h"\r
-#include "SessionCache.h"\r
-#include "SPRequest.h"\r
-\r
-#include <algorithm>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-\r
-    class ChainingAccessControl : public AccessControl\r
-    {\r
-    public:\r
-        ChainingAccessControl(const DOMElement* e);\r
-\r
-        ~ChainingAccessControl() {\r
-            for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
-        }\r
-\r
-        Lockable* lock() {\r
-            for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));\r
-            return this;\r
-        }\r
-        void unlock() {\r
-            for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));\r
-        }\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        enum operator_t { OP_AND, OP_OR } m_op;\r
-        vector<AccessControl*> m_ac;\r
-    };\r
-\r
-    AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)\r
-    {\r
-        return new ChainingAccessControl(e);\r
-    }\r
-\r
-    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
-    static const XMLCh _operator[] =        UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);\r
-    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);\r
-    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);\r
-    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);\r
-\r
-    extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);\r
-}\r
-\r
-void SHIBSP_API shibsp::registerAccessControls()\r
-{\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);\r
-    conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
-    conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
-}\r
-\r
-AccessControl::AccessControl()\r
-{\r
-}\r
-\r
-AccessControl::~AccessControl()\r
-{\r
-}\r
-\r
-ChainingAccessControl::ChainingAccessControl(const DOMElement* e)\r
-{\r
-    const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;\r
-    if (XMLString::equals(op, AND))\r
-        m_op=OP_AND;\r
-    else if (XMLString::equals(op, OR))\r
-        m_op=OP_OR;\r
-    else\r
-        throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");\r
-\r
-    try {\r
-        e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;\r
-        while (e) {\r
-            auto_ptr_char type(e->getAttributeNS(NULL, _type));\r
-            if (type.get() && *type.get()) {\r
-                Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());\r
-                m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));\r
-            }\r
-            e = XMLHelper::getNextSiblingElement(e, _AccessControl);\r
-        }\r
-    }\r
-    catch (exception&) {\r
-        for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
-        throw;\r
-    }\r
-    if (m_ac.empty())\r
-        throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");\r
-}\r
-\r
-AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    switch (m_op) {\r
-        case OP_AND:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
-                if ((*i)->authorized(request, session) != shib_acl_true)\r
-                    return shib_acl_false;\r
-            }\r
-            return shib_acl_true;\r
-        }\r
-\r
-        case OP_OR:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
-                if ((*i)->authorized(request,session) == shib_acl_true)\r
-                    return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-    }\r
-    request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");\r
-    return shib_acl_false;\r
-}\r
+/*
+ *  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.
+ */
+
+/**
+ * ChainingAccessControl.cpp
+ *
+ * Access control plugin that combines other plugins.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+
+#include <algorithm>
+#include <xmltooling/unicode.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+    class ChainingAccessControl : public AccessControl
+    {
+    public:
+        ChainingAccessControl(const DOMElement* e);
+
+        ~ChainingAccessControl() {
+            for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+        }
+
+        Lockable* lock() {
+            for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));
+            return this;
+        }
+        void unlock() {
+            for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));
+        }
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        enum operator_t { OP_AND, OP_OR } m_op;
+        vector<AccessControl*> m_ac;
+    };
+
+    AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)
+    {
+        return new ChainingAccessControl(e);
+    }
+
+    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+    static const XMLCh _operator[] =        UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
+    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);
+    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);
+
+    extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);
+}
+
+void SHIBSP_API shibsp::registerAccessControls()
+{
+    SPConfig& conf=SPConfig::getConfig();
+    conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);
+    conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
+    conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);
+}
+
+AccessControl::AccessControl()
+{
+}
+
+AccessControl::~AccessControl()
+{
+}
+
+ChainingAccessControl::ChainingAccessControl(const DOMElement* e)
+{
+    const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;
+    if (XMLString::equals(op, AND))
+        m_op=OP_AND;
+    else if (XMLString::equals(op, OR))
+        m_op=OP_OR;
+    else
+        throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");
+
+    try {
+        e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;
+        while (e) {
+            auto_ptr_char type(e->getAttributeNS(NULL, _type));
+            if (type.get() && *type.get()) {
+                Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());
+                m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));
+            }
+            e = XMLHelper::getNextSiblingElement(e, _AccessControl);
+        }
+    }
+    catch (exception&) {
+        for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+        throw;
+    }
+    if (m_ac.empty())
+        throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
+}
+
+AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+    switch (m_op) {
+        case OP_AND:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+                if ((*i)->authorized(request, session) != shib_acl_true)
+                    return shib_acl_false;
+            }
+            return shib_acl_true;
+        }
+
+        case OP_OR:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+                if ((*i)->authorized(request,session) == shib_acl_true)
+                    return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+    }
+    request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");
+    return shib_acl_false;
+}
index 9c2e4ca..7e08b73 100644 (file)
-/*\r
- *  Copyright 2001-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
- * XMLAccessControl.cpp\r
- *\r
- * XML-based access control syntax\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "AccessControl.h"\r
-#include "SessionCache.h"\r
-#include "SPRequest.h"\r
-#include "attribute/Attribute.h"\r
-\r
-#include <algorithm>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/util/ReloadableXMLFile.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xercesc/util/regx/RegularExpression.hpp>\r
-\r
-#ifndef HAVE_STRCASECMP\r
-# define strcasecmp _stricmp\r
-#endif\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-\r
-    class Rule : public AccessControl\r
-    {\r
-    public:\r
-        Rule(const DOMElement* e);\r
-        ~Rule() {}\r
-\r
-        Lockable* lock() {return this;}\r
-        void unlock() {}\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        string m_alias;\r
-        vector <string> m_vals;\r
-    };\r
-\r
-    class RuleRegex : public AccessControl\r
-    {\r
-    public:\r
-        RuleRegex(const DOMElement* e);\r
-        ~RuleRegex() {\r
-            delete m_re;\r
-        }\r
-\r
-        Lockable* lock() {return this;}\r
-        void unlock() {}\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        string m_alias;\r
-        auto_arrayptr<char> m_exp;\r
-        RegularExpression* m_re;\r
-    };\r
-\r
-    class Operator : public AccessControl\r
-    {\r
-    public:\r
-        Operator(const DOMElement* e);\r
-        ~Operator();\r
-\r
-        Lockable* lock() {return this;}\r
-        void unlock() {}\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;\r
-        vector<AccessControl*> m_operands;\r
-    };\r
-\r
-#if defined (_MSC_VER)\r
-    #pragma warning( push )\r
-    #pragma warning( disable : 4250 )\r
-#endif\r
-\r
-    class XMLAccessControl : public AccessControl, public ReloadableXMLFile\r
-    {\r
-    public:\r
-        XMLAccessControl(const DOMElement* e)\r
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {\r
-            load(); // guarantees an exception or the policy is loaded\r
-        }\r
-\r
-        ~XMLAccessControl() {\r
-            delete m_rootAuthz;\r
-        }\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    protected:\r
-        pair<bool,DOMElement*> load();\r
-\r
-    private:\r
-        AccessControl* m_rootAuthz;\r
-    };\r
-\r
-#if defined (_MSC_VER)\r
-    #pragma warning( pop )\r
-#endif\r
-\r
-    AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)\r
-    {\r
-        return new XMLAccessControl(e);\r
-    }\r
-\r
-    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
-    static const XMLCh ignoreCase[] =       UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);\r
-    static const XMLCh ignoreOption[] =     UNICODE_LITERAL_1(i);\r
-    static const XMLCh _list[] =            UNICODE_LITERAL_4(l,i,s,t);\r
-    static const XMLCh require[] =          UNICODE_LITERAL_7(r,e,q,u,i,r,e);\r
-    static const XMLCh NOT[] =              UNICODE_LITERAL_3(N,O,T);\r
-    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);\r
-    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);\r
-    static const XMLCh _Rule[] =            UNICODE_LITERAL_4(R,u,l,e);\r
-    static const XMLCh _RuleRegex[] =       UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);\r
-}\r
-\r
-Rule::Rule(const DOMElement* e)\r
-{\r
-    auto_ptr_char req(e->getAttributeNS(NULL,require));\r
-    if (!req.get() || !*req.get())\r
-        throw ConfigurationException("Access control rule missing require attribute");\r
-    m_alias=req.get();\r
-\r
-    auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));\r
-    if (!vals.get())\r
-        return;\r
-\r
-    const XMLCh* flag = e->getAttributeNS(NULL,_list);\r
-    if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {\r
-        if (*vals.get())\r
-            m_vals.push_back(vals.get());\r
-        return;\r
-    }\r
-\r
-#ifdef HAVE_STRTOK_R\r
-    char* pos=NULL;\r
-    const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);\r
-#else\r
-    const char* token=strtok(const_cast<char*>(vals.get())," ");\r
-#endif\r
-    while (token) {\r
-        m_vals.push_back(token);\r
-#ifdef HAVE_STRTOK_R\r
-        token=strtok_r(NULL," ",&pos);\r
-#else\r
-        token=strtok(NULL," ");\r
-#endif\r
-    }\r
-}\r
-\r
-AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    // We can make this more complex later using pluggable comparison functions,\r
-    // but for now, just a straight port to the new Attribute API.\r
-\r
-    // Map alias in rule to the attribute.\r
-    if (!session) {\r
-        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
-        return shib_acl_false;\r
-    }\r
-\r
-    if (m_alias == "valid-user") {\r
-        if (session) {\r
-            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
-            return shib_acl_true;\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-    if (m_alias == "user") {\r
-        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
-            if (*i == request.getRemoteUser()) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-    else if (m_alias == "authnContextClassRef") {\r
-        const char* ref = session->getAuthnContextClassRef();\r
-        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
-            if (!strcmp(i->c_str(),ref)) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-    else if (m_alias == "authnContextDeclRef") {\r
-        const char* ref = session->getAuthnContextDeclRef();\r
-        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
-            if (!strcmp(i->c_str(),ref)) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-\r
-    // Find the attribute(s) matching the require rule.\r
-    pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
-        session->getIndexedAttributes().equal_range(m_alias);\r
-    if (attrs.first == attrs.second) {\r
-        request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
-        return shib_acl_false;\r
-    }\r
-\r
-    for (; attrs.first != attrs.second; ++attrs.first) {\r
-        bool caseSensitive = attrs.first->second->isCaseSensitive();\r
-\r
-        // Now we have to intersect the attribute's values against the rule's list.\r
-        const vector<string>& vals = attrs.first->second->getSerializedValues();\r
-        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
-            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
-                if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {\r
-                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");\r
-                    return shib_acl_true;\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    return shib_acl_false;\r
-}\r
-\r
-RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))\r
-{\r
-    auto_ptr_char req(e->getAttributeNS(NULL,require));\r
-    if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())\r
-        throw ConfigurationException("Access control rule missing require attribute or element content.");\r
-    m_alias=req.get();\r
-\r
-    const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);\r
-    bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
-    try {\r
-        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));\r
-    }\r
-    catch (XMLException& ex) {\r
-        auto_ptr_char tmp(ex.getMessage());\r
-        throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));\r
-    }\r
-}\r
-\r
-AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    // Map alias in rule to the attribute.\r
-    if (!session) {\r
-        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
-        return shib_acl_false;\r
-    }\r
-\r
-    if (m_alias == "valid-user") {\r
-        if (session) {\r
-            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
-            return shib_acl_true;\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-\r
-    try {\r
-        if (m_alias == "user") {\r
-            if (m_re->matches(request.getRemoteUser().c_str())) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-        else if (m_alias == "authnContextClassRef") {\r
-            if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-        else if (m_alias == "authnContextDeclRef") {\r
-            if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-\r
-        // Find the attribute(s) matching the require rule.\r
-        pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
-            session->getIndexedAttributes().equal_range(m_alias);\r
-        if (attrs.first == attrs.second) {\r
-            request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
-            return shib_acl_false;\r
-        }\r
-\r
-        for (; attrs.first != attrs.second; ++attrs.first) {\r
-            // Now we have to intersect the attribute's values against the regular expression.\r
-            const vector<string>& vals = attrs.first->second->getSerializedValues();\r
-            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
-                if (m_re->matches(j->c_str())) {\r
-                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");\r
-                    return shib_acl_true;\r
-                }\r
-            }\r
-        }\r
-    }\r
-    catch (XMLException& ex) {\r
-        auto_ptr_char tmp(ex.getMessage());\r
-        request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());\r
-    }\r
-\r
-    return shib_acl_false;\r
-}\r
-\r
-Operator::Operator(const DOMElement* e)\r
-{\r
-    if (XMLString::equals(e->getLocalName(),NOT))\r
-        m_op=OP_NOT;\r
-    else if (XMLString::equals(e->getLocalName(),AND))\r
-        m_op=OP_AND;\r
-    else if (XMLString::equals(e->getLocalName(),OR))\r
-        m_op=OP_OR;\r
-    else\r
-        throw ConfigurationException("Unrecognized operator in access control rule");\r
-\r
-    try {\r
-        e=XMLHelper::getFirstChildElement(e);\r
-        if (XMLString::equals(e->getLocalName(),_Rule))\r
-            m_operands.push_back(new Rule(e));\r
-        else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
-            m_operands.push_back(new RuleRegex(e));\r
-        else\r
-            m_operands.push_back(new Operator(e));\r
-\r
-        if (m_op==OP_NOT)\r
-            return;\r
-\r
-        e=XMLHelper::getNextSiblingElement(e);\r
-        while (e) {\r
-            if (XMLString::equals(e->getLocalName(),_Rule))\r
-                m_operands.push_back(new Rule(e));\r
-            else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
-                m_operands.push_back(new RuleRegex(e));\r
-            else\r
-                m_operands.push_back(new Operator(e));\r
-            e=XMLHelper::getNextSiblingElement(e);\r
-        }\r
-    }\r
-    catch (exception&) {\r
-        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
-        throw;\r
-    }\r
-}\r
-\r
-Operator::~Operator()\r
-{\r
-    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
-}\r
-\r
-AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    switch (m_op) {\r
-        case OP_NOT:\r
-            switch (m_operands.front()->authorized(request,session)) {\r
-                case shib_acl_true:\r
-                    return shib_acl_false;\r
-                case shib_acl_false:\r
-                    return shib_acl_true;\r
-                default:\r
-                    return shib_acl_indeterminate;\r
-            }\r
-\r
-        case OP_AND:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
-                if ((*i)->authorized(request,session) != shib_acl_true)\r
-                    return shib_acl_false;\r
-            }\r
-            return shib_acl_true;\r
-        }\r
-\r
-        case OP_OR:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
-                if ((*i)->authorized(request,session) == shib_acl_true)\r
-                    return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-    }\r
-    request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");\r
-    return shib_acl_false;\r
-}\r
-\r
-pair<bool,DOMElement*> XMLAccessControl::load()\r
-{\r
-    // Load from source using base class.\r
-    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
-\r
-    // If we own it, wrap it.\r
-    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
-\r
-    // Check for AccessControl wrapper and drop a level.\r
-    if (XMLString::equals(raw.second->getLocalName(),_AccessControl))\r
-        raw.second = XMLHelper::getFirstChildElement(raw.second);\r
-\r
-    AccessControl* authz;\r
-    if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
-        authz=new Rule(raw.second);\r
-    else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))\r
-        authz=new RuleRegex(raw.second);\r
-    else\r
-        authz=new Operator(raw.second);\r
-\r
-    delete m_rootAuthz;\r
-    m_rootAuthz = authz;\r
-    return make_pair(false,(DOMElement*)NULL);\r
-}\r
-\r
-AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false;\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/**
+ * XMLAccessControl.cpp
+ *
+ * XML-based access control syntax
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+#include "attribute/Attribute.h"
+
+#include <algorithm>
+#include <xmltooling/unicode.h>
+#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
+
+#ifndef HAVE_STRCASECMP
+# define strcasecmp _stricmp
+#endif
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+    class Rule : public AccessControl
+    {
+    public:
+        Rule(const DOMElement* e);
+        ~Rule() {}
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        string m_alias;
+        vector <string> m_vals;
+    };
+
+    class RuleRegex : public AccessControl
+    {
+    public:
+        RuleRegex(const DOMElement* e);
+        ~RuleRegex() {
+            delete m_re;
+        }
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        string m_alias;
+        auto_arrayptr<char> m_exp;
+        RegularExpression* m_re;
+    };
+
+    class Operator : public AccessControl
+    {
+    public:
+        Operator(const DOMElement* e);
+        ~Operator();
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
+        vector<AccessControl*> m_operands;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 )
+#endif
+
+    class XMLAccessControl : public AccessControl, public ReloadableXMLFile
+    {
+    public:
+        XMLAccessControl(const DOMElement* e)
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {
+            load(); // guarantees an exception or the policy is loaded
+        }
+
+        ~XMLAccessControl() {
+            delete m_rootAuthz;
+        }
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    protected:
+        pair<bool,DOMElement*> load();
+
+    private:
+        AccessControl* m_rootAuthz;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+    AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)
+    {
+        return new XMLAccessControl(e);
+    }
+
+    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+    static const XMLCh ignoreCase[] =       UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);
+    static const XMLCh ignoreOption[] =     UNICODE_LITERAL_1(i);
+    static const XMLCh _list[] =            UNICODE_LITERAL_4(l,i,s,t);
+    static const XMLCh require[] =          UNICODE_LITERAL_7(r,e,q,u,i,r,e);
+    static const XMLCh NOT[] =              UNICODE_LITERAL_3(N,O,T);
+    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);
+    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);
+    static const XMLCh _Rule[] =            UNICODE_LITERAL_4(R,u,l,e);
+    static const XMLCh _RuleRegex[] =       UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);
+}
+
+Rule::Rule(const DOMElement* e)
+{
+    auto_ptr_char req(e->getAttributeNS(NULL,require));
+    if (!req.get() || !*req.get())
+        throw ConfigurationException("Access control rule missing require attribute");
+    m_alias=req.get();
+
+    auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));
+    if (!vals.get())
+        return;
+
+    const XMLCh* flag = e->getAttributeNS(NULL,_list);
+    if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {
+        if (*vals.get())
+            m_vals.push_back(vals.get());
+        return;
+    }
+
+#ifdef HAVE_STRTOK_R
+    char* pos=NULL;
+    const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);
+#else
+    const char* token=strtok(const_cast<char*>(vals.get())," ");
+#endif
+    while (token) {
+        m_vals.push_back(token);
+#ifdef HAVE_STRTOK_R
+        token=strtok_r(NULL," ",&pos);
+#else
+        token=strtok(NULL," ");
+#endif
+    }
+}
+
+AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const
+{
+    // We can make this more complex later using pluggable comparison functions,
+    // but for now, just a straight port to the new Attribute API.
+
+    // Map alias in rule to the attribute.
+    if (!session) {
+        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
+        return shib_acl_false;
+    }
+
+    if (m_alias == "valid-user") {
+        if (session) {
+            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
+            return shib_acl_true;
+        }
+        return shib_acl_false;
+    }
+    if (m_alias == "user") {
+        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
+            if (*i == request.getRemoteUser()) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");
+                return shib_acl_true;
+            }
+        }
+        return shib_acl_false;
+    }
+    else if (m_alias == "authnContextClassRef") {
+        const char* ref = session->getAuthnContextClassRef();
+        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
+            if (!strcmp(i->c_str(),ref)) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");
+                return shib_acl_true;
+            }
+        }
+        return shib_acl_false;
+    }
+    else if (m_alias == "authnContextDeclRef") {
+        const char* ref = session->getAuthnContextDeclRef();
+        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
+            if (!strcmp(i->c_str(),ref)) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");
+                return shib_acl_true;
+            }
+        }
+        return shib_acl_false;
+    }
+
+    // Find the attribute(s) matching the require rule.
+    pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =
+        session->getIndexedAttributes().equal_range(m_alias);
+    if (attrs.first == attrs.second) {
+        request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");
+        return shib_acl_false;
+    }
+
+    for (; attrs.first != attrs.second; ++attrs.first) {
+        bool caseSensitive = attrs.first->second->isCaseSensitive();
+
+        // Now we have to intersect the attribute's values against the rule's list.
+        const vector<string>& vals = attrs.first->second->getSerializedValues();
+        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
+            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+                if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {
+                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");
+                    return shib_acl_true;
+                }
+            }
+        }
+    }
+
+    return shib_acl_false;
+}
+
+RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))
+{
+    auto_ptr_char req(e->getAttributeNS(NULL,require));
+    if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())
+        throw ConfigurationException("Access control rule missing require attribute or element content.");
+    m_alias=req.get();
+
+    const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);
+    bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+    try {
+        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
+    }
+    catch (XMLException& ex) {
+        auto_ptr_char tmp(ex.getMessage());
+        throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));
+    }
+}
+
+AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const
+{
+    // Map alias in rule to the attribute.
+    if (!session) {
+        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
+        return shib_acl_false;
+    }
+
+    if (m_alias == "valid-user") {
+        if (session) {
+            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
+            return shib_acl_true;
+        }
+        return shib_acl_false;
+    }
+
+    try {
+        if (m_alias == "user") {
+            if (m_re->matches(request.getRemoteUser().c_str())) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");
+                return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+        else if (m_alias == "authnContextClassRef") {
+            if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");
+                return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+        else if (m_alias == "authnContextDeclRef") {
+            if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");
+                return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+
+        // Find the attribute(s) matching the require rule.
+        pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =
+            session->getIndexedAttributes().equal_range(m_alias);
+        if (attrs.first == attrs.second) {
+            request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");
+            return shib_acl_false;
+        }
+
+        for (; attrs.first != attrs.second; ++attrs.first) {
+            // Now we have to intersect the attribute's values against the regular expression.
+            const vector<string>& vals = attrs.first->second->getSerializedValues();
+            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+                if (m_re->matches(j->c_str())) {
+                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");
+                    return shib_acl_true;
+                }
+            }
+        }
+    }
+    catch (XMLException& ex) {
+        auto_ptr_char tmp(ex.getMessage());
+        request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());
+    }
+
+    return shib_acl_false;
+}
+
+Operator::Operator(const DOMElement* e)
+{
+    if (XMLString::equals(e->getLocalName(),NOT))
+        m_op=OP_NOT;
+    else if (XMLString::equals(e->getLocalName(),AND))
+        m_op=OP_AND;
+    else if (XMLString::equals(e->getLocalName(),OR))
+        m_op=OP_OR;
+    else
+        throw ConfigurationException("Unrecognized operator in access control rule");
+
+    try {
+        e=XMLHelper::getFirstChildElement(e);
+        if (XMLString::equals(e->getLocalName(),_Rule))
+            m_operands.push_back(new Rule(e));
+        else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+            m_operands.push_back(new RuleRegex(e));
+        else
+            m_operands.push_back(new Operator(e));
+
+        if (m_op==OP_NOT)
+            return;
+
+        e=XMLHelper::getNextSiblingElement(e);
+        while (e) {
+            if (XMLString::equals(e->getLocalName(),_Rule))
+                m_operands.push_back(new Rule(e));
+            else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+                m_operands.push_back(new RuleRegex(e));
+            else
+                m_operands.push_back(new Operator(e));
+            e=XMLHelper::getNextSiblingElement(e);
+        }
+    }
+    catch (exception&) {
+        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
+        throw;
+    }
+}
+
+Operator::~Operator()
+{
+    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
+}
+
+AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const
+{
+    switch (m_op) {
+        case OP_NOT:
+            switch (m_operands.front()->authorized(request,session)) {
+                case shib_acl_true:
+                    return shib_acl_false;
+                case shib_acl_false:
+                    return shib_acl_true;
+                default:
+                    return shib_acl_indeterminate;
+            }
+
+        case OP_AND:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
+                if ((*i)->authorized(request,session) != shib_acl_true)
+                    return shib_acl_false;
+            }
+            return shib_acl_true;
+        }
+
+        case OP_OR:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
+                if ((*i)->authorized(request,session) == shib_acl_true)
+                    return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+    }
+    request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");
+    return shib_acl_false;
+}
+
+pair<bool,DOMElement*> XMLAccessControl::load()
+{
+    // Load from source using base class.
+    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
+
+    // If we own it, wrap it.
+    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
+
+    // Check for AccessControl wrapper and drop a level.
+    if (XMLString::equals(raw.second->getLocalName(),_AccessControl))
+        raw.second = XMLHelper::getFirstChildElement(raw.second);
+
+    AccessControl* authz;
+    if (XMLString::equals(raw.second->getLocalName(),_Rule))
+        authz=new Rule(raw.second);
+    else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))
+        authz=new RuleRegex(raw.second);
+    else
+        authz=new Operator(raw.second);
+
+    delete m_rootAuthz;
+    m_rootAuthz = authz;
+    return make_pair(false,(DOMElement*)NULL);
+}
+
+AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+    return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false;
+}
index f35df0b..abd4f71 100644 (file)
@@ -1,53 +1,53 @@
-/*\r
- *  Copyright 2001-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
- * @file shibsp/paths.h\r
- * \r
- * Default configuration paths.\r
- */\r
-\r
-#ifndef __shibsp_paths_h__\r
-#define __shibsp_paths_h__\r
-\r
-/** Default schema catalogs. */\r
-#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"\r
-\r
-/** Default name of SP configuration file. */\r
-#define SHIBSP_CONFIG "shibboleth2.xml"\r
-\r
-/** Default name of SP console tool logging file. */\r
-#define SHIBSP_LOGGING "console.logger"\r
-\r
-/** Default prefix for installation (used to resolve relative paths). */\r
-#define SHIBSP_PREFIX  "@-PREFIX-@"\r
-\r
-/** Library directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LIBDIR  "@-LIBDIR-@"\r
-\r
-/** Log directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LOGDIR  "@-LOGDIR-@"\r
-\r
-/** Configuration directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_CFGDIR  "@-SYSCONFDIR-@"\r
-\r
-/** Runtime state directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_RUNDIR  "@-RUNDIR-@"\r
-\r
-/** XML directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_XMLDIR  "@-XMLDIR-@"\r
-\r
-#endif /* __shibsp_paths_h__ */\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/**
+ * @file shibsp/paths.h
+ * 
+ * Default configuration paths.
+ */
+
+#ifndef __shibsp_paths_h__
+#define __shibsp_paths_h__
+
+/** Default schema catalogs. */
+#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"
+
+/** Default name of SP configuration file. */
+#define SHIBSP_CONFIG "shibboleth2.xml"
+
+/** Default name of SP console tool logging file. */
+#define SHIBSP_LOGGING "console.logger"
+
+/** Default prefix for installation (used to resolve relative paths). */
+#define SHIBSP_PREFIX  "@-PREFIX-@"
+
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR  "@-LIBDIR-@"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR  "@-LOGDIR-@"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR  "@-SYSCONFDIR-@"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR  "@-RUNDIR-@"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR  "@-XMLDIR-@"
+
+#endif /* __shibsp_paths_h__ */
index 8df1c2f..79fe549 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by shibsp.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1000\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by shibsp.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
index 38f0a0a..6614bad 100644 (file)
-/*\r
- *  Copyright 2001-2007 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
- * SPConstants.cpp\r
- * \r
- * SP XML namespace constants \r
- */\r
-\r
-#include "internal.h"\r
-#include "util/SPConstants.h"\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibspconstants;\r
-\r
-const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);\r
-\r
-const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,\r
-  chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon,\r
-  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash,\r
-  chLatin_m, chLatin_a, chLatin_p, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon,\r
-  chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,\r
-  chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,\r
-  chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chColon,\r
-  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,\r
-    chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_u, chLatin_r, chLatin_i, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chColon,\r
-  chLatin_n, chLatin_a, chLatin_m, chLatin_e,\r
-    chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chColon,\r
-  chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon,\r
-  chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n,\r
-  chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull\r
-};\r
-\r
-const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";\r
-\r
-const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";\r
-\r
-const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";\r
+/*
+ *  Copyright 2001-2007 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.
+ */
+
+/**
+ * SPConstants.cpp
+ * 
+ * SP XML namespace constants 
+ */
+
+#include "internal.h"
+#include "util/SPConstants.h"
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibspconstants;
+
+const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chNull
+};
+
+const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,
+  chDigit_1, chPeriod, chDigit_0, chNull
+};
+
+const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);
+
+const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,
+  chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash,
+  chLatin_m, chLatin_a, chLatin_p, chNull
+};
+
+const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon,
+  chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,
+  chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,
+  chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+    chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_u, chLatin_r, chLatin_i, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chColon,
+  chLatin_n, chLatin_a, chLatin_m, chLatin_e,
+    chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chColon,
+  chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon,
+  chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n,
+  chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull
+};
+
+const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";
+
+const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";
+
+const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";
index 053e994..9b928a8 100644 (file)
-/*\r
- *  Copyright 2001-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
- * mdquery.cpp\r
- * \r
- * SAML Metadata Query tool layered on SP configuration\r
- */\r
-\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/Application.h>\r
-#include <shibsp/exceptions.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/metadata/MetadataProviderCriteria.h>\r
-#include <shibsp/util/SPConstants.h>\r
-#include <saml/saml2/metadata/Metadata.h>\r
-#include <xmltooling/logging.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml2md;\r
-using namespace opensaml;\r
-using namespace xmltooling::logging;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-using xercesc::XMLString;\r
-\r
-void usage()\r
-{\r
-    cerr << "usage: mdquery -e <entityID> [-a <app id> -nostrict]" << endl;\r
-    cerr << "       mdquery -e <entityID> -r <role> -p <protocol> [-a <app id> -ns <namespace> -nostrict]" << endl;\r
-}\r
-\r
-int main(int argc,char* argv[])\r
-{\r
-    char* entityID = NULL;\r
-    char* appID = "default";\r
-    bool strict = true;\r
-    char* prot = NULL;\r
-    const XMLCh* protocol = NULL;\r
-    char* rname = NULL;\r
-    char* rns = NULL;\r
-\r
-    for (int i=1; i<argc; i++) {\r
-        if (!strcmp(argv[i],"-e") && i+1<argc)\r
-            entityID=argv[++i];\r
-        else if (!strcmp(argv[i],"-a") && i+1<argc)\r
-            appID=argv[++i];\r
-        else if (!strcmp(argv[i],"-p") && i+1<argc)\r
-            prot=argv[++i];\r
-        else if (!strcmp(argv[i],"-r") && i+1<argc)\r
-            rname=argv[++i];\r
-        else if (!strcmp(argv[i],"-ns") && i+1<argc)\r
-            rns=argv[++i];\r
-        else if (!strcmp(argv[i],"-saml10"))\r
-            protocol=samlconstants::SAML10_PROTOCOL_ENUM;\r
-        else if (!strcmp(argv[i],"-saml11"))\r
-            protocol=samlconstants::SAML11_PROTOCOL_ENUM;\r
-        else if (!strcmp(argv[i],"-saml2"))\r
-            protocol=samlconstants::SAML20P_NS;\r
-        else if (!strcmp(argv[i],"-idp"))\r
-            rname="IDPSSODescriptor";\r
-        else if (!strcmp(argv[i],"-aa"))\r
-            rname="AttributeAuthorityDescriptor";\r
-        else if (!strcmp(argv[i],"-pdp"))\r
-            rname="PDPDescriptor";\r
-        else if (!strcmp(argv[i],"-sp"))\r
-            rname="SPSSODescriptor";\r
-        else if (!strcmp(argv[i],"-nostrict"))\r
-            strict = false;\r
-    }\r
-\r
-    if (!entityID) {\r
-        usage();\r
-        return -10;\r
-    }\r
-\r
-    if (rname) {\r
-        if (!protocol) {\r
-            if (prot)\r
-                protocol = XMLString::transcode(prot);\r
-        }\r
-        if (!protocol) {\r
-            usage();\r
-            return -10;\r
-        }\r
-    }\r
-\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);\r
-    if (!conf.init())\r
-        return -1;\r
-    if (!conf.instantiate()) {\r
-        conf.term();\r
-        return -2;\r
-    }\r
-\r
-    ServiceProvider* sp=conf.getServiceProvider();\r
-    sp->lock();\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery");\r
-\r
-    const Application* app = sp->getApplication(appID);\r
-    if (!app) {\r
-        log.error("unknown application ID (%s)", appID);\r
-        sp->unlock();\r
-        conf.term();\r
-        return -3;\r
-    }\r
-\r
-    app->getMetadataProvider()->lock();\r
-    MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict);\r
-    if (rname) {\r
-        const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS;\r
-        auto_ptr_XMLCh n(rname);\r
-        QName q(ns, n.get());\r
-        mc.role = &q;\r
-        mc.protocol = protocol;\r
-        const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second;\r
-        if (role)\r
-            XMLHelper::serialize(role->marshall(), cout, true);\r
-        else\r
-            log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID);\r
-    }\r
-    else {\r
-        const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first;\r
-        if (entity)\r
-            XMLHelper::serialize(entity->marshall(), cout, true);\r
-        else\r
-            log.error("no metadata found for (%s)", entityID);\r
-    }\r
-\r
-    app->getMetadataProvider()->unlock();\r
-\r
-    sp->unlock();\r
-    conf.term();\r
-    return 0;\r
-}\r
+/*
+ *  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
+ *
+ *     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.
+ */
+
+/**
+ * mdquery.cpp
+ * 
+ * SAML Metadata Query tool layered on SP configuration
+ */
+
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <shibsp/Application.h>
+#include <shibsp/exceptions.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <shibsp/metadata/MetadataProviderCriteria.h>
+#include <shibsp/util/SPConstants.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <xmltooling/logging.h>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+using xercesc::XMLString;
+
+void usage()
+{
+    cerr << "usage: mdquery -e <entityID> [-a <app id> -nostrict]" << endl;
+    cerr << "       mdquery -e <entityID> -r <role> -p <protocol> [-a <app id> -ns <namespace> -nostrict]" << endl;
+}
+
+int main(int argc,char* argv[])
+{
+    char* entityID = NULL;
+    char* appID = "default";
+    bool strict = true;
+    char* prot = NULL;
+    const XMLCh* protocol = NULL;
+    char* rname = NULL;
+    char* rns = NULL;
+
+    for (int i=1; i<argc; i++) {
+        if (!strcmp(argv[i],"-e") && i+1<argc)
+            entityID=argv[++i];
+        else if (!strcmp(argv[i],"-a") && i+1<argc)
+            appID=argv[++i];
+        else if (!strcmp(argv[i],"-p") && i+1<argc)
+            prot=argv[++i];
+        else if (!strcmp(argv[i],"-r") && i+1<argc)
+            rname=argv[++i];
+        else if (!strcmp(argv[i],"-ns") && i+1<argc)
+            rns=argv[++i];
+        else if (!strcmp(argv[i],"-saml10"))
+            protocol=samlconstants::SAML10_PROTOCOL_ENUM;
+        else if (!strcmp(argv[i],"-saml11"))
+            protocol=samlconstants::SAML11_PROTOCOL_ENUM;
+        else if (!strcmp(argv[i],"-saml2"))
+            protocol=samlconstants::SAML20P_NS;
+        else if (!strcmp(argv[i],"-idp"))
+            rname="IDPSSODescriptor";
+        else if (!strcmp(argv[i],"-aa"))
+            rname="AttributeAuthorityDescriptor";
+        else if (!strcmp(argv[i],"-pdp"))
+            rname="PDPDescriptor";
+        else if (!strcmp(argv[i],"-sp"))
+            rname="SPSSODescriptor";
+        else if (!strcmp(argv[i],"-nostrict"))
+            strict = false;
+    }
+
+    if (!entityID) {
+        usage();
+        return -10;
+    }
+
+    if (rname) {
+        if (!protocol) {
+            if (prot)
+                protocol = XMLString::transcode(prot);
+        }
+        if (!protocol) {
+            usage();
+            return -10;
+        }
+    }
+
+    SPConfig& conf=SPConfig::getConfig();
+    conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);
+    if (!conf.init())
+        return -1;
+    if (!conf.instantiate()) {
+        conf.term();
+        return -2;
+    }
+
+    ServiceProvider* sp=conf.getServiceProvider();
+    sp->lock();
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery");
+
+    const Application* app = sp->getApplication(appID);
+    if (!app) {
+        log.error("unknown application ID (%s)", appID);
+        sp->unlock();
+        conf.term();
+        return -3;
+    }
+
+    app->getMetadataProvider()->lock();
+    MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict);
+    if (rname) {
+        const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS;
+        auto_ptr_XMLCh n(rname);
+        QName q(ns, n.get());
+        mc.role = &q;
+        mc.protocol = protocol;
+        const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second;
+        if (role)
+            XMLHelper::serialize(role->marshall(), cout, true);
+        else
+            log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID);
+    }
+    else {
+        const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first;
+        if (entity)
+            XMLHelper::serialize(entity->marshall(), cout, true);
+        else
+            log.error("no metadata found for (%s)", entityID);
+    }
+
+    app->getMetadataProvider()->unlock();
+
+    sp->unlock();
+    conf.term();
+    return 0;
+}