changeset 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children d868534e9b75
files .classpath .hgignore .project .settings/Hoofbaby - Debug.launch .settings/Hoofbaby - Release.launch .settings/descent.core.prefs .settings/descent.ui.prefs .settings/org.eclipse.core.resources.prefs .settings/org.eclipse.core.runtime.prefs LICENSE.txt Platinum.sln.bat bin/build.bat bin/build/mcpp.exe bin/build/rebuild.conf/default bin/build/rebuild.conf/dmd-win-tango bin/build/rebuild.conf/tango bin/build/rebuild.exe bin/build/touch.exe bin/build/upx.exe deps/Platinum/Build/Targets/x86-microsoft-win32-vs2008/Platinum.ncb deps/Platinum/Build/Targets/x86-microsoft-win32-vs2008/Platinum.sln deps/Platinum/Build/Targets/x86-microsoft-win32-vs2008/Platinum/Platinum.vcproj deps/Platinum/CHANGELOG.txt deps/Platinum/LICENSE.txt deps/Platinum/README.txt deps/Platinum/Source/Core/Platinum.cpp deps/Platinum/Source/Core/Platinum.h deps/Platinum/Source/Core/PltAction.cpp deps/Platinum/Source/Core/PltAction.h deps/Platinum/Source/Core/PltArgument.cpp deps/Platinum/Source/Core/PltArgument.h deps/Platinum/Source/Core/PltCtrlPoint.cpp deps/Platinum/Source/Core/PltCtrlPoint.h deps/Platinum/Source/Core/PltCtrlPointTask.cpp deps/Platinum/Source/Core/PltCtrlPointTask.h deps/Platinum/Source/Core/PltDatagramStream.cpp deps/Platinum/Source/Core/PltDatagramStream.h deps/Platinum/Source/Core/PltDeviceData.cpp deps/Platinum/Source/Core/PltDeviceData.h deps/Platinum/Source/Core/PltDeviceHost.cpp deps/Platinum/Source/Core/PltDeviceHost.h deps/Platinum/Source/Core/PltDownloader.cpp deps/Platinum/Source/Core/PltDownloader.h deps/Platinum/Source/Core/PltEvent.cpp deps/Platinum/Source/Core/PltEvent.h deps/Platinum/Source/Core/PltHttp.cpp deps/Platinum/Source/Core/PltHttp.h deps/Platinum/Source/Core/PltHttpClientTask.cpp deps/Platinum/Source/Core/PltHttpClientTask.h deps/Platinum/Source/Core/PltHttpServer.cpp deps/Platinum/Source/Core/PltHttpServer.h deps/Platinum/Source/Core/PltHttpServerListener.h deps/Platinum/Source/Core/PltHttpServerTask.cpp deps/Platinum/Source/Core/PltHttpServerTask.h deps/Platinum/Source/Core/PltIconsData.cpp deps/Platinum/Source/Core/PltLeaks.cpp deps/Platinum/Source/Core/PltLeaks.h deps/Platinum/Source/Core/PltMetadataHandler.cpp deps/Platinum/Source/Core/PltMetadataHandler.h deps/Platinum/Source/Core/PltRingBufferStream.cpp deps/Platinum/Source/Core/PltRingBufferStream.h deps/Platinum/Source/Core/PltService.cpp deps/Platinum/Source/Core/PltService.h deps/Platinum/Source/Core/PltSsdp.cpp deps/Platinum/Source/Core/PltSsdp.h deps/Platinum/Source/Core/PltSsdpListener.h deps/Platinum/Source/Core/PltStateVariable.cpp deps/Platinum/Source/Core/PltStateVariable.h deps/Platinum/Source/Core/PltStreamPump.cpp deps/Platinum/Source/Core/PltStreamPump.h deps/Platinum/Source/Core/PltTaskManager.cpp deps/Platinum/Source/Core/PltTaskManager.h deps/Platinum/Source/Core/PltThreadTask.cpp deps/Platinum/Source/Core/PltThreadTask.h deps/Platinum/Source/Core/PltUPnP.cpp deps/Platinum/Source/Core/PltUPnP.h deps/Platinum/Source/Core/PltUPnPHelper.h deps/Platinum/Source/Core/PltVersion.h deps/Platinum/Source/Core/PltXmlHelper.h deps/Platinum/Source/Devices/FrameStreamer/PltFrameBuffer.cpp deps/Platinum/Source/Devices/FrameStreamer/PltFrameBuffer.h deps/Platinum/Source/Devices/FrameStreamer/PltFrameServer.cpp deps/Platinum/Source/Devices/FrameStreamer/PltFrameServer.h deps/Platinum/Source/Devices/FrameStreamer/PltFrameStream.cpp deps/Platinum/Source/Devices/FrameStreamer/PltFrameStream.h deps/Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp deps/Platinum/Source/Devices/MediaConnect/PltMediaConnect.h deps/Platinum/Source/Devices/MediaConnect/PltMediaConnectSCPDs.cpp deps/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.xml deps/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.xml deps/Platinum/Source/Devices/MediaRenderer/ConnectionManagerSCPD.xml deps/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp deps/Platinum/Source/Devices/MediaRenderer/PltMediaController.h deps/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.cpp deps/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.h deps/Platinum/Source/Devices/MediaRenderer/PltMediaRendererSCPDs.cpp deps/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.xml deps/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.xml deps/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.xml deps/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.xml deps/Platinum/Source/Devices/MediaServer/PltDidl.cpp deps/Platinum/Source/Devices/MediaServer/PltDidl.h deps/Platinum/Source/Devices/MediaServer/PltFileMediaServer.cpp deps/Platinum/Source/Devices/MediaServer/PltFileMediaServer.h deps/Platinum/Source/Devices/MediaServer/PltMediaBrowser.cpp deps/Platinum/Source/Devices/MediaServer/PltMediaBrowser.h deps/Platinum/Source/Devices/MediaServer/PltMediaCache.cpp deps/Platinum/Source/Devices/MediaServer/PltMediaCache.h deps/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp deps/Platinum/Source/Devices/MediaServer/PltMediaItem.h deps/Platinum/Source/Devices/MediaServer/PltMediaPlaylist.cpp deps/Platinum/Source/Devices/MediaServer/PltMediaPlaylist.h deps/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp deps/Platinum/Source/Devices/MediaServer/PltMediaServer.h deps/Platinum/Source/Devices/MediaServer/PltMediaServerSCPDs.cpp deps/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp deps/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h deps/Platinum/ThirdParty/Neptune/Build/Targets/x86-microsoft-win32-vs2008/Neptune.sln deps/Platinum/ThirdParty/Neptune/Build/Targets/x86-microsoft-win32-vs2008/Neptune/Neptune.vcproj deps/Platinum/ThirdParty/Neptune/README.txt deps/Platinum/ThirdParty/Neptune/Source/Core/Neptune.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/Neptune.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptArray.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptBase64.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptBase64.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptBufferedStreams.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptBufferedStreams.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptCommon.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptCommon.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptConfig.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptConsole.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptConsole.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptConstants.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptDataBuffer.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptDataBuffer.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptDebug.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptDebug.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptDefs.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptDynamicLibraries.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptDynamicLibraries.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptFile.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptFile.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptHttp.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptHttp.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptInterfaces.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptList.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptList.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptLogging.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptLogging.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptMap.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptMessaging.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptMessaging.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptNetwork.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptNetwork.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptQueue.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptReferences.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptResults.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptResults.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptRingBuffer.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptRingBuffer.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptSelectableMessageQueue.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptSerialPort.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptSimpleMessageQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptSimpleMessageQueue.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptSockets.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptSockets.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptStack.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptStreams.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptStreams.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptSystem.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptSystem.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptThreads.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptThreads.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptTime.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptTime.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptTls.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptTls.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptTypes.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptUri.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptUri.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptUtils.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptUtils.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptVersion.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptXml.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptXml.h deps/Platinum/ThirdParty/Neptune/Source/Core/NptZip.cpp deps/Platinum/ThirdParty/Neptune/Source/Core/NptZip.h deps/Platinum/ThirdParty/Neptune/Source/System/Bsd/NptBsdNetwork.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Bsd/NptBsdSockets.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Cocoa/NptCocoaMessageQueue.h deps/Platinum/ThirdParty/Neptune/Source/System/Cocoa/NptCocoaMessageQueue.mm deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullHttpProxy.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullNetwork.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullSerialPort.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullSystem.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullThreads.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PS3/NptPs3System.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPDirectory.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPFile.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPNetwork.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPSystem.cpp deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPThreads.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixDynamicLibraries.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixFile.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixNetwork.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixSystem.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixThreads.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptSelectableMessageQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcConsole.cpp deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcDebug.cpp deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcEnvironment.cpp deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcFile.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Symbian/NptSymbianSystem.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Console.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Debug.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32DynamicLibraries.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32File.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32HttpProxy.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32MessageQueue.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32MessageQueue.h deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Network.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Network.h deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Queue.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32SerialPort.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32System.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Threads.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Threads.h deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinCeUtils.h deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinceConsole.cpp deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinceEnvironment.cpp deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinceMain.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Xbox/NptXboxNetwork.cpp deps/Platinum/ThirdParty/Neptune/Source/System/Xbox/NptXboxNetwork.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/config/config.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/aes.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/bigint.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/bigint.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/bigint_impl.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/crypto.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/crypto_misc.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/hmac.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/md2.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/md5.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/rc4.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/rsa.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/sha1.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/asn1.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/cert.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/crypto_misc.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/gen_cert.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/loader.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/os_port.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/p12.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/ssl.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1_clnt.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1_svr.c deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/version.h deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/x509.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/README deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/adler32.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/compress.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/crc32.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/crc32.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/deflate.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/deflate.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/infback.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inffast.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inffast.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inffixed.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inflate.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inflate.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inftrees.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inftrees.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/trees.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/trees.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zconf.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zconf.in.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zlib.h deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zutil.c deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zutil.h deps/libav/avcodec.lib deps/libav/avformat.lib deps/libav/avutil.lib deps/libav/gcc.lib deps/libav/swscale.lib ref/UPnP.cpp ref/ffmpeg.c ref/opts ref/output_example.d src/build/frankenbuild.d src/dtypes.h src/impl/hoofbaby/app/codec_adhoc.d src/impl/hoofbaby/app/libs.d src/impl/hoofbaby/app/main.d src/impl/hoofbaby/codec/libav/avbuffer.d src/impl/hoofbaby/codec/libav/avcodec.d src/impl/hoofbaby/codec/libav/avformat.d src/impl/hoofbaby/codec/libav/avutil.d src/impl/hoofbaby/codec/libav/mingw.d src/impl/hoofbaby/codec/libav/swscale.d src/impl/hoofbaby/platinum/platif.d src/impl/hoofbaby/util/array.d src/impl/hoofbaby/util/buffer.d src/impl/hoofbaby/util/conv.d src/impl/hoofbaby/util/exception.d src/impl/hoofbaby/util/memory.d src/impl/hoofbaby/util/meta.d src/impl/hoofbaby/util/redblack.d src/impl/hoofbaby/util/set.d src/impl/hoofbaby/util/sharedlib.d src/platif/hoofbaby.cpp src/platif/platif.h src/platif/platif.vcproj src/platif/platif.vcproj.XPOFTHENIGHT.fraserofthenight.user
diffstat 319 files changed, 92879 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.classpath	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/impl"/>
+	<classpathentry kind="src" path="src/build"/>
+	<classpathentry kind="con" path="descent.USER_LIBRARY/Tango"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.project	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>hoofbaby</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>descent.core.dbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>descent.core.dnature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/Hoofbaby - Debug.launch	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/hoofbaby/bin/build.bat}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="debug"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/hoofbaby/bin}"/>
+</launchConfiguration>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/Hoofbaby - Release.launch	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/hoofbaby/bin/build.bat}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="release"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/hoofbaby/bin}"/>
+</launchConfiguration>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/descent.core.prefs	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,331 @@
+#Sun Jun 21 09:02:00 PDT 2009
+descent.core.compiler.allowDeprecated=enabled
+descent.core.compiler.debugIdentifiers=AVBuffer
+descent.core.compiler.debugLevel=1
+descent.core.compiler.enableSemanticErrorReporting=0
+descent.core.compiler.enableWarnings=enabled
+descent.core.compiler.source=1
+descent.core.compiler.taskCaseSensitive=enabled
+descent.core.compiler.taskPriorities=NORMAL,LOW,HIGH,HIGH,LOW,HIGH,LOW,LOW,LOW,HIGH
+descent.core.compiler.taskTags=TODO,PERHAPS,BUG,WTF,NEXTVERSION,WORKAREA,OPTIMIZE,CBUG,PORT,IMPORTANT
+descent.core.compiler.versionIdentifiers=DigitalMars, Windows, Win32, X86, LittleEndian, D_InlineAsm, D_InlineAsm_X86, all, Tango, Descent
+descent.core.compiler.versionLevel=0
+descent.core.formatter.alignment_for_array_literals=0
+descent.core.formatter.alignment_for_base_class_lists=0
+descent.core.formatter.alignment_for_function_declaration_parameters=0
+descent.core.formatter.alignment_for_function_invocation_arguments=0
+descent.core.formatter.alignment_for_multiple_variable_declarations=0
+descent.core.formatter.alignment_for_selective_imports=0
+descent.core.formatter.alignment_for_struct_initializer=0
+descent.core.formatter.alignment_for_template_declaration_parameters=0
+descent.core.formatter.alignment_for_template_invocation_arguments=0
+descent.core.formatter.blank_lines_after_module=1
+descent.core.formatter.blank_lines_before_module=0
+descent.core.formatter.brace_position_for_align_declaration=end_of_line
+descent.core.formatter.brace_position_for_anonymous_type=next_line
+descent.core.formatter.brace_position_for_conditional_declaration=next_line
+descent.core.formatter.brace_position_for_conditional_statement=next_line
+descent.core.formatter.brace_position_for_enum_declaration=next_line
+descent.core.formatter.brace_position_for_function_declaration=next_line
+descent.core.formatter.brace_position_for_function_literal=next_line
+descent.core.formatter.brace_position_for_loop_statement=next_line
+descent.core.formatter.brace_position_for_modifiers=next_line
+descent.core.formatter.brace_position_for_postblit_declaration=next_line
+descent.core.formatter.brace_position_for_pragmas=next_line
+descent.core.formatter.brace_position_for_scope_statement=next_line
+descent.core.formatter.brace_position_for_switch_case=next_line
+descent.core.formatter.brace_position_for_switch_statement=next_line
+descent.core.formatter.brace_position_for_synchronized_statement=next_line
+descent.core.formatter.brace_position_for_template_declaration=next_line
+descent.core.formatter.brace_position_for_try_catch_finally=next_line
+descent.core.formatter.brace_position_for_type_declaration=next_line
+descent.core.formatter.brace_position_for_with_statement=next_line
+descent.core.formatter.continuation_indentation=2
+descent.core.formatter.indent_body_declarations_compare_to_align_header=true
+descent.core.formatter.indent_body_declarations_compare_to_pragma_header=true
+descent.core.formatter.indent_body_declarations_compare_to_template_header=true
+descent.core.formatter.indent_body_declarations_compare_to_type_header=true
+descent.core.formatter.indent_break_compare_to_switch=false
+descent.core.formatter.indent_cases_compare_to_switch=true
+descent.core.formatter.indent_empty_lines=false
+descent.core.formatter.indent_enum_members_compare_to_enum_header=true
+descent.core.formatter.indent_in_out_body_compare_to_function_header=false
+descent.core.formatter.indent_statements_compare_to_case=true
+descent.core.formatter.indent_statements_compare_to_function_body_header=true
+descent.core.formatter.indent_statements_compare_to_function_header=true
+descent.core.formatter.indent_statements_compare_to_function_in_header=true
+descent.core.formatter.indent_statements_compare_to_function_out_header=true
+descent.core.formatter.indentation_size=4
+descent.core.formatter.indentation_style_compare_to_modifier_header=indent_normal
+descent.core.formatter.insert_new_line_after_case_or_default_statement=true
+descent.core.formatter.insert_new_line_after_label=true
+descent.core.formatter.insert_new_line_at_end_of_file_if_missing=false
+descent.core.formatter.insert_new_line_before_catch=true
+descent.core.formatter.insert_new_line_before_else_declaration=true
+descent.core.formatter.insert_new_line_before_else_statement=true
+descent.core.formatter.insert_new_line_before_finally=true
+descent.core.formatter.insert_new_line_before_while_in_do_statement=false
+descent.core.formatter.insert_space_after_assignment_operator=true
+descent.core.formatter.insert_space_after_closing_paren_in_casts=true
+descent.core.formatter.insert_space_after_colon_in_array_initializer=true
+descent.core.formatter.insert_space_after_colon_in_base_class_lists=true
+descent.core.formatter.insert_space_after_colon_in_case_default_statement=true
+descent.core.formatter.insert_space_after_colon_in_conditional_expressions=true
+descent.core.formatter.insert_space_after_colon_in_selective_imports=true
+descent.core.formatter.insert_space_after_colon_in_statement_labels=true
+descent.core.formatter.insert_space_after_colon_in_struct_initializer=true
+descent.core.formatter.insert_space_after_colon_in_template_specific_type=true
+descent.core.formatter.insert_space_after_comma_in_aggregate_template_parameters=true
+descent.core.formatter.insert_space_after_comma_in_array_access=true
+descent.core.formatter.insert_space_after_comma_in_array_literal=true
+descent.core.formatter.insert_space_after_comma_in_assert_statements=true
+descent.core.formatter.insert_space_after_comma_in_base_class_lists=true
+descent.core.formatter.insert_space_after_comma_in_delegates=true
+descent.core.formatter.insert_space_after_comma_in_foreach_statement=true
+descent.core.formatter.insert_space_after_comma_in_function_declaration_parameters=true
+descent.core.formatter.insert_space_after_comma_in_function_invocation_arguments=true
+descent.core.formatter.insert_space_after_comma_in_function_template_parameters=true
+descent.core.formatter.insert_space_after_comma_in_multiple_field_declarations=true
+descent.core.formatter.insert_space_after_comma_in_multiple_imports=true
+descent.core.formatter.insert_space_after_comma_in_new_arguments=true
+descent.core.formatter.insert_space_after_comma_in_pragmas=true
+descent.core.formatter.insert_space_after_comma_in_selective_imports=true
+descent.core.formatter.insert_space_after_comma_in_struct_initializer=true
+descent.core.formatter.insert_space_after_comma_in_template_declaration=true
+descent.core.formatter.insert_space_after_comma_in_template_invocation=true
+descent.core.formatter.insert_space_after_comma_in_traits_expression=true
+descent.core.formatter.insert_space_after_dot_in_qualified_names=false
+descent.core.formatter.insert_space_after_dot_in_type_dot_identifier_expressions=false
+descent.core.formatter.insert_space_after_elipsis_in_function_varargs=false
+descent.core.formatter.insert_space_after_elipsis_in_tuples=false
+descent.core.formatter.insert_space_after_equals_in_default_function_arguments=true
+descent.core.formatter.insert_space_after_equals_in_default_template_arguments=true
+descent.core.formatter.insert_space_after_equals_in_enum_constants=true
+descent.core.formatter.insert_space_after_equals_in_renamed_imports=true
+descent.core.formatter.insert_space_after_equals_in_variable_inits=true
+descent.core.formatter.insert_space_after_equals_in_version_debug_assignment=true
+descent.core.formatter.insert_space_after_exclamation_point_in_template_invocation=false
+descent.core.formatter.insert_space_after_infix_operator=true
+descent.core.formatter.insert_space_after_opening_bracket_in_array_access=false
+descent.core.formatter.insert_space_after_opening_bracket_in_array_constructors=false
+descent.core.formatter.insert_space_after_opening_bracket_in_array_literals=false
+descent.core.formatter.insert_space_after_opening_bracket_in_associative_arrays=false
+descent.core.formatter.insert_space_after_opening_bracket_in_slices=false
+descent.core.formatter.insert_space_after_opening_bracket_in_static_arrays=false
+descent.core.formatter.insert_space_after_opening_paren_in_align_declarations=false
+descent.core.formatter.insert_space_after_opening_paren_in_assert_statements=false
+descent.core.formatter.insert_space_after_opening_paren_in_c_style_fp=false
+descent.core.formatter.insert_space_after_opening_paren_in_casts=false
+descent.core.formatter.insert_space_after_opening_paren_in_catch=false
+descent.core.formatter.insert_space_after_opening_paren_in_class_template_params=false
+descent.core.formatter.insert_space_after_opening_paren_in_delegate=false
+descent.core.formatter.insert_space_after_opening_paren_in_extern_declarations=false
+descent.core.formatter.insert_space_after_opening_paren_in_file_imports=false
+descent.core.formatter.insert_space_after_opening_paren_in_for_loops=false
+descent.core.formatter.insert_space_after_opening_paren_in_foreach_loops=false
+descent.core.formatter.insert_space_after_opening_paren_in_function_declaration_parameters=false
+descent.core.formatter.insert_space_after_opening_paren_in_function_invocation=false
+descent.core.formatter.insert_space_after_opening_paren_in_function_template_args=false
+descent.core.formatter.insert_space_after_opening_paren_in_if_statements=false
+descent.core.formatter.insert_space_after_opening_paren_in_is_expressions=false
+descent.core.formatter.insert_space_after_opening_paren_in_mixins=false
+descent.core.formatter.insert_space_after_opening_paren_in_modified_type=false
+descent.core.formatter.insert_space_after_opening_paren_in_new_arguments=false
+descent.core.formatter.insert_space_after_opening_paren_in_out_declaration=false
+descent.core.formatter.insert_space_after_opening_paren_in_parenthesized_expressions=false
+descent.core.formatter.insert_space_after_opening_paren_in_pragmas=false
+descent.core.formatter.insert_space_after_opening_paren_in_scope_statements=false
+descent.core.formatter.insert_space_after_opening_paren_in_switch_statements=false
+descent.core.formatter.insert_space_after_opening_paren_in_synchronized_statement=false
+descent.core.formatter.insert_space_after_opening_paren_in_template_declarations=false
+descent.core.formatter.insert_space_after_opening_paren_in_template_invocation=false
+descent.core.formatter.insert_space_after_opening_paren_in_traits_expression=false
+descent.core.formatter.insert_space_after_opening_paren_in_type_dot_identifier_expression=false
+descent.core.formatter.insert_space_after_opening_paren_in_typeid_statements=false
+descent.core.formatter.insert_space_after_opening_paren_in_typeof_statements=false
+descent.core.formatter.insert_space_after_opening_paren_in_version_debug=false
+descent.core.formatter.insert_space_after_opening_paren_in_while_loops=false
+descent.core.formatter.insert_space_after_opening_paren_in_with_statements=false
+descent.core.formatter.insert_space_after_postfix_operator=false
+descent.core.formatter.insert_space_after_prefix_operator=false
+descent.core.formatter.insert_space_after_question_mark_in_conditional_expressions=true
+descent.core.formatter.insert_space_after_semicolon_in_for_statement=true
+descent.core.formatter.insert_space_after_semicolon_in_foreach_statement=true
+descent.core.formatter.insert_space_after_slice_operator=true
+descent.core.formatter.insert_space_after_slice_operator_in_foreach_range_statement=true
+descent.core.formatter.insert_space_after_star_in_c_style_fp=false
+descent.core.formatter.insert_space_after_trailing_comma_in_array_initializer=true
+descent.core.formatter.insert_space_before_assignment_operator=true
+descent.core.formatter.insert_space_before_asterisk_for_pointer_types=false
+descent.core.formatter.insert_space_before_closing_bracket_in_array_access=false
+descent.core.formatter.insert_space_before_closing_bracket_in_array_constructors=false
+descent.core.formatter.insert_space_before_closing_bracket_in_array_literals=false
+descent.core.formatter.insert_space_before_closing_bracket_in_associative_arrays=false
+descent.core.formatter.insert_space_before_closing_bracket_in_slices=false
+descent.core.formatter.insert_space_before_closing_bracket_in_static_arrays=false
+descent.core.formatter.insert_space_before_closing_paren_in_align_declarations=false
+descent.core.formatter.insert_space_before_closing_paren_in_assert_statements=false
+descent.core.formatter.insert_space_before_closing_paren_in_c_style_fp=false
+descent.core.formatter.insert_space_before_closing_paren_in_casts=false
+descent.core.formatter.insert_space_before_closing_paren_in_catch=false
+descent.core.formatter.insert_space_before_closing_paren_in_class_template_params=false
+descent.core.formatter.insert_space_before_closing_paren_in_delegate=false
+descent.core.formatter.insert_space_before_closing_paren_in_extern_declarations=false
+descent.core.formatter.insert_space_before_closing_paren_in_file_imports=false
+descent.core.formatter.insert_space_before_closing_paren_in_for_loops=false
+descent.core.formatter.insert_space_before_closing_paren_in_foreach_loops=false
+descent.core.formatter.insert_space_before_closing_paren_in_function_declaration_parameters=false
+descent.core.formatter.insert_space_before_closing_paren_in_function_invocation=false
+descent.core.formatter.insert_space_before_closing_paren_in_function_template_args=false
+descent.core.formatter.insert_space_before_closing_paren_in_if_statements=false
+descent.core.formatter.insert_space_before_closing_paren_in_is_expressions=false
+descent.core.formatter.insert_space_before_closing_paren_in_mixins=false
+descent.core.formatter.insert_space_before_closing_paren_in_modified_type=false
+descent.core.formatter.insert_space_before_closing_paren_in_new_arguments=false
+descent.core.formatter.insert_space_before_closing_paren_in_out_declaration=false
+descent.core.formatter.insert_space_before_closing_paren_in_parenthesized_expressions=false
+descent.core.formatter.insert_space_before_closing_paren_in_pragmas=false
+descent.core.formatter.insert_space_before_closing_paren_in_scope_statements=false
+descent.core.formatter.insert_space_before_closing_paren_in_switch_statements=false
+descent.core.formatter.insert_space_before_closing_paren_in_synchronized_statement=false
+descent.core.formatter.insert_space_before_closing_paren_in_template_declarations=false
+descent.core.formatter.insert_space_before_closing_paren_in_template_invocation=false
+descent.core.formatter.insert_space_before_closing_paren_in_traits_expression=false
+descent.core.formatter.insert_space_before_closing_paren_in_type_dot_identifier_expression=false
+descent.core.formatter.insert_space_before_closing_paren_in_typeid_statements=false
+descent.core.formatter.insert_space_before_closing_paren_in_typeof_statements=false
+descent.core.formatter.insert_space_before_closing_paren_in_version_debug=false
+descent.core.formatter.insert_space_before_closing_paren_in_while_loops=false
+descent.core.formatter.insert_space_before_closing_paren_in_with_statements=false
+descent.core.formatter.insert_space_before_colon_in_array_initializer=false
+descent.core.formatter.insert_space_before_colon_in_base_class_lists=true
+descent.core.formatter.insert_space_before_colon_in_case_default_statement=false
+descent.core.formatter.insert_space_before_colon_in_conditional_expressions=true
+descent.core.formatter.insert_space_before_colon_in_modifiers=false
+descent.core.formatter.insert_space_before_colon_in_selective_imports=false
+descent.core.formatter.insert_space_before_colon_in_statement_labels=false
+descent.core.formatter.insert_space_before_colon_in_struct_initializer=false
+descent.core.formatter.insert_space_before_colon_in_template_specific_type=false
+descent.core.formatter.insert_space_before_comma_in_aggregate_template_parameters=false
+descent.core.formatter.insert_space_before_comma_in_array_access=false
+descent.core.formatter.insert_space_before_comma_in_array_literal=false
+descent.core.formatter.insert_space_before_comma_in_assert_statements=false
+descent.core.formatter.insert_space_before_comma_in_base_class_lists=false
+descent.core.formatter.insert_space_before_comma_in_delegates=false
+descent.core.formatter.insert_space_before_comma_in_enum_member_lists=false
+descent.core.formatter.insert_space_before_comma_in_foreach_statement=false
+descent.core.formatter.insert_space_before_comma_in_function_declaration_parameters=false
+descent.core.formatter.insert_space_before_comma_in_function_invocation_arguments=false
+descent.core.formatter.insert_space_before_comma_in_function_template_parameters=false
+descent.core.formatter.insert_space_before_comma_in_multiple_field_declarations=false
+descent.core.formatter.insert_space_before_comma_in_multiple_imports=false
+descent.core.formatter.insert_space_before_comma_in_new_arguments=false
+descent.core.formatter.insert_space_before_comma_in_pragmas=false
+descent.core.formatter.insert_space_before_comma_in_selective_imports=false
+descent.core.formatter.insert_space_before_comma_in_struct_initializer=false
+descent.core.formatter.insert_space_before_comma_in_template_declaration=false
+descent.core.formatter.insert_space_before_comma_in_template_invocation=false
+descent.core.formatter.insert_space_before_comma_in_traits_expression=false
+descent.core.formatter.insert_space_before_dot_in_qualified_names=false
+descent.core.formatter.insert_space_before_dot_in_type_dot_identifier_expressions=false
+descent.core.formatter.insert_space_before_elipsis_in_function_varargs=false
+descent.core.formatter.insert_space_before_elipsis_in_tuples=false
+descent.core.formatter.insert_space_before_equals_in_default_function_arguments=true
+descent.core.formatter.insert_space_before_equals_in_default_template_arguments=true
+descent.core.formatter.insert_space_before_equals_in_enum_constants=true
+descent.core.formatter.insert_space_before_equals_in_renamed_imports=true
+descent.core.formatter.insert_space_before_equals_in_variable_inits=true
+descent.core.formatter.insert_space_before_equals_in_version_debug_assignment=true
+descent.core.formatter.insert_space_before_exclamation_point_in_template_invocation=false
+descent.core.formatter.insert_space_before_infix_operator=true
+descent.core.formatter.insert_space_before_opening_bracket_in_array_access=false
+descent.core.formatter.insert_space_before_opening_bracket_in_array_constructors=false
+descent.core.formatter.insert_space_before_opening_bracket_in_associative_arrays=false
+descent.core.formatter.insert_space_before_opening_bracket_in_dynamic_arrays=false
+descent.core.formatter.insert_space_before_opening_bracket_in_slices=false
+descent.core.formatter.insert_space_before_opening_bracket_in_static_arrays=false
+descent.core.formatter.insert_space_before_opening_paren_in_align_declarations=false
+descent.core.formatter.insert_space_before_opening_paren_in_assert_statements=false
+descent.core.formatter.insert_space_before_opening_paren_in_c_style_fp=true
+descent.core.formatter.insert_space_before_opening_paren_in_casts=false
+descent.core.formatter.insert_space_before_opening_paren_in_catch=false
+descent.core.formatter.insert_space_before_opening_paren_in_class_invariants=false
+descent.core.formatter.insert_space_before_opening_paren_in_class_template_params=false
+descent.core.formatter.insert_space_before_opening_paren_in_delegate=false
+descent.core.formatter.insert_space_before_opening_paren_in_extern_declarations=false
+descent.core.formatter.insert_space_before_opening_paren_in_file_imports=false
+descent.core.formatter.insert_space_before_opening_paren_in_for_loops=false
+descent.core.formatter.insert_space_before_opening_paren_in_foreach_loops=false
+descent.core.formatter.insert_space_before_opening_paren_in_function_declaration_parameters=false
+descent.core.formatter.insert_space_before_opening_paren_in_function_invocation=false
+descent.core.formatter.insert_space_before_opening_paren_in_function_template_args=false
+descent.core.formatter.insert_space_before_opening_paren_in_if_statements=false
+descent.core.formatter.insert_space_before_opening_paren_in_is_expressions=false
+descent.core.formatter.insert_space_before_opening_paren_in_mixins=false
+descent.core.formatter.insert_space_before_opening_paren_in_modified_type=false
+descent.core.formatter.insert_space_before_opening_paren_in_new_arguments=false
+descent.core.formatter.insert_space_before_opening_paren_in_out_declaration=false
+descent.core.formatter.insert_space_before_opening_paren_in_parenthesized_expressions=false
+descent.core.formatter.insert_space_before_opening_paren_in_pragmas=false
+descent.core.formatter.insert_space_before_opening_paren_in_scope_statements=false
+descent.core.formatter.insert_space_before_opening_paren_in_switch_statements=false
+descent.core.formatter.insert_space_before_opening_paren_in_synchronized_statement=false
+descent.core.formatter.insert_space_before_opening_paren_in_template_declarations=false
+descent.core.formatter.insert_space_before_opening_paren_in_traits_expression=false
+descent.core.formatter.insert_space_before_opening_paren_in_type_dot_identifier_expression=false
+descent.core.formatter.insert_space_before_opening_paren_in_typeid_statements=false
+descent.core.formatter.insert_space_before_opening_paren_in_typeof_statements=false
+descent.core.formatter.insert_space_before_opening_paren_in_version_debug=false
+descent.core.formatter.insert_space_before_opening_paren_in_while_loops=false
+descent.core.formatter.insert_space_before_opening_paren_in_with_statements=false
+descent.core.formatter.insert_space_before_postfix_operator=false
+descent.core.formatter.insert_space_before_prefix_operator=false
+descent.core.formatter.insert_space_before_question_mark_in_conditional_expressions=true
+descent.core.formatter.insert_space_before_semicolon=false
+descent.core.formatter.insert_space_before_semicolon_in_for_statement=false
+descent.core.formatter.insert_space_before_semicolon_in_foreach_statement=false
+descent.core.formatter.insert_space_before_slice_operator=true
+descent.core.formatter.insert_space_before_slice_operator_in_foreach_range_statement=true
+descent.core.formatter.insert_space_before_trailing_comma_in_array_initializer=false
+descent.core.formatter.insert_space_between_adjacent_brackets_in_multidimensional_arrays=false
+descent.core.formatter.insert_space_between_empty_brackets_in_dynamic_array_type=false
+descent.core.formatter.insert_space_between_empty_brackets_in_slice=false
+descent.core.formatter.insert_space_between_empty_parens_in_class_invariants=false
+descent.core.formatter.insert_space_between_empty_parens_in_class_template_params=false
+descent.core.formatter.insert_space_between_empty_parens_in_delegate=false
+descent.core.formatter.insert_space_between_empty_parens_in_extern_declarations=false
+descent.core.formatter.insert_space_between_empty_parens_in_function_declaration_parameters=false
+descent.core.formatter.insert_space_between_empty_parens_in_function_invocation=false
+descent.core.formatter.insert_space_between_empty_parens_in_function_template_args=false
+descent.core.formatter.insert_space_between_empty_parens_in_new_arguments=false
+descent.core.formatter.insert_space_between_empty_parens_in_out_declaration=false
+descent.core.formatter.insert_space_between_empty_parens_in_template_declarations=false
+descent.core.formatter.insert_space_between_empty_parens_in_template_invocation=false
+descent.core.formatter.insert_space_between_name_and_args_in_c_style_fp=false
+descent.core.formatter.insert_space_between_succesive_opcalls=false
+descent.core.formatter.insert_space_between_template_and_arg_parens_in_function_declaration=false
+descent.core.formatter.insert_space_between_template_args_and_function_args=false
+descent.core.formatter.keep_else_conditional_on_one_line=true
+descent.core.formatter.keep_else_version_debug_on_one_line=true
+descent.core.formatter.keep_functions_with_no_statement_in_one_line=true
+descent.core.formatter.keep_functions_with_one_statement_in_one_line=true
+descent.core.formatter.keep_simple_catch_statement_on_same_line=false
+descent.core.formatter.keep_simple_else_declaration_on_same_line=true
+descent.core.formatter.keep_simple_else_statement_on_same_line=false
+descent.core.formatter.keep_simple_finally_statement_on_same_line=false
+descent.core.formatter.keep_simple_loop_statement_on_same_line=false
+descent.core.formatter.keep_simple_scope_statement_on_same_line=true
+descent.core.formatter.keep_simple_synchronized_statement_on_same_line=true
+descent.core.formatter.keep_simple_then_declaration_on_same_line=true
+descent.core.formatter.keep_simple_then_statement_on_same_line=false
+descent.core.formatter.keep_simple_try_statement_on_same_line=false
+descent.core.formatter.keep_simple_with_statement_on_same_line=false
+descent.core.formatter.line_split=80
+descent.core.formatter.never_indent_block_comments_on_first_column=false
+descent.core.formatter.never_indent_line_comments_on_first_column=false
+descent.core.formatter.number_of_empty_lines_to_preserve=1
+descent.core.formatter.page_width=80
+descent.core.formatter.tab_char=tab
+descent.core.formatter.tab_size=4
+descent.core.formatter.use_tabs_only_for_leading_indentations=false
+eclipse.preferences.version=1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/descent.ui.prefs	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,6 @@
+#Sun Jun 21 09:02:00 PDT 2009
+descent.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
+eclipse.preferences.version=1
+formatter_profile=_hoofbaby
+formatter_settings_version=1
+internal.default.compliance=user
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/org.eclipse.core.resources.prefs	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,3 @@
+#Wed May 27 17:45:01 PDT 2009
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/org.eclipse.core.runtime.prefs	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,3 @@
+#Wed Apr 01 04:51:49 PDT 2009
+eclipse.preferences.version=1
+line.separator=\r\n
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.txt	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platinum.sln.bat	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1 @@
+start deps\Platinum\Build\Targets\x86-microsoft-win32-vs2008\Platinum.sln
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/build.bat	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,4 @@
+@echo off
+cd /d %~dp0
+build\rebuild.exe -offrankenbuild.exe -oqobjs/build ../src/build/frankenbuild.d
+frankenbuild.exe %*
\ No newline at end of file
Binary file bin/build/mcpp.exe has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/build/rebuild.conf/default	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1 @@
+profile=dmd-win-tango
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/build/rebuild.conf/dmd-win-tango	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,72 @@
+profile=tango
+
+compiler=dmd
+inifile=sc.ini
+
+exeext=.exe
+objext=obj
+objmodsep=-
+
+
+version=DigitalMars
+noversion=GNU
+noversion=linux
+noversion=Unix
+noversion=Posix
+version=Windows
+testversion=Win32
+testversion=Win64
+version=X86
+noversion=PPC
+noversion=X86_64
+version=D_InlineAsm
+version=D_InlineAsm_X86
+noversion=D_InlineAsm_PPC
+noversion=D_InlineAsm_X86_64
+version=LittleEndian
+noversion=BigEndian
+version=Tango
+
+
+[compile]
+cmd=dmd -version=Tango -c $i
+response=@
+
+flag=$i
+incdir=-I$i
+libdir=-L-L$i
+optimize=-O
+version=-version=$i
+
+
+[link]
+oneatatime=yes
+cmd=dmd $i -of$o
+response=@
+
+libdir=-L+$i\
+lib=-L+$i.lib
+flag=-L$i
+gui=-L/subsystem:windows
+
+
+[liblink]
+safe=yes
+oneatatime=yes
+cmd=lib -c -p512 $o $i
+response=@
+
+libdir=
+lib=
+flag=
+
+
+[postliblink]
+cmd=echo $i
+
+
+[shliblink]
+shlibs=no
+
+[dyliblink]
+dylibs=no
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/build/rebuild.conf/tango	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1 @@
+ignore=gcc. object
Binary file bin/build/rebuild.exe has changed
Binary file bin/build/touch.exe has changed
Binary file bin/build/upx.exe has changed
Binary file deps/Platinum/Build/Targets/x86-microsoft-win32-vs2008/Platinum.ncb has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Build/Targets/x86-microsoft-win32-vs2008/Platinum.sln	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,35 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Platinum", "Platinum\Platinum.vcproj", "{568611D3-AFA7-4294-99C1-E9AED0D8057E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Neptune", "..\..\..\ThirdParty\Neptune\Build\Targets\x86-microsoft-win32-vs2008\Neptune\Neptune.vcproj", "{12AFF2E5-6D95-4809-9728-9551677C078A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "platif", "..\..\..\..\..\src\platif\platif.vcproj", "{7D9FD95C-249A-4026-BEA1-BF21738D91A7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{568611D3-AFA7-4294-99C1-E9AED0D8057E} = {568611D3-AFA7-4294-99C1-E9AED0D8057E}
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{568611D3-AFA7-4294-99C1-E9AED0D8057E}.Debug|Win32.ActiveCfg = Debug|Win32
+		{568611D3-AFA7-4294-99C1-E9AED0D8057E}.Debug|Win32.Build.0 = Debug|Win32
+		{568611D3-AFA7-4294-99C1-E9AED0D8057E}.Release|Win32.ActiveCfg = Release|Win32
+		{568611D3-AFA7-4294-99C1-E9AED0D8057E}.Release|Win32.Build.0 = Release|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Debug|Win32.Build.0 = Debug|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Release|Win32.ActiveCfg = Release|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Release|Win32.Build.0 = Release|Win32
+		{7D9FD95C-249A-4026-BEA1-BF21738D91A7}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7D9FD95C-249A-4026-BEA1-BF21738D91A7}.Debug|Win32.Build.0 = Debug|Win32
+		{7D9FD95C-249A-4026-BEA1-BF21738D91A7}.Release|Win32.ActiveCfg = Release|Win32
+		{7D9FD95C-249A-4026-BEA1-BF21738D91A7}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Build/Targets/x86-microsoft-win32-vs2008/Platinum/Platinum.vcproj	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,558 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="Platinum"
+	ProjectGUID="{568611D3-AFA7-4294-99C1-E9AED0D8057E}"
+	RootNamespace="Platinum"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..\..\ThirdParty\Neptune\Source\Config;..\..\..\..\ThirdParty\Neptune\Source\Core;..\..\..\..\ThirdParty\Neptune\Source\Neptune;..\..\..\..\Source\Core;..\..\..\..\Source\Devices\MediaServer"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;NPT_CONFIG_ENABLE_LOGGING;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/Platinum.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				OmitFramePointers="true"
+				WholeProgramOptimization="true"
+				AdditionalIncludeDirectories="..\..\..\..\ThirdParty\Neptune\Source\Config;..\..\..\..\ThirdParty\Neptune\Source\Core;..\..\..\..\ThirdParty\Neptune\Source\Neptune;..\..\..\..\Source\Core;..\..\..\..\Source\Devices\MediaServer"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/Platinum.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{D5F7DD40-709C-455b-A225-F1917F8750A3}"
+			>
+			<Filter
+				Name="Core"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Core\Platinum.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltAction.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltArgument.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltCtrlPoint.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltCtrlPointTask.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDatagramStream.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDeviceData.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDeviceHost.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDownloader.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltEvent.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttp.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpClientTask.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpServer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpServerTask.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltLeaks.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltMetadataHandler.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltRingBufferStream.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltService.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltSsdp.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltStateVariable.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltStreamPump.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltTaskManager.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltThreadTask.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltUPnP.cpp"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MediaServer"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltDidl.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltFileMediaServer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaBrowser.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaCache.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaItem.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaPlaylist.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaServer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaServerSCPDs.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltSyncMediaBrowser.cpp"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MediaRenderer"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaRenderer\PltMediaController.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaRenderer\PltMediaRenderer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaRenderer\PltMediaRendererSCPDs.cpp"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MediaConnect"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaConnect\PltMediaConnect.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaConnect\PltMediaConnectSCPDs.cpp"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{564B3B10-7EA5-4cb8-AE61-F5C00342EBCE}"
+			>
+			<Filter
+				Name="Core"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Core\Platinum.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltAction.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltArgument.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltCtrlPoint.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltCtrlPointTask.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDatagramStream.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDeviceData.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDeviceHost.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltDownloader.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltEvent.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttp.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpClientTask.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpServer.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpServerListener.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltHttpServerTask.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltLeaks.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltMetadataHandler.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltRingBufferStream.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltService.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltSsdp.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltSsdpListener.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltStateVariable.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltStreamPump.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltTaskManager.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltThreadTask.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltUPnP.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltUPnPHelper.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltVersion.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Core\PltXmlHelper.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MediaServer"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltDidl.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltFileMediaServer.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaBrowser.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaBrowserListener.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaCache.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaItem.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaPlaylist.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltMediaServer.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaServer\PltSyncMediaBrowser.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MediaRenderer"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaRenderer\PltMediaController.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaRenderer\PltMediaControllerListener.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaRenderer\PltMediaRenderer.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="MediaConnect"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\MediaConnect\PltMediaConnect.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="FrameStreamer"
+				>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\FrameStreamer\PltFrameBuffer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\FrameStreamer\PltFrameBuffer.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\FrameStreamer\PltFrameServer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\FrameStreamer\PltFrameServer.h"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\FrameStreamer\PltFrameStream.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\..\..\Source\Devices\FrameStreamer\PltFrameStream.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{D679E99D-9E2C-4288-A353-B64B3A54D93F}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/CHANGELOG.txt	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,309 @@
+Platinum 0.4.9
+--------------
+added: PlatinumiPhone target to Platinum.xcodeproj
+changed: PlatinumApps.xcodeproj now depends on Platinum.xcodeproj
+changed: PLT_MediaBrowser and PLT_MediaController now asks delegate before subscribing to events to let a chance to decide if device is worth listening to events
+changed: renamed PLT_MediaBrowserListener to PLT_MediaBrowserDelegate and PLT_MediaControllerListener to PLT_MediaControllerDelegate
+changed: check for new event to notify every 100ms instead of 10ms, also reduce link list modifications to reduce allocatio/free
+added: can now specify custom user-agent and server http header
+fixed: missing didl resource if no protection attribute was set
+fixed: can now stop/restart devices without restarting entire upnp stack
+changed: honor Connection header from response if keep-alive is true
+fixed: more PS3 support
+added: now can specify initial port can be ignored if failed and try again with a random port
+added: support for resolution in didl, can now prevent certain files from being advertised in didl, better mimetype support in FileServer
+fixed: now aborts properly client socket tasks
+removed: null/null in array, uses NPT_ARRAY_SIZE instead
+removed: NPT_ERROR_INTERNAL result when closing a socket while still reading on it, now returns NPT_ERROR_EOS
+added: support for icons (MediaConnect sample for PS3)
+added: PLT_HttpRequestContext can hold a request and a context now
+changed: better dlna support, can now use request information to decide what to return (important to support xbox 360, ps3, etc..)
+fixed: XBox 360 not finding us anymore, don't hardcode same guid! and fix mp4 playback on 360
+
+Platinum 0.4.8
+--------------
+fixed: XBox 360 and PS3 video playback
+added: removed some FATAL logs, can pass path to MediaConnect cmd line
+changed: changes to http server to support path without a query
+added: frame streamer example (mjpeg live stream advertised via upnp)
+changed: verified that content-length was indeed set on the entity before writing it, to avoid writing 0 when the length wasn't known (multipart)
+
+Platinum 0.4.7
+--------------
+fixed: listener being called multiple times with same device when appearing or disapearing
+added: dc:date support in didl
+added: better dlna support for videos
+changed: don't cache empty results in media cache
+fixed: WMP 11 crash when unsubscribing
+fixed: crash after 15 min due to not cleaning up properly interface list before reusing it
+changed: allow for services with no actions (although not upnp compliant)
+fixed: lock media cache before access
+changed: switching to native eol
+changed: fixed xcode proj, add delay to get description/scpd for Rhapsody to be happy
+changed: uses HTTP 1.1 in server with keep-alive. Greatly improves performance
+updated: license is now GPLv2 or later
+changed: do not search, announce or respond on localhost anymore
+
+Platinum 0.4.6
+--------------
+changed: upnp server now uses same port for upnp and serving files (helps with firewall)
+added: upnp support for embedded devices
+changed: upnp device description can now be modified according to request (user agent header)
+fixed: better upnp eventing mechanism, can now pause eventing to set multiple state variables, and send update in a batch
+changed: detect xbox and change description to pretend to be WMP
+fixed: artist role attribute is not supposed to be in upnp namespace
+updated: Neptune to support Unicode filenames
+added: Sonos support! XBMC server can now be browsed by Sonos Desktop Controller and music can be played on multiple Sonos ZonePlayers all synchronously and streamed from XBMC. Sweeeeeeeeeeet!
+fixed: deadlock on subscribe
+fixed: crach on subscription cancellation
+fixed: first event notification was sent to early and could be missed
+fixed: UPnP Renderer Intel Validity Tool tests
+
+Platinum 0.4.5
+--------------
+fixed: better embedded devices support
+fixed: Unicode support on Win32 platforms
+changed: now can pause eventing to set multiple state variables and resume eventing then
+
+Platinum 0.4.3
+--------------
+fixed: vs2008 solution
+fixed: mp3 invalid protocol
+
+Platinum 0.4.2
+--------------
+changed: don't set an entity on request if no body is expected
+added: support for PS3 (basic dlna support)
+changed: MediaCrawler now derives from MediaConnect so that it's seen by XBox 360
+fixed: now passes the proper reachable interface when subscribing to events by keeping track of which interface was used when retrieving a device description
+fixed: gcc 4.2.3 errors (Ubuntu 8.04)
+changed: removed all NPT_Integer references
+fixed: didl parsing of resource with size > 2GB
+changed: didl resource duration is now unsigned
+added: support for SCons 1.0 (0.98.5)
+fixed: support for files > 4GB
+fixed: SIGPIPE errors on both Ubuntu and MacOSX
+fixed: potential memory leaks reported by valgrind
+changed: updated to use Neptune 1.0.1
+
+Platinum 0.4.1
+--------------
+fixed: crash caused by typo when fixing gcc warnings, was adding the wrong http handler
+changed: don't use an outside lock for requests in PltHttpClientTask which can cause delay and hang out when queuing requests in a row like when updating state (Thanks Andy B.!)
+added: copyright 2008
+
+Platinum 0.4.0
+--------------
+added: new PlatinumApps project for XCode
+added: apple iphone target
+fixed: fixing scons build, automatic stripping in release mode now
+fixed: potential crash due to trying to use connector of a client that didn't exist anymore
+added: support for Vs2008
+fixed: leopard support with both 10.4 and 10.5 sdk installed
+fixed: gcc 4 warnings
+changed: renamed fopen_s to fopen_wrapper
+fixed: Fix for unbuffered file streams on OSX (was callign setvbuf after seek)
+added: Support for SO_REUSEPORT on OSX
+added: Set NOSIGPIPE flag
+
+Platinum 0.3.9
+--------------
+added: Xbox360 support!
+fixed: warning appearing with gcc4 on macosx
+fixed: leaks when getting ip addresses
+added: new ring buffer stream and tests
+changed: Browse to pass a flag instead of UPnP browse text flag
+changed: Browse prototype
+changed: switched to static crt
+added: can now pass http port to FileMediaServerTest
+added: more mediatypes (avi, divx) support
+fixed: content-type not being set properly if file extension was uppercase
+fixed: MediaCrawler prototypes due to changes to Browse signature
+added: MediaConnect project
+added: arm-unknown-linux config (iphone support)
+added: RingBufferStream class
+fixed: NPT_Xml now writes the xml header
+changed: listen task now passed to Start/Stop function to have ctrlpoint, device remove themselves from it
+changed: working on better subscriber support in ctrlpoints (switching to references)
+removed: embedded devices support until we have a better idea on how to support it (is it DLNA compliant anyway?)
+added: a PresentationUrl element to description only if present otherwise Intel UPnP DeviceSpy is confused!
+added: avi & divx extension support to content-type
+added: custom http chunk decoder even though we don't support HTTP 1.1 yet
+fixed: server not reading socket info properly when receiving datagrams which would cause a device to respond to M-SEARCH requests on the wrong udp port (and Xbox360s to not discover our server!)
+fixed: Http Server handlers seem to trigger only on the path of a url NOT including the query which means that SCPD Urls with queries currently don't work! For now we switch to not use queries in SCPD urls
+changed: now announce and respond to search requests on loopback adapter
+fixed: Task manager thread was not sleeping enough! now 100ms
+added: ContentDirectorywSearchSCPD.xml SCPD (Xbox 360 needs Search !)
+updated: latest Neptune
+added: jpg content-type
+fixed: now don't allow to start if specified port for server is in use already
+added: more mimetype to class support
+added: can now pass a port for the file server of PLT_FileMediaServer
+changed: Device host and ctrl points now get their own task manager so that when they stop, all tasks stop so there's no need to keep track of running tasks
+changed: ctrl point now issue a search at least on localhost if no interfaces were found
+fixed: UPnP devices and ctrl points are now freed when stopped (removed)
+fixed: UPnP devices and ctrl points can be restarted (reused) now 
+added: better support for icons
+fixed: EventSubscribers now have their own task and try to reuse the socket (Connection Keep-Alive) when possible
+changed: Service uses NPT_List instead of NPT_Arrays to improve manipulation of state vars
+added: Can now use Connection keep-alive with HTTP/1.0 clients
+added: State variables can now be moderated. Service has a task that monitors if vars have changed and send updates if it's time (according to moderation)
+added: Service now supports the "LastChange" state variable
+changed: PLT_SsdpInitMulticastIterator joins group on any interface
+fixed: possible lock when stopping all tasks (lock, notify tasks to stop, unlock then wait for list to be empty)
+added: some dlna support
+changed: moved File Media server from PLT_MediaServer to PLT_FileMediaServer
+added: placeholder for Search in PLT_MediaServer
+changed: removed MediaRenderer and MediaServer projects, now all is in Platinum project
+changed: moved MediaConnect source in Source/Devices
+fixed: build to not include ../ in path.. hopefully fixing gcc 3.3.5 errors
+added: MediaServer now sets variable rate
+fixed: bug where subscribers were deleted all the time after first notification
+fixed: eventing of moderated state variable changes
+fixed: temporary hack for XBMC support of Xbox360, we urlencoded the ? to that the 360 doesn't strip out the query and then the query ends being parsed as part of the path
+changed: didl now forces an empty upnp:artist
+added: Search action to look for ContainerID instead of ObjectId in xml since that's what the xbox 360 sends!
+changed: refactored to use NPT_HttpRequestContext instead of NPT_SocketInfo
+added: new macosx target (universal)
+fixed: use of NPT_CONFIG_THREAD_STACK_SIZE for xbox
+added: can now reset the connector of a NPT_HttpClient
+changed: Updates missing headers only if they're really missing (user_agent, connection, ..)
+changed: Updated NPT_MessageQueue to reflect new blocking way
+changed: Neptune Http server now uses reuse_address when binding
+fixed: single quote in urls
+changed: now can abort NPT_HttpServer
+fixed: If a request is forwarded, don't try to send the body if there's no content length...
+fixed: UPnP Renderer now receives moderated events properly
+fixed: Platinum scons Build, added MediaConnect target
+improved: HttpClientSocketTask now uses keep-alive so if the server is 1.1 or 1.0 with Connection: Keep-alive, it reuses the socket, useful for eventing
+added: Split up MediaConnect support and services into separate class, now CUPnPServer derives from PLT_MediaConnect.
+refactored: move httpserver in start/stop so that it actually stops and cleans up when the device is stopped
+fixed: now starts a thread only when there's a need to event state variable changes to subscribers instead of in the ctor. Useful since the class is also used by ctrl points and they don't need to notify.
+fixed: check that the body stream of a request is rewindable before trying to send a request on a keep-alive socket. If it fails, we wouldn't be able to resend it, so instead, we close the socket and reopen a new one.
+added: new downloader class
+fixed: potential deadlock when stopping upnp while devices are running
+changed: made file server port public in PLT_FileMediaServer so that we can update/query it without recreating a new class (no need for setter/getter)
+
+Platinum 0.3.8
+---------------
+
+fixed: crash in MicroMediaController (ctrlpoint really) when devices go away and a new one reappear. The control point was not removing subscribers from its list for the removed device.
+added: Visual Studio 2005 project files
+changed: switched to using new Neptune Logging system
+changed: PLT_DeviceHost now appends the ip address to friendly name if asked
+
+Platinum 0.3.7
+---------------
+changed: removed projects in the works from solution
+changed: dont restrict an interface to have the MULTICAST flag to send multicast data. If it's not multicast, it just won't send it. Cygwin doesn't report MULTICAST flag properly on interfaces that are multicast so that's why.
+fixed: clear SyncMediaBrowser cache for a device when it disappears
+changed: put back interface matching in proxy using netmask
+fixed: linux build
+fixed: workaround Windows Media Player bug that replaces back slashes to forward slashes in a url query !
+fixed: duplicate headers in crawler response
+changed: fileserver now defaults to serving root "/" with all children so that crawler can use /foo.wma
+changed: made ProcessFileRequest overridable for Crawler
+changed: Mega update:
+ - revamped to use http handlers from Neptune
+ - extensive switch to using address instead of pointers for NPT_HttpRequest & NPT_HttpResponse
+ - using eventhandlers now in devicehost (static for desc & scpds + dynamic for control/event) and controlpoint (event notifications)
+ - fixed host advertising twice byebye on exit
+ - Moved DeviceHost and Ctrlpoint Start/Stop into protected. It's PLT_UPnP now that starts and stop a device (via Add/Remove..)
+ - Created templated PLT_HttpRequestHandler
+fixed: 10 secs to get a M-SEARCH response is fine
+fixed: make it possible to pass an address to send the response back from a search, this is necessary when the udp.connect didn't actually find out which local interface to use
+fixed: now advertises on all interfaces even in broadcast
+fixed: setting MX to 1 in proxy, setting extra header to make sure we don't loop more
+changed: new ssdp proxy using broadcast instead of unicast, no need to keep track of unicasters anymore
+changed: when using broadcast mode, try to use interface broadcast address instead of 255.255.255.255
+changed: made presentation url public (so it can be overridden from the outside)
+hacked: device icons
+changed: better advertising in broadcast mode (less verbose)
+fixed: crash when a device disappears while trying to unsubscribe
+fixed: subscribers being added twice
+fixed: no need to set random seed in task, must be done in threads instead (using thread id)
+changed: added a media cache to cache data responses from servers to speed up
+fixed: better event support (fixed a couple of bugs), unsubscribe on device remove, still need to implement subscription renewal
+changed: improved NPT_Directory to read size & type with 1 call
+fixed: assuming forward unix style delimiters in resource urls was wrong, we want to keep whatever we're passed, it may matter
+changed: now can specify to keep file extension in item title
+changed: can now put a list of UUIDs to ignore in a ctrl point
+changed: now sends a search on localhost if no valid interfaces were found
+changed: now supports broadcast announcements for devices (mainly used by XBOX)
+fixed: changed callbackurls list to be NPT_List<NPT_String> instead of NPT_List<NPT_String*> for event subscribers to fix a weird crash
+fixed: SsdpListenTask takes a true UdpSocket if broadcast mode set
+changed: adding support of NPT_StringFinder for NPT_List<NPT_String> containers
+changed: using a HttpUrl for base urls instead of string
+changed: StreamHandler interface, now passing socket info to ModifyResource
+
+Platinum 0.3.6
+---------------
+- fixed list of devices not being cleared when ctrl point is stopped
+- fixed setting bad content length when serving a file with a byte-range request causing
+- filemediaserver now exposes one resource per network interface and put the proper one first (one the browse request was received on)
+- start listening for ssdp when upnp starts and stops when it stops
+- reversing back adding the Search method to ContentDirectory service
+- rewrite of action processing after finding a major flaw due to parallel processing of multiple calls to the same action. Now each invocation of an action gets its own sets of arguments (in and out).
+
+Platinum 0.3.5
+---------------
+Fixes/Changes:
+- updated directory structure so that everything falls under Build/Targets (even scons based stuff)
+- Fixing ip address being 0.0.0.0 in media resources under cygwin in some cases
+- switching to using HTTP/1.0 for http responses
+- scons build output to Targets top level folder now
+- fixed bug where files with no extensions were not advertised (linux)
+- now strips the executables in Targets folder only in release build
+- Fixed cygwin bug where devices wouldn't be detected when started after a Control Point. Was advertising on disconnected interfaces.
+- Fixed logging wrong ip address, now defaults to 127.0.0.1 if no valid one found
+- fixed bug in server socket task
+- added back HttpClientTests to solution
+- fixed bug in client socket task
+- switch to using NPT_StringOutputStream instead of PLT_OutputStringStream
+- improved PLT_Downloader
+- started working on a SQLite abstraction layer for a better Media Server (work in progress)
+
+Platinum 0.3.2
+---------------
+Fixes/Changes:
+- Tasks and TaskManager rewrote. No more housekeeping thread to cleanup tasks. Tasks are automatically cleaned up when done.
+- Stopping a ControlPoint will also stop the SSDP search tasks.
+- HttpServer can limit the number of connections (threads) it can handle at once.
+- Didl processing rewrote. Didl objects are more C++ oriented now.
+- Some progress in regards to DLNA validation. HTTP Server is 1.0 only (connections are closed immediately once all data has been sent. No more keep-alive support).
+- Started working on Ozone (Sqlite3 abstraction layer)
+
+Platinum 0.3.1 
+---------------
+Fixes/Changes:
+- Fixed LightSample Test
+- Fixed MediaRenderer Test
+- Removed old source and project files to avoid confusion
+
+Platinum 0.3.00 
+---------------
+Fixes/Changes:
+- Added MacOSX support.
+- Fixed socket abortion problem on Linux (using a pipe).
+- Complete rewrite to use threads instead of interrupt driven round-robin. The benefit is that throughput is now greatly improved (for streaming especially).
+- Addded a new App: MediaCrawler
+- Split up AV MediaServer code. Now the FileMediaServer is one implementation of the AV MediaServer. More to follow.
+- Added README, CHANGELOG, LICENSE files
+
+Known issues:
+- AV MediaServer Search not implemented yet.
+- Http server does not use a thread pool. This can be a problem with hungry ControlPoints like the Intel Tools AV MediaController.
+
+Platinum 0.2.00 
+---------------
+Fixes/Changes:
+- Added support for Linux, Xbox, cygwin platforms (using Scons http://scons.org)
+- Now using timeouts on sockets. Fixed search not being repeatly sent.
+- Moved Neptune under ThirdParty folder
+
+Known issues:
+- Aborting on some platforms (linux/xbox) is not immediate. Sockets cannot be easily aborted by simply calling closesocket.
+
+Platinum 0.1.00 
+---------------
+Initial Release
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/LICENSE.txt	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,372 @@
+Platinum UPnP SDK
+-----------------
+This software is provided under the following license:
+
+Plutinosoft, LLC provides its Platinum UPnP SDK under a dual 
+license model designed to meet the development and distribution 
+needs of both commercial distributors (such as OEMs, ISVs and VARs) 
+and open source projects.
+
+For OEMs, ISVs, VARs and Other Distributors of Commercial Applications:
+OEMs, ISVs, VARs and other distributors that combine and distribute 
+commercially licensed software with Platinum software and do not wish 
+to distribute the source code for the commercially licensed software 
+under version 2, or (at your option) any later version, of the GNU 
+General Public License (the "GPL") must enter into a commercial 
+license agreement with Plutinosoft, LLC.
+
+For developers of Free Open Source Software ("FOSS") applications 
+under the GPL that want to combine and distribute those FOSS 
+applications with Platinum software, Plutinosoft's Platinum 
+open source software licensed under the GPL version 2, or (at your option) 
+any later version, is the best option.
+
+Note that Platinum SDK links with Neptune C++ Runtime 
+(http://sourceforge.net/projects/neptune), which is licensed under the 
+terms of the BSD license. This license is compatible with the GNU GPL.
+
+Platinum is copyrighted by Plutinosoft, LLC.
+http://www.plutinosoft.com <sylvain@plutinosoft.com>
+
+-------------------------------------------------------------------------
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/README.txt	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,74 @@
+Platinum UPnP SDK
+=================
+
+This toolkit consists of 2 modules:
+* Neptune : a C++ Runtime Library
+* Platinum: a modular UPnP Framework [Platinum uses Neptune]
+
+Unless you intend to use Neptune independently from Platinum, it is recommended that you build binaries directly from the "Build" tree of Platinum. All the dependent binaries will be rebuilt automatically (including Neptune).
+
+---------------------------------------------
+BUILDING SDK & SAMPLE APPLICATIONS
+
+* Windows:
+Open the Visual Studio 2005 solution located @ Build\Targets\x86-microsoft-win32-vs2005\Platinum.sln
+Open the Visual Studio 2008 solution located @ Build\Targets\x86-microsoft-win32-vs2008\Platinum.sln
+
+* XBox:
+Open the Visual Studio .NET 2003 solution located @ Build\Targets\x86-microsoft-xbox-vs2003\Platinum.sln
+
+* MacOSX:
+Open the XCode project file located @ Build\Targets\universal-apple-macosx\PlatinumApps.xcodeproj
+To include Platinum to your XCode projects, simply add the project file located @ Build\Targets\universal-apple-macosx\Platinum.xcodeproj.
+
+* Linux, Cygwin, MacOSX
+Open a shell, go to the Platinum root directory and type 'scons' (http://scons.org). 
+The output of the scons build will be found under Platinum/Build/Targets/{TARGET}/{Debug|Release}. 
+Additionally, the output is copied under Platinum/Targets/{TARGET}/{Debug|Release} for convenience.
+
+---------------------------------------------
+RUNNING SAMPLE APPLICATIONS
+
+* FileMediaServerTest
+This is an example of a UPnP MediaServer. Given a path, it allows a UPnP ControlPoint to browse the content of the directory and its sub-directories. Additionally, files can be streamed (Note that only files with known mimetypes are advertised).
+
+usage: FileMediaServerTest [-f <friendly_name>] <path>
+    -f : optional upnp server friendly name
+    <path> : local path to serve
+
+Once started, type 'q' to quit.
+
+* MediaRendererTest
+This is an example shell of a UPnP MediaRenderer. It is to be contolled by a UPnP ControlPoint. This is just a SHELL, this won't play anything. You need to hook up the playback functionality yourself.
+
+usage: MediaRendererTest [-f <friendly_name>]
+    -f : optional upnp server friendly name
+
+Once started, type 'q' to quit.
+
+* MediaCrawler
+This is a combo UPnP MediaServer + ControlPoint. It browses content from other MediaServers it finds on the network and present them under one single aggregated view. This is useful for some devices that need to select one single MediaServer at boot time (i.e. Roku).
+
+Once started, type 'q' to quit.
+
+* MicroMediaController
+This is a ControlPoint (synchronous) that lets you browse any MediaServer using a shell-like interface. Once started, a command prompt lets you enter commands such as:
+     quit    -   shutdown
+     exit    -   same as quit
+     setms   -   select a media server to become the active media server
+     getms   -   print the friendly name of the active media server
+     ls      -   list the contents of the current directory on the active 
+                 media server
+     cd      -   traverse down one level in the content tree on the active
+                 media server
+     cd ..   -   traverse up one level in the content tree on the active
+                 media server
+     pwd     -   print the path from the root to your current position in the 
+                 content tree on the active media server
+                 
+Experimental MediaRenderer commands (not yet full implemented):
+     setmr   -   select a media renderer to become the active media renderer
+     getmr   -   print the friendly name of the active media renderer
+     open    -   set the uri on the active media renderer
+     play    -   play the active uri on the active media renderer
+     stop    -   stop the active uri on the active media renderer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/Platinum.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,33 @@
+/*****************************************************************
+|
+|   Platinum
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/Platinum.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,52 @@
+/*****************************************************************
+|
+|   Platinum - Top Level Include
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+ ****************************************************************/
+
+#ifndef _PLATINUM_H_
+#define _PLATINUM_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltCtrlPoint.h"
+#include "PltDeviceData.h"
+#include "PltHttpServer.h"
+
+#ifdef PLT_DEVICE_HEADERS_INCLUDE
+#include "PltMediaServer.h"
+#include "PltMediaBrowser.h"
+#include "PltMediaRenderer.h"
+#include "PltMediaController.h"
+#endif
+
+#endif /* _PLATINUM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltAction.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,464 @@
+/*****************************************************************
+|
+|   Platinum - Service Action
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltAction.h"
+#include "PltService.h"
+#include "PltXmlHelper.h"
+
+#define REMOVE_WMP_DATATYPE_EXTENSION
+
+NPT_SET_LOCAL_LOGGER("platinum.core.action")
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDesc::PLT_ActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc::PLT_ActionDesc(const char* name, PLT_Service* service) : 
+    m_Name(name), 
+    m_Service(service)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDesc::~PLT_ActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc::~PLT_ActionDesc() 
+{
+    m_ArgumentDescs.Apply(NPT_ObjectDeleter<PLT_ArgumentDesc>());
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDesc::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ActionDesc::GetSCPDXML(NPT_XmlElementNode* node)
+{
+    NPT_XmlElementNode* action = new NPT_XmlElementNode("action");
+    NPT_CHECK_SEVERE(node->AddChild(action));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(action, "name", m_Name));
+
+    NPT_XmlElementNode* argumentList = new NPT_XmlElementNode("argumentList");
+    NPT_CHECK_SEVERE(action->AddChild(argumentList));
+
+    // no arguments is ok
+    if (!m_ArgumentDescs.GetItemCount()) return NPT_SUCCESS;
+
+    return m_ArgumentDescs.ApplyUntil(
+        PLT_GetSCPDXMLIterator<PLT_ArgumentDesc>(argumentList), 
+        NPT_UntilResultNotEquals(NPT_SUCCESS));
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDesc::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_ActionDesc::GetService() 
+{
+    return m_Service;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDesc::GetArgumentDesc
++---------------------------------------------------------------------*/
+PLT_ArgumentDesc*
+PLT_ActionDesc::GetArgumentDesc(const char* name)
+{
+    PLT_ArgumentDesc* arg_desc = NULL;
+    NPT_ContainerFind(m_ArgumentDescs, PLT_ArgumentDescNameFinder(name), arg_desc);
+    return arg_desc;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::PLT_Action(PLT_ActionDesc* action_desc) : 
+    m_ActionDesc(action_desc),
+    m_ErrorCode(0) 
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::~PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::~PLT_Action() 
+{
+    m_Arguments.Apply(NPT_ObjectDeleter<PLT_Argument>());
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_Action::GetArgumentValue(const char* name, NPT_String& value) 
+{
+    PLT_Argument* arg = GetArgument(name);
+    if (arg == NULL) {
+        return NPT_FAILURE;
+    }
+    value = arg->GetValue();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_Action::GetArgumentValue(const char* name, NPT_UInt32& value) 
+{
+    NPT_String tmp_value;
+    NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+    return tmp_value.ToInteger(value);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_Action::GetArgumentValue(const char* name, NPT_Int32& value) 
+{
+    NPT_String tmp_value;
+    NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+    return tmp_value.ToInteger(value);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::GetArgument
++---------------------------------------------------------------------*/
+PLT_Argument*
+PLT_Action::GetArgument(const char* name)
+{
+    PLT_Argument* argument = NULL;
+    NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(name), argument);
+    return argument;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::SetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentValue(const char* name,
+                             const char* value) 
+{
+    PLT_Argument* arg = NULL;
+
+    // look for this argument in our argument list
+    // and replace the value if we found it 
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(name), arg))) {
+        return arg->SetValue(value);
+    }
+
+    // since we didn't find it, create a clone 
+    // from the action arguments
+    PLT_ArgumentDesc* arg_desc = m_ActionDesc->GetArgumentDesc(name);
+    if (arg_desc == NULL) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+    arg = new PLT_Argument(arg_desc);
+
+    NPT_Result res = arg->SetValue(value);
+    if (NPT_FAILED(res)) {
+        delete arg;
+        return res;
+    }
+
+    m_Arguments.Add(arg);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::VerifyArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::VerifyArgumentValue(const char* name, const char* value)
+{
+    NPT_String str;
+    NPT_CHECK_SEVERE(GetArgumentValue(name, str));
+
+    return str.Compare(value, true)?NPT_FAILURE:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::VerifyArguments
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::VerifyArguments(bool input)
+{
+    NPT_Cardinal count = 0;
+
+    // Check we have all the required parameters (in or out)
+    for(unsigned int i=0; i<m_ActionDesc->GetArgumentDescs().GetItemCount(); i++) {
+        PLT_ArgumentDesc* arg_desc = m_ActionDesc->GetArgumentDescs()[i];
+
+        // only input arguments are needed
+        if (arg_desc->GetDirection().Compare(input?"in":"out", true))
+            continue;
+
+        // look for this argument in the list we received
+        PLT_Argument* arg = NULL;
+        if (NPT_FAILED(NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(arg_desc->GetName()), arg))) {
+            return NPT_FAILURE;
+        }
+        ++count;
+    }
+
+    SetError(0, "");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::SetArgumentOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentOutFromStateVariable(PLT_ArgumentDesc* arg_desc)
+{
+    // only output arguments can use a state variable
+    if (arg_desc->GetDirection().Compare("out", true)) {
+        return NPT_FAILURE;
+    }
+
+    PLT_StateVariable* variable = arg_desc->GetRelatedStateVariable();
+    if (!variable) return NPT_FAILURE;
+
+    // assign the value to an argument
+    NPT_CHECK_SEVERE(SetArgumentValue(arg_desc->GetName(), variable->GetValue()));
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::SetArgumentOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentOutFromStateVariable(const char* name)
+{
+    // look for this argument in the action list of arguments
+    PLT_ArgumentDesc* arg_desc = NULL;
+    NPT_CHECK_SEVERE(NPT_ContainerFind(m_ActionDesc->GetArgumentDescs(), 
+        PLT_ArgumentDescNameFinder(name), arg_desc));
+
+    return SetArgumentOutFromStateVariable(arg_desc);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::SetArgumentsOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentsOutFromStateVariable()
+{
+    // go through the list of the action output arguments
+    for(unsigned int i=0; i<m_ActionDesc->GetArgumentDescs().GetItemCount(); i++) {
+        PLT_ArgumentDesc* arg_desc = m_ActionDesc->GetArgumentDescs()[i];
+
+        // only output arguments are needed
+        if (arg_desc->GetDirection().Compare("out", true))
+            continue;
+
+        NPT_CHECK_SEVERE(SetArgumentOutFromStateVariable(arg_desc));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::SetError
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_Action::SetError(unsigned int code, const char* description) 
+{
+    m_ErrorCode = code;
+    m_ErrorDescription = description;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::GetError
++---------------------------------------------------------------------*/
+const char* 
+PLT_Action::GetError(unsigned int& code) 
+{
+    code = m_ErrorCode;
+    return m_ErrorDescription;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::GetErrorCode
++---------------------------------------------------------------------*/
+unsigned int 
+PLT_Action::GetErrorCode() 
+{
+    return m_ErrorCode;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::FormatSoapRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapRequest(NPT_OutputStream& stream)
+{
+    NPT_String str;
+    NPT_Result res;
+    NPT_XmlElementNode* body = NULL;
+    NPT_XmlElementNode* request = NULL;
+    NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+    NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+    body = new NPT_XmlElementNode("s", "Body");
+    NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+    request = new NPT_XmlElementNode("u", m_ActionDesc->GetName());
+    NPT_CHECK_LABEL_SEVERE(res = request->SetNamespaceUri("u", m_ActionDesc->GetService()->GetServiceType()), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = body->AddChild(request), cleanup);
+
+    for(unsigned int i=0; i<m_Arguments.GetItemCount(); i++) {
+        PLT_Argument* argument = m_Arguments[i];
+        if (argument->GetDesc()->GetDirection().Compare("in", true) == 0) {
+            NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(
+                request, 
+                argument->GetDesc()->GetName(), 
+                argument->GetValue()), cleanup);
+        }
+    }
+
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+    delete envelope;
+
+    return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+    delete envelope;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::FormatSoapResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapResponse(NPT_OutputStream& stream)
+{
+    if (m_ErrorCode) {
+        return FormatSoapError(m_ErrorCode, m_ErrorDescription, stream);
+    }
+
+    NPT_String str;
+    NPT_Result res;
+    NPT_XmlElementNode* body = NULL;
+    NPT_XmlElementNode* response = NULL;
+    NPT_XmlElementNode* node = NULL;
+    NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+    NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+    body = new NPT_XmlElementNode("s", "Body");
+    NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);        
+
+    response = new NPT_XmlElementNode("u", m_ActionDesc->GetName() + "Response");
+    NPT_CHECK_LABEL_SEVERE(response->SetNamespaceUri("u", m_ActionDesc->GetService()->GetServiceType()), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = body->AddChild(response), cleanup);    
+
+    for(unsigned int i=0; i<m_Arguments.GetItemCount(); i++) {
+        PLT_Argument* argument = m_Arguments[i];
+        if (argument->GetDesc()->GetDirection().Compare("out", true) == 0) {
+            node = new NPT_XmlElementNode(argument->GetDesc()->GetName());
+            NPT_CHECK_LABEL_SEVERE(res = node->AddText(argument->GetValue()), cleanup);
+            NPT_CHECK_LABEL_SEVERE(res = response->AddChild(node), cleanup);
+
+#ifndef REMOVE_WMP_DATATYPE_EXTENSION
+            PLT_StateVariable* var = argument->GetDesc()->GetRelatedStateVariable();
+            if (var) {
+                node->SetNamespaceUri("dt", "urn:schemas-microsoft-com:datatypes");
+                node->SetAttribute("dt", "dt", var->GetDataType());
+            }
+#endif
+        }
+    }
+
+    // this will xmlescape any values that contain xml characters
+    NPT_CHECK_LABEL_SEVERE(PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+    delete envelope;
+
+    return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+    delete envelope;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Action::FormatSoapError
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapError(unsigned int code, NPT_String desc, NPT_OutputStream& stream)
+{
+    NPT_String str;
+    NPT_Result res;
+    NPT_XmlElementNode* body = NULL;
+    NPT_XmlElementNode* fault = NULL;
+    NPT_XmlElementNode* detail = NULL;
+    NPT_XmlElementNode* UPnPError = NULL;
+    NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+    NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+    body = new NPT_XmlElementNode("s", "Body");
+    NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);   
+
+    fault = new NPT_XmlElementNode("s", "Fault");
+    NPT_CHECK_LABEL_SEVERE(res = body->AddChild(fault), cleanup);
+
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(fault, "faultCode", "s:Client"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(fault, "faultString", "UPnPError"), cleanup);
+
+    detail = new NPT_XmlElementNode("detail");
+    NPT_CHECK_LABEL_SEVERE(res = fault->AddChild(detail), cleanup);
+
+    UPnPError = new NPT_XmlElementNode("UPnPError");
+    NPT_CHECK_LABEL_SEVERE(res = UPnPError->SetNamespaceUri("", "urn:schemas-upnp-org:control-1-0"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = detail->AddChild(UPnPError), cleanup);
+
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(UPnPError, "errorCode", NPT_String::FromInteger(code)), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(UPnPError, "errorDescription", desc), cleanup);
+
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+    delete envelope;
+
+    return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+    delete envelope;
+    return res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltAction.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,157 @@
+/*****************************************************************
+|
+|   Platinum - Service Action
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_ACTION_H_
+#define _PLT_ACTION_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltArgument.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_Service;
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDesc
++---------------------------------------------------------------------*/
+class PLT_ActionDesc
+{
+public:
+    PLT_ActionDesc(const char* name, PLT_Service* service);
+   ~PLT_ActionDesc();
+
+    NPT_Array<PLT_ArgumentDesc*>& GetArgumentDescs() { 
+        return m_ArgumentDescs; 
+    }
+
+    const NPT_String& GetName() const { return m_Name;}
+    PLT_ArgumentDesc* GetArgumentDesc(const char* name);
+    NPT_Result        GetSCPDXML(NPT_XmlElementNode* node);
+    PLT_Service*      GetService();
+
+protected:
+    //members
+    NPT_String                   m_Name;
+    PLT_Service*                 m_Service;
+    NPT_Array<PLT_ArgumentDesc*> m_ArgumentDescs;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_Action
++---------------------------------------------------------------------*/
+class PLT_Action
+{
+public:
+    PLT_Action(PLT_ActionDesc* action_desc);
+   ~PLT_Action();
+
+    PLT_ActionDesc* GetActionDesc() { return m_ActionDesc; }
+    
+    NPT_Result    GetArgumentValue(const char* name, NPT_String& value);
+    NPT_Result    GetArgumentValue(const char* name, NPT_UInt32& value);
+    NPT_Result    GetArgumentValue(const char* name, NPT_Int32& value);
+    NPT_Result    VerifyArgumentValue(const char* name, const char* value);
+    NPT_Result    VerifyArguments(bool input);
+    NPT_Result    SetArgumentOutFromStateVariable(const char* name);
+    NPT_Result    SetArgumentsOutFromStateVariable();
+    NPT_Result    SetArgumentValue(const char* name, const char* value);
+
+    NPT_Result    SetError(unsigned int code, const char* description);
+    const char*   GetError(unsigned int& code);
+    unsigned int  GetErrorCode();
+    
+    NPT_Result    FormatSoapRequest(NPT_OutputStream& stream);
+    NPT_Result    FormatSoapResponse(NPT_OutputStream& stream);
+
+    static NPT_Result FormatSoapError(unsigned int      code, 
+        NPT_String        desc, 
+        NPT_OutputStream& stream);
+
+private:
+    NPT_Result    SetArgumentOutFromStateVariable(PLT_ArgumentDesc* arg_desc);
+    PLT_Argument* GetArgument(const char* name);
+
+protected:
+    // members
+    PLT_ActionDesc* m_ActionDesc;
+    PLT_Arguments   m_Arguments;
+    unsigned int    m_ErrorCode;
+    NPT_String      m_ErrorDescription;
+};
+
+typedef NPT_Reference<PLT_Action> PLT_ActionReference;
+
+/*----------------------------------------------------------------------
+|   PLT_GetSCPDXMLIterator
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_GetSCPDXMLIterator
+{
+public:
+    PLT_GetSCPDXMLIterator<T>(NPT_XmlElementNode* node) :
+        m_Node(node) {}
+      
+    NPT_Result operator()(T* const & data) const {
+        return data->GetSCPDXML(m_Node);
+    }
+
+private:
+    NPT_XmlElementNode* m_Node;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_ActionDescNameFinder
++---------------------------------------------------------------------*/
+class PLT_ActionDescNameFinder
+{
+public:
+    // methods
+    PLT_ActionDescNameFinder(PLT_Service* service, const char* name) : 
+        m_Service(service), m_Name(name) {}
+    virtual ~PLT_ActionDescNameFinder() {}
+
+    bool operator()(const PLT_ActionDesc* const & action_desc) const {
+        return action_desc->GetName().Compare(m_Name, true) ? false : true;
+    }
+
+private:
+    // members
+    PLT_Service* m_Service;
+    NPT_String   m_Name;
+};
+
+#endif /* _PLT_ACTION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltArgument.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,142 @@
+/*****************************************************************
+|
+|   Platinum - Action Argument
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltArgument.h"
+#include "PltStateVariable.h"
+#include "PltXmlHelper.h"
+#include "PltAction.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.argument")
+
+/*----------------------------------------------------------------------
+|   PLT_ArgumentDesc::PLT_ArgumentDesc
++---------------------------------------------------------------------*/
+PLT_ArgumentDesc::PLT_ArgumentDesc(const char*        name, 
+                                   const char*        dir, 
+                                   PLT_StateVariable* variable, 
+                                   bool               has_ret) :
+    m_Name(name),
+    m_Direction(dir), 
+    m_RelatedStateVariable(variable),
+    m_HasReturnValue(has_ret)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ArgumentDesc::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ArgumentDesc::GetSCPDXML(NPT_XmlElementNode* node)
+{
+    NPT_XmlElementNode* argument = new NPT_XmlElementNode("argument");
+    NPT_CHECK_SEVERE(node->AddChild(argument));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "name", m_Name));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "direction", m_Direction));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "relatedStateVariable", m_RelatedStateVariable->GetName()));
+
+    if (m_HasReturnValue) {
+        NPT_CHECK_SEVERE(argument->AddChild(new NPT_XmlElementNode("retval")));
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Argument::CreateArgument
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Argument::CreateArgument(PLT_ActionDesc* action_desc, 
+                             const char*     name, 
+                             const char*     value, 
+                             PLT_Argument*&  arg)
+{
+    // reset output params first
+    arg = NULL;
+
+    PLT_ArgumentDesc* arg_desc = action_desc->GetArgumentDesc(name);
+    if (!arg_desc) return NPT_ERROR_INVALID_PARAMETERS;
+
+    PLT_Argument* new_arg = new PLT_Argument(arg_desc);
+    if (NPT_FAILED(new_arg->SetValue(value))) {
+        delete new_arg;
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    arg = new_arg;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Argument::PLT_Argument
++---------------------------------------------------------------------*/
+PLT_Argument::PLT_Argument(PLT_ArgumentDesc* arg_desc) :
+    m_ArgDesc(arg_desc)
+{
+
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Argument::SetValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Argument::SetValue(const char* value) 
+{
+    NPT_CHECK_SEVERE(ValidateValue(value));
+
+    m_Value = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Argument::GetValue
++---------------------------------------------------------------------*/
+const NPT_String&
+PLT_Argument::GetValue() 
+{
+    return m_Value;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Argument::ValidateValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Argument::ValidateValue(const char* value)
+{
+    if (m_ArgDesc->GetRelatedStateVariable()) {
+        return m_ArgDesc->GetRelatedStateVariable()->ValidateValue(value);
+    }
+    return NPT_SUCCESS;    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltArgument.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,138 @@
+/*****************************************************************
+|
+|   Platinum - Action Argument
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_ARGUMENT_H_
+#define _PLT_ARGUMENT_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_StateVariable;
+class PLT_Argument;
+class PLT_ActionDesc;
+typedef NPT_Array<PLT_Argument*> PLT_Arguments;
+
+/*----------------------------------------------------------------------
+|   PLT_ArgumentDesc
++---------------------------------------------------------------------*/
+class PLT_ArgumentDesc
+{
+public:
+    PLT_ArgumentDesc(const char*        name,
+                     const char*        dir = "in",                  
+                     PLT_StateVariable* variable = NULL, 
+                     bool               has_ret = false);
+
+    // accessor methods
+    NPT_Result         GetSCPDXML(NPT_XmlElementNode* node);
+    const NPT_String&  GetName() const {return m_Name;}
+    const NPT_String&  GetDirection() const {return m_Direction;}
+    PLT_StateVariable* GetRelatedStateVariable() {return m_RelatedStateVariable;}
+    bool               HasRetValue() {return m_HasReturnValue;}
+
+protected:
+    NPT_String         m_Name;
+    NPT_String         m_Direction;
+    PLT_StateVariable* m_RelatedStateVariable;
+    bool               m_HasReturnValue;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_Argument
++---------------------------------------------------------------------*/
+class PLT_Argument
+{
+public:
+    PLT_Argument(PLT_ArgumentDesc* arg_desc);
+
+    // class methods
+    static NPT_Result CreateArgument(PLT_ActionDesc* action_desc, 
+                                     const char*     arg_name, 
+                                     const char*     arg_value,
+                                     PLT_Argument*&  arg);
+
+    // accessor methods
+    PLT_ArgumentDesc*  GetDesc() { return m_ArgDesc; }
+    NPT_Result         SetValue(const char* value);
+    const NPT_String&  GetValue();
+
+private:
+    NPT_Result         ValidateValue(const char* value);
+    
+protected:
+    PLT_ArgumentDesc*  m_ArgDesc;
+    NPT_String         m_Value;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_ArgumentNameFinder
++---------------------------------------------------------------------*/
+class PLT_ArgumentNameFinder
+{
+public:
+    // methods
+    PLT_ArgumentNameFinder(const char* name) : m_Name(name) {}
+
+    bool operator()(PLT_Argument* const & argument) const {
+        return argument->GetDesc()->GetName().Compare(m_Name, true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_ArgumentDescNameFinder
++---------------------------------------------------------------------*/
+class PLT_ArgumentDescNameFinder
+{
+public:
+    // methods
+    PLT_ArgumentDescNameFinder(const char* name) : m_Name(name) {}
+
+    bool operator()(PLT_ArgumentDesc* const & arg_desc) const {
+        return arg_desc->GetName().Compare(m_Name, true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String m_Name;
+};
+
+#endif /* _PLT_ARGUMENT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltCtrlPoint.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1396 @@
+/*****************************************************************
+|
+|   Platinum - Control Point
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltCtrlPoint.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltXmlHelper.h"
+#include "PltCtrlPointTask.h"
+#include "PltSsdp.h"
+#include "PltHttpServer.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.ctrlpoint")
+
+/*----------------------------------------------------------------------
+|   typedef
++---------------------------------------------------------------------*/
+typedef PLT_HttpRequestHandler<PLT_CtrlPoint> PLT_HttpCtrlPointRequestHandler;
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointListenerOnDeviceAddedIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnDeviceAddedIterator
+{
+public:
+    PLT_CtrlPointListenerOnDeviceAddedIterator(PLT_DeviceDataReference& device) :
+        m_Device(device) {}
+
+    NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+        return listener->OnDeviceAdded(m_Device);
+    }
+
+private:
+    PLT_DeviceDataReference& m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointListenerOnDeviceRemovedIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnDeviceRemovedIterator
+{
+public:
+    PLT_CtrlPointListenerOnDeviceRemovedIterator(PLT_DeviceDataReference& device) :
+        m_Device(device) {}
+
+    NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+        return listener->OnDeviceRemoved(m_Device);
+    }
+
+private:
+    PLT_DeviceDataReference& m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointListenerOnActionResponseIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnActionResponseIterator
+{
+public:
+    PLT_CtrlPointListenerOnActionResponseIterator(NPT_Result           res, 
+                                                  PLT_ActionReference& action, 
+                                                  void*                userdata) :
+        m_Res(res), m_Action(action), m_Userdata(userdata) {}
+
+    NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+        return listener->OnActionResponse(m_Res, m_Action, m_Userdata);
+    }
+
+private:
+    NPT_Result           m_Res;
+    PLT_ActionReference& m_Action;
+    void*                m_Userdata;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointListenerOnEventNotifyIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnEventNotifyIterator
+{
+public:
+    PLT_CtrlPointListenerOnEventNotifyIterator(PLT_Service*                  service, 
+                                               NPT_List<PLT_StateVariable*>* vars) :
+        m_Service(service), m_Vars(vars) {}
+
+    NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+        return listener->OnEventNotify(m_Service, m_Vars);
+    }
+
+private:
+    PLT_Service*                  m_Service;
+    NPT_List<PLT_StateVariable*>* m_Vars;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_AddGetSCPDRequestIterator class
++---------------------------------------------------------------------*/
+class PLT_AddGetSCPDRequestIterator
+{
+public:
+    PLT_AddGetSCPDRequestIterator(PLT_TaskManager*         task_manager, 
+                                  PLT_CtrlPoint*           ctrl_point, 
+                                  PLT_DeviceDataReference& device) :
+        m_TaskManager(task_manager), 
+        m_CtrlPoint(ctrl_point), 
+        m_Device(device) {}
+
+    NPT_Result operator()(PLT_Service*& service) const {
+        // look for the host and port of the device
+        PLT_DeviceData* device = service->GetDevice();
+        NPT_String scpd_url    = service->GetSCPDURL();
+
+        NPT_LOG_INFO_2("Fetching SCPD for service \"%s\" of device \"%s\"", 
+            (const char*)service->GetServiceID(),
+            (const char*)device->GetFriendlyName());
+
+        // if the SCPD Url starts with a "/", this means we should not append it to the base URI
+        // but instead go there directly
+        if (!scpd_url.StartsWith("/")) {
+            scpd_url = device->GetURLBase().GetPath() + scpd_url;
+        }
+
+        NPT_HttpUrl url(device->GetURLBase().GetHost(), 
+                        device->GetURLBase().GetPort(), 
+                        scpd_url);
+        
+        // Add a delay, some devices need it (aka Rhapsody)
+        NPT_TimeInterval delay(0.1f);
+        return m_TaskManager->StartTask(
+            new PLT_CtrlPointGetSCPDTask(url, 
+                                         m_CtrlPoint, 
+                                         (PLT_DeviceDataReference&)m_Device),
+            &delay);
+    }
+
+private:
+    PLT_TaskManager*        m_TaskManager;
+    PLT_CtrlPoint*          m_CtrlPoint;
+    PLT_DeviceDataReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriberRemoverIterator class
++---------------------------------------------------------------------*/
+class PLT_EventSubscriberRemoverIterator
+{
+public:
+    PLT_EventSubscriberRemoverIterator(PLT_CtrlPoint* ctrl_point) : 
+        m_CtrlPoint(ctrl_point) { 
+        m_CtrlPoint->m_Subscribers.Lock();
+    }
+    ~PLT_EventSubscriberRemoverIterator() {
+        m_CtrlPoint->m_Subscribers.Unlock();
+    }
+
+    NPT_Result operator()(PLT_Service*& service) const {
+        PLT_EventSubscriber* sub = NULL;
+        if (NPT_SUCCEEDED(NPT_ContainerFind(m_CtrlPoint->m_Subscribers, 
+                                            PLT_EventSubscriberFinderByService(service), sub))) {
+            m_CtrlPoint->m_Subscribers.Remove(sub);
+            delete sub;
+        }
+
+        return NPT_SUCCESS;
+    }
+
+private:
+    PLT_CtrlPoint* m_CtrlPoint;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_ServiceReadyIterator class
++---------------------------------------------------------------------*/
+class PLT_ServiceReadyIterator
+{
+public:
+    PLT_ServiceReadyIterator() {}
+
+    NPT_Result operator()(PLT_Service*& service) const {
+        return service->IsInitted()?NPT_SUCCESS:NPT_FAILURE;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceReadyIterator class
++---------------------------------------------------------------------*/
+class PLT_DeviceReadyIterator
+{
+public:
+    PLT_DeviceReadyIterator() {}
+    NPT_Result operator()(PLT_DeviceDataReference& device) const {
+        NPT_CHECK(device->m_Services.ApplyUntil(
+            PLT_ServiceReadyIterator(), 
+            NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+        NPT_CHECK(device->m_EmbeddedDevices.ApplyUntil(
+            PLT_DeviceReadyIterator(), 
+            NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+        // a device must have at least one service or embedded device 
+        // otherwise it's not ready
+        if (device->m_Services.GetItemCount() == 0 &&
+            device->m_EmbeddedDevices.GetItemCount() == 0) {
+            return NPT_FAILURE;
+        }
+        
+        return NPT_SUCCESS;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::PLT_CtrlPoint
++---------------------------------------------------------------------*/
+PLT_CtrlPoint::PLT_CtrlPoint(const char* autosearch /* = "upnp:rootdevice" */) :
+    m_EventHttpServer(new PLT_HttpServer()),
+    m_AutoSearch(autosearch)
+{
+    m_EventHttpServerHandler = new PLT_HttpCtrlPointRequestHandler(this);
+    m_EventHttpServer->AddRequestHandler(m_EventHttpServerHandler, "/", true);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::~PLT_CtrlPoint
++---------------------------------------------------------------------*/
+PLT_CtrlPoint::~PLT_CtrlPoint()
+{
+    delete m_EventHttpServer;
+    delete m_EventHttpServerHandler; 
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::IgnoreUUID
++---------------------------------------------------------------------*/
+void
+PLT_CtrlPoint::IgnoreUUID(const char* uuid)
+{
+    if (!m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) {
+        m_UUIDsToIgnore.Add(uuid);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Start(PLT_SsdpListenTask* task)
+{
+    m_EventHttpServer->Start();
+
+    // house keeping task
+    m_TaskManager.StartTask(new PLT_CtrlPointHouseKeepingTask(this));
+
+    task->AddListener(this);
+    return m_AutoSearch.GetLength()?Search(NPT_HttpUrl("239.255.255.250", 1900, "*"), m_AutoSearch):NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Stop(PLT_SsdpListenTask* task)
+{
+    task->RemoveListener(this);
+
+    m_TaskManager.StopAllTasks();
+    m_EventHttpServer->Stop();
+
+    // we can safely clear everything without a lock
+    // as there are no more tasks pending
+    m_Devices.Clear();
+
+    m_Subscribers.Apply(NPT_ObjectDeleter<PLT_EventSubscriber>());
+    m_Subscribers.Clear();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::AddListener
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::AddListener(PLT_CtrlPointListener* listener) 
+{
+    NPT_AutoLock lock(m_ListenerList);
+    if (!m_ListenerList.Contains(listener)) {
+        m_ListenerList.Add(listener);
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::RemoveListener
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::RemoveListener(PLT_CtrlPointListener* listener)
+{
+    NPT_AutoLock lock(m_ListenerList);
+    m_ListenerList.Remove(listener);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::CreateSearchTask
++---------------------------------------------------------------------*/
+PLT_SsdpSearchTask*
+PLT_CtrlPoint::CreateSearchTask(const NPT_HttpUrl&   url, 
+                                const char*          target, 
+                                NPT_Cardinal         mx, 
+                                const NPT_IpAddress& address)
+{
+    // make sure mx is at least 1
+    if (mx<1) mx=1;
+
+    // create socket
+    NPT_UdpMulticastSocket* socket = new NPT_UdpMulticastSocket();
+    socket->SetInterface(address);
+    socket->SetTimeToLive(4);
+
+    // create request
+    NPT_HttpRequest* request = new NPT_HttpRequest(url, "M-SEARCH", NPT_HTTP_PROTOCOL_1_1);
+    PLT_UPnPMessageHelper::SetMX(*request, mx);
+    PLT_UPnPMessageHelper::SetST(*request, target);
+    PLT_UPnPMessageHelper::SetMAN(*request, "\"ssdp:discover\"");
+    request->GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT, NPT_HttpClient::m_UserAgentHeader);
+
+    // create task
+    PLT_SsdpSearchTask* task = new PLT_SsdpSearchTask(
+        socket,
+        this, 
+        request,
+        mx*10000);
+    return task;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::Search
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Search(const NPT_HttpUrl& url, 
+                      const char*        target, 
+                      NPT_Cardinal       mx /* = 5 */)
+{
+    NPT_List<NPT_NetworkInterface*> if_list;
+    NPT_List<NPT_NetworkInterface*>::Iterator net_if;
+    NPT_List<NPT_NetworkInterfaceAddress>::Iterator net_if_addr;
+
+    NPT_CHECK_SEVERE(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list));
+
+    for (net_if = if_list.GetFirstItem(); net_if; net_if++) {
+        // make sure the interface is at least broadcast or multicast
+        if (!((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) &&
+            !((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST)) {
+            continue;
+        }       
+            
+        for (net_if_addr = (*net_if)->GetAddresses().GetFirstItem(); net_if_addr; net_if_addr++) {
+            // create task
+            PLT_SsdpSearchTask* task = CreateSearchTask(url, 
+                target, 
+                mx, 
+                (*net_if_addr).GetPrimaryAddress());
+            m_TaskManager.StartTask(task);
+        }
+    }
+
+//     {
+//         // create task on 127.0.0.1
+//         NPT_IpAddress address;
+//         address.ResolveName("127.0.0.1");
+// 
+//         PLT_ThreadTask* task = CreateSearchTask(url, 
+//             target, 
+//             mx, 
+//             address);
+//         m_TaskManager.StartTask(task);
+//     }
+
+    if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::Discover
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Discover(const NPT_HttpUrl& url, 
+                        const char*        target, 
+                        NPT_Cardinal       mx /* = 5 */,
+                        NPT_Timeout        repeat /* = 50000 */)
+{
+    // make sure mx is at least 1
+    if (mx<1) mx = 1;
+
+    // create socket
+    NPT_UdpSocket* socket = new NPT_UdpSocket();
+
+    // create request
+    NPT_HttpRequest* request = new NPT_HttpRequest(url, "M-SEARCH", NPT_HTTP_PROTOCOL_1_1);
+    PLT_UPnPMessageHelper::SetMX(*request, mx);
+    PLT_UPnPMessageHelper::SetST(*request, target);
+    PLT_UPnPMessageHelper::SetMAN(*request, "\"ssdp:discover\"");
+    request->GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT, NPT_HttpClient::m_UserAgentHeader);
+
+    // force HOST to be the regular multicast address:port
+    // Some servers do care (like WMC) otherwise they won't respond to us
+    request->GetHeaders().SetHeader(NPT_HTTP_HEADER_HOST, "239.255.255.250:1900");
+
+    // create task
+    PLT_ThreadTask* task = new PLT_SsdpSearchTask(
+        socket,
+        this, 
+        request,
+        repeat<(NPT_Timeout)mx*5000?(NPT_Timeout)mx*5000:repeat);  /* repeat no less than every 5 secs */
+    return m_TaskManager.StartTask(task);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::DoHouseKeeping
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::DoHouseKeeping()
+{
+    NPT_AutoLock lock_devices(m_Devices);
+    NPT_TimeStamp now;
+    int count = m_Devices.GetItemCount();
+    NPT_System::GetCurrentTimeStamp(now);
+
+    PLT_DeviceDataReference device;
+    while (count--) {
+        NPT_Result res = m_Devices.PopHead(device);
+        if (NPT_SUCCEEDED(res)) {
+            NPT_TimeStamp last_update = device->GetLeaseTimeLastUpdate();
+            NPT_TimeInterval lease_time = device->GetLeaseTime();
+
+            // check if device lease time has expired
+            if (now > last_update + NPT_TimeInterval((unsigned long)(((float)lease_time)*2), 0)) {
+                RemoveDevice(device);
+            } else {
+                // add the device back to our list since it is still alive
+                m_Devices.Add(device);
+            }
+        } else {
+            NPT_LOG_SEVERE("DoHouseKeeping failure!");
+            return NPT_FAILURE;
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::FindDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::FindDevice(const char*              uuid, 
+                          PLT_DeviceDataReference& device) 
+{
+    NPT_AutoLock lock(m_Devices);
+    return NPT_ContainerFind(m_Devices, PLT_DeviceDataFinder(uuid), device);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessHttpRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessHttpRequest(NPT_HttpRequest&              request,
+                                  const NPT_HttpRequestContext& context,
+                                  NPT_HttpResponse&             response)
+{
+    NPT_COMPILER_UNUSED(context);
+    if (!request.GetMethod().Compare("NOTIFY")) {
+        return ProcessHttpNotify(request, context, response);
+    }
+
+    NPT_LOG_SEVERE("CtrlPoint received bad http request\r\n");
+    response.SetStatus(412, "Precondition Failed");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessHttpNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessHttpNotify(NPT_HttpRequest&              request,
+                                 const NPT_HttpRequestContext& context,
+                                 NPT_HttpResponse&             response)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    NPT_List<PLT_StateVariable*> vars;
+    PLT_EventSubscriber*         sub = NULL;    
+    NPT_String                   str;
+    NPT_XmlElementNode*          xml = NULL;
+    NPT_String                   callback_uri;
+    NPT_String                   uuid;
+    NPT_String                   service_id;
+    NPT_UInt32                   seq = 0;
+    PLT_Service*                 service = NULL;
+    PLT_DeviceData*              device = NULL;
+    NPT_String                   content_type;
+
+    NPT_String method   = request.GetMethod();
+    NPT_String uri      = request.GetUrl().GetPath();
+
+//     NPT_LOG_FINE_3("CtrlPoint received %s request from %s:%d\r\n", 
+//         request.GetMethod(), 
+//         client_info.remote_address.GetIpAddress(), 
+//         client_info.remote_address.GetPort());
+// 
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINER, &request);
+
+    const NPT_String* sid = PLT_UPnPMessageHelper::GetSID(request);
+    const NPT_String* nt  = PLT_UPnPMessageHelper::GetNT(request);
+    const NPT_String* nts = PLT_UPnPMessageHelper::GetNTS(request);
+    PLT_HttpHelper::GetContentType(request, content_type);
+
+    {
+        NPT_AutoLock lock_subs(m_Subscribers);
+
+        // look for the subscriber with that subscription url
+        if (!sid || NPT_FAILED(NPT_ContainerFind(m_Subscribers, 
+                                                 PLT_EventSubscriberFinderBySID(*sid), 
+                                                 sub))) {
+            NPT_LOG_FINE_1("Subscriber %s not found\n", (const char*)sid);
+            goto bad_request;
+        }
+
+        // verify the request is syntactically correct
+        service = sub->GetService();
+        device  = service->GetDevice();
+
+        uuid = device->GetUUID();
+        service_id = service->GetServiceID();
+
+        // callback uri for this sub
+        callback_uri = "/" + uuid + "/" + service_id;
+
+        if (uri.Compare(callback_uri, true) ||
+            !nt || nt->Compare("upnp:event", true) || 
+            !nts || nts->Compare("upnp:propchange", true)) {
+            goto bad_request;
+        }
+
+        // if the sequence number is less than our current one, we got it out of order
+        // so we disregard it
+        PLT_UPnPMessageHelper::GetSeq(request, seq);
+        if (sub->GetEventKey() && seq <= sub->GetEventKey()) {
+            goto bad_request;
+        }
+
+        // parse body
+        if (NPT_FAILED(PLT_HttpHelper::ParseBody(request, xml))) {
+            goto bad_request;
+        }
+
+        // check envelope
+        if (xml->GetTag().Compare("propertyset", true))
+            goto bad_request;
+
+        // check namespace
+    //    xml.GetAttrValue("xmlns:e", str);
+    //    if (str.Compare("urn:schemas-upnp-org:event-1-0"))
+    //        goto bad_request;
+
+        // check property set
+        // keep a vector of the state variables that changed
+        NPT_XmlElementNode* property;
+        PLT_StateVariable*  var;
+        for (NPT_List<NPT_XmlNode*>::Iterator children = xml->GetChildren().GetFirstItem(); children; children++) {
+            NPT_XmlElementNode* child = (*children)->AsElementNode();
+            if (!child) continue;
+
+            // check property
+            if (child->GetTag().Compare("property", true))
+                goto bad_request;
+
+            if (NPT_FAILED(PLT_XmlHelper::GetChild(child, property))) {
+                goto bad_request;
+            }
+
+            var = service->FindStateVariable(property->GetTag());
+            if (var == NULL) {
+                goto bad_request;
+            }
+
+            if (NPT_FAILED(var->SetValue(property->GetText()?*property->GetText():""))) {
+                goto bad_request;
+            }
+            vars.Add(var);
+        }    
+
+        // update sequence
+        sub->SetEventKey(seq);
+    }
+
+    // notify listener we got an update
+    if (vars.GetItemCount()) {
+        NPT_AutoLock lock(m_ListenerList);
+        m_ListenerList.Apply(PLT_CtrlPointListenerOnEventNotifyIterator(service, &vars));
+    }
+
+    delete xml;
+    return NPT_SUCCESS;
+
+bad_request:
+    NPT_LOG_SEVERE("CtrlPoint received bad request\r\n");
+    response.SetStatus(412, "Precondition Failed");
+    delete xml;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessSsdpSearchResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSsdpSearchResponse(NPT_Result                    res, 
+                                         const NPT_HttpRequestContext& context, 
+                                         NPT_HttpResponse*             response)
+{
+    NPT_CHECK_SEVERE(res);
+    NPT_CHECK_POINTER_SEVERE(response);
+
+    NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String protocol   = response->GetProtocol();
+    
+    NPT_LOG_FINE_2("CtrlPoint received SSDP search response from %s:%d",
+        (const char*)context.GetRemoteAddress().GetIpAddress().ToString() , 
+        context.GetRemoteAddress().GetPort());
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, response);
+    
+    if (response->GetStatusCode() == 200) {
+        const NPT_String* st  = response->GetHeaders().GetHeaderValue("st");
+        const NPT_String* usn = response->GetHeaders().GetHeaderValue("usn");
+        const NPT_String* ext = response->GetHeaders().GetHeaderValue("ext");
+        NPT_CHECK_POINTER_SEVERE(st);
+        NPT_CHECK_POINTER_SEVERE(usn);
+        NPT_CHECK_POINTER_SEVERE(ext);
+        
+        NPT_String uuid;
+        // if we get an advertisement other than uuid
+        // verify it's formatted properly
+        if (usn != st) {
+            char tmp_uuid[200];
+            char tmp_st[200];
+            int  ret;
+            // FIXME: We can't use sscanf directly!
+            ret = sscanf(((const char*)*usn)+5, "%[^::]::%s",
+                tmp_uuid, 
+                tmp_st);
+            if (ret != 2)
+                return NPT_FAILURE;
+            
+            if (st->Compare(tmp_st, true))
+                return NPT_FAILURE;
+            
+            uuid = tmp_uuid;
+        } else {
+            uuid = ((const char*)*usn)+5;
+        }
+        
+        if (m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) {
+            NPT_LOG_FINE_1("CtrlPoint received a search response from ourselves (%s)\n", (const char*)uuid);
+            return NPT_SUCCESS;
+        }
+
+        return ProcessSsdpMessage(response, context, uuid);    
+    }
+    
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::OnSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::OnSsdpPacket(NPT_HttpRequest&              request,
+                            const NPT_HttpRequestContext& context)
+{
+    return ProcessSsdpNotify(request, context);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessSsdpNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSsdpNotify(NPT_HttpRequest&              request, 
+                                 const NPT_HttpRequestContext& context)
+{
+    // get the address of who sent us some data back
+    NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String method     = request.GetMethod();
+    NPT_String uri        = (const char*)request.GetUrl().GetPath();
+    NPT_String protocol   = request.GetProtocol();
+
+    if (method.Compare("NOTIFY") == 0) {
+        NPT_LOG_INFO_2("Received SSDP NOTIFY from %s:%d",
+            context.GetRemoteAddress().GetIpAddress().ToString().GetChars(), 
+            context.GetRemoteAddress().GetPort());
+        PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+        if ((uri.Compare("*") != 0) || (protocol.Compare("HTTP/1.1") != 0))
+            return NPT_FAILURE;
+        
+        const NPT_String* nts = PLT_UPnPMessageHelper::GetNTS(request);
+        const NPT_String* nt  = PLT_UPnPMessageHelper::GetNT(request);
+        const NPT_String* usn = PLT_UPnPMessageHelper::GetUSN(request);
+        NPT_CHECK_POINTER_SEVERE(nts);
+        NPT_CHECK_POINTER_SEVERE(nt);
+        NPT_CHECK_POINTER_SEVERE(usn);
+
+        NPT_String uuid;
+        // if we get an advertisement other than uuid
+        // verify it's formatted properly
+        if (*usn != *nt) {
+            char tmp_uuid[200];
+            char tmp_nt[200];
+            int  ret;
+            //FIXME: no sscanf!
+            ret = sscanf(((const char*)*usn)+5, "%[^::]::%s",
+                tmp_uuid, 
+                tmp_nt);
+            if (ret != 2)
+                return NPT_FAILURE;
+            
+            if (nt->Compare(tmp_nt, true))
+                return NPT_FAILURE;
+            
+            uuid = tmp_uuid;
+        } else {
+            uuid = ((const char*)*usn)+5;
+        }
+
+        if (m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) {
+            NPT_LOG_FINE_1("Received a NOTIFY request from ourselves (%s)\n", (const char*)uuid);
+            return NPT_SUCCESS;
+        }
+
+        // if it's a byebye, remove the device and return right away
+        if (nts->Compare("ssdp:byebye", true) == 0) {
+            NPT_LOG_INFO_1("Received a byebye NOTIFY request from %s\n", (const char*)uuid);
+        
+            PLT_DeviceDataReference data;
+            if (NPT_SUCCEEDED(FindDevice(uuid, data))) {
+                NPT_AutoLock lock_devices(m_Devices);
+                RemoveDevice(data);
+            }
+
+            return NPT_SUCCESS;
+        }
+        
+        return ProcessSsdpMessage(&request, context, uuid);
+    }
+    
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::RemoveDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::RemoveDevice(PLT_DeviceDataReference& data)
+{
+    NPT_LOG_INFO_1("Removing %s from device list\n", (const char*)data->GetUUID());
+    
+    /* recursively remove embedded devices */
+    NPT_Array<PLT_DeviceDataReference> embedded_devices = 
+        data->GetEmbeddedDevices();
+    for(NPT_Cardinal i=0;i>embedded_devices.GetItemCount();i++) {
+        RemoveDevice(embedded_devices[i]);
+    }
+
+    /* remove from list */
+    m_Devices.Remove(data);
+
+    /* unsubscribe from services */
+    data->m_Services.Apply(PLT_EventSubscriberRemoverIterator(this));
+
+    /* notify listeners */
+    {
+        NPT_AutoLock lock(m_ListenerList);
+        m_ListenerList.Apply(PLT_CtrlPointListenerOnDeviceRemovedIterator(data));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessSsdpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSsdpMessage(NPT_HttpMessage*              message, 
+                                  const NPT_HttpRequestContext& context,
+                                  NPT_String&                   uuid)
+{
+    NPT_COMPILER_UNUSED(context);
+    NPT_CHECK_POINTER_SEVERE(message);
+
+    if (m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) return NPT_SUCCESS;
+
+    const NPT_String* location = PLT_UPnPMessageHelper::GetLocation(*message);
+    NPT_CHECK_POINTER_SEVERE(location);
+    
+    // be nice and assume a default lease time if not found
+    NPT_Timeout leasetime;
+    if (NPT_FAILED(PLT_UPnPMessageHelper::GetLeaseTime(*message, leasetime))) {
+        leasetime = 1800;
+    }
+
+    return InspectDevice(*location, uuid, leasetime);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::InspectDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::InspectDevice(const char* location, 
+                             const char* uuid, 
+                             NPT_Timeout leasetime)
+{
+    NPT_HttpUrl url(location);
+    if (!url.IsValid()) return NPT_FAILURE;
+
+    // is it a new device?
+    PLT_DeviceDataReference data;
+    if (NPT_FAILED(FindDevice(uuid, data))) {
+        NPT_AutoLock lock(m_Devices);
+
+        NPT_LOG_INFO_2("New device \"%s\" detected @ %s", uuid, location);
+
+        data = new PLT_DeviceData(url, uuid, NPT_TimeInterval(leasetime, 0));
+        m_Devices.Add(data);
+        
+        // Start a task to retrieve the description
+        PLT_CtrlPointGetDescriptionTask* task = new PLT_CtrlPointGetDescriptionTask(
+            url,
+            this, 
+            data);
+        // Add a delay, some devices need it (aka Rhapsody)
+        NPT_TimeInterval delay(0.2f);
+        m_TaskManager.StartTask(task, &delay);
+
+        return NPT_SUCCESS;
+    }
+    
+    // in case we missed the byebye and the device description has changed (ip or port)
+    // reset base and assumes device is the same (same number of services and SCPDs)
+    // FIXME: The right way is to remove the device and rescan it though
+    PLT_DeviceReadyIterator device_tester;
+    if (NPT_SUCCEEDED(device_tester(data)) && 
+        data->GetDescriptionUrl().Compare(location, true)) {
+        NPT_LOG_INFO_2("Old device \"%s\" detected @ new location %s", 
+            (const char*)data->GetFriendlyName(), 
+            location);
+        data->SetURLBase(url);
+    }
+
+    // renew expiration time
+    data->SetLeaseTime(NPT_TimeInterval(leasetime, 0));
+    NPT_LOG_FINE_1("Device (%s) expiration time renewed..", (const char*)uuid);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessGetDescriptionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessGetDescriptionResponse(NPT_Result                    res, 
+                                             const NPT_HttpRequestContext& context,
+                                             NPT_HttpResponse*             response, 
+                                             PLT_DeviceDataReference&      device)
+{    
+    NPT_LOG_INFO_2("Received device description for %s (result = %d)", 
+        (const char*)device->GetUUID(), 
+        res);
+
+    NPT_CHECK_FATAL(res);
+    NPT_CHECK_POINTER_FATAL(response);
+
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINER, response);
+
+    // make sure we have seen this device before
+    PLT_DeviceDataReference root_device;
+    res = FindDevice(device->GetUUID(), root_device);
+    NPT_CHECK_WARNING(res);
+
+    // get body
+    NPT_String desc;
+    res = PLT_HttpHelper::GetBody(*response, desc);
+    NPT_CHECK_LABEL_SEVERE(res, bad_response);
+    
+    // set the device description
+    res = root_device->SetDescription(desc, context.GetLocalAddress().GetIpAddress());
+    NPT_CHECK_LABEL_SEVERE(res, bad_response);
+
+    NPT_LOG_INFO_2("Device \"%s\" is now known as \"%s\"", 
+        (const char*)device->GetUUID(), 
+        (const char*)device->GetFriendlyName());
+
+    // add embedded devices to list of devices
+    // and fetch their services scpd
+    for (NPT_Cardinal i = 0;
+         i<root_device->m_EmbeddedDevices.GetItemCount();
+         i++) {
+
+         PLT_DeviceDataReference embedded_device = root_device->m_EmbeddedDevices[i];
+         PLT_DeviceDataReference data;
+         if (NPT_FAILED(FindDevice(embedded_device->GetUUID(), data))) {
+             NPT_AutoLock lock(m_Devices);
+             m_Devices.Add(embedded_device);
+         }
+
+         res = embedded_device->m_Services.Apply(PLT_AddGetSCPDRequestIterator(
+             &m_TaskManager, 
+             this, 
+             embedded_device));
+         NPT_CHECK_LABEL_SEVERE(res, bad_response);
+    }
+
+    // Get SCPD of root device services now
+    res = root_device->m_Services.Apply(PLT_AddGetSCPDRequestIterator(
+        &m_TaskManager, 
+        this, 
+        root_device));
+    NPT_CHECK_LABEL_SEVERE(res, bad_response);
+
+    return NPT_SUCCESS;
+
+bad_response:
+    NPT_LOG_SEVERE_2("Bad Description response for device \"%s\": %s", 
+        (const char*)device->GetUUID(),
+        (const char*)desc);
+
+    if (!root_device.IsNull()) {
+        NPT_AutoLock lock(m_Devices);    
+        RemoveDevice(root_device);
+    }
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessGetSCPDResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessGetSCPDResponse(NPT_Result               res, 
+                                      NPT_HttpRequest*         request,
+                                      NPT_HttpResponse*        response,
+                                      PLT_DeviceDataReference& device)
+{
+    PLT_DeviceReadyIterator device_tester;   
+    PLT_Service*            service = NULL;
+    
+    NPT_LOG_INFO_2("Received SCPD response for %s (result = %d)", 
+        (const char*)device->GetUUID(), 
+        res);
+
+    NPT_CHECK_FATAL(res);
+    NPT_CHECK_POINTER_FATAL(request);
+    NPT_CHECK_POINTER_FATAL(response);
+    
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINER, response);
+
+    PLT_DeviceDataReference data;
+    NPT_CHECK_WARNING(FindDevice(device->GetUUID(), data));
+
+    // get body
+    NPT_String scpd;
+    res = PLT_HttpHelper::GetBody(*response, scpd);
+    NPT_CHECK_LABEL_FATAL(res, bad_response);
+
+    // look for the service based on the SCPD uri
+    res = data->FindServiceByDescriptionURI(request->GetUrl().GetPath(), service);
+    NPT_CHECK_LABEL_FATAL(res, bad_response);
+    
+    {
+        // lock using listener list before testing
+        // to make sure an scpd is not getting set while we test
+        NPT_AutoLock lock(m_ListenerList);
+
+        // set the service scpd
+        res = service->SetSCPDXML(scpd);
+        NPT_CHECK_LABEL_FATAL(res, bad_response);
+
+        if (NPT_SUCCEEDED(device_tester(data))) {
+            // notify that the device is ready to use
+            m_ListenerList.Apply(PLT_CtrlPointListenerOnDeviceAddedIterator(data));
+        }
+
+        // if device is not root, notify listeners now if parent is ready
+        if (!data->GetParentUUID().IsEmpty()) {
+            PLT_DeviceDataReference parent;
+            NPT_CHECK_WARNING(FindDevice(data->GetParentUUID(), parent));
+
+            // lock using listener list before testing
+            // to make sure an scpd is not getting set while we test
+            if (NPT_SUCCEEDED(device_tester(parent))) {
+                // notify that the root device is ready to use
+                m_ListenerList.Apply(PLT_CtrlPointListenerOnDeviceAddedIterator(parent));
+            }
+        }
+    }
+    
+    return NPT_SUCCESS;
+
+bad_response:
+    NPT_LOG_SEVERE_2("Bad SCPD response for device \"%s\":%s", 
+        (const char*)device->GetFriendlyName(),
+        (const char*)scpd);
+
+    if (!data.IsNull()) {
+        NPT_AutoLock lock(m_Devices);
+        RemoveDevice(data);
+    }
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::Subscribe
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Subscribe(PLT_Service* service, bool cancel, void* userdata)
+{
+    NPT_AutoLock lock(m_Subscribers);
+
+    if (!service->IsSubscribable()) return NPT_FAILURE;
+
+    // look for the host and port of the device
+    PLT_DeviceData* device = service->GetDevice();
+
+    // get the relative event subscription url
+    // if URL starts with '/', it's not to be appended to base URL
+    NPT_String event_sub_url = service->GetEventSubURL();
+    if (!event_sub_url.StartsWith("/")) {
+        event_sub_url = device->GetURLBase().GetPath() + event_sub_url;
+    }
+
+    NPT_HttpUrl url(device->GetURLBase().GetHost(), 
+                    device->GetURLBase().GetPort(), 
+                    event_sub_url);
+
+    // look for the subscriber with that service to decide if it's a renewal or not
+    PLT_EventSubscriber* sub = NULL;
+    NPT_ContainerFind(m_Subscribers, 
+                      PLT_EventSubscriberFinderByService(service), 
+                      sub);
+
+    // create the request
+    NPT_HttpRequest* request = NULL;
+
+    if (cancel == false) {
+        // renewal?
+        if (sub) {
+            NPT_LOG_FINE_3("Renewing subscriber \"%s\" for service \"%s\" of device \"%s\"", 
+                (const char*)sub->GetSID(),
+                (const char*)service->GetServiceID(),
+                (const char*)device->GetFriendlyName());
+
+            // create the request
+            request = new NPT_HttpRequest(url, "SUBSCRIBE");
+
+            PLT_UPnPMessageHelper::SetSID(*request, sub->GetSID());
+            PLT_UPnPMessageHelper::SetTimeOut(*request, 1800);
+        } else {
+            NPT_LOG_INFO_2("Subscribing to service \"%s\" of device \"%s\"",
+                (const char*)service->GetServiceID(),
+                (const char*)service->GetDevice()->GetFriendlyName());
+
+            // prepare the callback url
+            NPT_String uuid         = device->GetUUID();
+            NPT_String service_id   = service->GetServiceID();
+            NPT_String callback_uri = "/" + uuid + "/" + service_id;
+
+            // create the request
+            request = new NPT_HttpRequest(url, "SUBSCRIBE");
+            // specify callback url using ip of interface used when 
+            // retrieving device description
+            NPT_HttpUrl callbackUrl(device->m_LocalIfaceIp.ToString(), 
+                m_EventHttpServer->GetPort(), 
+                callback_uri);
+
+            // set the required headers for a new subscription
+            PLT_UPnPMessageHelper::SetNT(*request, "upnp:event");
+            PLT_UPnPMessageHelper::SetCallbacks(*request, 
+                "<" + callbackUrl.ToString() + ">");
+            PLT_UPnPMessageHelper::SetTimeOut(*request, 1800);
+        }
+    } else {
+        NPT_LOG_INFO_3("Unsubscribing subscriber \"%s\" for service \"%s\" of device \"%s\"",
+            (const char*)(sub?sub->GetSID().GetChars():"unknown"),
+            (const char*)service->GetServiceID(),
+            (const char*)service->GetDevice()->GetFriendlyName());        
+        
+        // cancellation
+        if (!sub)return NPT_FAILURE;
+
+        // create the request
+        request = new NPT_HttpRequest(url, "UNSUBSCRIBE");
+        PLT_UPnPMessageHelper::SetSID(*request, sub->GetSID());
+
+        // remove from list now
+        m_Subscribers.Remove(sub, true);
+        delete sub;
+    }
+
+    NPT_CHECK_POINTER_FATAL(request);
+
+    // Prepare the request
+    // create a task to post the request
+    PLT_ThreadTask* task = new PLT_CtrlPointSubscribeEventTask(
+        request,
+        this, 
+        service, 
+        userdata);
+    m_TaskManager.StartTask(task);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessSubscribeResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSubscribeResponse(NPT_Result        res, 
+                                        NPT_HttpResponse* response,
+                                        PLT_Service*      service,
+                                        void*             /* userdata */)
+{
+    const NPT_String*    sid = NULL;
+    NPT_Int32            timeout;
+    PLT_EventSubscriber* sub = NULL;
+
+    NPT_AutoLock lock(m_Subscribers);
+
+    NPT_LOG_INFO_2("Received subscription response for service \"%s\" (result = %d)", 
+        (const char*)service->GetServiceID(),
+        res);
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINER, response);
+
+    // if there's a failure or it's a response to a cancellation
+    // we get out
+    if (NPT_FAILED(res) || response == NULL || response->GetStatusCode() != 200) {
+        NPT_CHECK_LABEL_SEVERE(NPT_FAILED(res)?res:NPT_FAILURE, failure);
+    }
+        
+    if (!(sid = PLT_UPnPMessageHelper::GetSID(*response)) || 
+        NPT_FAILED(PLT_UPnPMessageHelper::GetTimeOut(*response, timeout))) {
+        NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+    }
+
+    // look for the subscriber with that sid
+    if (NPT_FAILED(NPT_ContainerFind(m_Subscribers, 
+                                     PLT_EventSubscriberFinderBySID(*sid), 
+                                     sub))) {
+        NPT_LOG_INFO_3("Creating new subscriber \"%s\" for service \"%s\" of device \"%s\"",
+            (const char*)*sid,
+            (const char*)service->GetServiceID(),
+            (const char*)service->GetDevice()->GetFriendlyName());
+
+        sub = new PLT_EventSubscriber(&m_TaskManager, service, *sid);
+        m_Subscribers.Add(sub);
+    }
+
+    sub->SetTimeout(timeout);
+    return NPT_SUCCESS;
+
+failure:
+    NPT_LOG_SEVERE_3("(un)subscription failed of sub \"%s\" for service \"%s\" of device \"%s\"", 
+        (const char*)(sid?*sid:"?"),
+        (const char*)service->GetServiceID(),
+        (const char*)service->GetDevice()->GetFriendlyName());
+
+    // in case it was a renewal look for the subscriber with that service and remove it from the list
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers, 
+                                        PLT_EventSubscriberFinderByService(service), 
+                                        sub))) {
+        m_Subscribers.Remove(sub);
+        delete sub;
+    }
+
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::InvokeAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::InvokeAction(PLT_ActionReference& action, 
+                            void*                userdata)
+{
+    PLT_Service*    service = action->GetActionDesc()->GetService();
+    PLT_DeviceData* device  = service->GetDevice();
+
+    // look for the service control url
+    NPT_String control_url = service->GetControlURL();
+
+    // if URL starts with a "/", it's not to be appended to base URL
+    if (!control_url.StartsWith("/")) {
+        control_url = device->GetURLBase().GetPath() + control_url;
+    }
+
+    // create the request
+    // FIXME: hack use HTTP/1.0 for now because of WMC that returning 100 Continue when using HTTP/1.1
+    // and this screws up the http processing right now
+    NPT_HttpUrl url(device->GetURLBase().GetHost(), device->GetURLBase().GetPort(), control_url);
+    NPT_HttpRequest* request = new NPT_HttpRequest(url, "POST", NPT_HTTP_PROTOCOL_1_0);
+    
+    // create a memory stream for our request body
+    NPT_MemoryStreamReference stream(new NPT_MemoryStream);
+    action->FormatSoapRequest(*stream);
+
+    // set the request body
+    NPT_InputStreamReference input = stream;
+    PLT_HttpHelper::SetBody(*request, input);
+
+    PLT_HttpHelper::SetContentType(*request, "text/xml; charset=\"utf-8\"");
+    NPT_String service_type = service->GetServiceType();
+    NPT_String action_name   = action->GetActionDesc()->GetName();
+    request->GetHeaders().SetHeader("SOAPAction", "\"" + service_type + "#" + action_name + "\"");
+
+    // create a task to post the request
+    PLT_CtrlPointInvokeActionTask* task = new PLT_CtrlPointInvokeActionTask(
+        request,
+        this, 
+        action, 
+        userdata);
+
+    // queue the request
+    m_TaskManager.StartTask(task);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ProcessActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessActionResponse(NPT_Result           res, 
+                                     NPT_HttpResponse*    response,
+                                     PLT_ActionReference& action,
+                                     void*                userdata)
+{
+    NPT_String          service_type;
+    NPT_String          str;
+    NPT_XmlElementNode* xml = NULL;
+    NPT_String          name;
+    NPT_String          soap_action_name;
+    NPT_XmlElementNode* soap_action_response;
+    NPT_XmlElementNode* soap_body;
+    NPT_XmlElementNode* fault;
+    const NPT_String*   attr = NULL;
+    PLT_ActionDesc*     action_desc = action->GetActionDesc();
+
+    // reset the error code and desc
+    action->SetError(0, "");
+
+    // check context validity
+    if (NPT_FAILED(res) || response == NULL) {
+        goto failure;
+    }
+
+    NPT_LOG_FINE("Received Action Response:");
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, response);
+
+    NPT_LOG_FINER("Reading/Parsing Action Response Body...");
+    if (NPT_FAILED(PLT_HttpHelper::ParseBody(*response, xml))) {
+        goto failure;
+    }
+
+    NPT_LOG_FINER("Analyzing Action Response Body...");
+
+    // read envelope
+    if (xml->GetTag().Compare("Envelope", true))
+        goto failure;
+
+    // check namespace
+    if (!xml->GetNamespace() || xml->GetNamespace()->Compare("http://schemas.xmlsoap.org/soap/envelope/"))
+        goto failure;
+
+    // check encoding
+    attr = xml->GetAttribute("encodingStyle", "http://schemas.xmlsoap.org/soap/envelope/");
+    if (!attr || attr->Compare("http://schemas.xmlsoap.org/soap/encoding/"))
+        goto failure;
+
+    // read action
+    soap_body = PLT_XmlHelper::GetChild(xml, "Body");
+    if (soap_body == NULL)
+        goto failure;
+
+    // check if an error occurred
+    fault = PLT_XmlHelper::GetChild(soap_body, "Fault");
+    if (fault != NULL) {
+        // we have an error
+        ParseFault(action, fault);
+        goto failure;
+    }
+
+    if (NPT_FAILED(PLT_XmlHelper::GetChild(soap_body, soap_action_response)))
+        goto failure;
+
+    // verify action name is identical to SOAPACTION header
+    if (soap_action_response->GetTag().Compare(action_desc->GetName() + "Response", true))
+        goto failure;
+
+    // verify namespace
+    if (!soap_action_response->GetNamespace() ||
+         soap_action_response->GetNamespace()->Compare(action_desc->GetService()->GetServiceType()))
+         goto failure;
+
+    // read all the arguments if any
+    for (NPT_List<NPT_XmlNode*>::Iterator args = soap_action_response->GetChildren().GetFirstItem(); args; args++) {
+        NPT_XmlElementNode* child = (*args)->AsElementNode();
+        if (!child) continue;
+
+        action->SetArgumentValue(child->GetTag(), child->GetText()?*child->GetText():"");
+        if (NPT_FAILED(res)) goto failure; 
+    }
+
+    // create a buffer for our response body and call the service
+    res = action->VerifyArguments(false);
+    if (NPT_FAILED(res)) goto failure; 
+
+    goto cleanup;
+
+failure:
+    // override res with failure if necessary
+    if (NPT_SUCCEEDED(res)) res = NPT_ERROR_INVALID_FORMAT;
+    // fallthrough
+
+cleanup:
+    {
+        NPT_AutoLock lock(m_ListenerList);
+        m_ListenerList.Apply(PLT_CtrlPointListenerOnActionResponseIterator(res, action, userdata));
+    }
+    
+    delete xml;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint::ParseFault
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ParseFault(PLT_ActionReference& action,
+                          NPT_XmlElementNode*  fault)
+{
+    NPT_XmlElementNode* detail = fault->GetChild("detail");
+    if (detail == NULL) return NPT_FAILURE;
+
+    NPT_XmlElementNode *upnp_error, *error_code, *error_desc;
+    upnp_error = detail->GetChild("upnp_error");
+    if (upnp_error == NULL) return NPT_FAILURE;
+
+    error_code = upnp_error->GetChild("errorCode");
+    error_desc = upnp_error->GetChild("errorDescription");
+    NPT_Int32  code = 501;    
+    NPT_String desc;
+    if (error_code && error_code->GetText()) {
+        NPT_String value = *error_code->GetText();
+        value.ToInteger(code);
+    }
+    if (error_desc && error_desc->GetText()) {
+        desc = *error_desc->GetText();
+    }
+    action->SetError(code, desc);
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltCtrlPoint.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,175 @@
+/*****************************************************************
+|
+|   Platinum - Control Point
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_CONTROL_POINT_H_
+#define _PLT_CONTROL_POINT_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltService.h"
+#include "PltHttpServerListener.h"
+#include "PltSsdpListener.h"
+#include "PltDeviceData.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_HttpServer;
+class PLT_CtrlPointHouseKeepingTask;
+class PLT_SsdpSearchTask;
+class PLT_SsdpListenTask;
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointListener class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListener
+{
+public:
+    virtual ~PLT_CtrlPointListener() {}
+
+    virtual NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device) = 0;
+    virtual NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device) = 0;
+    virtual NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata) = 0;
+    virtual NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars) = 0;
+};
+
+typedef NPT_List<PLT_CtrlPointListener*> PLT_CtrlPointListenerList;
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPoint class
++---------------------------------------------------------------------*/
+class PLT_CtrlPoint : public PLT_SsdpPacketListener,
+                      public PLT_SsdpSearchResponseListener
+{
+public:
+    PLT_CtrlPoint(const char* autosearch = "upnp:rootdevice"); // pass NULL to bypass the multicast search
+
+    NPT_Result   AddListener(PLT_CtrlPointListener* listener);
+    NPT_Result   RemoveListener(PLT_CtrlPointListener* listener);
+    void         IgnoreUUID(const char* uuid);
+    NPT_Result   InspectDevice(const char* location, 
+                               const char* uuid, 
+                               NPT_Timeout leasetime = 1800);
+    NPT_Result   Search(const NPT_HttpUrl& url = NPT_HttpUrl("239.255.255.250", 1900, "*"), 
+                        const char*        target = "upnp:rootdevice", 
+                        NPT_Cardinal       mx = 5);
+    NPT_Result   Discover(const NPT_HttpUrl& url = NPT_HttpUrl("239.255.255.250", 1900, "*"), 
+                          const char*        target = "ssdp:all", 
+                          NPT_Cardinal       mx = 5,
+                          NPT_Timeout        repeat = 50000);
+    NPT_Result   InvokeAction(PLT_ActionReference& action, void* userdata = NULL);
+    NPT_Result   Subscribe(PLT_Service* service, bool cancel = false, void* userdata = NULL);
+
+    // NPT_HttpRequestHandler methods
+    virtual NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request,
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse&             response);
+
+    // PLT_SsdpSearchResponseListener methods
+    virtual NPT_Result ProcessSsdpSearchResponse(NPT_Result                    res, 
+                                                 const NPT_HttpRequestContext& context,
+                                                 NPT_HttpResponse*             response);
+    // PLT_SsdpPacketListener method
+    virtual NPT_Result OnSsdpPacket(NPT_HttpRequest&              request, 
+                                    const NPT_HttpRequestContext& context);
+    
+    // helper methods
+    NPT_Result  FindDevice(const char* uuid, PLT_DeviceDataReference& device);
+
+protected:
+    virtual ~PLT_CtrlPoint();
+
+    NPT_Result   Start(PLT_SsdpListenTask* task);
+    NPT_Result   Stop(PLT_SsdpListenTask* task);
+
+    NPT_Result   ProcessSsdpNotify(NPT_HttpRequest&              request, 
+                                   const NPT_HttpRequestContext& context);
+    NPT_Result   ProcessSsdpMessage(NPT_HttpMessage*              message, 
+                                    const NPT_HttpRequestContext& context,  
+                                    NPT_String&                   uuid);
+    NPT_Result   ProcessGetDescriptionResponse(NPT_Result                    res, 
+                                               const NPT_HttpRequestContext& context,
+                                               NPT_HttpResponse*             response,
+                                               PLT_DeviceDataReference&      device);
+    NPT_Result   ProcessGetSCPDResponse(NPT_Result               res, 
+                                        NPT_HttpRequest*         request,
+                                        NPT_HttpResponse*        response,
+                                        PLT_DeviceDataReference& device);
+    NPT_Result   ProcessActionResponse(NPT_Result               res, 
+                                       NPT_HttpResponse*        response,
+                                       PLT_ActionReference&     action,
+                                       void*                    userdata);
+    NPT_Result   ProcessSubscribeResponse(NPT_Result         res, 
+                                          NPT_HttpResponse*  response,
+                                          PLT_Service*       service,
+                                          void*              userdata);
+    NPT_Result   ProcessHttpNotify(NPT_HttpRequest&              request,
+                                   const NPT_HttpRequestContext& context,
+                                   NPT_HttpResponse&             response);
+private:
+    // methods
+    NPT_Result DoHouseKeeping();
+    NPT_Result RemoveDevice(PLT_DeviceDataReference& data);
+    NPT_Result ParseFault(PLT_ActionReference& action, NPT_XmlElementNode* fault);
+    PLT_SsdpSearchTask* CreateSearchTask(const NPT_HttpUrl&   url, 
+                                         const char*          target, 
+                                         NPT_Cardinal         mx, 
+                                         const NPT_IpAddress& address);
+    
+private:
+    friend class NPT_Reference<PLT_CtrlPoint>;
+    friend class PLT_UPnP;
+    friend class PLT_UPnP_CtrlPointStartIterator;
+    friend class PLT_UPnP_CtrlPointStopIterator;
+    friend class PLT_EventSubscriberRemoverIterator;
+    friend class PLT_CtrlPointGetDescriptionTask;
+    friend class PLT_CtrlPointGetSCPDTask;
+    friend class PLT_CtrlPointInvokeActionTask;
+    friend class PLT_CtrlPointHouseKeepingTask;
+    friend class PLT_CtrlPointSubscribeEventTask;
+
+    NPT_List<NPT_String>                         m_UUIDsToIgnore;
+    NPT_Lock<PLT_CtrlPointListenerList>          m_ListenerList;
+    PLT_HttpServer*                              m_EventHttpServer;
+    NPT_HttpRequestHandler*                      m_EventHttpServerHandler;
+    PLT_TaskManager                              m_TaskManager;
+    NPT_Lock<NPT_List<PLT_DeviceDataReference> > m_Devices;
+    NPT_Lock<NPT_List<PLT_EventSubscriber*> >    m_Subscribers;
+    NPT_String                                   m_AutoSearch;
+};
+
+typedef NPT_Reference<PLT_CtrlPoint> PLT_CtrlPointReference;
+
+#endif /* _PLT_CONTROL_POINT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltCtrlPointTask.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,201 @@
+/*****************************************************************
+|
+|   Platinum - Control Point Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|    includes
++---------------------------------------------------------------------*/
+#include "PltDeviceHost.h"
+#include "PltCtrlPointTask.h"
+#include "PltCtrlPoint.h"
+#include "PltDatagramStream.h"
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetDescriptionTask::PLT_CtrlPointGetDescriptionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetDescriptionTask::PLT_CtrlPointGetDescriptionTask(const NPT_HttpUrl&       url,
+                                                                 PLT_CtrlPoint*           ctrl_point, 
+                                                                 PLT_DeviceDataReference& device) :
+    PLT_HttpClientSocketTask(new NPT_HttpRequest(url, "GET")), 
+    m_CtrlPoint(ctrl_point), 
+    m_Device(device) 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetDescriptionTask::~PLT_CtrlPointGetDescriptionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetDescriptionTask::~PLT_CtrlPointGetDescriptionTask() 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetDescriptionTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_CtrlPointGetDescriptionTask::ProcessResponse(NPT_Result                    res, 
+                                                 NPT_HttpRequest*              request, 
+                                                 const NPT_HttpRequestContext& context, 
+                                                 NPT_HttpResponse*             response)
+{
+    NPT_COMPILER_UNUSED(request);
+    return m_CtrlPoint->ProcessGetDescriptionResponse(res, context, response, m_Device);
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetSCPDTask::PLT_CtrlPointGetSCPDTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetSCPDTask::PLT_CtrlPointGetSCPDTask(const NPT_HttpUrl&       url,
+                                                   PLT_CtrlPoint*           ctrl_point, 
+                                                   PLT_DeviceDataReference& device) :  
+    PLT_HttpClientSocketTask(new NPT_HttpRequest(url, "GET")), 
+    m_CtrlPoint(ctrl_point), 
+    m_Device(device) 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetSCPDTask::~PLT_CtrlPointGetSCPDTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetSCPDTask::~PLT_CtrlPointGetSCPDTask() 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetSCPDTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_CtrlPointGetSCPDTask::ProcessResponse(NPT_Result                    res, 
+                                          NPT_HttpRequest*              request, 
+                                          const NPT_HttpRequestContext& context, 
+                                          NPT_HttpResponse*             response)
+{
+    NPT_COMPILER_UNUSED(context);
+    return m_CtrlPoint->ProcessGetSCPDResponse(res, request, response, m_Device);
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointInvokeActionTask::PLT_CtrlPointInvokeActionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointInvokeActionTask::PLT_CtrlPointInvokeActionTask(NPT_HttpRequest*     request,
+                                                             PLT_CtrlPoint*       ctrl_point, 
+                                                             PLT_ActionReference& action,
+                                                             void*                userdata) : 
+    PLT_HttpClientSocketTask(request), 
+    m_CtrlPoint(ctrl_point), 
+    m_Action(action), 
+    m_Userdata(userdata)
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointInvokeActionTask::~PLT_CtrlPointInvokeActionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointInvokeActionTask::~PLT_CtrlPointInvokeActionTask() 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointInvokeActionTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_CtrlPointInvokeActionTask::ProcessResponse(NPT_Result                    res, 
+                                               NPT_HttpRequest*              request, 
+                                               const NPT_HttpRequestContext& context, 
+                                               NPT_HttpResponse*             response)
+{
+    NPT_COMPILER_UNUSED(request);
+    NPT_COMPILER_UNUSED(context);
+
+    return m_CtrlPoint->ProcessActionResponse(res, response, m_Action, m_Userdata);
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointHouseKeepingTask::PLT_CtrlPointHouseKeepingTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointHouseKeepingTask::PLT_CtrlPointHouseKeepingTask(PLT_CtrlPoint*   ctrl_point, 
+                                                             NPT_TimeInterval timer) : 
+    m_CtrlPoint(ctrl_point), 
+    m_Timer(timer)
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointHouseKeepingTask::DoRun
++---------------------------------------------------------------------*/
+void  
+PLT_CtrlPointHouseKeepingTask::DoRun() 
+{
+    while (1) {
+        if (m_CtrlPoint) {
+            m_CtrlPoint->DoHouseKeeping();
+        }
+
+        if (IsAborting(m_Timer.m_Seconds*1000)) break;
+    }
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointSubscribeEventTask::PLT_CtrlPointSubscribeEventTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointSubscribeEventTask::PLT_CtrlPointSubscribeEventTask(NPT_HttpRequest* request,
+                                                                 PLT_CtrlPoint*   ctrl_point, 
+                                                                 PLT_Service*     service,
+                                                                 void*            userdata) : 
+    PLT_HttpClientSocketTask(request), 
+    m_CtrlPoint(ctrl_point), 
+    m_Service(service), 
+    m_Userdata(userdata) 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointSubscribeEventTask::~PLT_CtrlPointSubscribeEventTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointSubscribeEventTask::~PLT_CtrlPointSubscribeEventTask() 
+{
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointSubscribeEventTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_CtrlPointSubscribeEventTask::ProcessResponse(NPT_Result                    res, 
+                                                 NPT_HttpRequest*              request, 
+                                                 const NPT_HttpRequestContext& context, 
+                                                 NPT_HttpResponse*             response)
+{
+    NPT_COMPILER_UNUSED(request);
+    NPT_COMPILER_UNUSED(context);
+
+    return m_CtrlPoint->ProcessSubscribeResponse(res, response, m_Service, m_Userdata);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltCtrlPointTask.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,167 @@
+/*****************************************************************
+|
+|   Platinum - Control Point Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_CONTROL_POINT_TASK_H_
+#define _PLT_CONTROL_POINT_TASK_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpClientTask.h"
+#include "PltDatagramStream.h"
+#include "PltDeviceData.h"
+#include "PltCtrlPoint.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_Action;
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointGetDescriptionTask class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointGetDescriptionTask : public PLT_HttpClientSocketTask
+{
+public:
+    PLT_CtrlPointGetDescriptionTask(const NPT_HttpUrl&       url,
+                                    PLT_CtrlPoint*           ctrl_point, 
+                                    PLT_DeviceDataReference& device);
+    virtual ~PLT_CtrlPointGetDescriptionTask();
+
+protected:
+    // PLT_HttpClientSocketTask methods
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response);
+
+protected:
+    PLT_CtrlPoint*          m_CtrlPoint;
+    PLT_DeviceDataReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointGetSCPDTask class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointGetSCPDTask : public PLT_HttpClientSocketTask
+{
+public:
+    PLT_CtrlPointGetSCPDTask(const NPT_HttpUrl&       url,
+                             PLT_CtrlPoint*           ctrl_point, 
+                             PLT_DeviceDataReference& m_Device);
+    virtual ~PLT_CtrlPointGetSCPDTask();
+
+protected:
+    // PLT_HttpClientSocketTask methods
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response);   
+
+protected:
+    PLT_CtrlPoint*          m_CtrlPoint;
+    PLT_DeviceDataReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointInvokeActionTask class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointInvokeActionTask : public PLT_HttpClientSocketTask
+{
+public:
+    PLT_CtrlPointInvokeActionTask(NPT_HttpRequest*     request,
+                                  PLT_CtrlPoint*       ctrl_point, 
+                                  PLT_ActionReference& action,
+                                  void*                userdata);
+    virtual ~PLT_CtrlPointInvokeActionTask();
+
+protected:
+    // PLT_HttpClientSocketTask methods
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response);   
+
+protected:
+    PLT_CtrlPoint*      m_CtrlPoint;
+    PLT_ActionReference m_Action;
+    void*               m_Userdata;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointHouseKeepingTask class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointHouseKeepingTask : public PLT_ThreadTask
+{
+public:
+    PLT_CtrlPointHouseKeepingTask(PLT_CtrlPoint*   ctrl_point, 
+                                  NPT_TimeInterval timer = NPT_TimeInterval(10, 0));
+
+protected:
+    ~PLT_CtrlPointHouseKeepingTask() {}
+
+    // PLT_ThreadTask methods
+    virtual void DoRun();
+
+protected:
+    PLT_CtrlPoint*   m_CtrlPoint;
+    NPT_TimeInterval m_Timer;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_CtrlPointSubscribeEventTask class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointSubscribeEventTask : public PLT_HttpClientSocketTask
+{
+public:
+    PLT_CtrlPointSubscribeEventTask(NPT_HttpRequest* request,
+                                    PLT_CtrlPoint*   ctrl_point, 
+                                    PLT_Service*     service,
+                                    void*            userdata);
+    virtual ~PLT_CtrlPointSubscribeEventTask();
+    
+protected:
+    // PLT_HttpClientSocketTask methods
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response);
+
+protected:
+    PLT_CtrlPoint*  m_CtrlPoint;
+    PLT_Service*    m_Service;
+    void*           m_Userdata;
+};
+
+#endif /* _PLT_CONTROL_POINT_TASK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDatagramStream.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,145 @@
+/*****************************************************************
+|
+|   Platinum - Datagram Stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltDatagramStream.h"
+
+/*----------------------------------------------------------------------
+|   PLT_InputDatagramStream::PLT_InputDatagramStream
++---------------------------------------------------------------------*/
+PLT_InputDatagramStream::PLT_InputDatagramStream(NPT_UdpSocket* socket) : 
+    m_Socket(socket)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_InputDatagramStream::~PLT_InputDatagramStream
++---------------------------------------------------------------------*/
+PLT_InputDatagramStream::~PLT_InputDatagramStream()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_InputDatagramStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_InputDatagramStream::Read(void*     buffer, 
+                              NPT_Size  bytes_to_read, 
+                              NPT_Size* bytes_read /*= 0*/)
+{
+
+    if (bytes_read) *bytes_read = 0;
+
+    if (bytes_to_read == 0) {
+        return NPT_SUCCESS;
+    }
+
+    NPT_DataBuffer data_buffer(buffer, bytes_to_read, false);
+
+    // read data into it now
+    NPT_SocketAddress addr;
+    NPT_Result res = m_Socket->Receive(data_buffer, &addr);
+
+    // update info
+    m_Socket->GetInfo(m_Info);
+    m_Info.remote_address = addr;
+
+    if (bytes_read) *bytes_read = data_buffer.GetDataSize();
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_OutputDatagramStream::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_InputDatagramStream::GetInfo(NPT_SocketInfo& info)
+{
+    info = m_Info;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_OutputDatagramStream::PLT_OutputDatagramStream
++---------------------------------------------------------------------*/
+PLT_OutputDatagramStream::PLT_OutputDatagramStream(NPT_UdpSocket*   socket, 
+                                                   NPT_Size         size, 
+                                                   const NPT_SocketAddress* address) : 
+    m_Socket(socket),
+    m_Address(address?new NPT_SocketAddress(address->GetIpAddress(), address->GetPort()):NULL)
+{
+    m_Buffer.SetBufferSize(size);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_OutputDatagramStream::~PLT_OutputDatagramStream
++---------------------------------------------------------------------*/
+PLT_OutputDatagramStream::~PLT_OutputDatagramStream()
+{
+    delete m_Address;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_OutputDatagramStream::Write
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_OutputDatagramStream::Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written /* = NULL */)
+{
+    // calculate if we need to increase the buffer
+    NPT_Int32 overflow = bytes_to_write - m_Buffer.GetBufferSize() + m_Buffer.GetDataSize();
+    if (overflow > 0) {
+        m_Buffer.Reserve(m_Buffer.GetBufferSize() + overflow);
+    }
+    // copy data in place at the end of what we have there already
+    NPT_CopyMemory(m_Buffer.UseData() + m_Buffer.GetDataSize(), buffer, bytes_to_write);
+    m_Buffer.SetDataSize(m_Buffer.GetDataSize() + bytes_to_write);
+
+    if (bytes_written) *bytes_written = bytes_to_write;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_OutputDatagramStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_OutputDatagramStream::Flush()
+{
+    // send buffer now
+    m_Socket->Send(m_Buffer, m_Address);
+
+    // reset buffer
+    m_Buffer.SetDataSize(0);
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDatagramStream.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,99 @@
+/*****************************************************************
+|
+|   Platinum - Datagram Stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_DATAGRAM_H_
+#define _PLT_DATAGRAM_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   PLT_InputDatagramStream
++---------------------------------------------------------------------*/
+class PLT_InputDatagramStream : public NPT_InputStream
+{
+public:
+    // methods
+    PLT_InputDatagramStream(NPT_UdpSocket* socket);
+    virtual ~PLT_InputDatagramStream();
+    
+    NPT_Result GetInfo(NPT_SocketInfo& info);
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read = 0);
+
+    NPT_Result Seek(NPT_Position offset) { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result Skip(NPT_Size offset) { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result Tell(NPT_Position& offset){ NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result GetSize(NPT_LargeSize& size)   { NPT_COMPILER_UNUSED(size); return NPT_FAILURE; }
+    NPT_Result GetAvailable(NPT_LargeSize& available) { NPT_COMPILER_UNUSED(available); return NPT_FAILURE; }
+        
+protected:
+    NPT_UdpSocket*      m_Socket;
+    NPT_SocketInfo      m_Info;
+};
+
+typedef NPT_Reference<PLT_InputDatagramStream> PLT_InputDatagramStreamReference;
+
+/*----------------------------------------------------------------------
+|   PLT_OutputDatagramStream
++---------------------------------------------------------------------*/
+class PLT_OutputDatagramStream : public NPT_OutputStream
+{
+public:
+    // methods
+    PLT_OutputDatagramStream(NPT_UdpSocket*           socket, 
+                             NPT_Size                 size = 4096,
+                             const NPT_SocketAddress* address = NULL);
+    virtual ~PLT_OutputDatagramStream();
+
+    // NPT_OutputStream methods
+    NPT_Result Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written = NULL);
+    NPT_Result Flush();
+
+    NPT_Result Seek(NPT_Position offset)  { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result Tell(NPT_Position& offset) { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+
+protected:
+    NPT_UdpSocket*     m_Socket;
+    NPT_DataBuffer     m_Buffer;
+    NPT_SocketAddress* m_Address;
+};
+
+typedef NPT_Reference<PLT_OutputDatagramStream> PLT_OutputDatagramStreamReference;
+
+#endif /* _PLT_DATAGRAM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDeviceData.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,618 @@
+/*****************************************************************
+|
+|   Platinum - Device Data
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltDeviceData.h"
+#include "PltService.h"
+#include "PltUPnP.h"
+#include "PltXmlHelper.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.devicedata")
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::PLT_DeviceData
++---------------------------------------------------------------------*/
+PLT_DeviceData::PLT_DeviceData(NPT_HttpUrl      description_url,
+                               const char*      uuid,
+                               NPT_TimeInterval lease_time,
+                               const char*      device_type,
+                               const char*      friendly_name) :
+    m_UUID(uuid),
+    m_URLDescription(description_url),
+    m_DeviceType(device_type),
+    m_FriendlyName(friendly_name)
+{
+    if (uuid == NULL || strlen(uuid) == 0) {
+        PLT_UPnPMessageHelper::GenerateGUID(m_UUID);
+    }
+
+    SetLeaseTime(lease_time);
+    SetURLBase(m_URLDescription);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::~PLT_DeviceData
++---------------------------------------------------------------------*/
+PLT_DeviceData::~PLT_DeviceData()
+{
+    Cleanup();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::Cleanup
++---------------------------------------------------------------------*/
+void
+PLT_DeviceData::Cleanup()
+{
+    m_Services.Apply(NPT_ObjectDeleter<PLT_Service>());
+    m_Services.Clear();
+    m_EmbeddedDevices.Clear();
+    m_Icons.Clear();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::SetDescriptionUrl
++---------------------------------------------------------------------*/
+/*NPT_Result
+PLT_DeviceData::SetDescriptionUrl(NPT_HttpUrl& url)
+{
+    NPT_CHECK_FATAL(SetURLBase(url));
+    m_URLDescription = url;
+    return NPT_SUCCESS;
+}*/
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::GetDescriptionUrl
++---------------------------------------------------------------------*/
+NPT_String
+PLT_DeviceData::GetDescriptionUrl(const char* bind_addr)
+{
+    NPT_HttpUrl url = m_URLDescription;
+
+    // override host
+    if (bind_addr) url.SetHost(bind_addr);
+    return url.ToString();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::SetURLBase
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetURLBase(NPT_HttpUrl& url) 
+{
+    // we're assuming param passed to be relative (Host/port not different than description)
+    m_URLBasePath = url.GetPath();
+
+    // remove trailing file according to RFC 2396
+    if (!m_URLBasePath.EndsWith("/")) {
+        int index = m_URLBasePath.ReverseFind('/');
+        if (index < 0) return NPT_FAILURE;
+        m_URLBasePath.SetLength(index+1);
+    }
+
+    return NPT_SUCCESS;
+}    
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::GetURLBase
++---------------------------------------------------------------------*/
+NPT_HttpUrl
+PLT_DeviceData::GetURLBase()
+{
+    return NPT_HttpUrl(m_URLDescription.GetHost(),
+                       m_URLDescription.GetPort(),
+                       m_URLBasePath);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::GetIconUrl
++---------------------------------------------------------------------*/
+NPT_String
+PLT_DeviceData::GetIconUrl(const char* mimetype, 
+                           NPT_Int32   maxsize, 
+                           NPT_Int32   maxdepth)
+{
+    PLT_DeviceIcon icon;
+
+    for (NPT_Cardinal i=0; i<m_Icons.GetItemCount(); i++) {
+        if ((mimetype && m_Icons[i].m_MimeType != mimetype) ||
+            (maxsize  && m_Icons[i].m_Width > maxsize)      ||
+            (maxsize  && m_Icons[i].m_Height > maxsize)     ||
+            (maxdepth && m_Icons[i].m_Depth > maxdepth))
+            continue;
+
+        // pick the biggest and better resolution we can
+        if (icon.m_Width  >= m_Icons[i].m_Width  ||
+            icon.m_Height >= m_Icons[i].m_Height ||
+            icon.m_Depth  >= m_Icons[i].m_Depth  ||
+            m_Icons[i].m_UrlPath.IsEmpty())
+            continue;
+
+        icon = m_Icons[i];
+    }
+
+    if (icon.m_UrlPath == "") return "";
+
+    // make absolut path from url base if necessary
+    NPT_HttpUrl url(icon.m_UrlPath);
+    if (!url.IsValid()) {
+        url = GetURLBase();
+        if (icon.m_UrlPath.StartsWith("/")) {
+            url.SetPathPlus(icon.m_UrlPath);
+        } else {
+            url.SetPathPlus(url.GetPath() + icon.m_UrlPath);
+        }
+    }
+
+    return url.ToString();
+}
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::SetLeaseTime
++---------------------------------------------------------------------*/
+NPT_Result   
+PLT_DeviceData::SetLeaseTime(NPT_TimeInterval lease_time) 
+{
+    m_LeaseTime = lease_time;
+    NPT_System::GetCurrentTimeStamp(m_LeaseTimeLastUpdate);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::GetLeaseTimeLastUpdate
++---------------------------------------------------------------------*/
+NPT_TimeStamp 
+PLT_DeviceData::GetLeaseTimeLastUpdate() 
+{
+    return m_LeaseTimeLastUpdate;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::ToLog
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::ToLog(int level /* = NPT_LOG_LEVEL_FINE */)
+{
+    NPT_COMPILER_UNUSED(level);
+
+    NPT_StringOutputStreamReference stream(new NPT_StringOutputStream);
+    stream->WriteString("Device GUID: ");
+    stream->WriteString((const char*)m_UUID);
+
+    stream->WriteString("Device Type: ");
+    stream->WriteString((const char*)m_DeviceType);
+
+    stream->WriteString("Device Base Url: ");
+    stream->WriteString((const char*)GetURLBase().ToString());
+
+    stream->WriteString("Device Friendly Name: ");
+    stream->WriteString((const char*)m_FriendlyName);
+
+    NPT_LOG_1(level, "%s", (const char*)stream->GetString());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::AddDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::AddDevice(PLT_DeviceDataReference& device)
+{
+    device->m_ParentUUID = m_UUID;
+    m_EmbeddedDevices.Add(device);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::AddService
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::AddService(PLT_Service* service)
+{
+    if (service->m_ServiceType == "" ||
+        service->m_ServiceID   == "" ||
+        service->m_SCPDURL     == "" ||
+        service->m_ControlURL  == "" ||
+        service->m_EventSubURL == "") {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return m_Services.Add(service);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_GetDescriptionIterator class
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_GetDescriptionIterator
+{
+public:
+    PLT_GetDescriptionIterator<T>(NPT_XmlElementNode* parent) :
+      m_Parent(parent) {}
+
+      NPT_Result operator()(T& data) const {
+          return data->GetDescription(m_Parent);
+      }
+
+private:
+    NPT_XmlElementNode* m_Parent;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::ToXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::GetDescription(NPT_XmlElementNode* root, NPT_XmlElementNode** device_out)
+{
+    NPT_XmlElementNode* device = new NPT_XmlElementNode("device");
+    if (device_out) {
+        *device_out = device;
+    }
+
+    NPT_CHECK_SEVERE(root->AddChild(device));
+
+    // device properties
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "deviceType", m_DeviceType));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "friendlyName", m_FriendlyName));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "manufacturer", m_Manufacturer));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "manufacturerURL", m_ManufacturerURL));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelDescription", m_ModelDescription));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelName", m_ModelName));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelURL", m_ModelURL));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelNumber", m_ModelNumber));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "serialNumber", m_SerialNumber));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "UDN", "uuid:" + m_UUID));
+    
+    if (!m_PresentationURL.IsEmpty()) {
+        NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "presentationURL", m_PresentationURL));
+    }
+    
+    // Extra info not UPnP specs
+    NPT_CHECK(OnAddExtraInfo(device));
+
+    // PS3 support
+    if (!m_DlnaDoc.IsEmpty()) {
+        NPT_XmlElementNode* dlnadoc = new NPT_XmlElementNode("dlna", "X_DLNADOC");
+        dlnadoc->AddText(m_DlnaDoc);
+        device->AddChild(dlnadoc);
+    }
+    if (!m_DlnaCap.IsEmpty()) {
+        NPT_XmlElementNode* dlnacap = new NPT_XmlElementNode("dlna", "X_DLNACAP");
+        dlnacap->AddText(m_DlnaCap);
+        device->AddChild(dlnacap);
+    }
+
+    // icons
+    if (m_Icons.GetItemCount()) {
+        NPT_XmlElementNode* icons = new NPT_XmlElementNode("iconList");
+        NPT_CHECK_SEVERE(device->AddChild(icons));
+        for (NPT_Cardinal i=0; i<m_Icons.GetItemCount(); i++) {
+            NPT_XmlElementNode* icon = new NPT_XmlElementNode("icon");
+            NPT_CHECK_SEVERE(icons->AddChild(icon));
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "mimetype", m_Icons[i].m_MimeType));
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "width", NPT_String::FromInteger(m_Icons[i].m_Width)));
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "height", NPT_String::FromInteger(m_Icons[i].m_Height)));
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "depth", NPT_String::FromInteger(m_Icons[i].m_Depth)));
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "url", m_Icons[i].m_UrlPath));
+        }
+    }
+
+    // services
+    NPT_XmlElementNode* services = new NPT_XmlElementNode("serviceList");
+    NPT_CHECK_SEVERE(device->AddChild(services));
+    NPT_CHECK_SEVERE(m_Services.ApplyUntil(PLT_GetDescriptionIterator<PLT_Service*>(services), 
+                                           NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+    // PS3 support
+    NPT_XmlElementNode* aggr = new NPT_XmlElementNode("av", "aggregationFlags");
+    NPT_CHECK_SEVERE(aggr->SetNamespaceUri("av", "urn:schemas-sonycom:av"));
+    aggr->AddText("10");
+    device->AddChild(aggr);
+
+    // embedded devices
+    if (m_EmbeddedDevices.GetItemCount()) {
+        NPT_XmlElementNode* deviceList = new NPT_XmlElementNode("deviceList");
+        NPT_CHECK_SEVERE(device->AddChild(deviceList));
+
+        NPT_CHECK_SEVERE(m_EmbeddedDevices.ApplyUntil(
+            PLT_GetDescriptionIterator<PLT_DeviceDataReference>(deviceList), 
+            NPT_UntilResultNotEquals(NPT_SUCCESS)));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::GetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::GetDescription(NPT_String& desc)
+{
+    NPT_Result res;
+    NPT_XmlElementNode* spec = NULL;
+    NPT_XmlElementNode* root = new NPT_XmlElementNode("root");
+
+    NPT_CHECK_LABEL_SEVERE(res = root->SetNamespaceUri("", "urn:schemas-upnp-org:device-1-0"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = root->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"), cleanup);
+
+    // add spec version
+    spec = new NPT_XmlElementNode("specVersion");
+    NPT_CHECK_LABEL_SEVERE(res = root->AddChild(spec), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "major", "1"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "minor", "0"), cleanup);
+
+    // get device xml
+    NPT_CHECK_LABEL_SEVERE(res = GetDescription(root), cleanup);
+
+    // serialize node
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*root, desc), cleanup);
+
+cleanup:
+    delete root;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::SetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetDescription(const char*          description, 
+                               const NPT_IpAddress& local_iface_ip)
+{
+    NPT_XmlParser       parser;
+    NPT_XmlNode*        tree = NULL;
+    NPT_Result          res;
+    NPT_XmlElementNode* root = NULL;
+    NPT_String          URLBase;
+    
+    res = parser.Parse(description, tree);
+    NPT_CHECK_LABEL_SEVERE(res, cleanup);
+
+    root = tree->AsElementNode();
+    if (!root || 
+        root->GetTag() != "root" || 
+        !root->GetNamespace() || 
+        *root->GetNamespace() != "urn:schemas-upnp-org:device-1-0") {
+        NPT_LOG_INFO_1("root namespace is invalid: %s", 
+            (root&&root->GetNamespace())?root->GetNamespace()->GetChars():"null");
+        NPT_CHECK_LABEL_SEVERE(NPT_FAILURE, cleanup);
+    }
+
+    // look for optional URLBase element
+    if (NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(root, "URLBase", URLBase))) {
+        NPT_HttpUrl url(URLBase);
+        
+        if (!url.IsValid()) {
+            NPT_CHECK_LABEL_SEVERE(NPT_FAILURE, cleanup);
+        }
+
+        SetURLBase(url);
+    }
+
+    // at least one root device child element is required
+    NPT_XmlElementNode* device;
+    if (!(device = PLT_XmlHelper::GetChild(root, "device"))) {
+        NPT_CHECK_LABEL_SEVERE(NPT_FAILURE, cleanup);
+    }
+
+    res = SetDescriptionDevice(device);
+
+cleanup:
+    // delete the tree
+    delete tree;
+
+    m_LocalIfaceIp = local_iface_ip;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::SetDescriptionDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetDescriptionDevice(NPT_XmlElementNode* device_node)
+{
+    NPT_Result res;
+
+    NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node, "deviceType", m_DeviceType));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node, "UDN", m_UUID));
+
+    // jump uuid:, we should probably check first
+    m_UUID = ((const char*)m_UUID)+5;
+
+    // optional attributes
+    PLT_XmlHelper::GetChildText(device_node, "friendlyName", m_FriendlyName);
+    PLT_XmlHelper::GetChildText(device_node, "manufacturer", m_Manufacturer);
+    PLT_XmlHelper::GetChildText(device_node, "manufacturerURL", m_ManufacturerURL);
+    PLT_XmlHelper::GetChildText(device_node, "modelDescription", m_ModelDescription);
+    PLT_XmlHelper::GetChildText(device_node, "modelName", m_ModelName);
+    PLT_XmlHelper::GetChildText(device_node, "modelNumber", m_ModelNumber);
+    PLT_XmlHelper::GetChildText(device_node, "serialNumber", m_SerialNumber);
+
+    // enumerate icons
+    NPT_XmlElementNode* iconList = PLT_XmlHelper::GetChild(device_node, "iconList");
+    if (iconList) {
+        NPT_Array<NPT_XmlElementNode*> icons;
+        PLT_XmlHelper::GetChildren(iconList, icons, "icon");
+
+        for (NPT_Cardinal k=0 ; k<icons.GetItemCount(); k++) {
+            PLT_DeviceIcon icon;
+            NPT_String integer, height, depth;
+
+            PLT_XmlHelper::GetChildText(icons[k], "mimetype", icon.m_MimeType);
+            PLT_XmlHelper::GetChildText(icons[k], "url", icon.m_UrlPath);
+
+            if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "width", integer)))
+                NPT_ParseInteger32(integer, icon.m_Width);
+            if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "height", integer)))
+                NPT_ParseInteger32(integer, icon.m_Height);
+            if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "depth", integer)))
+                NPT_ParseInteger32(integer, icon.m_Depth);
+
+            m_Icons.Add(icon);
+        }
+    }
+
+    // enumerate device services
+    NPT_XmlElementNode* serviceList = PLT_XmlHelper::GetChild(device_node, "serviceList");
+    if (serviceList) {
+        NPT_Array<NPT_XmlElementNode*> services;
+        PLT_XmlHelper::GetChildren(serviceList, services, "service");
+        for( int k = 0 ; k < (int)services.GetItemCount(); k++) {    
+            PLT_Service* service = new PLT_Service(this);
+            PLT_XmlHelper::GetChildText(services[k], "serviceType", service->m_ServiceType);
+            PLT_XmlHelper::GetChildText(services[k], "serviceId", service->m_ServiceID);
+            PLT_XmlHelper::GetChildText(services[k], "SCPDURL", service->m_SCPDURL);
+            PLT_XmlHelper::GetChildText(services[k], "controlURL", service->m_ControlURL);
+            PLT_XmlHelper::GetChildText(services[k], "eventSubURL", service->m_EventSubURL);
+            if (NPT_FAILED(res = AddService(service))) {
+                delete service;
+                return res;
+            }
+        }
+    }
+
+    // enumerate embedded devices
+    NPT_XmlElementNode* deviceList = PLT_XmlHelper::GetChild(device_node, "deviceList");
+    if (deviceList) {
+        NPT_Array<NPT_XmlElementNode*> devices;
+        PLT_XmlHelper::GetChildren(deviceList, devices, "device");
+        for( int k = 0 ; k < (int)devices.GetItemCount(); k++) {    
+            PLT_DeviceDataReference device(new PLT_DeviceData(m_URLDescription, "", m_LeaseTime));
+            NPT_CHECK_SEVERE(device->SetDescriptionDevice(devices[k]));
+            AddDevice(device);
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::FindEmbeddedDeviceByType
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindEmbeddedDeviceByType(const char*              type, 
+                                         PLT_DeviceDataReference& device)
+{
+    return NPT_ContainerFind(m_EmbeddedDevices, 
+                             PLT_DeviceDataFinderByType(type), 
+                             device);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::FindServiceById
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceById(const char* id, PLT_Service*& service)
+{
+    return NPT_ContainerFind(m_Services, 
+                             PLT_ServiceIDFinder(id),
+                             service);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::FindServiceByType
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByType(const char* type, PLT_Service*& service)
+{
+    return NPT_ContainerFind(m_Services, 
+                             PLT_ServiceTypeFinder(type), 
+                             service);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::FindServiceByDescriptionURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByDescriptionURI(const char*   uri, 
+                                            PLT_Service*& service)
+{
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Services, 
+                                        PLT_ServiceSCPDURLFinder(uri), 
+                                        service))) {
+        return NPT_SUCCESS;
+    }
+
+    for (int i=0; i < (int)m_EmbeddedDevices.GetItemCount(); i++) {
+        if (NPT_SUCCEEDED(NPT_ContainerFind(m_EmbeddedDevices[i]->m_Services, 
+                                            PLT_ServiceSCPDURLFinder(uri), 
+                                            service)))
+            return NPT_SUCCESS;
+    }
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::FindServiceByControlURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByControlURI(const char*   uri, 
+                                        PLT_Service*& service)
+{
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Services, 
+                                        PLT_ServiceControlURLFinder(uri), 
+                                        service))) {
+        return NPT_SUCCESS;
+    }
+
+    for (int i=0; i < (int)m_EmbeddedDevices.GetItemCount(); i++) {
+        if (NPT_SUCCEEDED(NPT_ContainerFind(m_EmbeddedDevices[i]->m_Services, 
+                                            PLT_ServiceControlURLFinder(uri), 
+                                            service)))
+            return NPT_SUCCESS;
+    }
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData::FindServiceByEventSubURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByEventSubURI(const char*   uri, 
+                                         PLT_Service*& service)
+{       
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Services, 
+                                        PLT_ServiceEventSubURLFinder(uri), 
+                                        service))) {
+        return NPT_SUCCESS;
+    }
+
+    for (int i=0; i < (int)m_EmbeddedDevices.GetItemCount(); i++) {
+        if (NPT_SUCCEEDED(NPT_ContainerFind(m_EmbeddedDevices[i]->m_Services, 
+                                            PLT_ServiceEventSubURLFinder(uri), 
+                                            service)))
+            return NPT_SUCCESS;
+    }
+    return NPT_FAILURE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDeviceData.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,211 @@
+/*****************************************************************
+|
+|   Platinum - Device Data
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_DEVICE_DATA_H_
+#define _PLT_DEVICE_DATA_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_Service;
+class PLT_DeviceData;
+
+typedef NPT_Reference<PLT_DeviceData> PLT_DeviceDataReference;
+typedef NPT_List<PLT_DeviceDataReference> PLT_DeviceDataReferenceList;
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceIcon class
++---------------------------------------------------------------------*/
+class PLT_DeviceIcon
+{
+public:
+    PLT_DeviceIcon(const char* mimetype = "", 
+                   NPT_Int32   width = 0, 
+                   NPT_Int32   height = 0,
+                   NPT_Int32   depth = 0,
+                   const char* urlpath = "") :
+        m_MimeType(mimetype),
+        m_Width(width),
+        m_Height(height),
+        m_Depth(depth),
+        m_UrlPath(urlpath) {}
+    virtual ~PLT_DeviceIcon() {}
+   
+    NPT_String  m_MimeType;
+    NPT_Int32   m_Width;
+    NPT_Int32   m_Height;
+    NPT_Int32   m_Depth;
+    NPT_String  m_UrlPath;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceData class
++---------------------------------------------------------------------*/
+class PLT_DeviceData
+{
+public:
+    PLT_DeviceData(
+        NPT_HttpUrl      description_url = NPT_HttpUrl(NULL, 0, "/"), 
+        const char*      uuid = "",
+        NPT_TimeInterval lease_time = NPT_TimeInterval(1800, 0),
+        const char*      device_type = "",
+        const char*      friendly_name = "");
+
+    /* Getters */
+    virtual NPT_Result  GetDescription(NPT_String& desc);
+    virtual NPT_String  GetDescriptionUrl(const char* bind_addr = NULL);
+    virtual NPT_HttpUrl GetURLBase();
+    virtual NPT_Result  GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** device = NULL);
+    virtual NPT_String  GetIconUrl(const char* mimetype = NULL, NPT_Int32 maxsize = 0, NPT_Int32 maxdepth = 0);
+
+    const NPT_TimeInterval& GetLeaseTime()    const { return m_LeaseTime;        }
+    const NPT_String&   GetUUID()             const { return m_UUID;             }
+    const NPT_String&   GetFriendlyName()     const { return m_FriendlyName;     }
+    const NPT_String&   GetType()             const { return m_DeviceType;       }
+    const NPT_String&   GetModelDescription() const { return m_ModelDescription; }
+    const NPT_String&   GetParentUUID()       const { return m_ParentUUID;       }
+
+    const NPT_Array<PLT_Service*>&            GetServices()        const { return m_Services; }
+    const NPT_Array<PLT_DeviceDataReference>& GetEmbeddedDevices() const { return m_EmbeddedDevices; }
+
+    NPT_Result FindEmbeddedDeviceByType(const char* type, PLT_DeviceDataReference& device);
+    NPT_Result FindServiceById(const char* id, PLT_Service*& service);
+    NPT_Result FindServiceByType(const char* type, PLT_Service*& service);
+    NPT_Result FindServiceByDescriptionURI(const char* uri, PLT_Service*& service);
+    NPT_Result FindServiceByControlURI(const char* uri, PLT_Service*& service);
+    NPT_Result FindServiceByEventSubURI(const char* uri, PLT_Service*& service);
+
+    /* called by PLT_Device subclasses */
+    NPT_Result AddDevice(PLT_DeviceDataReference& device);
+    NPT_Result AddService(PLT_Service* service);
+
+    NPT_Result ToLog(int level = NPT_LOG_LEVEL_FINE);
+
+protected:
+    virtual ~PLT_DeviceData();
+    virtual void       Cleanup();
+    virtual NPT_Result OnAddExtraInfo(NPT_XmlElementNode* /*device_node*/) { return NPT_SUCCESS; }
+
+private:
+    /* called by PLT_CtrlPoint when new device is discovered */
+    NPT_Result    SetURLBase(NPT_HttpUrl& url_base);
+    NPT_TimeStamp GetLeaseTimeLastUpdate();
+    NPT_Result    SetLeaseTime(NPT_TimeInterval lease_time);
+    NPT_Result    SetDescription(const char*          szDescription, 
+                                 const NPT_IpAddress& local_iface_ip);
+    NPT_Result    SetDescriptionDevice(NPT_XmlElementNode* device_node);
+
+public:
+    NPT_String m_Manufacturer;
+    NPT_String m_ManufacturerURL;
+    NPT_String m_ModelDescription;
+    NPT_String m_ModelName;
+    NPT_String m_ModelNumber;
+    NPT_String m_ModelURL;
+    NPT_String m_SerialNumber;
+    NPT_String m_UPC;
+    NPT_String m_PresentationURL;
+    NPT_String m_DlnaDoc;
+    NPT_String m_DlnaCap;
+
+protected:
+    friend class NPT_Reference<PLT_DeviceData>;
+    friend class PLT_DeviceDataFinder;
+    friend class PLT_DeviceDataFinderByType;
+    friend class PLT_CtrlPoint;
+    friend class PLT_DeviceReadyIterator;
+    friend class PLT_DeviceHost;
+
+    //members
+    NPT_String                         m_ParentUUID;
+    NPT_String                         m_UUID;
+    NPT_HttpUrl                        m_URLDescription;
+    NPT_String                         m_URLBasePath;
+    NPT_String                         m_DeviceType;
+    NPT_String                         m_FriendlyName;
+    NPT_TimeInterval                   m_LeaseTime;
+    NPT_TimeStamp                      m_LeaseTimeLastUpdate;
+    NPT_Array<PLT_Service*>            m_Services;
+    NPT_Array<PLT_DeviceDataReference> m_EmbeddedDevices;
+    NPT_Array<PLT_DeviceIcon>          m_Icons;
+
+    /* IP address of interface used when retrieving device description.
+       We need the info for the control point subscription callback */
+    NPT_IpAddress                      m_LocalIfaceIp; 
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceDataFinder
++---------------------------------------------------------------------*/
+class PLT_DeviceDataFinder
+{
+public:
+    // methods
+    PLT_DeviceDataFinder(const char* uuid) : m_UUID(uuid) {}
+    virtual ~PLT_DeviceDataFinder() {}
+
+    bool operator()(const PLT_DeviceDataReference& data) const {
+        return data->m_UUID.Compare(m_UUID, true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String m_UUID;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceDataFinderByType
++---------------------------------------------------------------------*/
+class PLT_DeviceDataFinderByType
+{
+public:
+    // methods
+    PLT_DeviceDataFinderByType(const char* type) : m_Type(type) {}
+    virtual ~PLT_DeviceDataFinderByType() {}
+
+    bool operator()(const PLT_DeviceDataReference& data) const {
+        return data->m_DeviceType.Compare(m_Type, true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String m_Type;
+};
+
+#endif /* _PLT_DEVICE_DATA_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDeviceHost.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,775 @@
+/*****************************************************************
+|
+|   Platinum - Device Host
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltService.h"
+#include "PltDeviceHost.h"
+#include "PltUPnP.h"
+#include "PltXmlHelper.h"
+#include "PltSsdp.h"
+#include "PltHttpServer.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.devicehost")
+
+/*----------------------------------------------------------------------
+|   typedef
++---------------------------------------------------------------------*/
+typedef PLT_HttpRequestHandler<PLT_DeviceHost> PLT_HttpDeviceHostRequestHandler;
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::PLT_DeviceHost
++---------------------------------------------------------------------*/
+PLT_DeviceHost::PLT_DeviceHost(const char*  description_path /* = "/" */, 
+                               const char*  uuid             /* = "" */,
+                               const char*  device_type      /* = "" */,
+                               const char*  friendly_name    /* = "" */,
+                               bool         show_ip          /* = false */,
+                               NPT_UInt16   port             /* = 0 */,
+                               bool         port_rebind      /* = false */) :
+    PLT_DeviceData(NPT_HttpUrl(NULL, 0, description_path), 
+                   uuid, 
+                   NPT_TimeInterval(1800, 0), 
+                   device_type, 
+                   friendly_name), 
+    m_HttpServer(NULL),
+    m_Broadcast(false),
+    m_Port(port),
+    m_PortRebind(port_rebind)
+{
+    if (show_ip) {
+        NPT_List<NPT_String> ips;
+        PLT_UPnPMessageHelper::GetIPAddresses(ips);
+        if (ips.GetItemCount()) {
+            m_FriendlyName += " (" + *ips.GetFirstItem() + ")";
+        }
+    }
+}
+    
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::~PLT_DeviceHost
++---------------------------------------------------------------------*/
+PLT_DeviceHost::~PLT_DeviceHost() 
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::AddIcon
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_DeviceHost::AddIcon(const PLT_DeviceIcon& icon, const char* filepath)
+{
+    NPT_HttpFileRequestHandler* icon_handler = 
+        new NPT_HttpFileRequestHandler(icon.m_UrlPath, filepath);
+    m_HttpServer->AddRequestHandler(icon_handler, icon.m_UrlPath, false);
+    m_RequestHandlers.Add(icon_handler);
+    return m_Icons.Add(icon);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::AddIcon
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_DeviceHost::AddIcon(const PLT_DeviceIcon& icon, 
+                        const void*           data, 
+                        NPT_Size              size, 
+                        bool                  copy /* = true */)
+{
+    NPT_HttpStaticRequestHandler* icon_handler = 
+        new NPT_HttpStaticRequestHandler(
+        data, 
+        size,
+        icon.m_MimeType,
+        copy);
+    m_HttpServer->AddRequestHandler(icon_handler, icon.m_UrlPath, false);
+    m_RequestHandlers.Add(icon_handler);
+    return m_Icons.Add(icon);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::SetupIcons
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SetupIcons()
+{
+    AddIcon(
+        PLT_DeviceIcon("image/jpeg", 120, 120, 24, "/images/platinum-120x120.jpg"),
+        "platinum-120x120.jpg");
+    AddIcon(
+        PLT_DeviceIcon("image/jpeg", 48, 48, 24, "/images/platinum-48x48.jpg"),
+        "platinum-48x48.jpg");
+    AddIcon(
+        PLT_DeviceIcon("image/png", 120, 120, 24, "/images/platinum-120x120.png"),
+        "platinum-120x120.png");
+    AddIcon(
+        PLT_DeviceIcon("image/png", 48, 48, 24, "/images/platinum-48x48.png"),
+        "platinum-48x48.png");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::SetupDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SetupDevice()
+{
+    NPT_CHECK_WARNING(SetupIcons());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::SetupServiceSCPDHandler
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SetupServiceSCPDHandler(PLT_Service* service)
+{    
+    NPT_HttpUrl url;    
+    NPT_String  doc;
+    
+    // static scpd document
+    NPT_String scpd_url = service->GetSCPDURL();
+    if (!scpd_url.StartsWith("/")) {
+        scpd_url = GetURLBase().GetPath() + scpd_url;
+    }
+    url.SetPathPlus(scpd_url);
+    NPT_CHECK_FATAL(service->GetSCPDXML(doc));
+
+    NPT_HttpStaticRequestHandler* scpd_handler = new NPT_HttpStaticRequestHandler(doc, "text/xml");
+    m_HttpServer->AddRequestHandler(scpd_handler, url.GetPath(), false);
+    m_RequestHandlers.Add(scpd_handler);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::Start(PLT_SsdpListenTask* task)
+{
+    // TODO: We should reuse address otherwise we might fail if we're passed the same port during fast restart
+#ifdef _XBOX
+    m_HttpServer = new PLT_HttpServer(m_Port, m_PortRebind, 5);  
+#else
+    m_HttpServer = new PLT_HttpServer(m_Port, m_PortRebind, 20); // limit to 20 threads max  
+#endif
+
+    NPT_CHECK_FATAL(SetupServices(*this));
+
+    // start the server
+    NPT_CHECK_SEVERE(m_HttpServer->Start());
+
+    // read back assigned port in case 
+    // we passed 0 to randomly select one
+    m_Port = m_HttpServer->GetPort();
+    m_URLDescription.SetPort(m_Port);
+
+    // callback to initialize the device
+    NPT_CHECK_FATAL(SetupDevice());
+
+    // set up static handlers first as the order is important
+
+    // services static root device scpd documents
+    for (NPT_Cardinal i=0; i<m_Services.GetItemCount(); i++) {
+        SetupServiceSCPDHandler(m_Services[i]);
+    }
+
+    // services static embedded devices scpd documents
+    for (NPT_Cardinal j=0; j<m_EmbeddedDevices.GetItemCount(); j++) {
+        for (NPT_Cardinal i=0; i<m_EmbeddedDevices[j]->m_Services.GetItemCount(); i++) {
+            SetupServiceSCPDHandler(m_EmbeddedDevices[j]->m_Services[i]);
+        }
+    }
+
+    // all other requests including description document
+    // and service control are dynamically handled
+    PLT_HttpDeviceHostRequestHandler* device_handler = new PLT_HttpDeviceHostRequestHandler(this);
+    m_RequestHandlers.Add(device_handler);
+    m_HttpServer->AddRequestHandler(device_handler, "/", true);
+
+    // we should not advertise right away
+    // spec says randomly less than 100ms
+    NPT_TimeInterval delay(0, NPT_System::GetRandomInteger() % 100000000);
+
+    // calculate when we should send another announcement
+    NPT_Size leaseTime = (NPT_Size)(float)GetLeaseTime();
+    NPT_TimeInterval repeat;
+    repeat.m_Seconds = leaseTime?(int)((leaseTime >> 1) + ((unsigned short)NPT_System::GetRandomInteger() % (leaseTime >> 2))):30;
+    
+    // the XBOX cannot receive multicast, so we blast every 7 secs
+#ifdef _XBOX
+    repeat.m_Seconds = 7;
+#endif
+
+    PLT_ThreadTask* announce_task = new PLT_SsdpDeviceAnnounceTask(
+        this, 
+        repeat, 
+        true, 
+        m_Broadcast);
+    m_TaskManager.StartTask(announce_task, &delay);
+
+    // register ourselves as a listener for ssdp requests
+    task->AddListener(this);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::Stop(PLT_SsdpListenTask* task)
+{    
+    // unregister ourselves as a listener for ssdp requests
+    task->RemoveListener(this);
+
+    // remove all our running tasks
+    m_TaskManager.StopAllTasks();
+
+    if (m_HttpServer) {
+        // stop our internal http server
+        m_HttpServer->Stop();
+        delete m_HttpServer;
+        m_HttpServer = NULL;
+
+        // notify we're gone
+        NPT_List<NPT_NetworkInterface*> if_list;
+        PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list);
+        if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(this, true, m_Broadcast));
+        if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+    }
+
+    m_RequestHandlers.Apply(NPT_ObjectDeleter<NPT_HttpRequestHandler>());
+    m_RequestHandlers.Clear();
+    
+    PLT_DeviceData::Cleanup();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::Announce
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::Announce(PLT_DeviceData*  device, 
+                         NPT_HttpRequest& req, 
+                         NPT_UdpSocket&   socket, 
+                         bool             byebye)
+{
+    NPT_Result res = NPT_SUCCESS;
+
+    NPT_LOG_INFO_3("Sending SSDP NOTIFY (%s) Request to %s with location:%s", 
+        byebye?"ssdp:byebye":"ssdp:alive",
+        (const char*)req.GetUrl().ToString(),
+        (const char*)(PLT_UPnPMessageHelper::GetLocation(req)?*PLT_UPnPMessageHelper::GetLocation(req):""));
+        
+    if (byebye == false) {
+        // get location URL based on ip address of interface
+        PLT_UPnPMessageHelper::SetNTS(req, "ssdp:alive");
+        PLT_UPnPMessageHelper::SetLeaseTime(req, (NPT_Timeout)(float)device->GetLeaseTime());
+        PLT_UPnPMessageHelper::SetServer(req, NPT_HttpServer::m_ServerHeader, false);
+    } else {
+        PLT_UPnPMessageHelper::SetNTS(req, "ssdp:byebye");
+    }
+
+    // target address
+    NPT_IpAddress ip;
+    if (NPT_FAILED(res = ip.ResolveName(req.GetUrl().GetHost()))) {
+        return res;
+    }
+    NPT_SocketAddress addr(ip, req.GetUrl().GetPort());
+
+    // upnp:rootdevice
+    if (device->m_ParentUUID.IsEmpty()) {
+        PLT_SsdpSender::SendSsdp(req,
+            NPT_String("uuid:" + device->m_UUID + "::upnp:rootdevice"), 
+            "upnp:rootdevice",
+            socket,
+            true, 
+            &addr);
+    }
+
+    // uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:ver
+    PLT_SsdpSender::SendSsdp(req,
+        NPT_String("uuid:" + device->m_UUID + "::" + device->m_DeviceType), 
+        device->m_DeviceType,
+        socket,
+        true,
+        &addr);
+
+    // services
+    for (int i=0; i < (int)device->m_Services.GetItemCount(); i++) {
+        // uuid:device-UUID::urn:schemas-upnp-org:service:serviceType:ver
+        PLT_SsdpSender::SendSsdp(req,
+            NPT_String("uuid:" + device->m_UUID + "::" + device->m_Services[i]->GetServiceType()), 
+            device->m_Services[i]->GetServiceType(),
+            socket,
+            true, 
+            &addr);        
+    }
+
+    // uuid:device-UUID
+    PLT_SsdpSender::SendSsdp(req,
+        "uuid:" + device->m_UUID, 
+        "uuid:" + device->m_UUID, 
+        socket, 
+        true, 
+        &addr);
+
+
+    // embedded devices
+    for (int j=0; j < (int)device->m_EmbeddedDevices.GetItemCount(); j++) {
+        Announce(device->m_EmbeddedDevices[j].AsPointer(), 
+            req, 
+            socket, 
+            byebye);
+    }
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::ProcessHttpRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_DeviceHost::ProcessHttpRequest(NPT_HttpRequest&              request,
+                                   const NPT_HttpRequestContext& context,
+                                   NPT_HttpResponse&             response)
+{
+    // get the address of who sent us some data back*/
+    NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String method     = request.GetMethod();
+    NPT_String protocol   = request.GetProtocol(); 
+
+    if (method.Compare("POST") == 0) {
+        return ProcessHttpPostRequest(request, context, response);
+    } else if (method.Compare("SUBSCRIBE") == 0 || method.Compare("UNSUBSCRIBE") == 0) {
+        return ProcessHttpSubscriberRequest(request, context, response);
+    } else if (method.Compare("GET") == 0) {
+        if (request.GetUrl().GetPath() == m_URLDescription.GetPath()) {
+            return ProcessGetDescription(request, context, response);
+        }
+    }
+
+    response.SetStatus(405, "Bad Request");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::ProcessGetDescription
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_DeviceHost::ProcessGetDescription(NPT_HttpRequest&              /*request*/,
+                                      const NPT_HttpRequestContext& /*context*/,
+                                      NPT_HttpResponse&             response)
+{
+    NPT_String doc;
+    NPT_CHECK_FATAL(GetDescription(doc));
+    PLT_HttpHelper::SetBody(response, doc);    
+    PLT_HttpHelper::SetContentType(response, "text/xml");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::ProcessPostRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessHttpPostRequest(NPT_HttpRequest&              request,
+                                       const NPT_HttpRequestContext& context,
+                                       NPT_HttpResponse&             response) 
+{
+    NPT_Result                res;
+    NPT_String                service_type;
+    NPT_String                str;
+    NPT_XmlElementNode*       xml = NULL;
+    NPT_String                soap_action_header;
+    PLT_Service*              service;
+    NPT_XmlElementNode*       soap_body;
+    NPT_XmlElementNode*       soap_action;
+    const NPT_String*         attr;
+    PLT_ActionDesc*           action_desc;
+    PLT_ActionReference       action;
+    NPT_MemoryStreamReference resp(new NPT_MemoryStream);
+    NPT_String                ip_address  = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String                method      = request.GetMethod();
+    NPT_String                url         = request.GetUrl().ToRequestString(true);
+    NPT_String                protocol    = request.GetProtocol();
+
+    if (NPT_FAILED(FindServiceByControlURI(url, service)))
+        goto bad_request;
+
+    if (!request.GetHeaders().GetHeaderValue("SOAPAction"))
+        goto bad_request;
+
+    // extract the soap action name from the header
+    soap_action_header = *request.GetHeaders().GetHeaderValue("SOAPAction");
+    soap_action_header.TrimLeft('"');
+    soap_action_header.TrimRight('"');
+    char prefix[200];
+    char soap_action_name[100];
+    int  ret;
+    //FIXME: no sscanf
+    ret = sscanf(soap_action_header, "%[^#]#%s",
+                 prefix, 
+                 soap_action_name);
+    if (ret != 2)
+        goto bad_request;
+
+    // read the xml body and parse it
+    if (NPT_FAILED(PLT_HttpHelper::ParseBody(request, xml)))
+        goto bad_request;
+
+    // check envelope
+    if (xml->GetTag().Compare("Envelope", true))
+        goto bad_request;
+
+    // check namespace
+    if (!xml->GetNamespace() || xml->GetNamespace()->Compare("http://schemas.xmlsoap.org/soap/envelope/"))
+        goto bad_request;
+
+    // check encoding
+    attr = xml->GetAttribute("encodingStyle", "http://schemas.xmlsoap.org/soap/envelope/");
+    if (!attr || attr->Compare("http://schemas.xmlsoap.org/soap/encoding/"))
+        goto bad_request;
+
+    // read action
+    soap_body = PLT_XmlHelper::GetChild(xml, "Body");
+    if (soap_body == NULL)
+        goto bad_request;
+
+    PLT_XmlHelper::GetChild(soap_body, soap_action);
+    if (soap_action == NULL)
+        goto bad_request;
+
+    // verify action name is identical to SOAPACTION header*/
+    if (soap_action->GetTag().Compare(soap_action_name, true))
+        goto bad_request;
+
+    // verify namespace
+    if (!soap_action->GetNamespace() || soap_action->GetNamespace()->Compare(service->GetServiceType()))
+        goto bad_request;
+
+    // create a buffer for our response body and call the service
+    if ((action_desc = service->FindActionDesc(soap_action_name)) == NULL) {
+        res = NPT_FAILURE;
+        // create a bastard soap response
+        PLT_Action::FormatSoapError(401, "Invalid Action", *resp);
+        goto error;
+    }
+
+    // create an action object
+    action = new PLT_Action(action_desc);
+
+    // read all the arguments if any
+    for (NPT_List<NPT_XmlNode*>::Iterator args = soap_action->GetChildren().GetFirstItem(); args; args++) {
+        NPT_XmlElementNode* child = (*args)->AsElementNode();
+        if (!child) continue;
+
+        // Total HACK for xbox360 upnp uncompliance!
+        NPT_String name = child->GetTag();
+        if (action_desc->GetName() == "Browse" && name == "ContainerID") {
+            name = "ObjectID";
+        }
+
+        res = action->SetArgumentValue(
+            name,
+            child->GetText()?*child->GetText():"");
+
+        if (NPT_FAILED(res)) {
+            // FIXME: incorrect upnp error?
+            PLT_Action::FormatSoapError(401, "Invalid Action", *resp);
+            goto error;
+        }
+    }
+
+    if (NPT_FAILED(action->VerifyArguments(true))) {
+        action->SetError(402, "Invalid Args");
+        goto error;
+    }
+    
+    // call the virtual function, it's all good
+    // set the error in case the it wasn't done
+    if (NPT_FAILED(OnAction(action, PLT_HttpRequestContext(request, context)))) {
+        goto error;
+    }
+
+    // create the soap response now
+    action->FormatSoapResponse(*resp);
+    goto done;
+
+error:
+    if (!action.IsNull() && action->GetErrorCode() == 0) {
+        action->SetError(501, "Action Failed");
+        action->FormatSoapResponse(*resp);
+    }
+    response.SetStatus(500, "Internal Server Error");
+
+done:
+    //args.Apply(NPT_ObjectDeleter<PLT_Argument>());
+
+    NPT_LargeSize resp_body_size;    
+    if (NPT_SUCCEEDED(resp->GetAvailable(resp_body_size))) {
+        PLT_HttpHelper::SetContentType(response, "text/xml; charset=\"utf-8\"");
+        response.GetHeaders().SetHeader("Ext", ""); // should only be for M-POST but oh well
+        NPT_InputStreamReference input = resp;
+        PLT_HttpHelper::SetBody(response, input);
+    }    
+    
+    delete xml;
+    return NPT_SUCCESS;
+
+bad_request:
+    delete xml;
+    response.SetStatus(400, "Bad Request");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::ProcessHttpSubscriberRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessHttpSubscriberRequest(NPT_HttpRequest&              request,
+                                             const NPT_HttpRequestContext& context,
+                                             NPT_HttpResponse&             response) 
+{
+    NPT_String  ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String  method     = request.GetMethod();
+    NPT_String  url        = request.GetUrl().ToRequestString(true);
+    NPT_String  protocol   = request.GetProtocol();
+
+    const NPT_String* nt            = PLT_UPnPMessageHelper::GetNT(request);
+    const NPT_String* callback_urls = PLT_UPnPMessageHelper::GetCallbacks(request);
+    const NPT_String* sid           = PLT_UPnPMessageHelper::GetSID(request);
+    
+    PLT_Service* service;
+    if (NPT_FAILED(FindServiceByEventSubURI(url, service))) {
+        goto cleanup;
+    }
+
+    if (method.Compare("SUBSCRIBE") == 0) {
+        // Do we have a sid ?
+        if (sid) {
+            // make sure we don't have a callback nor a nt
+            if (nt || callback_urls) {
+                goto cleanup;
+            }
+          
+            NPT_Int32 timeout;
+            if (NPT_FAILED(PLT_UPnPMessageHelper::GetTimeOut(request, timeout))) {
+                timeout = 1800;
+            }
+            // subscription renewed
+            // send the info to the service
+            service->ProcessRenewSubscription(context.GetLocalAddress(), 
+                                              *sid, 
+                                              timeout, 
+                                              response);
+            return NPT_SUCCESS;
+        } else {
+            // new subscription ?
+            // verify nt is present and valid
+            if (!nt || nt->Compare("upnp:event", true)) {
+                response.SetStatus(412, "Precondition failed");
+                return NPT_FAILURE;
+            }
+            // verify callback is present
+            if (!callback_urls) {
+                response.SetStatus(412, "Precondition failed");
+                return NPT_FAILURE;
+            }
+
+            NPT_Int32 timeout;
+            if (NPT_FAILED(PLT_UPnPMessageHelper::GetTimeOut(request, timeout))) {
+                timeout = 1800;
+            }
+
+            // send the info to the service
+            service->ProcessNewSubscription(&m_TaskManager,
+                                            context.GetLocalAddress(), 
+                                            *callback_urls, 
+                                            timeout, 
+                                            response);
+            return NPT_SUCCESS;
+        }
+    } else if (method.Compare("UNSUBSCRIBE") == 0) {
+        // Do we have a sid ?
+        if (sid && sid->GetLength() > 0) {
+            // make sure we don't have a callback nor a nt
+            if (nt || callback_urls) {
+                goto cleanup;
+            }
+
+            // subscription cancelled
+            // send the info to the service
+            service->ProcessCancelSubscription(context.GetLocalAddress(), 
+                                               *sid, 
+                                               response);
+            return NPT_SUCCESS;
+        }
+    }
+
+cleanup:
+    response.SetStatus(405, "Bad Request");
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::OnSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::OnSsdpPacket(NPT_HttpRequest&              request, 
+                             const NPT_HttpRequestContext& context)
+{
+    return ProcessSsdpSearchRequest(request, context);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::ProcessSsdpSearchRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessSsdpSearchRequest(NPT_HttpRequest&              request,
+                                         const NPT_HttpRequestContext& context) 
+{
+    // get the address of who sent us some data back*/
+    NPT_String  ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String  method     = request.GetMethod();
+    NPT_String  url        = request.GetUrl().ToRequestString(true);
+    NPT_String  protocol   = request.GetProtocol();
+
+    if (method.Compare("M-SEARCH") == 0) {
+        NPT_LOG_INFO_1("Received M-SEARCH from %s", (const char*) ip_address);
+        PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+        if (url.Compare("*") || protocol.Compare("HTTP/1.1"))
+            return NPT_FAILURE;
+
+        const NPT_String* st = PLT_UPnPMessageHelper::GetST(request);
+        NPT_CHECK_POINTER_SEVERE(st);
+
+        const NPT_String* man = PLT_UPnPMessageHelper::GetMAN(request);
+        if (!man || man->Compare("\"ssdp:discover\"", true))
+            return NPT_FAILURE;
+
+        NPT_UInt32 mx;
+        if (NPT_FAILED(PLT_UPnPMessageHelper::GetMX(request, mx)))
+            return NPT_FAILURE;
+
+        // create a task to respond to the request
+        NPT_TimeInterval timer((mx==0)?0:((int)(0 + ((unsigned short)NPT_System::GetRandomInteger() % ((mx>10)?10:mx)))), 0);
+        PLT_SsdpDeviceSearchResponseTask* task = new PLT_SsdpDeviceSearchResponseTask(this, context.GetRemoteAddress(), *st);
+        m_TaskManager.StartTask(task, &timer);
+        return NPT_SUCCESS;
+    }
+
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::SendSsdpSearchResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SendSsdpSearchResponse(PLT_DeviceData*    device, 
+                                       NPT_HttpResponse&  response, 
+                                       NPT_UdpSocket&     socket, 
+                                       const char*        st,
+                                       const NPT_SocketAddress* addr /* = NULL */)
+{    
+    NPT_LOG_INFO_1("Responding to a M-SEARCH request for %s", st);
+
+    // ssdp:all or upnp:rootdevice
+    if (NPT_String::Compare(st, "ssdp:all") == 0 || NPT_String::Compare(st, "upnp:rootdevice") == 0) {
+        if (device->m_ParentUUID.IsEmpty()) {
+           // upnp:rootdevice
+           PLT_SsdpSender::SendSsdp(response, 
+                    NPT_String("uuid:" + device->m_UUID + "::upnp:rootdevice"), 
+                    "upnp:rootdevice",
+                    socket,
+                    false,
+                    addr);
+        }
+    }
+
+    // uuid:device-UUID
+    if (NPT_String::Compare(st, "ssdp:all", false) == 0 || NPT_String::Compare(st, "uuid:" + device->m_UUID, false) == 0) {
+        // uuid:device-UUID
+        PLT_SsdpSender::SendSsdp(response, 
+                 "uuid:" + device->m_UUID, 
+                 "uuid:" + device->m_UUID, 
+                 socket, 
+                 false,
+                 addr);
+    }
+
+    // urn:schemas-upnp-org:device:deviceType:ver
+    if (NPT_String::Compare(st, "ssdp:all", false) == 0 || NPT_String::Compare(st, device->m_DeviceType, false) == 0) {
+        // uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:ver
+        PLT_SsdpSender::SendSsdp(response, 
+                 NPT_String("uuid:" + device->m_UUID + "::" + device->m_DeviceType), 
+                 device->m_DeviceType,
+                 socket,
+                 false,
+                 addr);
+    }
+
+    // services
+    for (int i=0; i < (int)device->m_Services.GetItemCount(); i++) {
+        if (NPT_String::Compare(st, "ssdp:all", false) == 0 || NPT_String::Compare(st, device->m_Services[i]->GetServiceType(), false) == 0) {
+            // uuid:device-UUID::urn:schemas-upnp-org:service:serviceType:ver
+            PLT_SsdpSender::SendSsdp(response, 
+                     NPT_String("uuid:" + device->m_UUID + "::" + device->m_Services[i]->GetServiceType()), 
+                     device->m_Services[i]->GetServiceType(),
+                     socket,
+                     false,
+                     addr);
+        }
+    }
+
+    // embedded devices
+    for (int j=0; j < (int)device->m_EmbeddedDevices.GetItemCount(); j++) {
+        SendSsdpSearchResponse(device->m_EmbeddedDevices[j].AsPointer(), response, socket, st, addr);
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::OnAction(PLT_ActionReference&          action, 
+                         const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+    action->SetError(401, "Invalid Action");
+    return NPT_FAILURE;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDeviceHost.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,163 @@
+/*****************************************************************
+|
+|   Platinum - Device Host
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_DEVICE_HOST_H_
+#define _PLT_DEVICE_HOST_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltDeviceData.h"
+#include "PltHttpServerListener.h"
+#include "PltSsdpListener.h"
+#include "PltTaskManager.h"
+#include "PltAction.h"
+#include "PltHttp.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_HttpServer;
+class PLT_HttpServerHandler;
+class PLT_SsdpDeviceAnnounceTask;
+class PLT_SsdpListenTask;
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceHost class
++---------------------------------------------------------------------*/
+class PLT_DeviceHost : public PLT_DeviceData,
+                       public PLT_SsdpPacketListener
+{
+public:
+    PLT_DeviceHost(const char*  description_path = "/",
+                   const char*  uuid = "",
+                   const char*  device_type = "",
+                   const char*  friendly_name = "",
+                   bool         show_ip = false,
+                   NPT_UInt16   port = 0,
+                   bool         port_rebind = false);
+
+    // public methods
+    virtual void       SetBroadcast(bool broadcast) { m_Broadcast = broadcast; }
+    virtual NPT_UInt16 GetPort() { return m_Port; };
+
+    // NPT_HttpRequestHandler forward for control/event requests
+    virtual NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request,
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse&             response);
+    
+    // PLT_SsdpDeviceAnnounceTask & PLT_SsdpDeviceAnnounceUnicastTask
+    virtual NPT_Result Announce(PLT_DeviceData*  device, 
+                                NPT_HttpRequest& request, 
+                                NPT_UdpSocket&   socket, 
+                                bool             byebye);
+
+    virtual NPT_Result Announce(NPT_HttpRequest& request, 
+                                NPT_UdpSocket&   socket, 
+                                bool             byebye) {
+        return Announce(this, request, socket, byebye);
+    }
+
+    // PLT_SsdpPacketListener method
+    virtual NPT_Result OnSsdpPacket(NPT_HttpRequest&              request, 
+                                    const NPT_HttpRequestContext& context);
+
+    // PLT_SsdpDeviceSearchListenTask
+    virtual NPT_Result ProcessSsdpSearchRequest(NPT_HttpRequest&              request, 
+                                                const NPT_HttpRequestContext& context);
+
+    // PLT_SsdpDeviceSearchResponseTask
+    virtual NPT_Result SendSsdpSearchResponse(PLT_DeviceData*   device, 
+                                              NPT_HttpResponse& response, 
+                                              NPT_UdpSocket&    socket, 
+                                              const char*       st,
+                                              const NPT_SocketAddress* addr  = NULL);
+    virtual NPT_Result SendSsdpSearchResponse(NPT_HttpResponse& response, 
+                                              NPT_UdpSocket&    socket, 
+                                              const char*       ST,
+                                              const NPT_SocketAddress* addr = NULL) {
+        return SendSsdpSearchResponse(this, response, socket, ST, addr);
+    }
+    
+protected:
+    virtual ~PLT_DeviceHost();
+
+    // pure methods
+    virtual NPT_Result SetupServices(PLT_DeviceData& data) = 0;
+    
+    // setup methods
+    virtual NPT_Result SetupIcons();
+    virtual NPT_Result SetupDevice();
+    
+    // overridable methods
+    virtual NPT_Result AddIcon(const PLT_DeviceIcon& icon, 
+                               const char*           filepath);
+    virtual NPT_Result AddIcon(const PLT_DeviceIcon& icon, 
+                               const void*           data, 
+                               NPT_Size              size, 
+                               bool                  copy = true);
+    virtual NPT_Result Start(PLT_SsdpListenTask* task);
+    virtual NPT_Result Stop(PLT_SsdpListenTask* task);
+    virtual NPT_Result SetupServiceSCPDHandler(PLT_Service* service);
+    virtual NPT_Result OnAction(PLT_ActionReference&          action, 
+                                const PLT_HttpRequestContext& context);
+    virtual NPT_Result ProcessGetDescription(NPT_HttpRequest&              request,
+                                             const NPT_HttpRequestContext& context,
+                                             NPT_HttpResponse&             response);
+    virtual NPT_Result ProcessHttpPostRequest(NPT_HttpRequest&              request,
+                                              const NPT_HttpRequestContext& context,
+                                              NPT_HttpResponse&             response);
+    virtual NPT_Result ProcessHttpSubscriberRequest(NPT_HttpRequest&              request,
+                                                    const NPT_HttpRequestContext& context,
+                                                    NPT_HttpResponse&             response);
+
+protected:
+    friend class PLT_UPnP;
+    friend class PLT_UPnP_DeviceStartIterator;
+    friend class PLT_UPnP_DeviceStopIterator;
+    friend class PLT_Service;
+    friend class NPT_Reference<PLT_DeviceHost>;
+
+private:
+    PLT_TaskManager                   m_TaskManager;
+    PLT_HttpServer*                   m_HttpServer;
+    bool                              m_Broadcast;
+    NPT_UInt16                        m_Port;
+    bool                              m_PortRebind;
+    NPT_List<NPT_HttpRequestHandler*> m_RequestHandlers;
+};
+
+typedef NPT_Reference<PLT_DeviceHost> PLT_DeviceHostReference;
+
+#endif /* _PLT_DEVICE_HOST_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDownloader.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,135 @@
+/*****************************************************************
+|
+|   Platinum - Downloader
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltDownloader.h"
+#include "PltTaskManager.h"
+
+/*----------------------------------------------------------------------
+|   PLT_Downloader::PLT_Downloader
++---------------------------------------------------------------------*/
+PLT_Downloader::PLT_Downloader(PLT_TaskManager*           task_manager,
+                               const char*                url, 
+                               NPT_OutputStreamReference& output) :
+    m_URL(url),
+    m_Output(output),
+    m_TaskManager(task_manager),
+    m_Task(NULL),
+    m_State(PLT_DOWNLOADER_IDLE)
+{
+}
+    
+/*----------------------------------------------------------------------
+|   PLT_Downloader::~PLT_Downloader
++---------------------------------------------------------------------*/
+PLT_Downloader::~PLT_Downloader()
+{
+    Stop();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Downloader::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Downloader::Start()
+{
+    Stop();
+
+    m_Task = new PLT_HttpDownloadTask(NPT_HttpUrl(m_URL), this);
+    NPT_Result res = m_TaskManager->StartTask(m_Task, NULL, false);
+    if (NPT_FAILED(res)) {
+        m_State = PLT_DOWNLOADER_ERROR;
+        return res;
+    }
+
+    m_State = PLT_DOWNLOADER_STARTED;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Downloader::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Downloader::Stop()
+{
+    if (m_Task) {
+        m_Task->Kill();
+        m_Task = NULL;
+    }
+
+    m_State = PLT_DOWNLOADER_IDLE;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Downloader::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_Downloader::ProcessResponse(NPT_Result                    res, 
+                                NPT_HttpRequest*              request, 
+                                const NPT_HttpRequestContext& context, 
+                                NPT_HttpResponse* response)
+{
+    NPT_COMPILER_UNUSED(request);
+    NPT_COMPILER_UNUSED(context);
+
+    if (NPT_FAILED(res)) {
+        m_State = PLT_DOWNLOADER_ERROR;
+        return res;
+    }
+
+    m_State = PLT_DOWNLOADER_DOWNLOADING;
+
+    NPT_HttpEntity* entity;
+    NPT_InputStreamReference body;
+    if (!response || !(entity = response->GetEntity()) || NPT_FAILED(entity->GetInputStream(body))) {
+        m_State = PLT_DOWNLOADER_ERROR;
+        return NPT_FAILURE;
+    }
+
+    // Read body (no content length means until socket is closed)
+    res = NPT_StreamToStreamCopy(*body.AsPointer(), 
+        *m_Output.AsPointer(), 
+        0, 
+        entity->GetContentLength());
+
+    if (NPT_FAILED(res)) {
+        m_State = PLT_DOWNLOADER_ERROR;
+        return res;
+    }
+
+    m_State = PLT_DOWNLOADER_SUCCESS;
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltDownloader.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,91 @@
+/*****************************************************************
+|
+||
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_DOWNLOADER_H_
+#define _PLT_DOWNLOADER_H_
+
+/*----------------------------------------------------------------------
+|   Includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpClientTask.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_Downloader;
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef PLT_HttpClientTask<PLT_Downloader> PLT_HttpDownloadTask;
+
+typedef enum {
+    PLT_DOWNLOADER_IDLE,
+    PLT_DOWNLOADER_STARTED,
+    PLT_DOWNLOADER_DOWNLOADING,
+    PLT_DOWNLOADER_ERROR,
+    PLT_DOWNLOADER_SUCCESS
+} Plt_DowloaderState;
+
+/*----------------------------------------------------------------------
+|   PLT_Downloader class
++---------------------------------------------------------------------*/
+class PLT_Downloader
+{
+public:
+    PLT_Downloader(PLT_TaskManager*           task_manager, 
+                   const char*                url, 
+                   NPT_OutputStreamReference& output);
+    virtual ~PLT_Downloader();
+
+    NPT_Result Start();
+    NPT_Result Stop();
+    Plt_DowloaderState GetState() { return m_State; }
+
+    // PLT_HttpClientTask method
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response);
+
+
+private:
+    // members
+    NPT_String                m_URL;
+    NPT_OutputStreamReference m_Output;
+    PLT_TaskManager*          m_TaskManager;
+    PLT_HttpDownloadTask*     m_Task;
+    Plt_DowloaderState        m_State;
+};
+
+#endif /* _PLT_DOWNLOADER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltEvent.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,261 @@
+/*****************************************************************
+|
+|   Platinum - Control/Event
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltEvent.h"
+#include "PltService.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltXmlHelper.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.event")
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::PLT_EventSubscriber
++---------------------------------------------------------------------*/
+PLT_EventSubscriber::PLT_EventSubscriber(PLT_TaskManager* task_manager, 
+                                         PLT_Service*     service,
+                                         const char*      sid,
+                                         int              timeout /* = -1 */) : 
+    m_TaskManager(task_manager), 
+    m_Service(service), 
+    m_EventKey(0),
+    m_SubscriberTask(NULL),
+    m_SID(sid)
+{
+    NPT_LOG_FINE_1("Creating new subscriber (%s)", m_SID.GetChars());
+    SetTimeout(timeout);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::~PLT_EventSubscriber
++---------------------------------------------------------------------*/
+PLT_EventSubscriber::~PLT_EventSubscriber() 
+{
+    NPT_LOG_FINE_1("Deleting subscriber (%s)", m_SID.GetChars());
+    if (m_SubscriberTask) {
+        m_SubscriberTask->Kill();
+        m_SubscriberTask = NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_EventSubscriber::GetService() 
+{
+    return m_Service;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetEventKey
++---------------------------------------------------------------------*/
+NPT_Ordinal
+PLT_EventSubscriber::GetEventKey() 
+{
+    return m_EventKey;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::SetEventKey
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetEventKey(NPT_Ordinal value) 
+{
+    m_EventKey = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetLocalIf
++---------------------------------------------------------------------*/
+NPT_SocketAddress
+PLT_EventSubscriber::GetLocalIf() 
+{
+    return m_LocalIf;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::SetLocalIf
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetLocalIf(NPT_SocketAddress value) 
+{
+    m_LocalIf = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetExpirationTime
++---------------------------------------------------------------------*/
+// a TimeStamp of 0 means no expiration
+NPT_TimeStamp
+PLT_EventSubscriber::GetExpirationTime()
+{
+    return m_ExpirationTime;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::SetExpirationTime
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetTimeout(int timeout /* = -1 */) 
+{
+    NPT_LOG_FINE_2("subscriber (%s) expiring in %d seconds",
+        m_SID.GetChars(),
+        timeout);
+
+    // -1 means infinite so we set an expiration time of 0
+    if (timeout == -1) {
+        m_ExpirationTime = NPT_TimeStamp(0, 0);
+    } else {
+        NPT_System::GetCurrentTimeStamp(m_ExpirationTime);
+        m_ExpirationTime += NPT_TimeInterval(timeout, 0);
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::FindCallbackURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::FindCallbackURL(const char* callback_url) 
+{
+    NPT_String res;
+    return NPT_ContainerFind(m_CallbackURLs, 
+                             NPT_StringFinder(callback_url), 
+                             res);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::AddCallbackURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::AddCallbackURL(const char* callback_url) 
+{
+    NPT_CHECK_POINTER_FATAL(callback_url);
+
+    NPT_LOG_FINE_2("Adding callback \"%s\" to subscriber %s", 
+        callback_url, 
+        m_SID.GetChars());
+    return m_CallbackURLs.Add(callback_url);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::Notify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::Notify(NPT_List<PLT_StateVariable*>& vars)
+{
+    // verify we have eventable variables
+    bool foundVars = false;
+    NPT_XmlElementNode* propertyset = new NPT_XmlElementNode("e", "propertyset");
+    NPT_CHECK_SEVERE(propertyset->SetNamespaceUri("e", "urn:schemas-upnp-org:event-1-0"));
+
+    NPT_List<PLT_StateVariable*>::Iterator var = vars.GetFirstItem();
+    while (var) {
+        if ((*var)->IsSendingEvents()) {
+            NPT_XmlElementNode* property = new NPT_XmlElementNode("e", "property");
+            propertyset->AddChild(property);
+            PLT_XmlHelper::AddChildText(property, (*var)->GetName(), (*var)->GetValue());
+            foundVars = true;
+        }
+        ++var;
+    }
+
+    // no eventable state variables found!
+    if (foundVars == false) {
+        delete propertyset;
+        return NPT_FAILURE;
+    }
+
+    // format the body with the xml
+    NPT_String xml;
+    if (NPT_FAILED(PLT_XmlHelper::Serialize(*propertyset, xml))) {
+        delete propertyset;
+        NPT_CHECK_FATAL(NPT_FAILURE);
+    }
+    delete propertyset;
+
+
+    // parse the callback url
+    NPT_HttpUrl url(m_CallbackURLs[0]);
+    if (!url.IsValid()) {
+        NPT_CHECK_FATAL(NPT_FAILURE);
+    }
+    // format request
+    NPT_HttpRequest* request = new NPT_HttpRequest(url,
+                                                   "NOTIFY",
+                                                   NPT_HTTP_PROTOCOL_1_0);
+    request->GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "keep-alive");
+
+    // add the extra headers
+    PLT_HttpHelper::SetContentType(*request, "text/xml");
+    PLT_UPnPMessageHelper::SetNT(*request, "upnp:event");
+    PLT_UPnPMessageHelper::SetNTS(*request, "upnp:propchange");
+    PLT_UPnPMessageHelper::SetSID(*request, m_SID);
+    PLT_UPnPMessageHelper::SetSeq(*request, m_EventKey);
+
+    // wrap around sequence to 1
+    if (++m_EventKey == 0) m_EventKey = 1;
+
+    PLT_HttpHelper::SetBody(*request, xml);
+
+    // start the task now if not started already
+    if (!m_SubscriberTask) {
+        m_SubscriberTask = new PLT_HttpClientSocketTask(request, true);
+        NPT_TimeInterval delay(0.5f);
+        // delay start to make sure ctrlpoint receives response to subscription
+        // before our first NOTIFY. Also make sure task is not auto-destroy
+        // since we want to destroy it ourselves when the subscriber goes away.
+        NPT_CHECK_FATAL(m_TaskManager->StartTask(m_SubscriberTask, &delay, false));
+    } else {
+        m_SubscriberTask->AddRequest(request);
+    }
+     
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriberFinderByService::operator()
++---------------------------------------------------------------------*/
+bool 
+PLT_EventSubscriberFinderByService::operator()(PLT_EventSubscriber* const & eventSub) const 
+{
+    return m_Service->GetDevice()->GetUUID().Compare(
+        eventSub->GetService()->GetDevice()->GetUUID(), true) ? false : true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltEvent.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,140 @@
+/*****************************************************************
+|
+|   Platinum - Event
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_EVENT_H_
+#define _PLT_EVENT_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpClientTask.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_StateVariable;
+class PLT_DeviceData;
+class PLT_Service;
+class PLT_TaskManager;
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber class
++---------------------------------------------------------------------*/
+class PLT_EventSubscriber
+{
+public:
+    PLT_EventSubscriber(PLT_TaskManager* task_manager, 
+                        PLT_Service*     service,
+                        const char*      sid,
+                        int              timeout = -1);
+    ~PLT_EventSubscriber();
+
+    PLT_Service*        GetService();
+    NPT_Ordinal         GetEventKey();
+    NPT_Result          SetEventKey(NPT_Ordinal value);
+    NPT_SocketAddress   GetLocalIf();
+    NPT_Result          SetLocalIf(NPT_SocketAddress value);
+    NPT_TimeStamp       GetExpirationTime();
+    NPT_Result          SetTimeout(int timeout = -1);
+    const NPT_String&   GetSID() const { return m_SID; }
+    NPT_Result          FindCallbackURL(const char* callback_url);
+    NPT_Result          AddCallbackURL(const char* callback_url);
+    NPT_Result          Notify(NPT_List<PLT_StateVariable*>& vars);
+    
+protected:
+    //members
+    PLT_TaskManager*          m_TaskManager;
+    PLT_Service*              m_Service;
+    NPT_Ordinal               m_EventKey;
+    PLT_HttpClientSocketTask* m_SubscriberTask;
+    NPT_String                m_SID;
+    NPT_SocketAddress         m_LocalIf;
+    NPT_Array<NPT_String>     m_CallbackURLs;
+    NPT_TimeStamp             m_ExpirationTime;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriberFinderBySID
++---------------------------------------------------------------------*/
+class PLT_EventSubscriberFinderBySID
+{
+public:
+    // methods
+    PLT_EventSubscriberFinderBySID(const char* sid) : m_SID(sid) {}
+
+    bool operator()(PLT_EventSubscriber* const & sub) const {
+        return m_SID.Compare(sub->GetSID(), true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String m_SID;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriberFinderByCallbackURL
++---------------------------------------------------------------------*/
+class PLT_EventSubscriberFinderByCallbackURL
+{
+public:
+    // methods
+    PLT_EventSubscriberFinderByCallbackURL(const char* callback_url) : 
+      m_CallbackURL(callback_url) {}
+
+    bool operator()(PLT_EventSubscriber* const & sub) const {
+        return NPT_SUCCEEDED(sub->FindCallbackURL(m_CallbackURL));
+    }
+
+private:
+    // members
+    NPT_String m_CallbackURL;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriberFinderByService
++---------------------------------------------------------------------*/
+class PLT_EventSubscriberFinderByService
+{
+public:
+    // methods
+    PLT_EventSubscriberFinderByService(PLT_Service* service) : m_Service(service) {}
+    virtual ~PLT_EventSubscriberFinderByService() {}
+    bool operator()(PLT_EventSubscriber* const & eventSub) const;
+
+private:
+    // members
+    PLT_Service* m_Service;
+};
+
+#endif /* _PLT_EVENT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttp.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,616 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Protocol Helper
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltHttp.h"
+#include "PltDatagramStream.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http")
+
+/*----------------------------------------------------------------------
+|   external references
++---------------------------------------------------------------------*/
+extern NPT_String HttpServerHeader;
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaderFinder
++---------------------------------------------------------------------*/
+class NPT_HttpHeaderFinder
+{
+ public:
+    // methods
+    NPT_HttpHeaderFinder(const char* name) : m_Name(name) {}
+    bool operator()(const NPT_HttpHeader* const & header) const {
+		if (header->GetName().Compare(m_Name, true)) {
+			return true;
+		} else {
+			return false;
+		}
+    }
+
+ private:
+    // members
+    NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaderPrinter
++---------------------------------------------------------------------*/
+class NPT_HttpHeaderPrinter
+{
+public:
+    // methods
+    NPT_HttpHeaderPrinter(NPT_OutputStreamReference& stream) : m_Stream(stream) {}
+    NPT_Result operator()(NPT_HttpHeader*& header) const {
+        m_Stream->WriteString(header->GetName());
+        m_Stream->Write(": ", 2);
+        m_Stream->WriteString(header->GetValue());
+        m_Stream->Write("\r\n", 2, NULL);
+        return NPT_SUCCESS;
+    }
+
+private:
+    // members
+    NPT_OutputStreamReference& m_Stream;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaderLogger
++---------------------------------------------------------------------*/
+class NPT_HttpHeaderLogger
+{
+public:
+    // methods
+    NPT_HttpHeaderLogger(NPT_LoggerReference& logger, int level) : 
+      m_Logger(logger), m_Level(level) {}
+	NPT_Result operator()(NPT_HttpHeader*& header) const {
+        NPT_COMPILER_UNUSED(header);
+
+        NPT_LOG_L2(m_Logger, m_Level, "%s: %s", 
+            (const char*)header->GetName(), 
+            (const char*)header->GetValue());
+        return NPT_SUCCESS;
+    }
+
+    NPT_LoggerReference& m_Logger;
+    int                  m_Level;
+};
+
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::GetContentType
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetContentType(NPT_HttpMessage& message, NPT_String& type) 
+{ 
+    type = "";
+
+    const NPT_String* val = 
+        message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_TYPE);
+    NPT_CHECK_POINTER(val);
+
+    type = *val;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::SetContentType
++---------------------------------------------------------------------*/
+void
+PLT_HttpHelper::SetContentType(NPT_HttpMessage& message, const char* type)   
+{
+    message.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, type);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::GetContentLength
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetContentLength(NPT_HttpMessage& message, NPT_LargeSize& len) 
+{ 
+    len = 0;
+
+    const NPT_String* val = 
+        message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH);
+    NPT_CHECK_POINTER(val);
+
+    return val->ToInteger(len);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::SetContentLength
++---------------------------------------------------------------------*/
+void
+PLT_HttpHelper::SetContentLength(NPT_HttpMessage& message, NPT_LargeSize len)   
+{
+    message.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, NPT_String::FromIntegerU(len));
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message, NPT_String& body)
+{
+    return SetBody(message, (const char*)body, body.GetLength());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message, const char* body, NPT_Size len)
+{
+    if (len == 0) {
+        return NPT_SUCCESS;
+    }
+
+    // dump the body in a memory stream
+    NPT_MemoryStreamReference stream(new NPT_MemoryStream);
+    stream->Write(body, len);
+
+    // set content length
+    PLT_HttpHelper::SetContentLength(message, len);
+
+    NPT_InputStreamReference input = stream;
+    return SetBody(message, input, len);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message, NPT_InputStreamReference& stream, NPT_LargeSize len)
+{
+    if (len == 0) {
+        NPT_CHECK_SEVERE(stream->GetAvailable(len));
+    }
+
+    // get the entity
+    NPT_HttpEntity* entity = message.GetEntity();
+    if (entity == NULL) {
+        // no entity yet, create one
+        message.SetEntity(entity = new NPT_HttpEntity());
+    }
+
+    // set the entity body
+    entity->SetInputStream(stream);
+    entity->SetContentLength(len);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::GetBody
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_HttpHelper::GetBody(NPT_HttpMessage& message, NPT_String& body) 
+{
+    NPT_Result res;
+    NPT_InputStreamReference stream;
+
+    // get stream
+    NPT_HttpEntity* entity = message.GetEntity();
+    if (!entity || NPT_FAILED(entity->GetInputStream(stream))) {
+        return NPT_FAILURE;
+    }
+
+    // extract body
+    NPT_StringOutputStream* output_stream = new NPT_StringOutputStream(&body);
+    res = NPT_StreamToStreamCopy(*stream, *output_stream, 0, entity->GetContentLength());
+    delete output_stream;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::ParseBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::ParseBody(NPT_HttpMessage& message, NPT_XmlElementNode*& tree) 
+{
+    // reset tree
+    tree = NULL;
+
+    // read body
+    NPT_String body;
+    NPT_CHECK_WARNING(GetBody(message, body));
+
+    // parse body
+    NPT_XmlParser parser;
+    NPT_XmlNode*  node;
+    NPT_CHECK_WARNING(parser.Parse(body, node));
+    
+    tree = node->AsElementNode();
+    if (!tree) {
+        delete node;
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::IsConnectionKeepAlive
++---------------------------------------------------------------------*/
+bool
+PLT_HttpHelper::IsConnectionKeepAlive(NPT_HttpMessage& message) 
+{
+    const NPT_String* connection = 
+        message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
+
+    // if we have the keep-alive header then no matter what protocol version, we want keep-alive
+    // if we are in HTTP 1.1 and we don't have the keep-alive header, make sure we also don't have the Connection: close header.
+    NPT_String protocol = message.GetProtocol();
+    if ((!protocol.Compare(NPT_HTTP_PROTOCOL_1_1, true) && (!connection || connection->Compare("close", true))) || 
+        (connection && !connection->Compare("keep-alive", true))) {
+        return true; 
+    }
+
+    return false;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::IsBodyStreamSeekable
++---------------------------------------------------------------------*/
+bool
+PLT_HttpHelper::IsBodyStreamSeekable(NPT_HttpMessage& message)
+{
+    NPT_HttpEntity* entity = message.GetEntity();
+    NPT_InputStreamReference stream;
+    if (!entity || NPT_FAILED(entity->GetInputStream(stream))) return true;
+
+    // try to get current position and seek there
+    NPT_Position position;
+    if (NPT_FAILED(stream->Tell(position)) || 
+        NPT_FAILED(stream->Seek(position))) {
+        return false;
+    }
+
+    return true;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::GetHost
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetHost(NPT_HttpRequest& request, NPT_String& value)    
+{ 
+    value = "";
+
+    const NPT_String* val = 
+        request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_HOST);
+    NPT_CHECK_POINTER(val);
+
+    value = *val;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::SetHost
++---------------------------------------------------------------------*/
+void         
+PLT_HttpHelper::SetHost(NPT_HttpRequest& request, const char* host)
+{ 
+    request.GetHeaders().SetHeader(NPT_HTTP_HEADER_HOST, host); 
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::GetRange
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetRange(NPT_HttpRequest& request, 
+                         NPT_Position&    start, 
+                         NPT_Position&    end)
+{
+    start = (NPT_Position)-1;
+    end = (NPT_Position)-1;    
+    
+    const NPT_String* range = 
+        request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE);
+    NPT_CHECK_POINTER(range);
+
+    char s[32], e[32];
+    s[0] = '\0';
+    e[0] = '\0';
+    int ret = sscanf(*range, "bytes=%[^-]-%s", s, e);
+    if (ret < 1) {
+        return NPT_FAILURE;
+    }
+    if (s[0] != '\0') {
+        NPT_ParseInteger64U(s, start);
+    }
+    if (e[0] != '\0') {
+        NPT_ParseInteger64U(e, end);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::SetRange
++---------------------------------------------------------------------*/
+void
+PLT_HttpHelper::SetRange(NPT_HttpRequest& request, NPT_Position start, NPT_Position end)
+{
+    NPT_String range = "bytes=";
+    if (start != (NPT_Position)-1) {
+        range += NPT_String::FromIntegerU(start);
+    }
+    range += '-';
+    if (end != (NPT_Position)-1) {
+        range += NPT_String::FromIntegerU(end);
+    }
+    request.GetHeaders().SetHeader(NPT_HTTP_HEADER_RANGE, range);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::ToLog
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::ToLog(NPT_LoggerReference logger, int level, NPT_HttpRequest* request)
+{
+    NPT_COMPILER_UNUSED(logger);
+    NPT_COMPILER_UNUSED(level);
+
+    if (!request) {
+        NPT_LOG_L(logger, level, "NULL HTTP Request!");
+        return NPT_FAILURE;
+    }
+
+    NPT_StringOutputStreamReference stream(new NPT_StringOutputStream);
+    NPT_OutputStreamReference output = stream;
+    request->GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output));
+
+    NPT_LOG_L4(logger, level, "\n%s %s %s\n%s", 
+        (const char*)request->GetMethod(), 
+        (const char*)request->GetUrl().ToRequestString(true), 
+        (const char*)request->GetProtocol(),
+        (const char*)stream->GetString());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::GetContentRange
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetContentRange(NPT_HttpResponse& response, 
+                                NPT_Position&     start, 
+                                NPT_Position&     end, 
+                                NPT_LargeSize&    length)
+{
+    const NPT_String* range = 
+        response.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_RANGE);
+    NPT_CHECK_POINTER(range);
+
+    start  = (NPT_Position)-1;
+    end    = (NPT_Position)-1;
+    length = (NPT_LargeSize)-1;
+
+    char s[32], e[32], l[32];
+    s[0] = '\0';
+    e[0] = '\0';
+    l[0] = '\0';
+    int ret = sscanf(*range, "bytes %[^-]-%s[^/]/%s", s, e, l);
+    if (ret < 3) {
+        return NPT_FAILURE;
+    }
+    if (s[0] != '\0') {
+        NPT_ParseInteger64U(s, start);
+    }
+    if (e[0] != '\0') {
+        NPT_ParseInteger64U(e, end);
+    }
+    if (l[0] != '\0') {
+        NPT_ParseInteger64U(l, length);
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper::SetContentRange
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetContentRange(NPT_HttpResponse& response, 
+                                NPT_Position      start, 
+                                NPT_Position      end, 
+                                NPT_LargeSize     length)
+{
+    if (start == (NPT_Position)-1 || end == (NPT_Position)-1 || length == (NPT_Size)-1) {
+        NPT_LOG_WARNING_3("Content Range is exactly -1? (start=%d, end=%d, length=%d)", start, end, length);
+    }
+
+    NPT_String range = "bytes ";
+    range += NPT_String::FromIntegerU(start);
+    range += '-';
+    range += NPT_String::FromIntegerU(end);
+    range += '/';
+    range += NPT_String::FromIntegerU(length);
+    response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, range);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse::ToLog
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::ToLog(NPT_LoggerReference logger, int level, NPT_HttpResponse* response)
+{
+    NPT_COMPILER_UNUSED(logger);
+    NPT_COMPILER_UNUSED(level);
+
+    if (!response) {
+        NPT_LOG_L(logger, level, "NULL HTTP Response!");
+        return NPT_FAILURE;
+    }
+
+    NPT_StringOutputStreamReference stream(new NPT_StringOutputStream);
+    NPT_OutputStreamReference output = stream;
+    response->GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output));
+
+    NPT_LOG_L4(logger, level, "\n%s %d %s\n%s", 
+        (const char*)response->GetProtocol(), 
+        response->GetStatusCode(), 
+        (const char*)response->GetReasonPhrase(),
+        (const char*)stream->GetString());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClient::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClient::Connect(NPT_Socket* connection, NPT_HttpRequest& request, NPT_Timeout timeout)
+{
+    // get the address of the server
+    NPT_IpAddress server_address;
+    NPT_CHECK_SEVERE(server_address.ResolveName(request.GetUrl().GetHost(), timeout));
+    NPT_SocketAddress address(server_address, request.GetUrl().GetPort());
+
+    // connect to the server
+    NPT_LOG_FINER_2("Connecting to %s:%d\n", (const char*)request.GetUrl().GetHost(), request.GetUrl().GetPort());
+    NPT_CHECK_SEVERE(connection->Connect(address, timeout));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClient::SendRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClient::SendRequest(NPT_OutputStreamReference& output_stream, 
+                            NPT_HttpRequest&           request, 
+                            NPT_Timeout                timeout)
+{
+    NPT_COMPILER_UNUSED(timeout);
+
+    // connect to the server
+    NPT_LOG_FINE("Sending:");
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+    // add any headers that may be missing
+    NPT_HttpHeaders& headers = request.GetHeaders();
+    headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close", false); // set but don't replace
+    headers.SetHeader(NPT_HTTP_HEADER_USER_AGENT, 
+                      NPT_HttpClient::m_UserAgentHeader, false); // set but don't replace
+
+    // set host only if not already set
+    if (!headers.GetHeader(NPT_HTTP_HEADER_HOST)) {
+        NPT_String host = request.GetUrl().GetHost();
+        if (request.GetUrl().GetPort() != NPT_HTTP_DEFAULT_PORT) {
+            host += ":";
+            host += NPT_String::FromInteger(request.GetUrl().GetPort());
+        }
+        headers.SetHeader(NPT_HTTP_HEADER_HOST, host);
+    }
+
+    // get the request entity to set additional headers
+    NPT_InputStreamReference body_stream;
+    NPT_HttpEntity* entity = request.GetEntity();
+    if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
+        // content length
+        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, 
+            NPT_String::FromIntegerU(entity->GetContentLength()));
+
+        // content type
+        NPT_String content_type = entity->GetContentType();
+        if (!content_type.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+        }
+
+        // content encoding
+        NPT_String content_encoding = entity->GetContentEncoding();
+        if (!content_encoding.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+        }
+    } else {
+        // force content length to 0 is there is no message body
+        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
+    }
+
+    // create a memory stream to buffer the headers
+    NPT_MemoryStream header_stream;
+
+    // emit the request headers into the header buffer
+    request.Emit(header_stream);
+
+    // send the headers
+    NPT_CHECK_SEVERE(output_stream->WriteFully(header_stream.GetData(), header_stream.GetDataSize()));
+
+    // send request body
+    if (!body_stream.IsNull() && entity->GetContentLength()) {
+        NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(*body_stream.AsPointer(), *output_stream.AsPointer()));
+    }
+
+    // flush the output stream so that everything is sent to the server
+    output_stream->Flush();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClient::WaitForResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClient::WaitForResponse(NPT_InputStreamReference&     input_stream,
+                                NPT_HttpRequest&              request, 
+                                const NPT_HttpRequestContext& context,
+                                NPT_HttpResponse*&            response)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    // create a buffered stream for this connection stream
+    NPT_BufferedInputStreamReference buffered_input_stream(new NPT_BufferedInputStream(input_stream));
+
+    // parse the response
+    NPT_CHECK(NPT_HttpResponse::Parse(*buffered_input_stream, response));
+
+    // unbuffer the stream
+    buffered_input_stream->SetBufferSize(0);
+
+    // create an entity if one is expected in the response
+    if (request.GetMethod() == NPT_HTTP_METHOD_GET || request.GetMethod() == NPT_HTTP_METHOD_POST) {
+        NPT_HttpEntity* response_entity = new NPT_HttpEntity(response->GetHeaders());
+        // Transfer-Encoding: chunked ?
+        if (response_entity->GetTransferEncoding() == "chunked") {
+            NPT_InputStreamReference body_stream(new NPT_HttpChunkedDecoderInputStream(buffered_input_stream));
+            response_entity->SetInputStream((NPT_InputStreamReference)body_stream);
+        } else {
+            response_entity->SetInputStream((NPT_InputStreamReference)buffered_input_stream);
+        }
+        response->SetEntity(response_entity);
+    }
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttp.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,157 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Helper
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_HTTP_H_
+#define _PLT_HTTP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   PLT_HttpHelper
++---------------------------------------------------------------------*/
+class PLT_HttpHelper {
+ public:
+    static bool         IsConnectionKeepAlive(NPT_HttpMessage& message);
+    static bool         IsBodyStreamSeekable(NPT_HttpMessage& message);
+
+    static NPT_Result   ToLog(NPT_LoggerReference logger, int level, NPT_HttpRequest* request);
+    static NPT_Result   ToLog(NPT_LoggerReference logger, int level, NPT_HttpResponse* response);
+
+    static NPT_Result   GetContentType(NPT_HttpMessage& message, NPT_String& type);
+    static     void     SetContentType(NPT_HttpMessage& message, const char* type);
+    static NPT_Result   GetContentLength(NPT_HttpMessage& message, NPT_LargeSize& len);
+    static void         SetContentLength(NPT_HttpMessage& message, NPT_LargeSize len);
+
+    static NPT_Result   GetHost(NPT_HttpRequest& request, NPT_String& value);
+    static void         SetHost(NPT_HttpRequest& request, const char* host);
+    static NPT_Result   GetRange(NPT_HttpRequest& request, NPT_Position& start, NPT_Position& end);
+    static void         SetRange(NPT_HttpRequest& request, NPT_Position start, NPT_Position end = (NPT_Position)-1);
+
+    static NPT_Result   GetContentRange(NPT_HttpResponse& response, NPT_Position& start, NPT_Position& end, NPT_LargeSize& length);
+    static NPT_Result   SetContentRange(NPT_HttpResponse& response, NPT_Position start, NPT_Position end, NPT_LargeSize length);
+
+    static NPT_Result   SetBody(NPT_HttpMessage& message, NPT_String& body);
+    static NPT_Result   SetBody(NPT_HttpMessage& message, const char* body, NPT_Size len);
+    static NPT_Result   SetBody(NPT_HttpMessage& message, NPT_InputStreamReference& stream, NPT_LargeSize len = 0);
+
+
+    static NPT_Result   GetBody(NPT_HttpMessage& message, NPT_String& body);
+    static NPT_Result   ParseBody(NPT_HttpMessage& message, NPT_XmlElementNode*& xml);
+};
+
+/*----------------------------------------------------------------------
+|   PLT_HttpRequestContext
++---------------------------------------------------------------------*/
+class PLT_HttpRequestContext : public NPT_HttpRequestContext {
+public:
+    // constructors and destructor
+    PLT_HttpRequestContext(NPT_HttpRequest& request) : 
+        m_Request(request) {}
+    PLT_HttpRequestContext(NPT_HttpRequest& request, const NPT_HttpRequestContext& context) :
+        NPT_HttpRequestContext(&context.GetLocalAddress(), &context.GetRemoteAddress()),
+        m_Request(request) {}
+    virtual ~PLT_HttpRequestContext() {}
+    
+    NPT_HttpRequest& GetRequest() const { return m_Request; }
+    
+private:
+    NPT_HttpRequest& m_Request;
+};
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_ENABLE_LOGGING)
+#define PLT_LOG_HTTP_MESSAGE_L(_logger, _level, _msg) \
+    PLT_HttpHelper::ToLog(_logger, _level, _msg)
+#define PLT_LOG_HTTP_MESSAGE(_level, _msg) \
+    PLT_LOG_HTTP_MESSAGE_L(_NPT_LocalLogger, _level, _msg)
+
+#else /* NPT_CONFIG_ENABLE_LOGGING */
+#define PLT_LOG_HTTP_MESSAGE_L(_logger, _level, _msg)
+#define PLT_LOG_HTTP_MESSAGE(_level, _msg)
+#endif /* NPT_CONFIG_ENABLE_LOGGING */
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClient
++---------------------------------------------------------------------*/
+class PLT_HttpClient {
+public:
+    // constructors and destructor
+    PLT_HttpClient() {}
+    virtual ~PLT_HttpClient() {}
+
+    // methods
+    NPT_Result Connect(NPT_Socket*       connection,
+                       NPT_HttpRequest&  request,
+                       NPT_Timeout       timeout = NPT_TIMEOUT_INFINITE);
+
+    NPT_Result SendRequest(NPT_OutputStreamReference& output_stream, 
+                           NPT_HttpRequest&           request,
+                           NPT_Timeout                timeout = NPT_TIMEOUT_INFINITE);
+
+    NPT_Result WaitForResponse(NPT_InputStreamReference&     input_stream,
+                               NPT_HttpRequest&              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*&            response);
+
+protected:
+    // members
+};
+
+/*----------------------------------------------------------------------
+|   PLT_HttpRequestHandler
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_HttpRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+    PLT_HttpRequestHandler<T>(T* data) : m_Data(data) {}
+    virtual ~PLT_HttpRequestHandler<T>() {}
+
+    // NPT_HttpRequestHandler methods
+    NPT_Result SetupResponse(NPT_HttpRequest&              request, 
+                             const NPT_HttpRequestContext& context,
+                             NPT_HttpResponse&             response) {
+        return m_Data->ProcessHttpRequest(request, context, response);
+    }
+
+private:
+    T* m_Data;
+};
+
+
+#endif /* _PLT_HTTP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpClientTask.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,292 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Client Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltHttpClientTask.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.clienttask")
+
+/*----------------------------------------------------------------------
+|   PLT_HttpTcpConnector::PLT_HttpTcpConnector
++---------------------------------------------------------------------*/
+PLT_HttpTcpConnector::PLT_HttpTcpConnector() :
+    NPT_HttpClient::Connector(),
+    m_Socket(new NPT_TcpClientSocket())
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpTcpConnector::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpTcpConnector::Connect(const char*                hostname, 
+                              NPT_UInt16                 port, 
+                              NPT_Timeout                connection_timeout,
+                              NPT_Timeout                io_timeout,
+                              NPT_Timeout                name_resolver_timeout,
+                              NPT_InputStreamReference&  input_stream, 
+                              NPT_OutputStreamReference& output_stream)
+{
+    if (m_HostName == hostname && m_Port == port) {
+        input_stream  = m_InputStream;
+        output_stream = m_OutputStream;
+        return NPT_SUCCESS;
+    }
+
+    // get the address and port to which we need to connect
+    NPT_IpAddress address;
+    NPT_CHECK_FATAL(address.ResolveName(hostname, name_resolver_timeout));
+
+    // connect to the server
+    NPT_LOG_FINE_2("NPT_HttpTcpConnector::Connect - will connect to %s:%d\n", hostname, port);
+    m_Socket->SetReadTimeout(io_timeout);
+    m_Socket->SetWriteTimeout(io_timeout);
+    NPT_SocketAddress socket_address(address, port);
+    NPT_CHECK_FATAL(m_Socket->Connect(socket_address, connection_timeout));
+
+    // get and keep the streams
+    NPT_CHECK(m_Socket->GetInputStream(m_InputStream));
+    NPT_CHECK(m_Socket->GetOutputStream(m_OutputStream));
+    NPT_CHECK(m_Socket->GetInfo(m_SocketInfo));
+
+    m_HostName    = hostname;
+    m_Port        = port;
+    input_stream  = m_InputStream;
+    output_stream = m_OutputStream;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClientSocketTask::PLT_HttpClientSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpClientSocketTask::PLT_HttpClientSocketTask(NPT_HttpRequest* request,
+                                                   bool             wait_forever /* = false */) :
+    m_WaitForever(wait_forever),
+    m_Connector(NULL)
+{
+    if (request) m_Requests.Push(request);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClientSocketTask::~PLT_HttpClientSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpClientSocketTask::~PLT_HttpClientSocketTask()
+{
+    // delete any outstanding requests
+    NPT_HttpRequest* request;
+    while (NPT_SUCCEEDED(m_Requests.Pop(request, false))) {
+        delete request;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::AddRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::AddRequest(NPT_HttpRequest* request)
+{
+    return m_Requests.Push(request);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::GetNextRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::GetNextRequest(NPT_HttpRequest*& request, NPT_Timeout timeout)
+{
+    return m_Requests.Pop(request, timeout);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::SetConnector
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::SetConnector(PLT_HttpTcpConnector* connector)
+{
+    NPT_AutoLock autolock(m_ConnectorLock);
+    
+    if (IsAborting(0)) return NPT_ERROR_CONNECTION_ABORTED;
+    
+    // NPT_HttpClient will delete old connector and own the new one
+    m_Client.SetConnector(connector);
+    m_Connector = connector;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::DoAbort
++---------------------------------------------------------------------*/
+void
+PLT_HttpClientSocketTask::DoAbort()
+{
+    NPT_AutoLock autolock(m_ConnectorLock);
+    if (m_Connector) m_Connector->Abort();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_HttpClientSocketTask::DoRun()
+{
+    NPT_HttpRequest*       request;
+    NPT_HttpRequestContext context;
+    bool                   using_previous_connector;
+    NPT_Result             res;
+    NPT_HttpResponse*      response;
+
+    using_previous_connector = false;
+    SetConnector(new PLT_HttpTcpConnector());
+
+    do {
+        // pop next request or wait for one for 100ms
+        if (NPT_SUCCEEDED(GetNextRequest(request, 100))) {
+            response = NULL;
+retry:
+            // if body is not seekable, don't even try to
+            // reuse previous connector since in case it fails because
+            // server closed connection, we won't be able to
+            // rewind the body to resend the request
+            if (!PLT_HttpHelper::IsBodyStreamSeekable(*request) && using_previous_connector) {
+                using_previous_connector = false;
+                if (NPT_FAILED(SetConnector(new PLT_HttpTcpConnector()))) 
+                    goto abort;
+            }
+            
+            if (IsAborting(0)) goto abort;
+
+            // send request
+            res = m_Client.SendRequest(*request, response);
+
+            // retry only if we were reusing a previous connector
+            if (NPT_FAILED(res) && using_previous_connector) {
+                using_previous_connector = false;
+                if (NPT_FAILED(SetConnector(new PLT_HttpTcpConnector()))) 
+                    goto abort;
+
+                // server may have closed socket on us
+                NPT_HttpEntity* entity = request->GetEntity();
+                NPT_InputStreamReference input_stream;
+
+                // rewind request body if any to be able to resend it
+                if (entity && NPT_SUCCEEDED(entity->GetInputStream(input_stream))) {
+                    input_stream->Seek(0);
+                }
+
+                goto retry;
+            }
+
+            NPT_LOG_FINE_1("PLT_HttpClientSocketTask receiving: res = %d", res);
+            PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, response);
+
+            // callback to process response
+            NPT_SocketInfo info;
+            m_Connector->GetInfo(info);
+            context.SetLocalAddress(info.local_address);
+            context.SetRemoteAddress(info.remote_address);
+            ProcessResponse(res, request, context, response);
+
+            // check if server says keep-alive to keep our connector
+            if (response && PLT_HttpHelper::IsConnectionKeepAlive(*response)) {
+                using_previous_connector = true;
+            } else {
+                using_previous_connector = false;
+                if (NPT_FAILED(SetConnector(new PLT_HttpTcpConnector())))
+                    goto abort;
+            }
+
+            // cleanup
+            delete response;
+            response = NULL;
+            delete request;
+            request = NULL;
+        }
+    } while (m_WaitForever && !IsAborting(0));
+    
+abort:
+    if (request) delete request;
+    if (response) delete response;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_HttpClientSocketTask::ProcessResponse(NPT_Result                    res, 
+                                          NPT_HttpRequest*              request, 
+                                          const NPT_HttpRequestContext& context, 
+                                          NPT_HttpResponse*             response) 
+{
+    NPT_COMPILER_UNUSED(request);
+    NPT_COMPILER_UNUSED(context);
+
+    NPT_LOG_FINE_1("PLT_HttpClientSocketTask::ProcessResponse (result=%d)", res);
+    NPT_CHECK_WARNING(res);
+
+    NPT_HttpEntity* entity;
+    NPT_InputStreamReference body;
+    if (!response || 
+        !(entity = response->GetEntity()) || 
+        NPT_FAILED(entity->GetInputStream(body))) {
+        return NPT_FAILURE;
+    }
+
+    // dump body into memory (if no content-length specified, read until disconnection)
+    NPT_MemoryStream output;
+    NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(*body, 
+                                            output,
+                                            0, 
+                                            entity->GetContentLength()));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileHttpClientTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileHttpClientTask::ProcessResponse(NPT_Result                    res, 
+                                        NPT_HttpRequest*              request, 
+                                        const NPT_HttpRequestContext& context, 
+                                        NPT_HttpResponse*             response) 
+{
+    NPT_COMPILER_UNUSED(res);
+    NPT_COMPILER_UNUSED(request);
+    NPT_COMPILER_UNUSED(context);
+    NPT_COMPILER_UNUSED(response);
+
+    NPT_LOG_FINE_1("PLT_FileHttpClientTask::ProcessResponse (status=%d)\n", res);
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpClientTask.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,158 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Client Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_HTTP_CLIENT_TASK_H_
+#define _PLT_HTTP_CLIENT_TASK_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+#include "PltThreadTask.h"
+
+/*----------------------------------------------------------------------
+|   PLT_HttpTcpConnector
++---------------------------------------------------------------------*/
+class PLT_HttpTcpConnector : public NPT_HttpClient::Connector
+{
+public:
+    PLT_HttpTcpConnector();
+    virtual ~PLT_HttpTcpConnector() {}
+    virtual NPT_Result Connect(const char*                   hostname, 
+                               NPT_UInt16                    port, 
+                               NPT_Timeout                   connection_timeout,
+                               NPT_Timeout                   io_timeout,
+                               NPT_Timeout                   name_resolver_timeout,
+                               NPT_InputStreamReference&     input_stream, 
+                               NPT_OutputStreamReference&    output_stream);
+
+public:
+    void    GetInfo(NPT_SocketInfo& info) { info = m_SocketInfo;}
+    void    Abort() { if (!m_Socket.IsNull()) m_Socket->Disconnect(); }
+
+private:
+    NPT_String                 m_HostName;
+    NPT_UInt16                 m_Port;
+    NPT_InputStreamReference   m_InputStream;
+    NPT_OutputStreamReference  m_OutputStream;
+    NPT_SocketInfo             m_SocketInfo;
+    NPT_Reference<NPT_Socket>  m_Socket;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClientSocketTask class
++---------------------------------------------------------------------*/
+class PLT_HttpClientSocketTask : public PLT_ThreadTask
+{
+friend class PLT_ThreadTask;
+
+public:
+    PLT_HttpClientSocketTask(NPT_HttpRequest* request = NULL, 
+                             bool             wait_forever = false);
+
+    NPT_Result AddRequest(NPT_HttpRequest* request);
+
+protected:
+    virtual ~PLT_HttpClientSocketTask();
+
+protected:
+    virtual NPT_Result SetConnector(PLT_HttpTcpConnector* connector);
+    
+    // PLT_ThreadTask methods
+    virtual void DoAbort();
+    virtual void DoRun();
+
+    virtual NPT_Result ProcessResponse(NPT_Result                    res, 
+                                       NPT_HttpRequest*              request, 
+                                       const NPT_HttpRequestContext& context,
+                                       NPT_HttpResponse*             response);
+
+private:
+    NPT_Result GetNextRequest(NPT_HttpRequest*& request, NPT_Timeout timeout);
+
+protected:
+    NPT_HttpClient              m_Client;
+    bool                        m_WaitForever;
+    NPT_Queue<NPT_HttpRequest>  m_Requests;
+    NPT_Mutex                   m_ConnectorLock;
+    PLT_HttpTcpConnector*       m_Connector;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_HttpClientTask class
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_HttpClientTask : public PLT_HttpClientSocketTask
+{
+public:
+    PLT_HttpClientTask<T>(const NPT_HttpUrl& url, T* data) : 
+        PLT_HttpClientSocketTask(new NPT_HttpRequest(url, "GET")), 
+                                 m_Data(data) {}
+ protected:
+    virtual ~PLT_HttpClientTask<T>() {}
+
+protected:
+    // PLT_HttpClientSocketTask method
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response) {
+        return m_Data->ProcessResponse(res, request, context, response);
+    }
+
+protected:
+    T* m_Data;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_FileHttpClientTask class
++---------------------------------------------------------------------*/
+class PLT_FileHttpClientTask : public PLT_HttpClientSocketTask
+{
+public:
+    PLT_FileHttpClientTask(const NPT_HttpUrl& url) : 
+        PLT_HttpClientSocketTask(new NPT_HttpRequest(url, "GET")) {}
+
+protected:
+    virtual ~PLT_FileHttpClientTask() {}
+
+protected:
+    // PLT_HttpClientSocketTask method
+    NPT_Result ProcessResponse(NPT_Result                    res, 
+                               NPT_HttpRequest*              request, 
+                               const NPT_HttpRequestContext& context, 
+                               NPT_HttpResponse*             response);
+};
+
+#endif /* _PLT_HTTP_CLIENT_TASK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpServer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,266 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Server
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltHttp.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.server")
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServer::PLT_HttpServer
++---------------------------------------------------------------------*/
+PLT_HttpServer::PLT_HttpServer(unsigned int port,
+                               bool         port_rebind   /* = false */,
+                               NPT_Cardinal max_clients   /* = 0 */,
+                               bool         reuse_address /* = false */) :
+    m_TaskManager(new PLT_TaskManager(max_clients)),
+    m_Port(port),
+    m_PortRebind(port_rebind),
+    m_ReuseAddress(reuse_address),
+    m_HttpListenTask(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServer::~PLT_HttpServer
++---------------------------------------------------------------------*/
+PLT_HttpServer::~PLT_HttpServer()
+{ 
+    delete m_TaskManager;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServer::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServer::Start()
+{
+    NPT_Result res = NPT_FAILURE;
+    
+    // if we're given a port for our http server, try it
+    if (m_Port) {
+        res = SetListenPort(m_Port, m_ReuseAddress);
+        // return right away on failure if told not to try to rebind randomly
+        if (NPT_FAILED(res) && !m_PortRebind) {
+            NPT_CHECK_SEVERE(res);
+        }
+    }
+    
+    // try random port now
+    if (!m_Port || NPT_FAILED(res)) {
+        // randomly try a port for our http server
+        int retries = 100;
+        do {    
+            int random = NPT_System::GetRandomInteger();
+            int port = (unsigned short)(50000 + (random % 15000));
+            if (NPT_SUCCEEDED(SetListenPort(port, m_ReuseAddress))) {
+                break;
+            }
+        } while (--retries > 0);
+
+        if (retries == 0) NPT_CHECK_SEVERE(NPT_FAILURE);
+    }
+
+    m_Port = m_Config.m_ListenPort;
+    
+    // start a task to listen
+    m_HttpListenTask = new PLT_HttpServerListenTask(this, &m_Socket, false);
+    m_TaskManager->StartTask(m_HttpListenTask, NULL, false);
+
+    NPT_SocketInfo info;
+    m_Socket.GetInfo(info);
+    NPT_LOG_INFO_2("HttpServer listening on %s:%d", 
+        (const char*)info.local_address.GetIpAddress().ToString(), 
+        m_Port);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServer::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServer::Stop()
+{
+    if (m_HttpListenTask) {
+        m_HttpListenTask->Kill();
+        m_HttpListenTask = NULL;
+    }
+
+    // stop all other pending tasks 
+    m_TaskManager->StopAllTasks();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServer::ProcessHttpRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_HttpServer::ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                   const NPT_HttpRequestContext& context,
+                                   NPT_HttpResponse*&            response,
+                                   bool&                         headers_only) 
+{
+    
+    NPT_LOG_INFO_3("Received %s Request from %s for %s", 
+        (const char*) request.GetMethod(),
+        (const char*) context.GetRemoteAddress().GetIpAddress().ToString(),
+        (const char*) request.GetUrl().GetPath());
+        
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+    NPT_HttpRequestHandler* handler = FindRequestHandler(request);
+    if (handler == NULL) {
+        response = new NPT_HttpResponse(404, "Not Found", NPT_HTTP_PROTOCOL_1_1);
+    } else {
+        // create a repsones object
+        response = new NPT_HttpResponse(200, "OK", NPT_HTTP_PROTOCOL_1_1);
+        response->GetHeaders().SetHeader("Server", "Platinum/" PLT_PLATINUM_VERSION_STRING);
+
+        // prepare the response
+        response->SetEntity(new NPT_HttpEntity());
+
+        // ask the handler to setup the response
+        handler->SetupResponse(request, context, *response);
+
+        // set headers_only flag
+        headers_only = (request.GetMethod()==NPT_HTTP_METHOD_HEAD);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileServer::GetMimeType
++---------------------------------------------------------------------*/
+const char* 
+PLT_FileServer::GetMimeType(const NPT_String& filename)
+{
+    int last_dot = filename.ReverseFind('.');
+    if (last_dot > 0) {
+        NPT_String extension = filename.GetChars()+last_dot+1;
+        extension.MakeLowercase();
+
+        for (unsigned int i=0; i<NPT_ARRAY_SIZE(NPT_HttpFileRequestHandler_DefaultFileTypeMap); i++) {
+            if (extension == NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].extension) {
+                return NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].mime_type;
+            }
+        }
+    }
+
+    return "application/octet-stream";
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileServer::ServeFile
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileServer::ServeFile(NPT_HttpResponse& response,
+                          NPT_String        file_path, 
+                          NPT_Position      start,
+                          NPT_Position      end,
+                          bool              request_is_head) 
+{
+    NPT_LargeSize            total_len;
+    NPT_InputStreamReference stream;
+    NPT_File                 file(file_path);
+    NPT_Result               result;
+
+    // prevent hackers from accessing files outside of our root
+    if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0)) {
+        response.SetStatus(404, "File Not Found");
+        return NPT_SUCCESS;
+    }
+
+    if (NPT_FAILED(result = file.Open(NPT_FILE_OPEN_MODE_READ)) || 
+        NPT_FAILED(result = file.GetInputStream(stream))        ||
+        NPT_FAILED(result = stream->GetSize(total_len))) {
+        // file didn't open
+        response.SetStatus(404, "File Not Found");
+        return NPT_SUCCESS;
+    } else {
+        NPT_HttpEntity* entity = new NPT_HttpEntity();
+        entity->SetContentLength(total_len);
+        response.SetEntity(entity);
+
+        // set the content type if we can
+        entity->SetContentType(GetMimeType(file_path));
+
+        // request is HEAD, returns without setting a body
+        if (request_is_head) return NPT_SUCCESS;
+
+        // see if it was a byte range request
+        if (start != (NPT_Position)-1 || end != (NPT_Position)-1) {
+            // we can only support a range from an offset to the end of the resource for now
+            // due to the fact we can't limit how much to read from a stream yet
+            NPT_Position start_offset = (NPT_Position)-1, end_offset = total_len - 1, len;
+            if (start == (NPT_Position)-1 && end != (NPT_Position)-1) {
+                // we are asked for the last N=end bytes
+                // adjust according to total length
+                if (end >= total_len) {
+                    start_offset = 0;
+                } else {
+                    start_offset = total_len-end;
+                }
+            } else if (start != (NPT_Position)-1) {
+                start_offset = start;
+                // if the end is specified but incorrect
+                // set the end_offset in order to generate a bad response
+                if (end != (NPT_Position)-1 && end < start) {
+                    end_offset = (NPT_Position)-1;
+                }
+            }
+
+            // in case the range request was invalid or we can't seek then respond appropriately
+            if (start_offset == (NPT_Position)-1 || end_offset == (NPT_Position)-1 || 
+                start_offset > end_offset || NPT_FAILED(stream->Seek(start_offset))) {
+                response.SetStatus(416, "Requested range not satisfiable");
+            } else {
+                len = end_offset - start_offset + 1;
+                response.SetStatus(206, "Partial Content");
+                PLT_HttpHelper::SetContentRange(response, start_offset, end_offset, total_len);
+
+                entity->SetInputStream(stream);
+                entity->SetContentLength(len);
+            }
+        } else {
+            entity->SetInputStream(stream);
+        }
+        return NPT_SUCCESS;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpServer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,98 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Server
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_HTTP_SERVER_H_
+#define _PLT_HTTP_SERVER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpServerListener.h"
+#include "PltHttpServerTask.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_HttpServerStartIterator;
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServer class
++---------------------------------------------------------------------*/
+class PLT_HttpServer : public PLT_HttpServerListener,
+                       public NPT_HttpServer
+{
+    friend class PLT_HttpServerTask<class PLT_HttpServer>;
+    friend class PLT_HttpServerStartIterator;
+
+public:
+    PLT_HttpServer(unsigned int port = 0,
+                   bool         port_rebind = false,
+                   NPT_Cardinal max_clients = 0,
+                   bool         reuse_address = false);
+    virtual ~PLT_HttpServer();
+
+    // PLT_HttpServerListener method
+    NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                  const NPT_HttpRequestContext& context,
+                                  NPT_HttpResponse*&            response,
+                                  bool&                         headers_only);
+
+    virtual NPT_Result   Start();
+    virtual NPT_Result   Stop();
+    virtual unsigned int GetPort() { return m_Port; }
+
+private:
+    PLT_TaskManager*          m_TaskManager;
+    unsigned int              m_Port;
+    bool                      m_PortRebind;
+    bool                      m_ReuseAddress;
+    PLT_HttpServerListenTask* m_HttpListenTask;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_FileServer class
++---------------------------------------------------------------------*/
+class PLT_FileServer
+{
+public:
+    // class methods
+    static NPT_Result ServeFile(NPT_HttpResponse& response, 
+                                NPT_String        file_path, 
+                                NPT_Position      start = (NPT_Position)-1, 
+                                NPT_Position      end = (NPT_Position)-1,
+                                bool              request_is_head = false);
+    static const char* GetMimeType(const NPT_String& filename);
+};
+
+#endif /* _PLT_HTTP_SERVER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpServerListener.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,55 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Server Listener
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#ifndef _PLT_HTTP_SERVER_LISTENER_H_
+#define _PLT_HTTP_SERVER_LISTENER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerListener Interface
++---------------------------------------------------------------------*/
+class PLT_HttpServerListener
+{
+ public:
+    virtual ~PLT_HttpServerListener() {}
+    
+    virtual NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse*&            response,
+                                          bool&                         headers_only) = 0;
+};
+
+#endif /* _PLT_HTTP_SERVER_LISTENER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpServerTask.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,294 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Server Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltHttpServerTask.h"
+#include "PltHttp.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.servertask")
+
+/*----------------------------------------------------------------------
+|   external references
++---------------------------------------------------------------------*/
+extern NPT_String HttpServerHeader;
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::PLT_HttpServerSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpServerSocketTask::PLT_HttpServerSocketTask(NPT_Socket* socket, 
+                                                   bool        stay_alive_forever) :
+    m_Socket(socket),
+    m_StayAliveForever(stay_alive_forever)
+{
+    socket->SetReadTimeout(30000);
+    socket->SetWriteTimeout(30000);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::~PLT_HttpServerSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpServerSocketTask::~PLT_HttpServerSocketTask() 
+{
+    delete m_Socket;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_HttpServerSocketTask::DoRun()
+{
+    NPT_BufferedInputStreamReference buffered_input_stream;
+    NPT_HttpRequestContext           context;
+    NPT_Result                       res = NPT_SUCCESS;
+    bool                             headers_only;
+    bool                             keep_alive = false;
+
+    // create a buffered input stream to parse http request
+    // as it comes
+    NPT_InputStreamReference input_stream;
+    NPT_CHECK_LABEL_SEVERE(GetInputStream(input_stream), done);
+    buffered_input_stream = new NPT_BufferedInputStream(input_stream);
+
+    while (!IsAborting(0)) {
+        NPT_HttpRequest*  request = NULL;
+        NPT_HttpResponse* response = NULL;
+
+        // reset keep-alive in case of failure
+        keep_alive = false;
+
+        // wait for a request
+        res = Read(buffered_input_stream, request, &context);
+        if (NPT_FAILED(res) || (request == NULL)) goto cleanup;
+
+        // callback to process request and get back a response
+        headers_only = false;
+        res = ProcessRequest(*request, context, response, headers_only);
+        if (NPT_FAILED(res) || (response == NULL)) goto cleanup;
+
+        // send back response
+        keep_alive = PLT_HttpHelper::IsConnectionKeepAlive(*request);
+        res = Write(response, keep_alive, headers_only);
+
+cleanup:
+        // cleanup
+        delete request;
+        delete response;
+
+        if (!keep_alive && !m_StayAliveForever) {
+            // if we were to support persistent connections 
+            // we would stop only if res would be a failure
+            // (like a timeout or a read/write error)
+            goto done;
+        }
+    }
+
+done:
+    return;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::GetInputStream(NPT_InputStreamReference& stream)
+{
+    return m_Socket->GetInputStream(stream);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::GetInfo(NPT_SocketInfo& info)
+{
+    return m_Socket->GetInfo(info);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::Read
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::Read(NPT_BufferedInputStreamReference& buffered_input_stream, 
+                               NPT_HttpRequest*&                 request,
+                               NPT_HttpRequestContext*           context) 
+{
+    NPT_SocketInfo info;
+    GetInfo(info);
+
+    if (context) {
+        // extract socket info
+        context->SetLocalAddress(info.local_address);
+        context->SetRemoteAddress(info.remote_address);
+    }
+
+    // parse request
+    NPT_Result res = NPT_HttpRequest::Parse(*buffered_input_stream, &info.local_address, request);
+    if (NPT_FAILED(res) || !request) {
+        // only log if not timeout
+        res = NPT_FAILED(res)?res:NPT_FAILURE;
+        if (res != NPT_ERROR_TIMEOUT && res != NPT_ERROR_EOS) NPT_CHECK_WARNING(res);
+        return res;
+    }
+
+    // read socket info again to refresh the remote address in case it was a udp socket
+    GetInfo(info);
+    if (context) {
+        context->SetLocalAddress(info.local_address);
+        context->SetRemoteAddress(info.remote_address);
+    }
+
+    // return right away if no body is expected
+    if (request->GetMethod() == NPT_HTTP_METHOD_GET || 
+        request->GetMethod() == NPT_HTTP_METHOD_HEAD) 
+        return NPT_SUCCESS;
+
+    // create an entity
+    NPT_HttpEntity* request_entity = new NPT_HttpEntity(request->GetHeaders());
+    request->SetEntity(request_entity);
+
+    // buffer body now if any
+    if (request_entity->GetContentLength() > 0) {
+        // unbuffer the stream
+        buffered_input_stream->SetBufferSize(0);
+
+        NPT_MemoryStream* body_stream = new NPT_MemoryStream();
+        NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(
+            *buffered_input_stream.AsPointer(), 
+            *body_stream, 
+            0, 
+            request_entity->GetContentLength()));
+
+        // set entity body
+        request_entity->SetInputStream((NPT_InputStreamReference)body_stream);
+
+        // rebuffer the stream
+        buffered_input_stream->SetBufferSize(NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::Write
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::Write(NPT_HttpResponse* response, 
+                                bool&             keep_alive, 
+                                bool              headers_only /* = false */) 
+{
+    // add any headers that may be missing
+    NPT_HttpHeaders& headers = response->GetHeaders();
+    const NPT_String* value = headers.GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
+    if (value) {
+        // only replace Connection header if already set and keep_alive passed not allowed
+        if (!keep_alive) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONNECTION,  "close"); // override
+        } else {
+            keep_alive =  value->Compare("keep-alive") == 0; // keep-alive ok but use whatever was set
+        }
+    } else {
+        headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, keep_alive?"keep-alive":"close");
+    }
+
+    // set user agent
+    headers.SetHeader(NPT_HTTP_HEADER_SERVER, 
+                      NPT_HttpServer::m_ServerHeader, false); // set but don't replace
+                      
+    // get the response entity to set additional headers
+    NPT_HttpEntity* entity = response->GetEntity();
+    if (entity) {
+        if (entity->HasContentLength()) {
+            // content length
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, 
+                NPT_String::FromIntegerU(entity->GetContentLength()));
+        }
+
+        // content type
+        NPT_String content_type = entity->GetContentType();
+        if (!content_type.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+        }
+
+        // content encoding
+        NPT_String content_encoding = entity->GetContentEncoding();
+        if (!content_encoding.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+        }
+    } else {
+        // force content length to 0 is there is no message body
+        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
+    }
+
+    //headers.SetHeader("DATE", "Wed, 13 Feb 2008 22:32:57 GMT");
+    //headers.SetHeader("Accept-Ranges", "bytes");
+
+    NPT_LOG_FINE("PLT_HttpServerTask Sending response:");
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, response);
+
+    // get the socket stream to send the request
+    NPT_OutputStreamReference output_stream;
+    NPT_CHECK_SEVERE(m_Socket->GetOutputStream(output_stream));
+
+    // create a memory stream to buffer the headers
+    NPT_MemoryStream header_stream;
+    
+    // emit the response headers into the header buffer
+    response->Emit(header_stream);
+
+    // send the headers
+    NPT_CHECK_SEVERE(output_stream->WriteFully(header_stream.GetData(), header_stream.GetDataSize()));
+
+    // send response body if any
+    if (!headers_only && entity) {
+        NPT_InputStreamReference body_stream;
+        entity->GetInputStream(body_stream);
+
+        if (!body_stream.IsNull()) {
+            NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(
+                *body_stream.AsPointer(), 
+                *output_stream.AsPointer(),
+                0,
+                entity->GetContentLength()));
+        }
+    }
+
+    // flush the output stream so that everything is sent to the server
+    output_stream->Flush();
+
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltHttpServerTask.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,163 @@
+/*****************************************************************
+|
+|   Platinum - HTTP Server Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_HTTP_SERVER_TASK_H_
+#define _PLT_HTTP_SERVER_TASK_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+#include "PltDatagramStream.h"
+#include "PltThreadTask.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+template <class T> class PLT_HttpListenTask;
+class PLT_HttpServerListener; 
+typedef PLT_HttpListenTask<PLT_HttpServerListener> PLT_HttpServerListenTask;
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask class
++---------------------------------------------------------------------*/
+class PLT_HttpServerSocketTask : public PLT_ThreadTask
+{
+    friend class PLT_ThreadTask;
+
+public:
+    PLT_HttpServerSocketTask(NPT_Socket* socket, bool stay_alive_forever = false);
+
+protected:
+    virtual ~PLT_HttpServerSocketTask();
+
+protected:
+    // Request callback handler
+    virtual NPT_Result ProcessRequest(NPT_HttpRequest&              request, 
+                                      const NPT_HttpRequestContext& context,
+                                      NPT_HttpResponse*&            response,
+                                      bool&                         headers_only) = 0;
+
+    // overridables
+    virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    virtual NPT_Result GetInfo(NPT_SocketInfo& info);
+
+    // PLT_ThreadTask methods
+    virtual void DoAbort() { m_Socket->Disconnect(); }
+    virtual void DoRun();
+
+private:
+    virtual NPT_Result Read(NPT_BufferedInputStreamReference& buffered_input_stream, 
+                            NPT_HttpRequest*&                 request,
+                            NPT_HttpRequestContext*           context = NULL);
+    virtual NPT_Result Write(NPT_HttpResponse* response, 
+                             bool&             keep_alive, 
+                             bool              headers_only = false);
+
+protected:
+    NPT_Socket*         m_Socket;
+    bool                m_StayAliveForever;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerTask class
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_HttpServerTask : public PLT_HttpServerSocketTask
+{
+public:
+    PLT_HttpServerTask<T>(T*          data, 
+                          NPT_Socket* socket, 
+                          bool        keep_alive = false) : 
+        PLT_HttpServerSocketTask(socket, keep_alive), m_Data(data) {}
+
+protected:
+    virtual ~PLT_HttpServerTask<T>() {}
+
+protected:
+    NPT_Result ProcessRequest(NPT_HttpRequest&              request, 
+                              const NPT_HttpRequestContext& context,
+                              NPT_HttpResponse*&            response,
+                              bool&                         headers_only) {
+        return m_Data->ProcessHttpRequest(request, context, response, headers_only);
+    }
+
+protected:
+    T* m_Data;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_HttpListenTask class
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_HttpListenTask : public PLT_ThreadTask
+{
+public:
+    PLT_HttpListenTask<T>(T* data, NPT_TcpServerSocket* socket, bool cleanup_socket = true) : 
+        m_Data(data), m_Socket(socket), m_CleanupSocket(cleanup_socket) {}
+
+protected:
+    virtual ~PLT_HttpListenTask<T>() { 
+        if (m_CleanupSocket) delete m_Socket;
+    }
+
+protected:
+    // PLT_ThreadTask methods
+    virtual void DoAbort() { m_Socket->Disconnect(); }
+    virtual void DoRun() {
+        while (!IsAborting(0)) {
+            NPT_Socket* client = NULL;
+            NPT_Result  result = m_Socket->WaitForNewClient(client, 5000);
+            if (NPT_FAILED(result) && result != NPT_ERROR_TIMEOUT) {
+                if (client) delete client;
+                //NPT_LOG_WARNING_2("PLT_HttpListenTask exiting with %d (%s)", result, NPT_ResultText(result));
+                break;
+            }
+
+            if (NPT_SUCCEEDED(result)) {
+                PLT_ThreadTask* task = new PLT_HttpServerTask<T>(m_Data, client);
+                if (NPT_FAILED(m_TaskManager->StartTask(task))) {
+                    task->Kill();
+                }
+            }
+        }
+    }
+
+protected:
+    T*                   m_Data;
+    NPT_TcpServerSocket* m_Socket;
+    bool                 m_CleanupSocket;
+};
+
+#endif /* _PLT_HTTP_SERVER_TASK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltIconsData.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,2579 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Server Device SCPDs
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+NPT_UInt8 Platinum_120x120_jpg[16096] =
+{
+  0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 
+  0xFF, 0xDB, 0x00, 0x43, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xDB, 0x00, 0x43, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xC0, 
+  0x00, 0x11, 0x08, 0x00, 0x81, 0x00, 0x81, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, 0xC4, 0x00, 
+  0x1F, 0x00, 0x00, 0x01, 0x04, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 
+  0x06, 0x07, 0x08, 0x02, 0x05, 0x09, 0x0A, 0x01, 0x00, 0x0B, 0xFF, 0xC4, 0x00, 0x49, 0x10, 0x00, 0x01, 0x03, 0x03, 0x02, 
+  0x04, 0x03, 0x04, 0x07, 0x04, 0x04, 0x0C, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x07, 0x21, 
+  0x00, 0x12, 0x31, 0x41, 0x08, 0x13, 0x51, 0x14, 0x61, 0x71, 0x81, 0x09, 0x15, 0x22, 0x32, 0x91, 0xA1, 0xB1, 0x23, 0x52, 
+  0xC1, 0xD1, 0x42, 0x72, 0xB2, 0xE1, 0x0A, 0x16, 0x17, 0x24, 0x34, 0x35, 0x62, 0x92, 0xB3, 0xD2, 0xF0, 0xF1, 0x25, 0x33, 
+  0x37, 0x45, 0x73, 0x74, 0x75, 0xFF, 0xC4, 0x00, 0x1A, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xFF, 0xC4, 0x00, 0x3B, 0x11, 0x01, 0x00, 
+  0x01, 0x03, 0x03, 0x03, 0x01, 0x06, 0x05, 0x03, 0x02, 0x06, 0x01, 0x05, 0x00, 0x00, 0x01, 0x11, 0x02, 0x21, 0x31, 0x00, 
+  0x03, 0x41, 0x12, 0x51, 0x61, 0x71, 0x22, 0x32, 0x81, 0x91, 0xB1, 0xF0, 0x04, 0x13, 0xA1, 0xC1, 0xD1, 0x42, 0xE1, 0xF1, 
+  0x52, 0x72, 0x05, 0x23, 0x62, 0x92, 0xB2, 0xD2, 0xA2, 0x14, 0x33, 0x34, 0x53, 0x83, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 
+  0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0xA3, 0xEA, 0x9A, 0x46, 0x7E, 0xD1, 0x3F, 0x2D, 0xBA, 0xFA, 0x9D, 0xBE, 
+  0x7F, 0x87, 0x1F, 0x5B, 0x22, 0x90, 0xFD, 0xC3, 0x30, 0xE7, 0xE5, 0xEA, 0x61, 0xD7, 0xB1, 0xA4, 0x15, 0x37, 0xD5, 0x5B, 
+  0x1C, 0xF7, 0x07, 0xF0, 0xC6, 0x00, 0xE0, 0x99, 0x40, 0xF0, 0x91, 0x78, 0xEF, 0x2F, 0x57, 0x6B, 0x73, 0x9F, 0x99, 0xA1, 
+  0x97, 0x37, 0x03, 0xAE, 0x76, 0xF8, 0x9E, 0xFB, 0x8C, 0x6D, 0x9F, 0x97, 0x4C, 0x9E, 0x19, 0x32, 0xCB, 0xCF, 0xBA, 0x5A, 
+  0x42, 0x3C, 0xCD, 0xFD, 0x6C, 0x97, 0xD1, 0xA1, 0xD5, 0x3B, 0xB7, 0x37, 0xC7, 0x7F, 0xE4, 0x7A, 0x1F, 0x99, 0xFC, 0xF8, 
+  0x86, 0xA6, 0xF2, 0x0C, 0x31, 0x8B, 0x19, 0xF9, 0xCF, 0xED, 0xA2, 0x13, 0x26, 0x6E, 0x79, 0x3B, 0xE8, 0x45, 0xCD, 0x38, 
+  0xFB, 0xDB, 0x9E, 0x9F, 0x0F, 0xC7, 0x3E, 0xBD, 0x8E, 0xDB, 0xF0, 0x99, 0x8B, 0x4F, 0x4A, 0x5B, 0xB0, 0x4F, 0x3C, 0x4C, 
+  0xFC, 0x7B, 0xF6, 0xD1, 0x6E, 0x71, 0xF2, 0xD0, 0x6B, 0x9F, 0x83, 0xF7, 0xBD, 0x49, 0xDF, 0xD7, 0xB8, 0xCF, 0x5F, 0x87, 
+  0xBB, 0x6E, 0x15, 0xCB, 0x4F, 0x9B, 0x7A, 0x7F, 0x19, 0xD3, 0x33, 0x89, 0xF0, 0xFF, 0x00, 0x67, 0xE5, 0xF4, 0x9D, 0x0F, 
+  0xF5, 0xA0, 0x49, 0x19, 0x39, 0x00, 0x6D, 0xBE, 0xE3, 0x3D, 0x32, 0x36, 0xDB, 0x61, 0x9F, 0x81, 0x07, 0xAF, 0x0B, 0xEE, 
+  0xD9, 0xF8, 0x6A, 0x8A, 0x2A, 0x49, 0x88, 0x26, 0x26, 0x4F, 0xA4, 0xCE, 0xAD, 0x5F, 0x85, 0x0D, 0x3A, 0x4E, 0xBC, 0x6B, 
+  0x56, 0x9A, 0x69, 0x04, 0x7A, 0xEC, 0x2B, 0x71, 0xFD, 0x40, 0xBB, 0xA8, 0x76, 0xD3, 0xF7, 0x14, 0xE6, 0x84, 0x98, 0xD4, 
+  0x36, 0x6A, 0xF2, 0x1D, 0x41, 0x99, 0xEC, 0x85, 0xD6, 0x13, 0x32, 0x51, 0x8D, 0x16, 0x69, 0x81, 0x09, 0x4F, 0xB0, 0x89, 
+  0x72, 0x9B, 0x44, 0x75, 0xBC, 0xD2, 0x56, 0x5C, 0x47, 0x2E, 0xEE, 0xF3, 0x49, 0x5C, 0x13, 0xD2, 0x32, 0x77, 0x01, 0x98, 
+  0xF3, 0x24, 0x46, 0x42, 0xF7, 0xD4, 0xEE, 0x46, 0xD6, 0xDD, 0x55, 0xB7, 0x42, 0xA8, 0xB5, 0x96, 0x60, 0x8E, 0x50, 0xB7, 
+  0xAE, 0x6D, 0x31, 0xAF, 0x43, 0x9E, 0x27, 0xBE, 0x86, 0x3B, 0x52, 0xC6, 0xD1, 0x9B, 0x8A, 0xF6, 0xD1, 0x6B, 0xD6, 0xF6, 
+  0xAF, 0xDD, 0x56, 0x45, 0xBF, 0x3A, 0xE0, 0xAB, 0x5B, 0x37, 0xCA, 0x2D, 0xF9, 0x6C, 0x5D, 0x94, 0xCA, 0x44, 0x57, 0x27, 
+  0x56, 0x53, 0x45, 0x95, 0x43, 0xA5, 0xD1, 0xDE, 0xA0, 0xD7, 0x9A, 0x84, 0xC4, 0xA9, 0x90, 0x21, 0x3C, 0x9A, 0x9D, 0x3A, 
+  0x72, 0xD8, 0xFA, 0xB4, 0xB9, 0x19, 0xE7, 0x5A, 0x97, 0xC7, 0x9F, 0xB7, 0xF8, 0xCA, 0xBA, 0x82, 0xB2, 0x05, 0xB4, 0x4C, 
+  0x4B, 0x7C, 0x3D, 0xCC, 0xB2, 0x45, 0xE3, 0x9D, 0x70, 0xD1, 0xF8, 0x95, 0xA8, 0x2A, 0x08, 0x58, 0xB5, 0xA2, 0x70, 0xDF, 
+  0x31, 0xCD, 0xCB, 0x73, 0xAF, 0x2C, 0xFA, 0x80, 0x88, 0xF0, 0x64, 0xAD, 0x4C, 0x6E, 0xD2, 0xC1, 0x29, 0x3B, 0x0E, 0x60, 
+  0x49, 0xC1, 0x29, 0x23, 0x9B, 0x9B, 0x19, 0x4A, 0x87, 0xAF, 0x50, 0x9D, 0xC8, 0xF5, 0x76, 0xF7, 0x1A, 0x80, 0x42, 0xEE, 
+  0x66, 0xE6, 0x6C, 0xC0, 0x52, 0x71, 0xF0, 0x73, 0x3A, 0xF5, 0x28, 0x07, 0xA5, 0x48, 0xF6, 0x7A, 0x5E, 0xAB, 0x65, 0x95, 
+  0x2E, 0x79, 0x27, 0x99, 0x49, 0xBC, 0x6A, 0x18, 0x91, 0x51, 0x1C, 0xEA, 0x3C, 0xD8, 0x03, 0xA1, 0xC8, 0xC0, 0x18, 0x39, 
+  0xCE, 0x46, 0xFB, 0x11, 0xE9, 0xD7, 0xAF, 0x6E, 0x35, 0xD5, 0xDC, 0x83, 0xB4, 0x94, 0xD8, 0xC0, 0x81, 0x49, 0x1D, 0xA1, 
+  0xEE, 0xF9, 0x67, 0x4E, 0x7B, 0x2A, 0x8B, 0x5E, 0xBF, 0xAE, 0xDB, 0x4A, 0xC0, 0xB3, 0x28, 0xD3, 0x6E, 0x8B, 0xDA, 0xFA, 
+  0xB8, 0xA9, 0x56, 0xA5, 0xA1, 0x6C, 0xD3, 0x7C, 0x91, 0x3A, 0xB5, 0x70, 0xD6, 0xA5, 0x37, 0x12, 0x9F, 0x4F, 0x60, 0xC9, 
+  0x71, 0x88, 0xED, 0x79, 0x8F, 0x38, 0x14, 0xF4, 0x99, 0x2F, 0x35, 0x16, 0x24, 0x74, 0xBB, 0x26, 0x4B, 0xCD, 0x30, 0xD3, 
+  0x8E, 0x27, 0x1D, 0xCD, 0xCE, 0x96, 0x1F, 0x64, 0x89, 0x96, 0xD3, 0x69, 0xFA, 0x71, 0x9C, 0x5B, 0xB4, 0xD4, 0x94, 0x8D, 
+  0x4B, 0x14, 0xD2, 0x2B, 0x52, 0x58, 0x82, 0x6E, 0x5F, 0xD2, 0x09, 0x56, 0x20, 0x67, 0x5B, 0xCD, 0x6F, 0xD3, 0x1B, 0xFB, 
+  0x40, 0xF5, 0x2E, 0xE9, 0xD1, 0xDD, 0x59, 0xB7, 0x45, 0xA3, 0xA8, 0xB6, 0x7A, 0xE9, 0xAA, 0xAC, 0xD1, 0x51, 0x54, 0xA5, 
+  0xD6, 0xE2, 0x2A, 0x2D, 0x66, 0x9B, 0x16, 0xAF, 0x48, 0xA8, 0xD3, 0x2B, 0x34, 0x79, 0x12, 0xE9, 0xB5, 0x5A, 0x5D, 0x4A, 
+  0x99, 0x36, 0x34, 0xC8, 0x73, 0xA1, 0xBE, 0xB6, 0xDC, 0x6D, 0xD2, 0x16, 0x1B, 0x79, 0x2E, 0x34, 0x99, 0xDB, 0xDE, 0xA6, 
+  0xA2, 0x69, 0xAB, 0xAA, 0x94, 0x91, 0xCC, 0xDE, 0xF1, 0x37, 0xE1, 0x02, 0xD7, 0x83, 0x0E, 0x9E, 0xDD, 0x54, 0xD7, 0x4D, 
+  0x35, 0xD3, 0x7A, 0x5B, 0x8B, 0x24, 0x5D, 0xA5, 0x22, 0x24, 0x7A, 0x88, 0xB9, 0xC6, 0x0D, 0x42, 0x8E, 0xCC, 0xCA, 0xB3, 
+  0xCF, 0x8D, 0xF7, 0xC7, 0x4E, 0xDE, 0x83, 0x07, 0x3E, 0x83, 0x60, 0x77, 0xEF, 0xC6, 0x8E, 0xE4, 0x60, 0x7F, 0xF8, 0xFE, 
+  0xF2, 0x7E, 0xFA, 0x26, 0xCC, 0x07, 0xCB, 0x17, 0xEF, 0x76, 0xF3, 0x0F, 0xC3, 0x41, 0xB9, 0x28, 0x0C, 0x1E, 0x6E, 0xA0, 
+  0x8E, 0xBB, 0xE0, 0x7C, 0x89, 0xCE, 0x3A, 0x0E, 0xFD, 0x08, 0xDF, 0x69, 0xEA, 0xA9, 0x11, 0x88, 0x99, 0x2C, 0x3F, 0xDE, 
+  0x33, 0x67, 0xE9, 0x6D, 0x13, 0x09, 0xDD, 0x78, 0x1C, 0x47, 0x08, 0x21, 0x98, 0x7B, 0x6B, 0x5E, 0xE4, 0xCC, 0x64, 0x76, 
+  0xDC, 0x6F, 0xD8, 0x80, 0x4F, 0x41, 0x8E, 0xA3, 0x71, 0xF2, 0xDB, 0x89, 0xBF, 0xDE, 0x0F, 0xE0, 0xFD, 0x25, 0xF3, 0xA9, 
+  0xEA, 0x2F, 0xD8, 0x3D, 0x6D, 0x3C, 0x44, 0xC5, 0xFB, 0xC7, 0x37, 0xEE, 0x2F, 0xB4, 0x9F, 0x51, 0xFE, 0xE9, 0xE1, 0x49, 
+  0xDC, 0xF9, 0x9A, 0x99, 0x7B, 0xD1, 0xF3, 0x75, 0x63, 0x97, 0x3B, 0x6F, 0xBD, 0x83, 0xE8, 0x08, 0x39, 0xF5, 0xD8, 0x93, 
+  0xF2, 0xCF, 0xA6, 0xDB, 0xEF, 0xC7, 0x62, 0x12, 0x5F, 0x30, 0x37, 0x2D, 0x01, 0xCD, 0xBD, 0x27, 0xEB, 0x31, 0xAC, 0xB1, 
+  0xDE, 0xFF, 0x00, 0x27, 0xF9, 0x8F, 0xD3, 0x43, 0xAA, 0x76, 0xD8, 0xCF, 0x7C, 0x1C, 0x91, 0xD3, 0xD7, 0x19, 0xED, 0xB7, 
+  0xA7, 0xAF, 0x71, 0xC2, 0xEA, 0x66, 0x66, 0xF8, 0xC4, 0x31, 0xF2, 0x8F, 0xAE, 0xA8, 0xA1, 0x89, 0x7D, 0x41, 0x21, 0x38, 
+  0xE7, 0x1C, 0xBF, 0x1D, 0x0E, 0xA9, 0xDE, 0xFD, 0xFA, 0x9C, 0x9D, 0xBA, 0x0F, 0x71, 0x39, 0xDF, 0xB9, 0xEE, 0x07, 0x0B, 
+  0xE2, 0xCF, 0x1F, 0x73, 0x6F, 0x1A, 0x3A, 0x19, 0x99, 0x31, 0x39, 0xB5, 0xEF, 0x0C, 0x5A, 0x43, 0xCE, 0x19, 0xBE, 0x74, 
+  0x32, 0xA6, 0xEE, 0x72, 0xAD, 0xB7, 0x03, 0xFB, 0x8E, 0x73, 0xE9, 0xBF, 0x0A, 0x7F, 0x9F, 0x5D, 0x5B, 0xB6, 0xF4, 0x89, 
+  0xD5, 0x3D, 0xD8, 0x0B, 0xBF, 0xD2, 0x37, 0xB5, 0xDB, 0x97, 0xED, 0x0E, 0x85, 0x72, 0x6F, 0xA9, 0x3B, 0xE4, 0x01, 0x9C, 
+  0x0F, 0x78, 0xDC, 0xE3, 0xA6, 0x77, 0xCE, 0x3F, 0x11, 0x87, 0x2F, 0x7E, 0xC7, 0xCB, 0x1A, 0xAA, 0x68, 0xA4, 0x60, 0x25, 
+  0x61, 0x7A, 0x81, 0x98, 0x23, 0x36, 0x3C, 0xC4, 0x62, 0x74, 0x0B, 0xB3, 0x39, 0x72, 0x79, 0x8F, 0x43, 0xD4, 0xEF, 0xF3, 
+  0x38, 0xEB, 0x80, 0x3B, 0x7B, 0xC6, 0xF8, 0xE1, 0x6A, 0xA0, 0x38, 0x26, 0xE4, 0x90, 0x5A, 0xE6, 0x0E, 0x7E, 0x30, 0xF6, 
+  0xBE, 0x9B, 0xF5, 0x0A, 0xA1, 0x6D, 0xB2, 0xA2, 0xA3, 0x80, 0x36, 0x19, 0xC6, 0x48, 0x19, 0x1D, 0x09, 0xE8, 0x08, 0x03, 
+  0xAF, 0x50, 0x73, 0xC4, 0x57, 0x54, 0x16, 0x61, 0xCE, 0x26, 0xDC, 0xDB, 0xFB, 0xE9, 0x2F, 0x49, 0x3F, 0x29, 0x39, 0xE2, 
+  0x1E, 0x7E, 0x87, 0x6D, 0x3F, 0xBC, 0x31, 0xEA, 0x24, 0xC4, 0x6B, 0x25, 0x56, 0xD4, 0xA7, 0x55, 0x57, 0x47, 0xBC, 0x9C, 
+  0xB6, 0xA9, 0x97, 0xF6, 0x9B, 0x54, 0x10, 0xF2, 0xDA, 0x78, 0xDD, 0x5A, 0x63, 0x5B, 0x35, 0x19, 0xD4, 0xF8, 0xCA, 0x42, 
+  0x92, 0xB3, 0x25, 0xFA, 0x15, 0x72, 0x54, 0xC6, 0x9B, 0x4A, 0xB9, 0xD6, 0x8A, 0x73, 0xC0, 0x0C, 0x24, 0x94, 0xF3, 0x52, 
+  0x1B, 0x8D, 0x74, 0x0B, 0x35, 0x52, 0x24, 0xDD, 0xEA, 0xA5, 0x6E, 0xF8, 0xA8, 0x59, 0x7B, 0xF7, 0x35, 0x8E, 0xF5, 0x43, 
+  0x45, 0x15, 0xE6, 0x92, 0xB6, 0x8D, 0xCA, 0x5C, 0x94, 0xEE, 0x10, 0x3C, 0x91, 0x34, 0x87, 0xC7, 0x8B, 0x1A, 0xF6, 0xA7, 
+  0xE1, 0xF3, 0xE9, 0x5F, 0xD3, 0xDD, 0x5A, 0xF0, 0xD3, 0x72, 0x3D, 0xA9, 0x0E, 0x33, 0x4D, 0xD5, 0x0B, 0x6E, 0xCE, 0xAB, 
+  0xD2, 0x2E, 0x18, 0xAB, 0x71, 0xA6, 0xD8, 0xAC, 0x4F, 0x6E, 0x93, 0x2A, 0x1B, 0x95, 0x03, 0x1D, 0xDE, 0x55, 0xB4, 0x97, 
+  0xC9, 0xE7, 0x7D, 0x00, 0x2D, 0xB7, 0x1C, 0x56, 0x42, 0x80, 0x5E, 0xFC, 0x55, 0x7E, 0x0E, 0xA3, 0x76, 0x98, 0xB0, 0x54, 
+  0x49, 0x0C, 0xC9, 0x0C, 0x52, 0xF9, 0xC9, 0xDA, 0x39, 0xD7, 0x99, 0x5E, 0xCB, 0x4D, 0x47, 0x48, 0xD5, 0x4B, 0x0D, 0x29, 
+  0xCC, 0xFF, 0x00, 0x49, 0x7C, 0xF6, 0x96, 0x53, 0x5E, 0x20, 0x2F, 0xAD, 0x44, 0x87, 0x5A, 0xAF, 0xD4, 0x5A, 0x88, 0xE2, 
+  0x56, 0xC2, 0xD1, 0x4E, 0xA9, 0xC6, 0xF2, 0xD5, 0x90, 0x63, 0xD5, 0x69, 0xEC, 0x49, 0x40, 0x46, 0x4E, 0x0A, 0x4B, 0xDE, 
+  0xD0, 0x12, 0x53, 0xB6, 0x47, 0x41, 0x93, 0xC7, 0x65, 0x29, 0x4A, 0x2C, 0x0A, 0x72, 0x48, 0x29, 0xDB, 0x98, 0x26, 0xE4, 
+  0xDF, 0x18, 0x75, 0xED, 0xAF, 0x45, 0x03, 0x52, 0xC8, 0xD5, 0x49, 0x1C, 0x34, 0xA8, 0xF8, 0xF2, 0xA6, 0x64, 0x88, 0xBC, 
+  0x30, 0x5F, 0xA9, 0xE5, 0xA5, 0x10, 0xA2, 0x0F, 0xEE, 0x93, 0x90, 0x3B, 0xF6, 0xEF, 0xD8, 0xFA, 0x1D, 0xFB, 0xF1, 0x6D, 
+  0x7C, 0xB5, 0x2D, 0xE4, 0x25, 0x3B, 0x98, 0xB6, 0x1C, 0x29, 0xAC, 0xFA, 0xCE, 0x95, 0xBC, 0xCD, 0xB1, 0x72, 0xF2, 0xA6, 
+  0x48, 0x4F, 0x8D, 0xBE, 0x0D, 0xFB, 0x67, 0x57, 0x35, 0x1B, 0x4A, 0xF5, 0x46, 0xCE, 0xD4, 0x2D, 0x2C, 0xAA, 0x2E, 0x97, 
+  0xA8, 0xDA, 0x7E, 0xB9, 0x57, 0xC5, 0x87, 0x35, 0x08, 0x0E, 0xA9, 0xBB, 0x96, 0xD3, 0x93, 0x4E, 0xAD, 0x84, 0x25, 0xA5, 
+  0xA5, 0x69, 0x79, 0x4F, 0xD1, 0x21, 0xD6, 0xDB, 0x53, 0x45, 0x0A, 0x0E, 0xB3, 0xE7, 0x20, 0x82, 0x09, 0xC6, 0x2D, 0x4D, 
+  0x4B, 0x4A, 0x53, 0x54, 0xD3, 0x54, 0x09, 0x94, 0x27, 0xA7, 0xCC, 0x9C, 0x4C, 0xD4, 0x76, 0xD2, 0xFC, 0xCA, 0x5A, 0x2A, 
+  0xA3, 0x70, 0x2A, 0xA6, 0xA5, 0x2A, 0x9B, 0x59, 0x13, 0x27, 0x25, 0x50, 0xCE, 0x6D, 0x6D, 0x11, 0xA8, 0xFA, 0xD7, 0xAA, 
+  0x9A, 0xCD, 0xAB, 0xF7, 0x4D, 0xFF, 0x00, 0xAC, 0x97, 0x3C, 0x9B, 0xBB, 0x54, 0x2B, 0xB1, 0xE1, 0x4E, 0xBF, 0xEB, 0x4F, 
+  0xA9, 0x20, 0x37, 0x71, 0xD4, 0x98, 0x6A, 0x4B, 0x16, 0xEC, 0x56, 0x50, 0x12, 0xD4, 0x78, 0x76, 0x85, 0xB0, 0xDD, 0xB9, 
+  0x42, 0x6E, 0x23, 0x69, 0xF2, 0xE2, 0xC9, 0x62, 0x73, 0x21, 0x21, 0x68, 0x58, 0x08, 0x4F, 0x70, 0xA4, 0xA7, 0xA0, 0xA7, 
+  0xA8, 0x31, 0x2C, 0x55, 0xD2, 0x3C, 0x01, 0x02, 0x77, 0x52, 0x64, 0x75, 0x25, 0x61, 0x47, 0x46, 0xD5, 0x26, 0xDD, 0x33, 
+  0x3C, 0xAA, 0x79, 0x9B, 0xCD, 0x4B, 0x54, 0xC6, 0x24, 0xF5, 0xD2, 0x0D, 0xCB, 0x52, 0x92, 0x30, 0xA2, 0x7A, 0x83, 0xB9, 
+  0x00, 0xEC, 0x37, 0x27, 0x23, 0x3B, 0xEC, 0x7E, 0x3B, 0x8E, 0x35, 0x2B, 0xEF, 0xF7, 0xF7, 0x7F, 0x97, 0x2E, 0xA6, 0x5E, 
+  0xEF, 0x7F, 0xBB, 0xFD, 0xA5, 0xB9, 0xD6, 0x4A, 0x92, 0x7D, 0x73, 0xB1, 0xD8, 0x91, 0xCA, 0x77, 0xDF, 0xB1, 0xE9, 0xDB, 
+  0xAE, 0x4F, 0xB8, 0x6C, 0x35, 0xE2, 0xC6, 0x49, 0xCC, 0xC4, 0xF6, 0x88, 0xED, 0xCD, 0xB3, 0x6D, 0x3E, 0xA6, 0xC5, 0xA0, 
+  0xE3, 0xED, 0x99, 0xF8, 0xE6, 0xFA, 0x19, 0x6F, 0x9E, 0x84, 0xFB, 0x86, 0xF8, 0xC0, 0xDF, 0x7C, 0x8D, 0xFD, 0x01, 0xCE, 
+  0x07, 0x5E, 0x9B, 0x01, 0x2D, 0x4B, 0xF2, 0x8C, 0xB3, 0xF0, 0xB8, 0x03, 0xDA, 0x3F, 0x9D, 0x4E, 0x92, 0xF3, 0x8F, 0xA0, 
+  0xFC, 0x47, 0xFC, 0xDC, 0x4C, 0xD5, 0xDE, 0x9F, 0xFB, 0x0F, 0xE7, 0x46, 0xA7, 0x95, 0xCC, 0x3D, 0xCF, 0xBF, 0x07, 0x6C, 
+  0x7B, 0x8F, 0x40, 0x32, 0x7A, 0x7B, 0xBA, 0xF5, 0xE3, 0xD1, 0xB5, 0xA2, 0x7C, 0xFF, 0x00, 0x6D, 0x74, 0xC1, 0x25, 0xC0, 
+  0xA5, 0x60, 0xA7, 0xA8, 0xE3, 0x29, 0x24, 0xF1, 0xC9, 0x7B, 0xB3, 0xA4, 0x15, 0x33, 0x24, 0x9C, 0xEC, 0x7D, 0x0F, 0x4E, 
+  0xA3, 0x61, 0xDB, 0x39, 0xDF, 0xAF, 0xC7, 0x85, 0xA2, 0xDE, 0xB3, 0xC5, 0xED, 0xF2, 0x8F, 0xD3, 0x48, 0x2A, 0x6E, 0x4E, 
+  0xCB, 0xC0, 0xDB, 0xA1, 0xC1, 0xEF, 0xD3, 0xE3, 0xEE, 0x19, 0xF4, 0xDF, 0x27, 0x83, 0xEF, 0xEF, 0xFB, 0xE8, 0x98, 0x33, 
+  0x7E, 0xD1, 0x8F, 0x23, 0xDE, 0xC7, 0x9D, 0x0E, 0xA9, 0x80, 0x83, 0xB8, 0xC1, 0xDC, 0x9C, 0xE0, 0x9C, 0x76, 0xC7, 0x51, 
+  0xF9, 0x74, 0x19, 0xCF, 0x06, 0x89, 0x7B, 0xBF, 0xE7, 0x43, 0xAE, 0x67, 0x30, 0xC0, 0x3B, 0x01, 0x9D, 0xCE, 0xF8, 0xE9, 
+  0xD7, 0x38, 0xEB, 0xD3, 0x04, 0x91, 0xB6, 0x31, 0x8E, 0x06, 0xD9, 0xE6, 0x39, 0xEF, 0x89, 0xED, 0x3C, 0x4E, 0x96, 0x65, 
+  0xF8, 0xE8, 0x67, 0x64, 0x13, 0xFD, 0x2D, 0x80, 0x04, 0x6F, 0xD0, 0xE7, 0xD7, 0xB1, 0x3E, 0x9B, 0xED, 0xC0, 0xDA, 0x7B, 
+  0xF6, 0xD3, 0x87, 0xF6, 0xF9, 0xE2, 0xD9, 0xBE, 0x9B, 0x55, 0x67, 0x14, 0xA6, 0x54, 0x32, 0x72, 0x93, 0x91, 0x82, 0x09, 
+  0xC6, 0xF9, 0x03, 0x07, 0xA6, 0xE3, 0x38, 0x1B, 0x8E, 0xF8, 0xE3, 0x9F, 0x75, 0xF7, 0xBC, 0x40, 0x7A, 0x4C, 0x76, 0xE5, 
+  0x9E, 0xFE, 0x35, 0x35, 0xFB, 0xB7, 0x98, 0x5B, 0x7C, 0x33, 0xCD, 0xB1, 0xAA, 0xC3, 0x7E, 0xDD, 0xB5, 0xFD, 0x33, 0xB9, 
+  0xEC, 0xDD, 0x5F, 0xB5, 0x8B, 0x82, 0xE1, 0xD2, 0xFB, 0x9A, 0x9B, 0x77, 0xC4, 0x6D, 0x1F, 0x68, 0xCE, 0x83, 0x4F, 0x5A, 
+  0xDA, 0xAF, 0x51, 0xDD, 0x46, 0xC1, 0xC8, 0xF5, 0xBB, 0x7A, 0x45, 0x56, 0x96, 0xEB, 0x2A, 0xE6, 0x43, 0x86, 0x4A, 0x32, 
+  0x3E, 0xC8, 0xC7, 0x15, 0x75, 0xD5, 0xB7, 0x55, 0x1B, 0xB4, 0xCC, 0xED, 0x55, 0xD5, 0x04, 0xFB, 0x54, 0x90, 0xD4, 0x31, 
+  0x93, 0xA6, 0x78, 0xB3, 0x39, 0xCE, 0xB9, 0x77, 0x09, 0xA1, 0xEC, 0x17, 0x0E, 0x69, 0xC2, 0x7C, 0xAE, 0x46, 0x18, 0xD5, 
+  0xD2, 0xF1, 0x1D, 0xAD, 0xF5, 0xDB, 0x22, 0xB8, 0xCD, 0xDB, 0xA6, 0xD5, 0x82, 0x9B, 0x1B, 0x5B, 0x2C, 0x88, 0xF7, 0x14, 
+  0x35, 0xC4, 0x6B, 0xCD, 0x69, 0xE6, 0xAB, 0x34, 0xD6, 0x66, 0xA0, 0x2E, 0x43, 0x88, 0x24, 0x33, 0xE4, 0xBC, 0xD7, 0x98, 
+  0xCA, 0x31, 0xCE, 0xF0, 0xC3, 0x8B, 0x0D, 0x80, 0x13, 0xDD, 0xF8, 0xAD, 0xDA, 0x68, 0x28, 0xAE, 0x81, 0x8D, 0xCA, 0x3A, 
+  0x84, 0xB8, 0x89, 0x37, 0x02, 0x6C, 0x7C, 0xE3, 0x29, 0x95, 0xF8, 0x7A, 0xC2, 0x92, 0x9A, 0xA9, 0xEB, 0xAB, 0x6E, 0xA6, 
+  0x16, 0xA6, 0x1A, 0x4E, 0x48, 0x85, 0x99, 0x18, 0x64, 0xCD, 0xF5, 0x4F, 0x68, 0x35, 0x77, 0x45, 0x52, 0x86, 0x85, 0x3A, 
+  0xA5, 0x17, 0x34, 0xD7, 0x4E, 0x9F, 0x59, 0x59, 0xCA, 0x96, 0xE4, 0x8A, 0x64, 0xD7, 0x5E, 0x59, 0xED, 0xCC, 0x56, 0xA5, 
+  0x73, 0x1D, 0xB7, 0x18, 0xC0, 0xC0, 0x03, 0x8C, 0xAA, 0x6A, 0x26, 0xFF, 0x00, 0xF2, 0xF6, 0x92, 0x00, 0x09, 0xA5, 0xC7, 
+  0xD6, 0xD3, 0x9B, 0xEB, 0x4E, 0xA6, 0xB6, 0xA6, 0xA4, 0x56, 0xA6, 0x63, 0x03, 0xC8, 0x78, 0xFD, 0x42, 0x09, 0xB6, 0xA6, 
+  0x06, 0xDF, 0x2E, 0x35, 0x82, 0x01, 0x27, 0x04, 0xE3, 0xAF, 0x63, 0xB7, 0xE9, 0x9F, 0x43, 0xC5, 0xF8, 0x96, 0x3B, 0x4D, 
+  0xB4, 0x69, 0x8F, 0x70, 0xD1, 0xD7, 0x35, 0xF8, 0xD2, 0x58, 0x95, 0x32, 0x0C, 0xD8, 0x32, 0x5B, 0x99, 0x02, 0x7D, 0x3E, 
+  0x53, 0xF0, 0xA7, 0xC0, 0x94, 0xC9, 0xE6, 0x6E, 0x4C, 0x29, 0x91, 0x56, 0xD4, 0x88, 0xCF, 0x37, 0x95, 0x04, 0xB8, 0xD3, 
+  0x88, 0x5E, 0x14, 0xA4, 0xF3, 0x72, 0xAD, 0x41, 0x53, 0x03, 0x1C, 0x24, 0x22, 0x4C, 0x8B, 0x61, 0x1B, 0x33, 0x6C, 0xF1, 
+  0x17, 0xC6, 0x91, 0x0D, 0x3E, 0x55, 0xE2, 0xC8, 0x58, 0xBB, 0x79, 0xB6, 0x62, 0xF6, 0x8D, 0x0D, 0x41, 0xA3, 0x26, 0x96, 
+  0x95, 0x84, 0x17, 0x56, 0xB7, 0x5D, 0x76, 0x44, 0x87, 0xDF, 0x71, 0xC9, 0x12, 0x24, 0xC9, 0x79, 0xC5, 0xBA, 0xF4, 0x89, 
+  0x32, 0x1E, 0x53, 0x8F, 0x48, 0x90, 0xFB, 0xCE, 0x2D, 0xE7, 0x9D, 0x75, 0xC5, 0x38, 0xEB, 0xAB, 0x5B, 0x8E, 0x2D, 0x4A, 
+  0x52, 0x94, 0x40, 0x29, 0x23, 0xCC, 0x0B, 0x2A, 0xAE, 0x65, 0xBB, 0x77, 0xBA, 0xFC, 0xA3, 0x4E, 0x39, 0xE6, 0xD1, 0x76, 
+  0x63, 0x9B, 0x44, 0x5E, 0xDE, 0x74, 0xF5, 0x43, 0xBC, 0x8D, 0x80, 0x0F, 0x6C, 0x6D, 0x9C, 0x1C, 0xF7, 0x04, 0x6F, 0xD3, 
+  0xD7, 0x6E, 0x2B, 0xEF, 0xE5, 0xA3, 0x5F, 0x0B, 0xFE, 0xFF, 0x00, 0xCC, 0x9F, 0xD3, 0x83, 0x46, 0x90, 0x5C, 0x8F, 0xFB, 
+  0x7E, 0xB9, 0xDF, 0x6F, 0x99, 0xED, 0xEB, 0xC1, 0xA3, 0x48, 0x7B, 0x4A, 0x7F, 0x7C, 0x7E, 0x29, 0xFE, 0x7C, 0x1A, 0x35, 
+  0x35, 0x19, 0x5B, 0xEC, 0xAF, 0x76, 0xD9, 0xC7, 0xA7, 0xC8, 0x83, 0xEB, 0xB7, 0x7E, 0xFC, 0x77, 0xA8, 0x31, 0x97, 0xC5, 
+  0xE3, 0xD6, 0x3F, 0xCF, 0x8D, 0x74, 0xC7, 0x90, 0xED, 0x3C, 0xFD, 0xF9, 0xD2, 0x66, 0x59, 0xDC, 0x67, 0x63, 0x9C, 0x8C, 
+  0xF6, 0x3D, 0x7A, 0x9E, 0xF9, 0xDB, 0x3E, 0xBD, 0x3A, 0x70, 0xC4, 0xBC, 0x64, 0x0B, 0xCD, 0xA5, 0xF0, 0x42, 0x27, 0x99, 
+  0xBF, 0x11, 0xA5, 0xA4, 0x55, 0x27, 0x24, 0xE4, 0x8F, 0x76, 0xFD, 0x07, 0xBC, 0xF6, 0xDC, 0x7E, 0x67, 0xDD, 0xC4, 0x35, 
+  0x25, 0xA1, 0x1F, 0x17, 0xF8, 0x62, 0xE7, 0x78, 0x6C, 0x73, 0xAA, 0xB5, 0xAF, 0x79, 0x3D, 0xE0, 0x06, 0x7E, 0x67, 0xCF, 
+  0xE1, 0xA1, 0x97, 0x28, 0xEE, 0x79, 0x8E, 0x3E, 0xEF, 0x43, 0x8C, 0x83, 0xD3, 0x19, 0x1D, 0x3A, 0x9E, 0xFB, 0xF6, 0xDF, 
+  0x84, 0xD6, 0xDA, 0x0C, 0xDE, 0x6E, 0x23, 0x7B, 0x16, 0xB9, 0x21, 0x99, 0xE6, 0x24, 0x74, 0x9E, 0x7B, 0x0C, 0x7C, 0x78, 
+  0x26, 0xDE, 0x3E, 0xB1, 0x7D, 0x02, 0xE5, 0x4D, 0xA6, 0x81, 0x2B, 0x5A, 0x42, 0x53, 0x95, 0x12, 0x4F, 0xDD, 0xE5, 0x07, 
+  0x99, 0x4A, 0xDC, 0x8C, 0x80, 0x32, 0x76, 0x3D, 0x31, 0xDC, 0x71, 0x9B, 0x54, 0x5D, 0xA9, 0x26, 0xD9, 0xCF, 0xEF, 0x69, 
+  0xE3, 0x12, 0xBA, 0x5D, 0x45, 0xAE, 0x2B, 0x88, 0xF5, 0xF9, 0x7C, 0x31, 0x16, 0x2F, 0x89, 0xB6, 0xD8, 0xD1, 0x7D, 0x5A, 
+  0xB9, 0x74, 0x7A, 0xB7, 0xE2, 0x02, 0x97, 0xA6, 0x97, 0x5D, 0x5F, 0x45, 0x2D, 0x7B, 0x80, 0x5A, 0x97, 0x5E, 0xA5, 0x51, 
+  0xD8, 0x89, 0x57, 0xA1, 0x5A, 0x55, 0xC3, 0x06, 0x9D, 0x51, 0x43, 0x17, 0x54, 0x6A, 0x7C, 0xB7, 0xAB, 0x56, 0xE4, 0x25, 
+  0x44, 0xAB, 0x53, 0x1C, 0x4D, 0x76, 0xAD, 0x4C, 0x8F, 0x6F, 0x85, 0xCC, 0x65, 0x95, 0x55, 0x43, 0xA5, 0x48, 0x4B, 0xAB, 
+  0x7A, 0x2A, 0x09, 0xA2, 0x91, 0xF6, 0xC1, 0x95, 0xAA, 0x09, 0x42, 0x56, 0x60, 0x6E, 0x5A, 0x2E, 0xC7, 0x77, 0xD7, 0x41, 
+  0x5D, 0x3B, 0x6D, 0x54, 0x95, 0x27, 0x55, 0x34, 0xD4, 0x43, 0x59, 0x28, 0x42, 0xC0, 0xB9, 0xF6, 0x64, 0x5F, 0x2E, 0xA3, 
+  0x4A, 0xED, 0x05, 0xD4, 0x30, 0xA5, 0xB4, 0x8E, 0x74, 0x29, 0x3C, 0xC8, 0x5A, 0x47, 0xF4, 0x54, 0x01, 0x49, 0xC8, 0xC8, 
+  0xDC, 0x1E, 0xA3, 0xB1, 0x04, 0x6D, 0xB9, 0xCD, 0xAC, 0xA8, 0xA9, 0x98, 0x9C, 0x43, 0x03, 0x2D, 0xB3, 0x01, 0x31, 0x89, 
+  0x96, 0xEF, 0x94, 0xDC, 0x3A, 0x8B, 0x11, 0x2B, 0x97, 0xCF, 0x3D, 0xBE, 0xFC, 0x3A, 0xAC, 0xBA, 0x87, 0x49, 0xF6, 0x88, 
+  0x72, 0x98, 0x71, 0xAE, 0x64, 0xAD, 0xB7, 0x12, 0xB0, 0x40, 0x50, 0x51, 0xE5, 0x3F, 0x67, 0x1B, 0x9E, 0xF9, 0xC9, 0xC0, 
+  0xDB, 0xAE, 0x3A, 0xF3, 0xD6, 0x48, 0x98, 0x65, 0xF8, 0x70, 0xFA, 0x0E, 0x5C, 0xC8, 0xCC, 0x76, 0xE7, 0x66, 0xF4, 0xB1, 
+  0x34, 0xB0, 0x17, 0x98, 0x6D, 0x57, 0x84, 0x99, 0x99, 0x71, 0x11, 0xA6, 0x1B, 0xD5, 0x99, 0x77, 0x27, 0x84, 0x5B, 0x46, 
+  0x93, 0x2D, 0xD5, 0x3B, 0x53, 0xD0, 0xCD, 0x51, 0xAC, 0xE9, 0x8B, 0x6E, 0x2C, 0xF3, 0xB8, 0x9B, 0x62, 0xAE, 0x86, 0xEE, 
+  0x3B, 0x44, 0x2F, 0x39, 0x21, 0xA4, 0xD2, 0xAA, 0x8A, 0xA7, 0xB2, 0x09, 0x28, 0x50, 0xA7, 0xA8, 0x00, 0xAF, 0x2C, 0x81, 
+  0x2D, 0x7D, 0x7F, 0x83, 0xA6, 0x95, 0xF6, 0xB6, 0x37, 0x6A, 0xDA, 0x89, 0x67, 0xA6, 0xAF, 0x68, 0xF3, 0x69, 0x82, 0xF3, 
+  0x9B, 0x44, 0x47, 0x35, 0x07, 0x4D, 0x68, 0x70, 0xA7, 0x88, 0x26, 0x08, 0x99, 0xB1, 0xF0, 0x93, 0x5A, 0xEB, 0x45, 0xD7, 
+  0x16, 0xFD, 0xB0, 0xEA, 0xF2, 0x54, 0xAD, 0x3F, 0xB7, 0x23, 0x12, 0x41, 0x49, 0x4B, 0x94, 0x9A, 0xCD, 0xD5, 0x48, 0x75, 
+  0xB2, 0x49, 0xCF, 0x33, 0x0A, 0x84, 0x1B, 0x56, 0x7D, 0x06, 0x09, 0x04, 0x71, 0x3B, 0x6F, 0xB4, 0x75, 0x5D, 0xFC, 0xBD, 
+  0xBC, 0xC2, 0xC9, 0x55, 0x74, 0x85, 0xB9, 0x22, 0x23, 0x88, 0x9D, 0x6B, 0x4D, 0xBA, 0xA5, 0xB4, 0xB2, 0xE3, 0xBA, 0xAF, 
+  0xAF, 0x89, 0x67, 0x8D, 0x58, 0x08, 0x4F, 0x7E, 0xCD, 0x39, 0x3F, 0xD1, 0x03, 0x63, 0x9C, 0x90, 0x07, 0xBF, 0x6C, 0x91, 
+  0xEB, 0xEF, 0xC9, 0xED, 0xB0, 0xCC, 0xFA, 0xC7, 0x6F, 0xB8, 0xFD, 0x53, 0x54, 0xF5, 0x1C, 0x5E, 0x61, 0x11, 0x22, 0x32, 
+  0x5C, 0xBA, 0x77, 0xED, 0xE7, 0x4B, 0x38, 0x42, 0xBE, 0xD2, 0x80, 0xCF, 0x4C, 0xF7, 0x39, 0xC0, 0xC6, 0x7B, 0x9F, 0x4F, 
+  0xD3, 0x81, 0xE2, 0xDC, 0xFC, 0x4C, 0xC6, 0x31, 0x7F, 0xAE, 0x9E, 0x87, 0x2A, 0x03, 0xA9, 0xE0, 0x00, 0xC7, 0xA3, 0xA7, 
+  0x0C, 0x4C, 0x5B, 0x03, 0x6B, 0xF7, 0x8E, 0x6D, 0xCB, 0x10, 0x49, 0xA4, 0xD4, 0xEE, 0xD8, 0x07, 0x18, 0x39, 0xFE, 0x1D, 
+  0x37, 0xF5, 0xCF, 0xE7, 0x8E, 0xFC, 0x3D, 0x2D, 0x0E, 0xB7, 0xC2, 0x7A, 0x93, 0xBE, 0x76, 0x39, 0x39, 0xF5, 0xD8, 0x7E, 
+  0xA7, 0x6E, 0x14, 0xF8, 0xB9, 0x9C, 0xC0, 0xF6, 0x98, 0x8D, 0x1A, 0x11, 0x72, 0xB3, 0xB0, 0xC7, 0x5E, 0xA7, 0x7F, 0x5F, 
+  0xE8, 0x8C, 0x6F, 0xF1, 0x3E, 0xEE, 0x1F, 0xC7, 0xEF, 0xEF, 0xD7, 0x47, 0xF7, 0xFE, 0xDF, 0x2D, 0x23, 0xED, 0x4E, 0x7E, 
+  0xFA, 0xBF, 0x04, 0xF0, 0x68, 0xD4, 0xC1, 0xED, 0x60, 0x67, 0x24, 0x67, 0x3D, 0x46, 0x37, 0x27, 0x3D, 0xBB, 0xED, 0xD7, 
+  0x71, 0x9C, 0x67, 0xD7, 0x8E, 0x86, 0x5E, 0x5F, 0x12, 0xAF, 0xAF, 0x27, 0xC0, 0xE3, 0xE1, 0xAE, 0x82, 0xAE, 0x0C, 0xDB, 
+  0x0F, 0x4C, 0xE4, 0xB2, 0xCD, 0xA2, 0x5E, 0xDE, 0x75, 0x87, 0xB6, 0x24, 0x6C, 0x0E, 0x09, 0x19, 0x00, 0xF5, 0x24, 0x7E, 
+  0x78, 0xDB, 0x1D, 0x3F, 0x2E, 0x08, 0x59, 0x89, 0xB4, 0x4E, 0x71, 0x01, 0x96, 0x78, 0xFD, 0xF1, 0x7D, 0x2E, 0xB2, 0x62, 
+  0x03, 0x33, 0x29, 0x56, 0x30, 0x58, 0xB3, 0xE1, 0xB7, 0x1A, 0xCB, 0xDA, 0x49, 0xDB, 0x3D, 0x72, 0x70, 0x00, 0x38, 0x4E, 
+  0x33, 0x92, 0x70, 0x41, 0xDF, 0x73, 0xB1, 0xEF, 0xBE, 0x76, 0xE1, 0x08, 0xE1, 0x1F, 0x46, 0x75, 0x3F, 0x99, 0xDB, 0x3E, 
+  0x41, 0x23, 0x9E, 0x73, 0xDA, 0xDF, 0x2D, 0x20, 0xF2, 0xD7, 0xCB, 0x93, 0x91, 0xB6, 0xC7, 0x7C, 0x60, 0x9E, 0xD8, 0xC6, 
+  0x09, 0x1D, 0x4E, 0x09, 0x19, 0x38, 0xDB, 0x85, 0x55, 0x40, 0x59, 0xBD, 0xF9, 0x2D, 0xE7, 0xEC, 0xF8, 0xEA, 0x7A, 0xDE, 
+  0x6E, 0xDE, 0x2F, 0x21, 0xE8, 0x71, 0x78, 0x94, 0xBC, 0x7A, 0xE9, 0x9F, 0x57, 0x90, 0xA4, 0xB4, 0xE0, 0xE6, 0xC6, 0x52, 
+  0x52, 0x71, 0xB6, 0x32, 0x0E, 0xC4, 0xE3, 0xDD, 0x9C, 0x1E, 0xE3, 0x1B, 0x0E, 0x30, 0x73, 0xE5, 0x57, 0xE3, 0xDF, 0xF6, 
+  0xB4, 0x59, 0xB4, 0x6A, 0x2E, 0xCE, 0x56, 0x16, 0x66, 0xE4, 0x5E, 0x4E, 0xE1, 0xDB, 0x11, 0x2F, 0x7D, 0x4A, 0xFE, 0x0D, 
+  0xBE, 0x90, 0xCD, 0x49, 0xF0, 0x23, 0xA9, 0xA9, 0xAE, 0xC0, 0xAC, 0x26, 0x8F, 0x6D, 0x55, 0x61, 0x22, 0xD8, 0xB8, 0x2B, 
+  0x13, 0xE9, 0x72, 0xAE, 0xDD, 0x39, 0xBB, 0xEC, 0x75, 0x87, 0x19, 0xFF, 0x00, 0x27, 0x7E, 0x23, 0x74, 0xCA, 0x3F, 0x32, 
+  0xAF, 0x6B, 0x06, 0x2C, 0x59, 0x12, 0x60, 0x50, 0x75, 0x0E, 0xD8, 0x43, 0x5A, 0x97, 0xA7, 0x34, 0xE7, 0x95, 0x1D, 0x2D, 
+  0x5C, 0xD6, 0xEC, 0x63, 0x4D, 0x44, 0x55, 0x5D, 0x0F, 0xFC, 0xBD, 0xE6, 0x1C, 0xED, 0xD6, 0x4D, 0x2D, 0x2C, 0xB0, 0xBC, 
+  0xCD, 0x2C, 0x05, 0x54, 0xCB, 0x10, 0x45, 0x41, 0x09, 0xB8, 0x1B, 0xB4, 0xC5, 0x67, 0x53, 0x33, 0x6B, 0x34, 0xD5, 0xFE, 
+  0xBA, 0x2A, 0x5F, 0x65, 0x5B, 0xB4, 0xFB, 0x95, 0x25, 0xFA, 0x73, 0xAF, 0x41, 0x16, 0x8F, 0x83, 0x0F, 0x0B, 0x1F, 0x48, 
+  0xA5, 0x1A, 0x5D, 0xEB, 0xE0, 0x7E, 0xEF, 0xB7, 0x3C, 0x3E, 0xEB, 0x7C, 0xBA, 0x12, 0x6F, 0x3B, 0x97, 0xC1, 0xEE, 0xA0, 
+  0x57, 0x19, 0xB8, 0x74, 0xCA, 0xB5, 0x4C, 0x98, 0x9F, 0x31, 0x57, 0xB7, 0x87, 0x1D, 0x4D, 0xA2, 0x32, 0xFA, 0xAA, 0x5A, 
+  0x5F, 0x55, 0x90, 0xA2, 0x69, 0xD3, 0x29, 0x34, 0xFA, 0xED, 0x12, 0x84, 0xFB, 0xC8, 0xA5, 0xD7, 0xAD, 0xFD, 0x38, 0x90, 
+  0x81, 0x4C, 0x46, 0x6D, 0x7B, 0x9B, 0x2C, 0x6E, 0x4D, 0x74, 0x5B, 0xA7, 0x72, 0x9E, 0x69, 0x88, 0x3A, 0x8B, 0x88, 0xE3, 
+  0xA8, 0x85, 0xF2, 0x89, 0xAC, 0xFF, 0x00, 0xFA, 0x8A, 0xF6, 0x5A, 0x69, 0xDD, 0x5D, 0xDD, 0xBC, 0x53, 0xB8, 0x09, 0x59, 
+  0x68, 0xE9, 0xAE, 0x95, 0x89, 0x09, 0x91, 0x59, 0x8F, 0x66, 0xA4, 0x27, 0x5C, 0x80, 0xF1, 0x31, 0xE0, 0x9B, 0x57, 0xF4, 
+  0x72, 0xEE, 0x9D, 0xA7, 0xFA, 0xA3, 0xA7, 0xF5, 0xEB, 0x02, 0xF2, 0x69, 0xA7, 0x24, 0xB7, 0x4C, 0xAB, 0xB2, 0xD3, 0xF0, 
+  0x2B, 0x10, 0x52, 0xE2, 0x9A, 0x15, 0x6B, 0x62, 0xB7, 0x01, 0xD9, 0x54, 0x4B, 0x9E, 0x8C, 0xB7, 0x12, 0x52, 0x9A, 0x9D, 
+  0x16, 0x6C, 0xB6, 0x5B, 0x51, 0x0C, 0x4A, 0x11, 0xA4, 0xA5, 0x6C, 0x23, 0x5A, 0x6A, 0xA2, 0xA0, 0xAC, 0x69, 0x7B, 0x23, 
+  0xDC, 0xE7, 0x0F, 0xC1, 0x27, 0x5D, 0x74, 0x6E, 0x6D, 0x6F, 0x53, 0x22, 0x41, 0x07, 0x51, 0x05, 0x54, 0xA5, 0xFD, 0xA9, 
+  0x8C, 0x11, 0x26, 0x1C, 0x8C, 0x26, 0xA1, 0xCF, 0x0D, 0x1E, 0x01, 0xF5, 0x2B, 0x58, 0x6E, 0xBB, 0x8F, 0x47, 0x69, 0x54, 
+  0xC9, 0x72, 0x5D, 0xD5, 0x8D, 0x53, 0xD0, 0x34, 0xC0, 0x8C, 0xC4, 0x75, 0xAF, 0xC9, 0x91, 0x42, 0x99, 0x7B, 0xC9, 0xB9, 
+  0x6A, 0x2A, 0xC2, 0x4E, 0x19, 0x89, 0x6A, 0xB6, 0xDB, 0xB3, 0x9D, 0x50, 0x0D, 0xB4, 0xCB, 0x71, 0xC2, 0xD4, 0x39, 0xD1, 
+  0x95, 0x4D, 0x34, 0x51, 0x46, 0xF0, 0xFB, 0x5D, 0x55, 0x51, 0x55, 0xE3, 0xD9, 0x69, 0xEA, 0xEA, 0x89, 0x3F, 0xD3, 0x96, 
+  0x78, 0xD6, 0x55, 0xD3, 0xB3, 0xB7, 0x57, 0xE6, 0x35, 0x15, 0x52, 0x53, 0xB9, 0x53, 0x38, 0xEA, 0x0A, 0x7A, 0x60, 0xA5, 
+  0x89, 0x59, 0x85, 0x91, 0xF4, 0x9D, 0x3D, 0xBC, 0x74, 0xF8, 0x09, 0xB9, 0x7C, 0x1B, 0x78, 0x85, 0xB9, 0x34, 0xEE, 0x43, 
+  0x0F, 0x2E, 0x8F, 0x4C, 0x91, 0x32, 0x45, 0x15, 0xE2, 0x8C, 0x34, 0xFD, 0x0E, 0xE6, 0x6E, 0x3D, 0xCF, 0x4E, 0x2C, 0xAC, 
+  0x24, 0x25, 0x48, 0x62, 0xA6, 0xED, 0xD5, 0x1C, 0x04, 0x92, 0x94, 0x96, 0x79, 0x49, 0xCF, 0x50, 0x36, 0xE2, 0x9A, 0xB6, 
+  0xE2, 0x11, 0x84, 0x98, 0x86, 0xAE, 0xA2, 0x4B, 0xBE, 0xF4, 0xF9, 0xBC, 0x13, 0xC3, 0xD9, 0xFC, 0xBD, 0xFA, 0x3F, 0x30, 
+  0xF6, 0x2B, 0x40, 0xF6, 0x5F, 0x67, 0xAA, 0x8A, 0xA1, 0x2A, 0x15, 0x6E, 0x34, 0xE3, 0x0A, 0xA7, 0x9A, 0x80, 0x86, 0x14, 
+  0xCF, 0xD9, 0xE5, 0xC0, 0xCF, 0xDD, 0xE8, 0x47, 0x51, 0xDB, 0x61, 0xD0, 0x7A, 0x8F, 0x53, 0xB6, 0x38, 0xAB, 0xDF, 0x33, 
+  0x62, 0xE1, 0xDF, 0x33, 0xC8, 0xE4, 0x26, 0xD3, 0x16, 0x70, 0x00, 0xFB, 0x2F, 0xE6, 0x35, 0x13, 0x34, 0xD1, 0x48, 0x82, 
+  0x37, 0x85, 0x89, 0xB6, 0x59, 0xC1, 0xF2, 0x35, 0x11, 0x1D, 0x50, 0x2A, 0xE5, 0x24, 0x67, 0x18, 0xDC, 0x1E, 0x9D, 0x77, 
+  0x1B, 0x1F, 0x76, 0xFF, 0x00, 0x91, 0x1C, 0x39, 0x3B, 0xFA, 0x7C, 0x71, 0xEB, 0x9E, 0x38, 0xCC, 0x5B, 0x4E, 0xAA, 0x13, 
+  0xFE, 0x92, 0xC4, 0xD5, 0x55, 0x2C, 0xB1, 0x88, 0x1E, 0xF6, 0x66, 0xF0, 0x91, 0x7D, 0x06, 0xF3, 0x6B, 0x42, 0x8F, 0xD9, 
+  0xC7, 0x72, 0xA3, 0xB9, 0xED, 0xD7, 0xA6, 0x32, 0x09, 0xDF, 0x7E, 0x98, 0xDF, 0x83, 0xBC, 0x5A, 0x0B, 0x62, 0x3F, 0x9B, 
+  0x44, 0x3D, 0xB5, 0x35, 0x74, 0xDA, 0x2A, 0x54, 0xB4, 0x74, 0xC5, 0x30, 0x72, 0x25, 0x80, 0x88, 0x8F, 0x3C, 0xE7, 0x5A, 
+  0xC7, 0xD6, 0x12, 0x0F, 0x50, 0x72, 0x48, 0xC1, 0xFD, 0xDE, 0xA4, 0xFA, 0xFA, 0xE3, 0x1B, 0x9E, 0x09, 0x15, 0x84, 0x82, 
+  0x2F, 0xE5, 0xFA, 0x72, 0x4F, 0x3C, 0x76, 0xD4, 0xF7, 0xBF, 0xF7, 0xFB, 0x35, 0xAC, 0x71, 0xFC, 0x13, 0x93, 0xBE, 0xC7, 
+  0x23, 0x3B, 0xE7, 0xDF, 0xB6, 0x4F, 0xAE, 0x07, 0xE1, 0xBF, 0x0F, 0x46, 0x83, 0x5B, 0xDE, 0xF0, 0x3F, 0x1D, 0xFE, 0x03, 
+  0xAE, 0x77, 0xDF, 0xB6, 0xDB, 0xF0, 0x68, 0xD2, 0x5E, 0x7A, 0xBF, 0x79, 0x5F, 0x97, 0x06, 0x8D, 0x4A, 0xE6, 0x56, 0x09, 
+  0xC1, 0xEB, 0xD7, 0x7C, 0xF4, 0xF7, 0xA7, 0x6F, 0x5E, 0x98, 0xDB, 0x6E, 0x9C, 0x57, 0x53, 0xDD, 0x7B, 0x12, 0x91, 0xF2, 
+  0x8B, 0xBC, 0xFA, 0x1A, 0x6A, 0xB9, 0xF4, 0xF8, 0x18, 0x34, 0x98, 0x94, 0x02, 0xB2, 0x4F, 0x4F, 0x4D, 0xFA, 0x03, 0x9D, 
+  0xBE, 0x5E, 0xEF, 0x9E, 0x78, 0x95, 0x5E, 0x5E, 0xD6, 0x52, 0x49, 0x98, 0x5C, 0xA7, 0x86, 0x7E, 0x7A, 0x51, 0x36, 0x3F, 
+  0x7F, 0xDA, 0xFF, 0x00, 0x2D, 0x3A, 0x2D, 0x88, 0xD2, 0x6B, 0xF5, 0x8A, 0x65, 0x0A, 0x95, 0x06, 0xA1, 0x58, 0xAC, 0xD5, 
+  0xE6, 0x46, 0x81, 0x4B, 0xA3, 0xD1, 0xE0, 0xCA, 0xAA, 0xD5, 0xAA, 0x73, 0x66, 0x49, 0x6E, 0x24, 0x48, 0x54, 0xFA, 0x6C, 
+  0x26, 0x9E, 0x99, 0x2E, 0x64, 0xA9, 0x52, 0x18, 0x8B, 0x1A, 0x34, 0x76, 0x5C, 0x75, 0xF9, 0x2F, 0xB2, 0xC3, 0x28, 0x5B, 
+  0xCE, 0xB6, 0x95, 0x32, 0xA6, 0xE9, 0x90, 0xBD, 0x80, 0x39, 0xBD, 0xAD, 0xEB, 0xFC, 0x6B, 0x4D, 0xBA, 0x7D, 0xEA, 0xAA, 
+  0x80, 0x22, 0x9F, 0x6A, 0x00, 0x92, 0x58, 0x58, 0xE0, 0xF5, 0xED, 0x8D, 0x58, 0x9B, 0xFF, 0x00, 0xC3, 0xAE, 0xA7, 0x69, 
+  0x8B, 0xB0, 0xA9, 0x9A, 0xA3, 0xA6, 0xDA, 0x83, 0xA6, 0x35, 0x7A, 0x93, 0x2A, 0x7A, 0x9B, 0x4E, 0xD4, 0x4B, 0x36, 0xBF, 
+  0x67, 0xCA, 0xA9, 0xA1, 0x09, 0x2A, 0x5A, 0xA9, 0x82, 0xB7, 0x02, 0x1B, 0x35, 0x02, 0xD0, 0x27, 0xCD, 0x44, 0x27, 0x9F, 
+  0x71, 0x90, 0x0F, 0x9E, 0x84, 0x0D, 0x82, 0x37, 0x04, 0xCF, 0x51, 0x29, 0x33, 0x4B, 0x19, 0x12, 0x46, 0xDE, 0x3A, 0xA1, 
+  0x9B, 0x16, 0x9D, 0x5D, 0x2E, 0xD5, 0x63, 0xD2, 0xD1, 0x5F, 0x0F, 0x42, 0x31, 0x85, 0x58, 0xBC, 0xC2, 0x37, 0xB1, 0x95, 
+  0xB3, 0x15, 0x66, 0xEB, 0xA2, 0x48, 0x80, 0xB7, 0x1A, 0x71, 0x1C, 0xA3, 0x2A, 0x19, 0x23, 0xA8, 0xED, 0x92, 0xA2, 0x77, 
+  0x1E, 0x9D, 0x37, 0xD8, 0xE0, 0x1E, 0x1A, 0x1C, 0x36, 0x7C, 0xC3, 0xE9, 0x66, 0x71, 0xC9, 0xA5, 0x56, 0xD7, 0x4A, 0xB4, 
+  0xF5, 0x54, 0x49, 0xEC, 0x96, 0x4E, 0x51, 0xEF, 0x4D, 0x66, 0x2A, 0x9B, 0x7C, 0x75, 0x5F, 0xAE, 0x7A, 0x33, 0x72, 0x9B, 
+  0x79, 0x0E, 0x37, 0xE6, 0x36, 0xA0, 0x72, 0x92, 0x9C, 0xE4, 0x75, 0xE6, 0xED, 0x9C, 0x75, 0x1D, 0x30, 0x7A, 0x60, 0x90, 
+  0x38, 0xC7, 0x72, 0x92, 0xA1, 0xC6, 0x21, 0xF5, 0x2E, 0x77, 0xE6, 0x07, 0x98, 0xED, 0x7D, 0x64, 0x89, 0x12, 0x44, 0x92, 
+  0x1E, 0x38, 0xD7, 0xEF, 0x0E, 0x7E, 0x29, 0x6F, 0x9F, 0x05, 0x77, 0xE5, 0xBF, 0x39, 0x35, 0x2B, 0xAD, 0xED, 0x17, 0x87, 
+  0x74, 0x37, 0x72, 0x24, 0x5A, 0x95, 0x19, 0x14, 0xFB, 0xEB, 0x44, 0x2E, 0x67, 0x5D, 0x01, 0xED, 0x51, 0xD1, 0xAA, 0xB3, 
+  0x2A, 0xF6, 0x8A, 0x24, 0xF8, 0xF9, 0x2F, 0x5D, 0x56, 0x8A, 0x4A, 0xAD, 0xCB, 0xC6, 0x9C, 0x24, 0xC6, 0xA9, 0xD3, 0xDD, 
+  0x71, 0xC5, 0xAD, 0x58, 0xD3, 0xB8, 0xEC, 0xCE, 0xD6, 0xEC, 0x57, 0xB3, 0x52, 0xF6, 0xF6, 0x16, 0x30, 0xDA, 0x22, 0x61, 
+  0x26, 0x12, 0xD7, 0x8A, 0x87, 0x1A, 0xFD, 0x98, 0x52, 0x69, 0x42, 0x86, 0x4E, 0xAE, 0x93, 0x20, 0x9F, 0xD5, 0xB7, 0xC5, 
+  0x47, 0xBD, 0x47, 0xBD, 0x42, 0x45, 0x54, 0xD5, 0xFD, 0x04, 0xFC, 0x2C, 0xF8, 0xE2, 0xF0, 0xD9, 0xE3, 0xF7, 0x4D, 0xAD, 
+  0xBD, 0x03, 0xF1, 0xAC, 0xCE, 0x9E, 0x5C, 0xB7, 0x94, 0xDA, 0x14, 0x0B, 0xAB, 0x4E, 0x35, 0x38, 0x21, 0x34, 0x3B, 0x3F, 
+  0x58, 0x2D, 0xEA, 0x84, 0x46, 0xD7, 0x49, 0xD4, 0x4B, 0x1A, 0xB5, 0x0D, 0xD8, 0x92, 0xB4, 0xE6, 0xFB, 0x72, 0x2A, 0x90, 
+  0x8B, 0x9A, 0x87, 0x06, 0x74, 0x28, 0x8A, 0x98, 0x99, 0x49, 0x84, 0xB5, 0x40, 0x79, 0xCA, 0x4C, 0x63, 0x73, 0x63, 0x73, 
+  0x6A, 0xAE, 0xBD, 0xAB, 0xD2, 0xDC, 0x0B, 0x8D, 0x2E, 0x22, 0x72, 0x77, 0x33, 0x4F, 0x36, 0xD7, 0x2D, 0x5B, 0x75, 0xED, 
+  0xFF, 0x00, 0xCC, 0xDB, 0x92, 0x1E, 0x94, 0xCB, 0x42, 0x98, 0x52, 0x44, 0x73, 0x4B, 0xC9, 0x0D, 0xF3, 0xAE, 0x92, 0xE8, 
+  0x7E, 0x80, 0xF8, 0x3A, 0xF0, 0xA4, 0xF4, 0x8A, 0x86, 0x9A, 0x44, 0xA0, 0x33, 0x72, 0x55, 0x9B, 0x75, 0xB5, 0x5C, 0x35, 
+  0x2B, 0x91, 0x57, 0x75, 0xD2, 0xE4, 0x37, 0x92, 0xD8, 0x72, 0x24, 0x3A, 0x94, 0xB7, 0xDF, 0x34, 0xDA, 0x7B, 0x88, 0x6D, 
+  0xA4, 0xBE, 0x98, 0x0D, 0xC4, 0x13, 0x02, 0x1A, 0x44, 0xB7, 0x24, 0x06, 0xDB, 0x4A, 0x70, 0x4D, 0xFD, 0xD2, 0xF4, 0xD5, 
+  0x49, 0x00, 0xDB, 0xA4, 0x63, 0xBA, 0x67, 0x01, 0x7F, 0xF1, 0x8D, 0x7B, 0x95, 0xD6, 0x4D, 0x4A, 0x93, 0xC0, 0x04, 0xCC, 
+  0xE0, 0x01, 0x86, 0xE7, 0x6E, 0x35, 0x4B, 0x3E, 0x97, 0x0F, 0x05, 0x2C, 0xF8, 0xB3, 0xD2, 0x28, 0x5A, 0xCD, 0xA5, 0xF4, 
+  0xBF, 0xAF, 0xEF, 0xDB, 0x02, 0x9A, 0xF3, 0x75, 0x0A, 0x55, 0x39, 0x84, 0xC8, 0xA9, 0x5C, 0x96, 0x9C, 0x77, 0x17, 0x35, 
+  0xC4, 0xC0, 0x69, 0x80, 0xA7, 0x66, 0x55, 0xED, 0xF7, 0x17, 0x29, 0xF6, 0xE0, 0xA0, 0x2D, 0xF9, 0x94, 0xA9, 0xF5, 0x36, 
+  0xE2, 0x25, 0xC9, 0x88, 0x8B, 0x1D, 0xEB, 0xD9, 0xAD, 0xDB, 0xA9, 0xDB, 0xAE, 0xD0, 0xC9, 0xCF, 0x98, 0x99, 0x6C, 0xB3, 
+  0x09, 0x19, 0x78, 0xD6, 0xFF, 0x00, 0x85, 0xDF, 0xFC, 0x9A, 0xE1, 0xF7, 0x57, 0xE4, 0xDF, 0x0F, 0x03, 0xCB, 0xE0, 0xF5, 
+  0xD7, 0x8B, 0x0A, 0xCF, 0x87, 0x6A, 0xDA, 0xAB, 0x0A, 0x10, 0xA2, 0xBA, 0xA6, 0x5C, 0x79, 0x58, 0xC2, 0x15, 0xB6, 0x16, 
+  0x50, 0xA4, 0x91, 0x82, 0x52, 0xA4, 0x9C, 0x85, 0xA3, 0x62, 0x95, 0x85, 0x24, 0xF4, 0xE3, 0xB2, 0x69, 0x4B, 0x9E, 0xBE, 
+  0x1B, 0x19, 0xFB, 0xB1, 0xE3, 0x5E, 0xBB, 0x56, 0xD5, 0x41, 0x53, 0x03, 0x7B, 0x09, 0x2D, 0xBB, 0x99, 0x93, 0x10, 0xFD, 
+  0x2D, 0x78, 0xB4, 0x67, 0xE8, 0x9E, 0xD7, 0x9D, 0x67, 0xD0, 0x4D, 0x5A, 0xD7, 0xAB, 0x56, 0x05, 0x2E, 0x3D, 0xAF, 0xA5, 
+  0xB0, 0xE5, 0xBD, 0x12, 0x93, 0x54, 0x4D, 0x41, 0x37, 0x06, 0xA3, 0xCB, 0xA2, 0xC6, 0x35, 0x1B, 0xB2, 0x15, 0x94, 0xD3, 
+  0x11, 0xDC, 0x8E, 0xB5, 0x5B, 0x14, 0xA4, 0x97, 0xE5, 0x49, 0x9C, 0xE3, 0x6C, 0xD4, 0x2A, 0x59, 0xA1, 0xD3, 0xFC, 0xC9, 
+  0xCD, 0xC9, 0x31, 0xA2, 0xAD, 0xEA, 0x69, 0xAA, 0x9A, 0x3F, 0xD5, 0x84, 0xB8, 0x71, 0x78, 0x31, 0x38, 0xB8, 0xAF, 0x31, 
+  0xAC, 0x6B, 0xFC, 0x4E, 0xD5, 0x1B, 0x94, 0xED, 0xB3, 0x57, 0x5E, 0x64, 0xF6, 0x69, 0x92, 0x29, 0x91, 0xBC, 0x8E, 0x13, 
+  0x01, 0x36, 0x22, 0x79, 0xB3, 0x7B, 0x69, 0x25, 0x6E, 0x86, 0xA2, 0xE3, 0x71, 0x5C, 0x71, 0x85, 0xA4, 0x38, 0x83, 0xCA, 
+  0xA1, 0xF6, 0x14, 0x02, 0x81, 0x47, 0xD9, 0x24, 0x82, 0x92, 0x0E, 0x7A, 0x11, 0x92, 0x08, 0xCF, 0x17, 0x03, 0x8A, 0xA2, 
+  0x66, 0x46, 0x6E, 0xF6, 0x89, 0xB3, 0x68, 0xFE, 0xDA, 0xB2, 0x8A, 0x2A, 0x64, 0x4A, 0x23, 0xDE, 0x82, 0xCF, 0xFD, 0x5D, 
+  0x8F, 0x81, 0x0F, 0x1E, 0x2B, 0xCD, 0x71, 0x85, 0x53, 0x5D, 0x6D, 0x89, 0x5F, 0xB3, 0x7D, 0xF7, 0x3C, 0xA8, 0xEC, 0xE0, 
+  0x97, 0xE4, 0xBA, 0x4E, 0x03, 0x51, 0xD9, 0x40, 0x53, 0xAF, 0x2F, 0xA1, 0xF2, 0xDB, 0x42, 0x97, 0xB9, 0x18, 0xCE, 0x38, 
+  0x03, 0xA7, 0x38, 0x79, 0x8B, 0x09, 0xF3, 0xEF, 0x66, 0xDC, 0x27, 0x89, 0xAB, 0x6E, 0xAA, 0x6F, 0x0A, 0x1E, 0xF5, 0x44, 
+  0x74, 0x9D, 0xA7, 0x92, 0xC9, 0x33, 0x6E, 0xD0, 0x69, 0xA0, 0xEC, 0xB4, 0xAC, 0x73, 0x21, 0x43, 0x72, 0xAF, 0x8E, 0xC7, 
+  0x94, 0x8C, 0x60, 0x29, 0x04, 0x10, 0x52, 0xA4, 0x10, 0x08, 0x20, 0xA4, 0x80, 0xA1, 0xB5, 0x0D, 0xB8, 0xC4, 0xB9, 0x21, 
+  0x96, 0x46, 0x42, 0xE7, 0x2F, 0xC7, 0x59, 0xFC, 0x9F, 0x4C, 0x68, 0x25, 0x3E, 0x0F, 0x43, 0xF8, 0x1C, 0x7A, 0xFA, 0x12, 
+  0x78, 0x3A, 0xA9, 0xEE, 0x7C, 0xF4, 0x69, 0x3F, 0x38, 0x7B, 0xBF, 0x03, 0xC2, 0xEB, 0xA7, 0xBF, 0xE8, 0xFF, 0x00, 0x1A, 
+  0x35, 0x27, 0x2E, 0x48, 0xF5, 0xC0, 0xCE, 0x7E, 0x1F, 0x8F, 0xF2, 0x1F, 0x1F, 0x5A, 0xD1, 0xAD, 0x6C, 0xB9, 0xE5, 0xB0, 
+  0x70, 0xA0, 0x3A, 0x92, 0xA3, 0xBE, 0x36, 0x18, 0xEB, 0xEF, 0xEB, 0xD3, 0xE1, 0x81, 0xBA, 0x49, 0xCE, 0x3B, 0x4F, 0xDB, 
+  0xF0, 0x98, 0xD3, 0x42, 0x06, 0x6E, 0xCC, 0x84, 0x90, 0x63, 0x23, 0x79, 0xBF, 0xA7, 0xC7, 0x4D, 0x8B, 0x43, 0xC4, 0x5D, 
+  0x1B, 0x42, 0xF5, 0x36, 0x15, 0xD1, 0x77, 0xD4, 0xAF, 0xDB, 0x56, 0x92, 0x95, 0xDB, 0x95, 0x2B, 0x6F, 0x53, 0xB4, 0xD5, 
+  0xC5, 0x26, 0xEF, 0xD2, 0xCB, 0xF6, 0xCF, 0xAE, 0xAA, 0xB5, 0x6F, 0x5C, 0xF1, 0x5B, 0x42, 0x83, 0x8F, 0x40, 0x71, 0x52, 
+  0x5E, 0x6A, 0x58, 0x6B, 0x9D, 0x4D, 0xC8, 0x89, 0x0D, 0x4B, 0x6D, 0x49, 0x50, 0x29, 0xCB, 0xF3, 0x69, 0xA2, 0xB6, 0x9D, 
+  0xCA, 0x5F, 0xCA, 0xAA, 0x90, 0x9A, 0x61, 0xAA, 0x9A, 0xA9, 0x5B, 0xB3, 0x32, 0x43, 0x11, 0x86, 0xC4, 0x26, 0xB2, 0xAF, 
+  0x72, 0xAD, 0xB2, 0xE9, 0xD0, 0x8D, 0x29, 0x50, 0xB4, 0x22, 0x44, 0x55, 0x04, 0xD3, 0x25, 0xA4, 0xB0, 0x5B, 0xD7, 0xD5, 
+  0x9F, 0x87, 0xBF, 0xA7, 0x67, 0x4A, 0x3C, 0x44, 0x69, 0xAA, 0x34, 0x5F, 0xC5, 0x95, 0xBB, 0xA3, 0x3E, 0x39, 0xF4, 0xF6, 
+  0xAB, 0x19, 0xA8, 0x95, 0x2A, 0xBE, 0x9E, 0xD4, 0x2D, 0xFB, 0x2B, 0x5B, 0x4B, 0x49, 0x42, 0x92, 0x8A, 0xC5, 0x73, 0x43, 
+  0xAF, 0x79, 0xD4, 0x08, 0x35, 0x4B, 0xAE, 0x30, 0x52, 0x9F, 0x4D, 0xC1, 0xA6, 0x17, 0x2D, 0xBB, 0x5C, 0x44, 0xA6, 0xC4, 
+  0xA8, 0x11, 0x84, 0xB5, 0x82, 0xA8, 0x3F, 0x0F, 0x45, 0x75, 0x75, 0xFE, 0x1B, 0x76, 0x91, 0x99, 0xE9, 0x18, 0xBF, 0x9A, 
+  0x2A, 0x4A, 0x89, 0x42, 0xC2, 0x8D, 0xEC, 0x10, 0x6B, 0x9F, 0xF2, 0xCE, 0xAE, 0xBD, 0x9A, 0xEA, 0xDB, 0x78, 0x47, 0xAE, 
+  0x83, 0x88, 0xEB, 0xA1, 0xAA, 0xA0, 0xB6, 0x2A, 0xA7, 0x1E, 0x35, 0xCA, 0x6F, 0x1F, 0xBA, 0x69, 0xE1, 0x46, 0xDA, 0x88, 
+  0xFE, 0xAA, 0x78, 0x39, 0xF1, 0x15, 0x4D, 0xBF, 0xEC, 0x27, 0x6A, 0xD4, 0xF8, 0x17, 0x4F, 0x87, 0x4D, 0x5F, 0x6A, 0xA5, 
+  0xA7, 0x9E, 0x2A, 0x34, 0x6E, 0x5D, 0x72, 0x43, 0x8C, 0x53, 0xC2, 0x6D, 0x0B, 0xCA, 0x05, 0x0E, 0xAF, 0xAA, 0x36, 0x2A, 
+  0x26, 0x06, 0xE9, 0xEE, 0x5C, 0x74, 0x58, 0xD3, 0x2A, 0xD4, 0x17, 0x65, 0x40, 0x6E, 0xA7, 0x2A, 0xE2, 0x87, 0x21, 0xCA, 
+  0xEB, 0x5A, 0x1D, 0x61, 0x59, 0xBD, 0x4F, 0x4A, 0x05, 0xF0, 0x33, 0x11, 0xD0, 0x2C, 0xCF, 0x88, 0x4B, 0x49, 0x11, 0xAE, 
+  0xED, 0xAD, 0xDA, 0xDA, 0x6A, 0xA3, 0x7C, 0x6E, 0x56, 0x53, 0xBB, 0xB5, 0xD3, 0x5D, 0x15, 0x20, 0x44, 0xB4, 0xFB, 0xB5, 
+  0x0B, 0x99, 0x24, 0x11, 0xBD, 0xB5, 0xCA, 0xE6, 0xE4, 0x43, 0xAA, 0xF2, 0xAC, 0x3C, 0xCA, 0x19, 0x7C, 0x25, 0x48, 0x75, 
+  0x4B, 0x4A, 0x10, 0x52, 0xB1, 0x91, 0xF6, 0xD4, 0x40, 0x19, 0x07, 0x39, 0x38, 0xFB, 0x39, 0x38, 0x3C, 0xA4, 0x1B, 0x11, 
+  0xA4, 0x83, 0xA8, 0x83, 0x3C, 0xFA, 0xCF, 0xDC, 0xFC, 0xF4, 0x14, 0xD5, 0x5A, 0x40, 0xD6, 0xB7, 0xA9, 0x5E, 0xDE, 0xF2, 
+  0xBC, 0x73, 0x13, 0xA1, 0xEA, 0x7A, 0x40, 0xFD, 0xD9, 0x05, 0xC8, 0xF4, 0x90, 0xCD, 0x6D, 0xF9, 0x68, 0x28, 0x62, 0x9F, 
+  0x4A, 0x42, 0xAA, 0xF3, 0x65, 0xB8, 0xE7, 0xD9, 0x4B, 0x51, 0xE1, 0xC2, 0x4B, 0xEF, 0xBE, 0xE3, 0xA4, 0xF2, 0x36, 0x94, 
+  0x36, 0xA0, 0xA5, 0xE0, 0x1D, 0x8E, 0x44, 0x57, 0xB6, 0x54, 0x5E, 0xD6, 0x0B, 0x53, 0x28, 0x71, 0x19, 0x00, 0x0B, 0xC1, 
+  0x7B, 0xF7, 0xD6, 0xCE, 0xC5, 0x24, 0x35, 0x55, 0x1C, 0xC3, 0x49, 0x07, 0x89, 0xA9, 0x6C, 0xF6, 0xE4, 0xBC, 0xB1, 0xA9, 
+  0xC9, 0x8B, 0x93, 0x51, 0xBC, 0x37, 0x69, 0xB7, 0x87, 0xCD, 0x1C, 0xAB, 0x5B, 0xF7, 0x75, 0x12, 0xAB, 0xA6, 0x30, 0x2A, 
+  0xAF, 0xCE, 0xAC, 0xDC, 0x74, 0x6A, 0xCD, 0xB6, 0xE3, 0x4F, 0x5C, 0xD7, 0x15, 0x52, 0xE7, 0x8F, 0x41, 0xA1, 0x9A, 0xB4, 
+  0x58, 0x95, 0x39, 0x34, 0x3B, 0x4A, 0x34, 0xE8, 0xB4, 0xC3, 0x3D, 0xB8, 0xCC, 0x46, 0xA8, 0xBF, 0x1E, 0x52, 0xE9, 0xC5, 
+  0xC8, 0x26, 0x34, 0x97, 0x7A, 0x0E, 0x93, 0x6B, 0x6B, 0x6E, 0xEF, 0xE5, 0x91, 0x55, 0x51, 0x55, 0xA6, 0x50, 0x20, 0xB8, 
+  0x7F, 0x55, 0xA2, 0x63, 0x8D, 0x67, 0xB5, 0xB3, 0x45, 0x26, 0xE6, 0xE7, 0x50, 0xD0, 0x74, 0x80, 0x85, 0x49, 0x4D, 0x14, 
+  0xC1, 0xD4, 0x53, 0x24, 0xC4, 0x59, 0x94, 0x20, 0xE6, 0x35, 0x7B, 0x34, 0x8F, 0xE9, 0x04, 0xD4, 0x5A, 0x53, 0x16, 0xDA, 
+  0xDC, 0xB8, 0xAB, 0x55, 0x24, 0xCD, 0x6D, 0xD6, 0x24, 0x46, 0x55, 0xC4, 0xE5, 0x46, 0x40, 0x66, 0x90, 0x64, 0x3D, 0x33, 
+  0x31, 0x22, 0xC6, 0xA8, 0xF3, 0x79, 0x69, 0x8E, 0xDA, 0x9D, 0x66, 0x12, 0xA3, 0x35, 0x19, 0xB4, 0xBD, 0x1D, 0xF1, 0x1D, 
+  0xB4, 0xB8, 0x1E, 0xD2, 0x8D, 0xA2, 0xBA, 0x66, 0x94, 0xAA, 0x41, 0x61, 0x06, 0x55, 0x17, 0x88, 0xBE, 0x4E, 0x90, 0xCF, 
+  0x26, 0xB2, 0xAA, 0x8D, 0xAA, 0xBA, 0xA3, 0xA4, 0x48, 0x65, 0x12, 0xEC, 0x5D, 0x92, 0xC3, 0x29, 0x74, 0xB9, 0x36, 0x6C, 
+  0x7A, 0x48, 0xF0, 0x11, 0xF4, 0xB0, 0xD9, 0xB0, 0x51, 0x06, 0xD3, 0xD4, 0xF9, 0xD3, 0x21, 0xD1, 0x27, 0xA2, 0x29, 0x5C, 
+  0xE9, 0x05, 0x2F, 0x31, 0x4D, 0x7E, 0x40, 0x61, 0x11, 0xA5, 0xC5, 0x9C, 0xBF, 0x29, 0xC9, 0x49, 0x90, 0x5C, 0x0B, 0x79, 
+  0x87, 0x90, 0x56, 0xA2, 0xA5, 0x79, 0x13, 0x5F, 0x52, 0x3C, 0x86, 0x39, 0xBF, 0x13, 0xF8, 0x5E, 0xA2, 0x4F, 0x66, 0xA2, 
+  0x7D, 0xA7, 0x19, 0x8B, 0xDD, 0xB3, 0x1C, 0x58, 0x8B, 0x5B, 0x5C, 0x3B, 0x9B, 0x15, 0x13, 0x55, 0x1E, 0xD0, 0x4C, 0xDE, 
+  0x51, 0x1E, 0x4E, 0x24, 0x86, 0x71, 0x7F, 0x8E, 0xBA, 0x67, 0x5F, 0xF0, 0xA3, 0xF4, 0x7F, 0xF8, 0x84, 0xB8, 0x06, 0xAC, 
+  0xB3, 0x1A, 0xD2, 0x7E, 0x75, 0x72, 0x47, 0xD6, 0x75, 0x89, 0x56, 0x75, 0xF0, 0xF5, 0xA7, 0x02, 0xE3, 0x96, 0xEA, 0x92, 
+  0xEB, 0xB2, 0x6B, 0xD4, 0x28, 0x33, 0xA2, 0x34, 0x2A, 0x12, 0x4E, 0x4C, 0xE9, 0x2C, 0x46, 0x81, 0x3E, 0x52, 0xD6, 0xB7, 
+  0x25, 0xBE, 0xEB, 0xEA, 0x2E, 0x9F, 0x3E, 0x77, 0xE9, 0xB3, 0x4A, 0x85, 0xA9, 0xAA, 0x1A, 0xA0, 0x46, 0x4A, 0x6A, 0x8B, 
+  0x9F, 0xA2, 0x7C, 0x4D, 0x66, 0x6E, 0xEE, 0xD0, 0x14, 0x95, 0x20, 0x60, 0x41, 0x8F, 0x98, 0xDB, 0xB1, 0x83, 0x8D, 0x5D, 
+  0x7B, 0x3A, 0x4E, 0x92, 0xD9, 0xD4, 0x0A, 0x45, 0x8B, 0x65, 0x4C, 0xB2, 0xE8, 0x36, 0xF5, 0x0A, 0x03, 0x74, 0xDA, 0x3D, 
+  0xBD, 0x47, 0x99, 0x4D, 0x8F, 0x02, 0x0C, 0x24, 0x79, 0x98, 0x66, 0x3C, 0x74, 0x3A, 0x50, 0xA0, 0xEA, 0x94, 0xEB, 0xAF, 
+  0x38, 0xB5, 0x38, 0xEC, 0xA7, 0xDC, 0x79, 0xF9, 0x2E, 0x3A, 0xF3, 0xAE, 0xAD, 0x50, 0xD1, 0xB8, 0xCA, 0xD1, 0x5D, 0xB2, 
+  0xA3, 0x6E, 0x79, 0xE0, 0x3E, 0x44, 0x07, 0x06, 0xB3, 0x65, 0x56, 0xA9, 0x57, 0x33, 0x96, 0x7B, 0xEB, 0x99, 0xDA, 0xFF, 
+  0x00, 0xF4, 0x42, 0xF8, 0x43, 0xD4, 0x8A, 0x9D, 0x5E, 0xFD, 0x9F, 0x73, 0xDD, 0xBA, 0x45, 0x6D, 0xBA, 0xE4, 0xBA, 0xDD, 
+  0xCD, 0x06, 0xD7, 0xAD, 0x5A, 0x70, 0x2D, 0x18, 0xAC, 0x2D, 0x4A, 0x95, 0x51, 0x95, 0x06, 0x45, 0xCF, 0x44, 0xAA, 0x26, 
+  0xD9, 0x88, 0xAC, 0xBB, 0x21, 0xC4, 0x47, 0x96, 0xAA, 0x6C, 0x30, 0xA3, 0xEC, 0x91, 0x63, 0x32, 0x94, 0xB2, 0x34, 0xA3, 
+  0x7B, 0x70, 0x9A, 0x5A, 0x0A, 0x9B, 0x70, 0xCD, 0xB9, 0xB6, 0x3F, 0xB6, 0x59, 0x9D, 0x6F, 0x4F, 0xE2, 0x77, 0x40, 0xA4, 
+  0x8A, 0xDB, 0x47, 0x51, 0xD4, 0xD9, 0x22, 0x49, 0x3A, 0x83, 0xB3, 0x7D, 0x78, 0xEA, 0xFA, 0x52, 0x75, 0xA7, 0xC1, 0xBE, 
+  0x95, 0x45, 0x8F, 0xE1, 0xFF, 0x00, 0xC1, 0x0E, 0x8F, 0x5B, 0x2D, 0x50, 0x2E, 0x29, 0xAA, 0x7A, 0x7E, 0xBB, 0x5F, 0x31, 
+  0x9C, 0xBD, 0xB5, 0x93, 0x5A, 0x59, 0xB5, 0xAA, 0xAE, 0xC5, 0x95, 0x77, 0x37, 0x75, 0x5C, 0x88, 0x76, 0xA1, 0xA7, 0xFA, 
+  0x15, 0x4D, 0xB8, 0xA3, 0xAA, 0x15, 0xBD, 0x45, 0xB4, 0xE2, 0x5B, 0x55, 0x4D, 0x69, 0xB8, 0xE9, 0x4E, 0xBC, 0xF3, 0x74, 
+  0x2D, 0x3B, 0xA1, 0xD4, 0x13, 0x73, 0x75, 0x15, 0x57, 0x46, 0xDF, 0x5E, 0xEB, 0xED, 0x6E, 0x53, 0x14, 0x52, 0x47, 0x49, 
+  0x28, 0x2B, 0x30, 0xD5, 0x09, 0xDE, 0x54, 0x42, 0xC2, 0x3D, 0xF4, 0x9B, 0xB5, 0x51, 0x55, 0x7B, 0xD5, 0xAD, 0x40, 0xD2, 
+  0x6D, 0x8C, 0x51, 0x42, 0x94, 0xAD, 0x3D, 0x23, 0x0D, 0x68, 0xE5, 0x13, 0x6E, 0x1B, 0x2C, 0x47, 0x17, 0xA2, 0x4A, 0x70, 
+  0x34, 0x10, 0xEB, 0xCE, 0x48, 0x74, 0x95, 0xB8, 0xF3, 0xCE, 0xAC, 0x2D, 0xE7, 0xDE, 0x75, 0x4A, 0x71, 0xE7, 0xDD, 0x5E, 
+  0x00, 0x53, 0xAF, 0x3C, 0xA7, 0x1D, 0x75, 0x60, 0x00, 0xA7, 0x16, 0xA2, 0x12, 0x91, 0xB0, 0x54, 0xBE, 0xC8, 0xCA, 0xDA, 
+  0xF3, 0xFD, 0x4C, 0xDE, 0x6F, 0xDB, 0x3F, 0x6E, 0x9E, 0x3B, 0xE2, 0x49, 0x22, 0xCE, 0x38, 0x3E, 0xF3, 0xA3, 0x83, 0xD9, 
+  0x03, 0xAE, 0x31, 0xDB, 0x1F, 0xAE, 0xC7, 0x86, 0xE7, 0xEF, 0xF6, 0xE3, 0xB6, 0x8D, 0x61, 0xE6, 0x8F, 0x77, 0xFB, 0xC3, 
+  0xF9, 0x70, 0xB4, 0x6A, 0x44, 0x72, 0x4A, 0xBF, 0x78, 0xF5, 0xE8, 0x06, 0x33, 0xD7, 0xDF, 0x9D, 0xFD, 0xE4, 0x8F, 0x5D, 
+  0xF8, 0xE8, 0xFB, 0xF1, 0xF2, 0x9F, 0xEF, 0xA3, 0xBD, 0xBC, 0x4C, 0xF2, 0xE1, 0x88, 0xB9, 0x13, 0x24, 0x8C, 0x99, 0xD6, 
+  0xBA, 0x4B, 0xBE, 0x62, 0x31, 0x9C, 0xE3, 0xD0, 0xE7, 0x04, 0x7B, 0xF7, 0xE8, 0x73, 0xD7, 0x20, 0xEF, 0xDF, 0x83, 0xE3, 
+  0xF7, 0xF7, 0xFE, 0x74, 0x6A, 0x2F, 0xBA, 0x68, 0x4C, 0x55, 0x9A, 0x71, 0x89, 0x4C, 0x21, 0xC4, 0x38, 0x95, 0x05, 0x05, 
+  0xA7, 0x9D, 0x2B, 0x07, 0xD7, 0x3B, 0x10, 0x7B, 0x82, 0x4A, 0x76, 0x1D, 0xF7, 0xE3, 0x9A, 0xBA, 0x0A, 0xAC, 0xCC, 0x5F, 
+  0xE5, 0x6E, 0xE4, 0xFE, 0x87, 0xE9, 0x65, 0x17, 0x6E, 0xC3, 0x16, 0xE2, 0xDF, 0xB3, 0xCF, 0xF1, 0x6D, 0x56, 0xEA, 0xC6, 
+  0x86, 0x5A, 0xB2, 0xDE, 0x53, 0xE8, 0xA6, 0xA2, 0x3B, 0xE1, 0x7C, 0xED, 0xBF, 0x0C, 0xAE, 0x2B, 0xCD, 0x38, 0x14, 0x56, 
+  0x97, 0x10, 0xE4, 0x75, 0x36, 0xA4, 0x29, 0x2A, 0xDD, 0x25, 0x04, 0x28, 0x28, 0x05, 0x27, 0x97, 0x23, 0x8C, 0x5D, 0x90, 
+  0xB8, 0xA1, 0x30, 0x33, 0x51, 0x38, 0xC4, 0x7A, 0xC3, 0x11, 0xAC, 0xDD, 0x9D, 0xB5, 0x98, 0x86, 0x66, 0x45, 0xA5, 0x3D, 
+  0x3A, 0x50, 0xF8, 0xC6, 0xA5, 0xAB, 0x7A, 0xE2, 0xD6, 0xCA, 0x15, 0x32, 0x2D, 0xB6, 0x35, 0x5E, 0xE5, 0xAD, 0xDB, 0x94, 
+  0xF5, 0x05, 0x51, 0xE0, 0x5E, 0x70, 0xED, 0xFB, 0xEA, 0x5D, 0xB4, 0xB0, 0x92, 0x84, 0xBD, 0x68, 0xD7, 0x2E, 0xFA, 0x3D, 
+  0x62, 0xB9, 0x6B, 0x48, 0x65, 0x27, 0xFC, 0xDD, 0xEA, 0x3D, 0x46, 0x39, 0x8A, 0xAC, 0x3B, 0x18, 0x36, 0xF2, 0x10, 0xB4, 
+  0x69, 0x4D, 0x5F, 0x88, 0x0E, 0x93, 0x75, 0x48, 0x7A, 0x7A, 0x82, 0xB6, 0x99, 0xCA, 0x35, 0x8B, 0x4B, 0xD3, 0x37, 0x09, 
+  0x18, 0x88, 0x74, 0x8D, 0xA8, 0x7D, 0xFA, 0x92, 0xD2, 0x39, 0x81, 0x90, 0xEA, 0x89, 0x42, 0xF6, 0x55, 0xC5, 0xC9, 0x9D, 
+  0x4A, 0x5A, 0x43, 0xAB, 0x96, 0xA6, 0x8C, 0xEA, 0x4D, 0x97, 0x71, 0x5E, 0xEE, 0xD1, 0x69, 0xF4, 0x8A, 0x1D, 0x42, 0xDD, 
+  0xA9, 0x50, 0xEE, 0x2B, 0xC6, 0xC5, 0x63, 0x54, 0xB4, 0xFE, 0x8D, 0x71, 0xDB, 0xD5, 0x96, 0x2A, 0x11, 0xE0, 0xEA, 0x7D, 
+  0x81, 0x29, 0xC4, 0xAE, 0xE3, 0xD3, 0xFB, 0xA6, 0x3A, 0x3E, 0xAA, 0xB8, 0x1C, 0x8E, 0x5E, 0x97, 0x01, 0xC8, 0xF0, 0xDD, 
+  0x7D, 0xA9, 0x10, 0x25, 0xCF, 0x4F, 0x15, 0x46, 0xE5, 0x14, 0x55, 0xD1, 0xBA, 0xBD, 0x3D, 0x34, 0xD3, 0x4D, 0x64, 0xAD, 
+  0x0C, 0x16, 0xA8, 0x9E, 0x46, 0xED, 0x30, 0x96, 0x8C, 0x43, 0xA3, 0x5F, 0x42, 0x2C, 0x94, 0x23, 0x42, 0xD3, 0x53, 0x4A, 
+  0x75, 0x5A, 0x7A, 0x8F, 0x76, 0x33, 0x4A, 0x8D, 0x22, 0x7B, 0x50, 0x5F, 0x5E, 0xD8, 0xF4, 0x4B, 0xE9, 0xC0, 0xAA, 0x58, 
+  0xBA, 0x71, 0x42, 0xB9, 0x6E, 0x4F, 0x07, 0x7A, 0x1F, 0x5F, 0xA6, 0xCD, 0xA6, 0x34, 0x9B, 0x73, 0x55, 0xBC, 0x2F, 0x56, 
+  0x20, 0x43, 0xB0, 0x6B, 0x88, 0x0C, 0x24, 0x32, 0x63, 0xD0, 0xFE, 0xA4, 0x95, 0x55, 0xA2, 0x3A, 0xE6, 0x42, 0x97, 0x4A, 
+  0x15, 0x65, 0xAA, 0x38, 0x0E, 0xB4, 0x82, 0x92, 0xD7, 0x28, 0xD6, 0xAF, 0xC0, 0x55, 0x53, 0xD4, 0x6E, 0x55, 0x5D, 0x15, 
+  0x5F, 0xAE, 0x97, 0xAF, 0xA8, 0x57, 0x17, 0x2A, 0xF0, 0xD9, 0x73, 0x3D, 0xB5, 0xC8, 0xED, 0x51, 0x5D, 0x65, 0x3F, 0x9B, 
+  0x50, 0xC0, 0xF4, 0xEE, 0xD3, 0xED, 0x5E, 0xA4, 0xF6, 0x6A, 0x16, 0x8A, 0x80, 0x0A, 0xBA, 0x84, 0xB5, 0xE2, 0xDA, 0xF3, 
+  0xC1, 0xF4, 0x97, 0xF8, 0xC4, 0xB8, 0xBC, 0x6D, 0xEA, 0xD4, 0xAD, 0x40, 0xAF, 0xD0, 0xE8, 0xB6, 0xDB, 0x92, 0xD9, 0x11, 
+  0xE2, 0x00, 0xEB, 0x71, 0xE3, 0xC1, 0xA5, 0x42, 0x80, 0xB9, 0x8D, 0x31, 0xED, 0xBE, 0x6C, 0xB7, 0xA6, 0xAD, 0x84, 0x43, 
+  0x44, 0x46, 0x8B, 0x31, 0xD3, 0x29, 0x15, 0x36, 0xD0, 0xD3, 0x92, 0x62, 0x95, 0xB9, 0xC6, 0xCE, 0xD9, 0xB7, 0xB4, 0x6D, 
+  0xFB, 0xA6, 0x3D, 0xB6, 0x2A, 0x60, 0x2A, 0x55, 0x26, 0xD2, 0x42, 0x40, 0xF3, 0x33, 0x63, 0xB6, 0x9A, 0x69, 0xD8, 0xD9, 
+  0xAB, 0x6F, 0xA8, 0xA9, 0xAA, 0xA2, 0x52, 0x18, 0x7A, 0xA2, 0xAB, 0x62, 0xC1, 0x24, 0x4F, 0xA5, 0xB5, 0x41, 0x2D, 0x99, 
+  0xD1, 0x60, 0x4D, 0xF3, 0x11, 0x48, 0xA1, 0xCA, 0x2C, 0x4D, 0x75, 0x31, 0x90, 0xB9, 0x33, 0x1D, 0x5C, 0x1E, 0x68, 0x8D, 
+  0x35, 0x4F, 0x6D, 0x97, 0x91, 0xC9, 0x22, 0x50, 0x8E, 0xA6, 0x19, 0x71, 0xDF, 0x22, 0x62, 0x10, 0xD4, 0xC1, 0x24, 0x3C, 
+  0xE2, 0xE2, 0x48, 0xF2, 0xA3, 0x56, 0xDD, 0x6D, 0x0C, 0xD2, 0x02, 0x3E, 0xC8, 0xAB, 0xD3, 0x68, 0x29, 0xF3, 0x9F, 0x68, 
+  0x6D, 0x39, 0x52, 0x23, 0x9D, 0x9E, 0xE8, 0xF7, 0x2C, 0xF9, 0xC5, 0xA1, 0x72, 0x44, 0x63, 0xB6, 0xAC, 0x7D, 0x17, 0x59, 
+  0xE7, 0x44, 0xA9, 0xBD, 0x52, 0xF6, 0x18, 0x08, 0x54, 0xE7, 0x45, 0x51, 0xC6, 0x98, 0xA6, 0xAD, 0xA6, 0xD8, 0x2E, 0xB0, 
+  0x85, 0x30, 0x11, 0x04, 0xCF, 0x4B, 0x6D, 0x24, 0xCD, 0x68, 0xB8, 0xDC, 0x38, 0x73, 0xD9, 0x8E, 0xB8, 0x88, 0x6D, 0x4D, 
+  0x17, 0x9F, 0x0E, 0x46, 0x4F, 0x61, 0xBB, 0xB7, 0x5D, 0xAB, 0x2F, 0x79, 0x62, 0xD6, 0xF1, 0x2B, 0x93, 0xCF, 0x1F, 0x17, 
+  0x4F, 0xBB, 0xCD, 0x29, 0x00, 0x88, 0xCD, 0x23, 0xDA, 0xD7, 0x66, 0xF3, 0x29, 0x6E, 0x03, 0x56, 0xD6, 0xCF, 0xF1, 0x65, 
+  0x77, 0x5B, 0xCD, 0xC6, 0x9B, 0x4D, 0xB8, 0xDB, 0x8A, 0x3F, 0x62, 0x96, 0xE8, 0xD1, 0x59, 0x7A, 0x4C, 0xA5, 0x21, 0x2D, 
+  0x72, 0x00, 0x56, 0xF3, 0x4B, 0x72, 0x3B, 0x65, 0x2D, 0x97, 0xA4, 0x3A, 0xA4, 0x2D, 0x98, 0xE8, 0x52, 0x98, 0x8A, 0x66, 
+  0x48, 0x41, 0x68, 0x27, 0x67, 0x6E, 0xA2, 0x69, 0x88, 0x58, 0x22, 0x09, 0xF8, 0xF1, 0xCF, 0x07, 0xD3, 0x47, 0xB2, 0xC5, 
+  0x35, 0x27, 0x2C, 0xD5, 0x57, 0x4E, 0x5B, 0x3C, 0x7A, 0x44, 0xF1, 0x7E, 0xFA, 0x95, 0xE9, 0x9F, 0x48, 0x25, 0xF5, 0x44, 
+  0x4C, 0x89, 0x0F, 0x5D, 0x72, 0x21, 0xBC, 0xA9, 0x30, 0x54, 0x61, 0x42, 0x6D, 0x49, 0x90, 0xF3, 0x12, 0x1B, 0x68, 0x29, 
+  0xB5, 0xAB, 0x91, 0xA0, 0x95, 0x43, 0xA8, 0x05, 0x07, 0x63, 0x29, 0x4C, 0x14, 0xAE, 0x62, 0x1F, 0x93, 0x26, 0x34, 0x7F, 
+  0xD8, 0x89, 0x7F, 0x0F, 0x4C, 0x20, 0x8C, 0xAB, 0x12, 0x45, 0xC4, 0x0B, 0x5C, 0x06, 0xD7, 0xCC, 0x98, 0x9D, 0x1F, 0x97, 
+  0x4B, 0x1E, 0xCC, 0xA0, 0x84, 0xD4, 0x40, 0x4C, 0x73, 0xD5, 0xD4, 0x66, 0x1B, 0xB6, 0x8E, 0x63, 0x51, 0xF6, 0xBE, 0x7D, 
+  0x23, 0x7A, 0xB3, 0xA9, 0xBA, 0x57, 0x50, 0xB3, 0x59, 0xBE, 0xAB, 0xB2, 0xA2, 0xCE, 0xA6, 0xBE, 0xFC, 0x9A, 0x7B, 0x95, 
+  0x49, 0xD0, 0x59, 0xA9, 0xD3, 0x5B, 0x4B, 0x70, 0x90, 0x11, 0x02, 0x43, 0xC8, 0x21, 0x6F, 0x3A, 0xDC, 0x94, 0x08, 0x01, 
+  0xB4, 0x97, 0x52, 0x97, 0x24, 0xA1, 0x6F, 0x64, 0x3B, 0xC6, 0x3B, 0x9B, 0x25, 0x27, 0xFA, 0x4C, 0xCB, 0x27, 0xB3, 0x6A, 
+  0x6E, 0x30, 0x82, 0xAC, 0x0F, 0xD1, 0x75, 0xD1, 0xB1, 0xF8, 0x7A, 0x28, 0xAC, 0xAE, 0xAA, 0x69, 0xA6, 0xFE, 0x10, 0x59, 
+  0x44, 0x0F, 0x0A, 0xDF, 0x07, 0x9D, 0x71, 0x9B, 0x5A, 0xAE, 0xA5, 0xEA, 0x16, 0xA5, 0xD1, 0xEF, 0xC5, 0xB5, 0x22, 0x22, 
+  0x6A, 0x1A, 0x6B, 0x63, 0xD9, 0x52, 0x29, 0x32, 0xD1, 0xE5, 0x39, 0x6D, 0x57, 0x34, 0xF6, 0x1C, 0xCA, 0x45, 0x52, 0x88, 
+  0x59, 0xC0, 0x0C, 0x47, 0xA9, 0xC6, 0x91, 0x0A, 0xEC, 0xA5, 0xB8, 0x91, 0xE5, 0x54, 0x18, 0xAC, 0x4F, 0x71, 0x87, 0x1C, 
+  0x72, 0x14, 0xE0, 0xC7, 0x0E, 0xF5, 0x5D, 0x5B, 0xD4, 0xB4, 0x10, 0x74, 0x53, 0x49, 0x4B, 0x72, 0x8A, 0xE8, 0x1E, 0xA2, 
+  0x26, 0xE3, 0x34, 0xD6, 0x46, 0x44, 0xBF, 0x69, 0x24, 0x6A, 0xA7, 0xA9, 0xAA, 0x92, 0xBA, 0xEA, 0xA6, 0x0F, 0x69, 0x2A, 
+  0x56, 0x62, 0x4E, 0xAE, 0xD3, 0x78, 0xC7, 0x33, 0xA6, 0xEC, 0x71, 0xE5, 0xA4, 0x6E, 0x79, 0x48, 0xC8, 0x38, 0x07, 0x1B, 
+  0x6C, 0x37, 0x20, 0x63, 0xAE, 0xFD, 0x32, 0x47, 0x7C, 0xF0, 0x1E, 0xD6, 0x52, 0x40, 0x59, 0xCC, 0xCC, 0x32, 0x13, 0x10, 
+  0xDA, 0x3D, 0x2D, 0xA6, 0xFD, 0x39, 0xCF, 0xC3, 0xD3, 0xC1, 0xFC, 0x69, 0x75, 0x3E, 0x91, 0xDC, 0x10, 0x73, 0xD4, 0x63, 
+  0xE4, 0x72, 0x47, 0x4E, 0x9B, 0x67, 0x86, 0x53, 0x31, 0x09, 0x7E, 0x16, 0xFF, 0x00, 0x4F, 0x13, 0xE9, 0xA0, 0xBF, 0x11, 
+  0xE1, 0xCF, 0x89, 0xD7, 0xCF, 0x38, 0x7A, 0x1F, 0xC4, 0xFF, 0x00, 0xCD, 0xC1, 0xD3, 0xFF, 0x00, 0x55, 0x3F, 0x3D, 0x1A, 
+  0x90, 0x56, 0xF6, 0x47, 0x53, 0xD3, 0xAF, 0x41, 0x9C, 0xF7, 0xC9, 0xCE, 0x3D, 0xDE, 0xA7, 0x8D, 0xB4, 0x68, 0x65, 0xAF, 
+  0x98, 0x11, 0xBE, 0x37, 0xC6, 0xDD, 0x4E, 0xFB, 0xA7, 0x6E, 0x80, 0x75, 0xCF, 0x4F, 0x9F, 0x07, 0xD9, 0xFD, 0xFE, 0xFE, 
+  0x16, 0xBB, 0x62, 0x6D, 0x86, 0xE6, 0x64, 0xF0, 0xCF, 0x3F, 0x70, 0x6B, 0x5A, 0xF2, 0x12, 0xE7, 0x30, 0x50, 0x0A, 0xC6, 
+  0x70, 0x48, 0x19, 0x03, 0xD0, 0x75, 0xC7, 0xC8, 0xF5, 0xC7, 0x13, 0x50, 0x22, 0xF2, 0x1F, 0x4B, 0xE9, 0x6B, 0x52, 0xE4, 
+  0x06, 0x54, 0x4F, 0xD9, 0xEF, 0x9C, 0x8C, 0x1C, 0xF4, 0x20, 0x12, 0x06, 0xDD, 0xB2, 0x3F, 0x80, 0xE3, 0x26, 0x4B, 0x3A, 
+  0x1F, 0xBF, 0xBB, 0x68, 0x45, 0xD3, 0xD0, 0x91, 0xB2, 0x53, 0x8C, 0x75, 0x03, 0x18, 0x07, 0x39, 0xDC, 0x63, 0xAF, 0xAF, 
+  0x63, 0xD7, 0x7E, 0x83, 0x3C, 0xCB, 0x30, 0xE6, 0x73, 0x8F, 0x8F, 0xEB, 0xA5, 0x04, 0xCC, 0x5F, 0xBF, 0xDF, 0xDF, 0x18, 
+  0xD3, 0x02, 0xEA, 0xA2, 0xB1, 0x50, 0x88, 0xFC, 0x69, 0x2D, 0x25, 0xE6, 0x5D, 0x42, 0x90, 0xA4, 0x29, 0x21, 0x69, 0x29, 
+  0x5A, 0x79, 0x54, 0x0A, 0x54, 0x30, 0x46, 0x0E, 0x15, 0x9C, 0x82, 0x3F, 0x01, 0x15, 0xD1, 0xD6, 0xE2, 0x9B, 0x99, 0x6D, 
+  0x8C, 0x62, 0x03, 0x11, 0x7E, 0xFA, 0x12, 0x44, 0x4C, 0xF7, 0x24, 0x49, 0xB5, 0xAC, 0x27, 0xDB, 0x3A, 0xB4, 0x9F, 0x45, 
+  0xDD, 0xD9, 0x77, 0xE9, 0xE5, 0x77, 0xC4, 0x6E, 0x93, 0xBF, 0x50, 0x7E, 0x56, 0x8F, 0x9B, 0x0E, 0x15, 0xEC, 0xCD, 0x26, 
+  0xA6, 0xF4, 0x87, 0xE8, 0x54, 0x2B, 0x9E, 0x6D, 0x52, 0x45, 0x2D, 0xB6, 0x22, 0xB6, 0xEB, 0x8B, 0x87, 0x0D, 0x55, 0xA8, 
+  0xCD, 0xCA, 0x71, 0xC5, 0x29, 0x97, 0x0A, 0x5B, 0x84, 0xB9, 0x2D, 0xA3, 0xCF, 0x6C, 0xC8, 0x1D, 0x7F, 0xF0, 0xBA, 0xEB, 
+  0x2A, 0xDE, 0xDB, 0x56, 0xAD, 0xBA, 0x28, 0x2B, 0xCB, 0x14, 0xD4, 0xB0, 0x07, 0x07, 0x58, 0xBD, 0x46, 0x2D, 0x39, 0xBB, 
+  0xC5, 0xBB, 0x41, 0x4B, 0x07, 0x15, 0xD2, 0xD0, 0x02, 0xB4, 0x95, 0x75, 0x75, 0x53, 0x6B, 0x85, 0xA6, 0x0B, 0x3E, 0xA9, 
+  0xA6, 0xBE, 0xA8, 0xCA, 0x8B, 0x22, 0x7D, 0x56, 0xA3, 0x02, 0x36, 0x61, 0xB9, 0x35, 0xF4, 0x37, 0x30, 0x84, 0xC5, 0x9C, 
+  0x8A, 0x7C, 0x5F, 0xDA, 0xA2, 0x23, 0xED, 0x47, 0x8C, 0xA6, 0xFF, 0x00, 0xCE, 0xA4, 0xA5, 0x3E, 0xC8, 0xC8, 0x9E, 0xE7, 
+  0x90, 0xDA, 0x99, 0x75, 0xD6, 0x9A, 0x4C, 0x45, 0x29, 0x55, 0xBF, 0x57, 0x53, 0x30, 0x14, 0x1E, 0xCD, 0x30, 0x44, 0x52, 
+  0x37, 0x1E, 0x46, 0xAF, 0xD7, 0x9E, 0xC6, 0xFD, 0x55, 0x29, 0x2D, 0xC3, 0xB5, 0xBE, 0x91, 0x9B, 0xF7, 0xE7, 0x50, 0x83, 
+  0xD5, 0xB4, 0xC1, 0x92, 0xEB, 0xCD, 0xA9, 0xD4, 0xB6, 0x84, 0xF3, 0x36, 0xA5, 0x48, 0x4B, 0xCF, 0x3C, 0xDA, 0x96, 0xD2, 
+  0xCA, 0x14, 0xBF, 0x67, 0x05, 0x41, 0x2B, 0x4A, 0xDB, 0xF3, 0x0B, 0xAB, 0x05, 0x21, 0x7C, 0xD2, 0x9C, 0x58, 0x00, 0xE0, 
+  0x39, 0x8C, 0xCD, 0xB9, 0x83, 0x95, 0x56, 0x3E, 0x2F, 0x78, 0x94, 0xC0, 0x4A, 0xDB, 0x3F, 0x2F, 0xA6, 0x34, 0x92, 0x75, 
+  0x19, 0xF6, 0x5E, 0x4B, 0xA9, 0x7C, 0x73, 0x12, 0x14, 0xA3, 0xCD, 0xCD, 0xCA, 0x12, 0xA0, 0xB2, 0x81, 0xCC, 0x79, 0x0A, 
+  0x79, 0xB0, 0xE2, 0x10, 0x11, 0x90, 0x41, 0x2D, 0xE3, 0x9D, 0x45, 0x47, 0x5F, 0x32, 0x59, 0x52, 0x4B, 0xF3, 0x75, 0x9B, 
+  0x37, 0xBD, 0x89, 0x79, 0x89, 0x8A, 0xE9, 0x79, 0x40, 0x3B, 0xF6, 0xEF, 0x04, 0xE7, 0xD7, 0x8D, 0x6E, 0xE1, 0xEA, 0x9C, 
+  0xD5, 0xBA, 0xC9, 0x4D, 0x49, 0xE6, 0x14, 0x89, 0x0B, 0x79, 0x2F, 0xA9, 0xD7, 0x14, 0x86, 0x9F, 0x5E, 0x12, 0x99, 0x09, 
+  0x68, 0x2C, 0x25, 0x2E, 0xE0, 0x12, 0x1C, 0x29, 0x05, 0xA5, 0x80, 0xB0, 0x97, 0x1C, 0x52, 0x8A, 0x99, 0xB8, 0xA5, 0x37, 
+  0x83, 0x33, 0x2A, 0xB5, 0x70, 0xB7, 0x2A, 0x20, 0x20, 0xED, 0x7B, 0xDE, 0x74, 0x91, 0x99, 0xB2, 0xC0, 0x71, 0x31, 0x03, 
+  0x6F, 0x4E, 0xE6, 0xA4, 0x6A, 0x5D, 0xD0, 0xCC, 0xD7, 0xA2, 0x39, 0x1B, 0xDA, 0x23, 0xBC, 0xA7, 0x5B, 0x99, 0xE7, 0x41, 
+  0x88, 0x99, 0x6F, 0x48, 0x5A, 0x33, 0x09, 0xA6, 0xC3, 0xCB, 0x42, 0x9C, 0x85, 0x1B, 0xCD, 0x71, 0x2E, 0xC2, 0x8E, 0xD0, 
+  0x2B, 0x4C, 0xA5, 0x21, 0x28, 0xE5, 0x74, 0xA9, 0xA5, 0xE8, 0x6E, 0x32, 0x02, 0x9F, 0xD4, 0xC1, 0x75, 0x79, 0x3C, 0x36, 
+  0xE9, 0x0B, 0x88, 0xCC, 0xBA, 0x47, 0xD2, 0x39, 0x08, 0xF9, 0xF1, 0xDB, 0x00, 0xF1, 0x2D, 0xEC, 0x6E, 0x9C, 0xD9, 0xB5, 
+  0x6B, 0xD5, 0xEF, 0x66, 0xA4, 0x42, 0x95, 0x0A, 0xAC, 0xDC, 0x46, 0xD3, 0x1E, 0x1D, 0x4E, 0x96, 0x97, 0xCC, 0x38, 0xF1, 
+  0x60, 0x37, 0x11, 0x09, 0x94, 0xCA, 0xE4, 0x5B, 0xEF, 0xD3, 0x17, 0x10, 0xC9, 0x75, 0xE8, 0xCE, 0xCA, 0x6D, 0x71, 0xB9, 
+  0x17, 0xED, 0xB1, 0x63, 0x25, 0x0A, 0x4F, 0xB5, 0xF7, 0xED, 0x6D, 0x75, 0xD2, 0x54, 0xF5, 0x75, 0x24, 0x85, 0x44, 0xC0, 
+  0x90, 0x64, 0x1B, 0x8D, 0xEE, 0x5D, 0xEF, 0xAA, 0xA7, 0x77, 0xF2, 0xE6, 0xA5, 0x51, 0x6E, 0x75, 0x45, 0x52, 0x72, 0x37, 
+  0x82, 0x2C, 0xBF, 0xA9, 0x3A, 0xB7, 0x55, 0xB8, 0x36, 0x4D, 0x9B, 0xA3, 0xCF, 0x5B, 0xDE, 0x32, 0xBC, 0x24, 0xD9, 0xD5, 
+  0xFD, 0x3F, 0x4B, 0xCF, 0xC7, 0xB6, 0x35, 0xCE, 0x89, 0xAF, 0xB6, 0xB7, 0x87, 0x5D, 0x65, 0xB3, 0x66, 0x33, 0x22, 0x42, 
+  0x23, 0x2E, 0xDA, 0xB8, 0x6E, 0xE8, 0x95, 0x6B, 0x76, 0xEB, 0x8A, 0x95, 0x34, 0xB7, 0x93, 0x68, 0xDE, 0x34, 0x3A, 0x84, 
+  0x07, 0x88, 0x77, 0x91, 0x34, 0xD7, 0x94, 0xE3, 0xE9, 0xC3, 0xF1, 0x1B, 0x29, 0x4B, 0xD6, 0xED, 0x81, 0x01, 0x53, 0x5D, 
+  0x1B, 0x6E, 0x64, 0x26, 0xB8, 0xB8, 0x0D, 0xC5, 0xB3, 0x63, 0x53, 0x56, 0xFE, 0xD6, 0xE5, 0x4D, 0x74, 0x6E, 0x55, 0x4C, 
+  0x3E, 0xD6, 0xDF, 0x41, 0x5D, 0x19, 0xCF, 0x54, 0x9D, 0x29, 0x17, 0x4C, 0xA6, 0x1B, 0xEB, 0x9A, 0x4D, 0xDA, 0xFA, 0x15, 
+  0x73, 0x5C, 0xEE, 0xD3, 0xF4, 0xDB, 0x5F, 0xAB, 0xB3, 0xAD, 0xA5, 0xBC, 0xAF, 0x65, 0x6E, 0xAB, 0x6B, 0x69, 0x7E, 0xA0, 
+  0xDE, 0x10, 0x99, 0x27, 0x29, 0x66, 0x4C, 0x4D, 0x2A, 0xD6, 0x77, 0xD8, 0xAE, 0x3E, 0xD2, 0x70, 0x85, 0x4B, 0xA5, 0xD2, 
+  0xA1, 0x22, 0x41, 0x01, 0x69, 0x81, 0x1F, 0x98, 0xB6, 0x9E, 0x12, 0x9A, 0x15, 0xFC, 0xBD, 0xC2, 0xFD, 0xCD, 0xAA, 0xEA, 
+  0x96, 0xD1, 0xEC, 0x56, 0x4D, 0xF0, 0xF4, 0xDF, 0x96, 0x57, 0x54, 0x6E, 0xD3, 0x1E, 0xF5, 0x35, 0x36, 0x94, 0x58, 0xE3, 
+  0xC5, 0x97, 0x8E, 0x32, 0xE9, 0x83, 0xA8, 0x56, 0xDC, 0x9B, 0x0A, 0xA1, 0x23, 0xFF, 0x00, 0x10, 0xAA, 0x54, 0x2D, 0xF5, 
+  0x54, 0x69, 0xF4, 0xFA, 0x1D, 0x66, 0xE4, 0xB4, 0x65, 0x69, 0xE5, 0x4E, 0xE5, 0x72, 0x6B, 0x32, 0x9D, 0x90, 0xBA, 0x5D, 
+  0xAB, 0x55, 0xAA, 0x54, 0xEA, 0xDC, 0xB4, 0x8F, 0x65, 0x0B, 0xAA, 0xAD, 0xCF, 0x32, 0x2B, 0x51, 0xA4, 0x47, 0x90, 0x89, 
+  0x81, 0x4A, 0x11, 0x95, 0x9D, 0x65, 0x5B, 0x77, 0x57, 0xA7, 0xA8, 0x29, 0xEA, 0xA4, 0xA5, 0xA9, 0xCA, 0x53, 0x4C, 0xAC, 
+  0x05, 0xEA, 0x64, 0x19, 0x2E, 0x34, 0xB3, 0x65, 0x45, 0x8E, 0xFD, 0x99, 0xEF, 0xDE, 0x1C, 0x17, 0xB4, 0x4D, 0xA6, 0x67, 
+  0x4C, 0x0F, 0xF1, 0x96, 0x3F, 0xAB, 0x5F, 0x87, 0x07, 0xE6, 0x9F, 0xF5, 0xFF, 0x00, 0xDC, 0x7F, 0x1A, 0xAD, 0x4B, 0xA6, 
+  0x46, 0x08, 0xDF, 0xA7, 0x4F, 0x80, 0xDF, 0xB9, 0xE9, 0xF2, 0xDB, 0x8D, 0x9A, 0xC8, 0xB4, 0xDF, 0xE1, 0x1F, 0x5B, 0xE8, 
+  0x49, 0x13, 0xB9, 0x1A, 0x4C, 0xC8, 0xC6, 0x77, 0xF8, 0x9C, 0xF6, 0xF9, 0x03, 0x81, 0xBF, 0xAF, 0x07, 0x5D, 0xAC, 0x7C, 
+  0xD3, 0xFC, 0xBF, 0xBD, 0xF1, 0xA6, 0xB3, 0xD8, 0xF4, 0xF5, 0xD2, 0x66, 0x40, 0xDF, 0x71, 0xFC, 0x7E, 0x3B, 0x9F, 0x5E, 
+  0xBE, 0xFE, 0xDC, 0x4B, 0x5B, 0xDA, 0x0F, 0x9F, 0xD6, 0xDC, 0xF6, 0xD2, 0xD2, 0x45, 0xD4, 0xFC, 0x7E, 0x27, 0xBF, 0xC0, 
+  0x67, 0x3C, 0x4A, 0xAE, 0x63, 0xD7, 0x97, 0xD7, 0x4D, 0x9E, 0x67, 0xC4, 0xE8, 0x47, 0x5E, 0x4A, 0x41, 0xEF, 0x8E, 0xBB, 
+  0xE3, 0x1F, 0xAE, 0x3B, 0x75, 0xE8, 0x37, 0x38, 0x1C, 0x2B, 0xDB, 0x8E, 0xD6, 0xFF, 0x00, 0x1C, 0xFF, 0x00, 0x1A, 0x20, 
+  0x89, 0x50, 0x78, 0x32, 0xBD, 0xFD, 0x22, 0xF6, 0x72, 0x5F, 0x4C, 0x9A, 0xC4, 0xDC, 0xB7, 0x28, 0xA3, 0xCB, 0xC4, 0x76, 
+  0x83, 0xF2, 0xA4, 0x3A, 0xB2, 0xD4, 0x48, 0x2C, 0x2D, 0x61, 0xA4, 0x3D, 0x35, 0xFE, 0x47, 0x4B, 0x49, 0x75, 0xD3, 0xE4, 
+  0xC7, 0x69, 0xB6, 0xDE, 0x99, 0x31, 0xEF, 0xD8, 0x41, 0x8B, 0x25, 0xF3, 0xE5, 0x85, 0x51, 0x4C, 0x22, 0x2B, 0x66, 0xA1, 
+  0xB5, 0x24, 0x36, 0x5E, 0x7D, 0x69, 0x87, 0xA9, 0xE2, 0x72, 0x94, 0x0F, 0x3C, 0x1F, 0xF4, 0x83, 0x85, 0x82, 0xD6, 0x93, 
+  0x83, 0x1A, 0x94, 0x34, 0x62, 0xCB, 0xD6, 0x5B, 0xBE, 0x2B, 0xF6, 0xC6, 0x9A, 0xDA, 0x57, 0x33, 0x56, 0xC5, 0x66, 0xA3, 
+  0x1E, 0xB3, 0x74, 0x56, 0xD3, 0x45, 0xA8, 0xC5, 0x99, 0x76, 0x4B, 0x8C, 0x81, 0x1D, 0x89, 0x32, 0xC2, 0x19, 0x5B, 0x8C, 
+  0xD0, 0x68, 0x74, 0xFE, 0x78, 0x94, 0x6A, 0x2B, 0x6A, 0x7D, 0x31, 0x98, 0x91, 0x52, 0xA8, 0xCA, 0x7A, 0x4D, 0x56, 0xA3, 
+  0x2D, 0x51, 0xFA, 0x7F, 0x0B, 0xB5, 0xB9, 0xB9, 0xEC, 0x53, 0x4D, 0x54, 0x6D, 0xD7, 0x57, 0xE6, 0x6E, 0x56, 0x8D, 0x2D, 
+  0x49, 0x6B, 0x5F, 0xDD, 0x86, 0x29, 0xA6, 0x67, 0xA9, 0x6A, 0x4B, 0xDB, 0x0A, 0xEB, 0xA0, 0x46, 0xAA, 0xCA, 0x52, 0x49, 
+  0x88, 0xE9, 0xB7, 0x03, 0x79, 0x98, 0xF1, 0xDF, 0xCD, 0x88, 0xD5, 0x5D, 0x1A, 0xAD, 0x59, 0x74, 0x3A, 0x0D, 0x26, 0x7B, 
+  0x14, 0xF8, 0xD3, 0xA3, 0x53, 0x1B, 0xA9, 0x55, 0x63, 0xD3, 0x8C, 0xA9, 0x2E, 0xC6, 0x9B, 0x52, 0x3F, 0x5C, 0x3C, 0xF3, 
+  0xAF, 0x21, 0x58, 0x6E, 0x7C, 0xF8, 0x4F, 0xC4, 0x69, 0xF3, 0x36, 0x71, 0x7E, 0x98, 0x96, 0x55, 0x89, 0x2E, 0x38, 0xA0, 
+  0xE3, 0x9D, 0xDB, 0xBF, 0x86, 0x4A, 0x4E, 0x89, 0x20, 0xAA, 0xA6, 0x97, 0x96, 0x45, 0x66, 0xED, 0x55, 0x46, 0x2F, 0x07, 
+  0x90, 0xD4, 0xD0, 0x9B, 0x9D, 0x4D, 0x2D, 0x49, 0x31, 0x4F, 0x50, 0x52, 0xA1, 0x97, 0xB4, 0xE7, 0xBC, 0x97, 0x89, 0xD7, 
+  0x3D, 0x6F, 0x6A, 0x5C, 0x98, 0x52, 0x5D, 0x61, 0xB5, 0x2F, 0x08, 0x49, 0x0A, 0x09, 0x53, 0x89, 0x0B, 0x64, 0x82, 0xEB, 
+  0x0E, 0x29, 0x6F, 0xA1, 0x05, 0x28, 0x0D, 0xA8, 0x15, 0x25, 0x08, 0x08, 0x0A, 0x50, 0x08, 0x2E, 0x36, 0x09, 0x47, 0x8F, 
+  0xB9, 0x25, 0xAF, 0xE6, 0x0E, 0x12, 0xC5, 0xAD, 0x7B, 0x0D, 0xFE, 0x7A, 0xDA, 0x99, 0xBA, 0x04, 0x67, 0x30, 0x09, 0x98, 
+  0x61, 0xE2, 0x3C, 0x1D, 0xF5, 0x0D, 0x4A, 0xF6, 0xE2, 0xE1, 0x09, 0xF3, 0x76, 0xC9, 0xC6, 0xF8, 0x18, 0x1F, 0xBA, 0xA4, 
+  0xFA, 0x80, 0x01, 0x3B, 0x90, 0x36, 0x1C, 0xA5, 0x3C, 0x61, 0x52, 0xF9, 0x56, 0xC7, 0xF3, 0x7B, 0x58, 0xBF, 0x9D, 0x32, 
+  0x92, 0xCD, 0xB1, 0xC1, 0x9F, 0x87, 0x13, 0xCD, 0xA7, 0x89, 0xEE, 0xB4, 0x17, 0x26, 0xF9, 0x99, 0xFD, 0xA1, 0x00, 0x8C, 
+  0x9C, 0x64, 0x0F, 0xB6, 0x08, 0x04, 0x02, 0x3A, 0xA8, 0xA4, 0x00, 0x33, 0xCE, 0xA5, 0x04, 0x60, 0x1C, 0x80, 0xE9, 0x52, 
+  0x1E, 0x70, 0xFD, 0xC7, 0xED, 0xA2, 0x01, 0x18, 0x0B, 0xBC, 0xDB, 0x1C, 0xDA, 0xDF, 0x43, 0x32, 0xEA, 0xD1, 0x69, 0x64, 
+  0x07, 0xAA, 0x73, 0x19, 0x8A, 0xDB, 0xCC, 0x22, 0x51, 0x54, 0x59, 0x02, 0xA6, 0xF2, 0xA4, 0xE2, 0x0A, 0x0A, 0x10, 0x5D, 
+  0x92, 0x9E, 0x47, 0x59, 0x6A, 0x4B, 0x81, 0x28, 0xF2, 0x18, 0x8E, 0xF1, 0x41, 0x6A, 0x52, 0x82, 0x50, 0xE2, 0x12, 0x54, 
+  0xD9, 0xED, 0xD8, 0x1A, 0xEB, 0x29, 0xA6, 0xF5, 0x35, 0x28, 0xDC, 0x02, 0x61, 0x65, 0x60, 0x00, 0xB8, 0x1D, 0xA2, 0xD1, 
+  0x19, 0xA2, 0xCF, 0x48, 0xCE, 0x22, 0x03, 0xDA, 0xE0, 0x8E, 0x06, 0x18, 0x6F, 0x3D, 0xF9, 0xD7, 0x70, 0xFC, 0x2D, 0xDB, 
+  0xF4, 0xFA, 0x53, 0xB4, 0xA9, 0x93, 0xD8, 0x72, 0x44, 0x86, 0x56, 0x84, 0xCC, 0x44, 0xEA, 0x6D, 0x45, 0x97, 0x5D, 0x4A, 
+  0x14, 0xE2, 0xA5, 0xD5, 0x62, 0xB0, 0xD4, 0xF7, 0x98, 0x6D, 0x6F, 0xC2, 0x90, 0x89, 0x0F, 0x33, 0x25, 0x99, 0x08, 0x90, 
+  0xE4, 0x99, 0x0E, 0x37, 0x1F, 0xCD, 0x25, 0xF7, 0xFD, 0xFA, 0x08, 0x04, 0x9C, 0x86, 0x2A, 0x88, 0xC1, 0x67, 0x93, 0x2D, 
+  0xEC, 0xAE, 0x6D, 0x3C, 0xDB, 0xE9, 0x36, 0x98, 0xB4, 0x34, 0xB3, 0x4F, 0x22, 0x3F, 0x19, 0x33, 0x18, 0x09, 0xD7, 0x24, 
+  0x7E, 0x95, 0xEA, 0x9D, 0xDD, 0xAB, 0x5E, 0x37, 0xAE, 0x4B, 0x6E, 0xEC, 0x97, 0x21, 0xDB, 0x07, 0x4B, 0xEC, 0xDB, 0x1A, 
+  0x1E, 0x9E, 0x5B, 0xA0, 0xA4, 0x51, 0x58, 0x83, 0x70, 0xD1, 0xBE, 0xBA, 0x99, 0x55, 0x62, 0x1B, 0x63, 0xD9, 0x9E, 0x91, 
+  0x2E, 0x5B, 0xAF, 0x47, 0x71, 0xF2, 0x16, 0x53, 0xEC, 0xDE, 0xCA, 0xA2, 0x93, 0x14, 0xB6, 0x3E, 0x7F, 0xFE, 0x24, 0xD7, 
+  0x5F, 0xE2, 0x29, 0xDB, 0xBF, 0x45, 0x1B, 0x74, 0x34, 0x8E, 0x26, 0xB5, 0x54, 0x8C, 0xB6, 0x89, 0x8E, 0x23, 0xC6, 0xAB, 
+  0xF0, 0xFB, 0x54, 0xD7, 0x45, 0x2F, 0x4F, 0x13, 0x51, 0x71, 0xAB, 0x71, 0x5F, 0x69, 0xB7, 0x14, 0x94, 0xD2, 0x46, 0x21, 
+  0xB0, 0xBA, 0xA3, 0x67, 0x4F, 0xE8, 0x52, 0x59, 0x43, 0x4F, 0xD2, 0x62, 0x3C, 0xDA, 0x31, 0xC8, 0x97, 0x63, 0x32, 0xE7, 
+  0x21, 0x03, 0x00, 0xA4, 0x2D, 0xB5, 0x04, 0x9D, 0xF7, 0x23, 0x04, 0x76, 0x23, 0x1C, 0x70, 0x74, 0x01, 0x7B, 0x7D, 0x08, 
+  0xE2, 0xFC, 0x7A, 0xEB, 0xAB, 0xA0, 0x48, 0x4A, 0x78, 0x0B, 0x7D, 0x3E, 0x9F, 0x09, 0xB8, 0xC6, 0xB7, 0xD4, 0x6B, 0x3A, 
+  0x93, 0x45, 0x74, 0x48, 0x85, 0x05, 0x96, 0x9F, 0xE4, 0x0D, 0x07, 0x42, 0x79, 0x9D, 0x0D, 0x8C, 0xA8, 0x34, 0x16, 0x41, 
+  0x52, 0x5A, 0x18, 0x04, 0x36, 0x08, 0x40, 0x56, 0x0F, 0x28, 0xC6, 0x78, 0xA0, 0x2C, 0xC4, 0x29, 0x69, 0xCE, 0x03, 0x9C, 
+  0x62, 0xF1, 0xCF, 0x9D, 0x32, 0x8A, 0x69, 0x94, 0x01, 0xE5, 0xE6, 0x3F, 0x63, 0x94, 0x3E, 0x5A, 0x70, 0xFB, 0x10, 0xFD, 
+  0xD5, 0xFE, 0x23, 0xF9, 0x70, 0x41, 0xD8, 0xF9, 0x1A, 0x26, 0xAF, 0xF4, 0xFF, 0x00, 0xF2, 0x35, 0x3A, 0x2A, 0x46, 0x06, 
+  0x4F, 0xC3, 0xF8, 0x01, 0xDF, 0xE5, 0x8C, 0xF1, 0xD3, 0x9D, 0x56, 0x81, 0x91, 0x50, 0x6D, 0x94, 0xAD, 0x6E, 0x2C, 0x25, 
+  0x09, 0x49, 0x52, 0x94, 0xB5, 0x84, 0x24, 0x04, 0xEE, 0x54, 0x54, 0xAC, 0x00, 0x00, 0xDF, 0x24, 0xA4, 0x6D, 0xE8, 0x37, 
+  0x69, 0x01, 0x73, 0xBE, 0x70, 0x3D, 0xF8, 0x3F, 0xBF, 0x64, 0xD3, 0xE3, 0x82, 0x79, 0x81, 0x4F, 0xDF, 0xE1, 0x69, 0xD0, 
+  0x48, 0xAB, 0x07, 0xDD, 0x43, 0x31, 0xE3, 0xBE, 0xFB, 0x8E, 0x14, 0xA1, 0xB4, 0x36, 0xC3, 0xAB, 0x5B, 0x85, 0x5F, 0x71, 
+  0x2D, 0x24, 0xA1, 0x2A, 0x75, 0x6E, 0x67, 0x0D, 0xA1, 0xA0, 0xE2, 0xDC, 0x27, 0x0D, 0xA5, 0x44, 0xA4, 0x70, 0x0A, 0x90, 
+  0x4C, 0x66, 0x0F, 0xD3, 0xE1, 0x3F, 0xCD, 0xF4, 0x0B, 0x70, 0xAE, 0xAC, 0xF1, 0x34, 0x91, 0x30, 0x93, 0xD4, 0x90, 0xF2, 
+  0x27, 0xAF, 0x2E, 0x96, 0x66, 0x72, 0x5D, 0x4F, 0x3A, 0x56, 0x14, 0x08, 0x18, 0x20, 0x91, 0x9D, 0x89, 0xCE, 0x0E, 0xE9, 
+  0xC7, 0x70, 0x7A, 0x67, 0xA0, 0x24, 0xF0, 0x8B, 0x84, 0x4D, 0xEE, 0x59, 0x08, 0x6D, 0x2A, 0xC4, 0x71, 0xF6, 0x20, 0x9F, 
+  0x8D, 0xFB, 0xF7, 0xE7, 0xED, 0xD2, 0x72, 0x5F, 0x25, 0x0A, 0xC2, 0xBA, 0xFC, 0x77, 0xCF, 0x4F, 0x87, 0xE3, 0x9F, 0x5E, 
+  0xBC, 0x0D, 0xA6, 0x78, 0x17, 0x3E, 0x3C, 0x4F, 0xDF, 0x6D, 0x1A, 0x8B, 0x2B, 0x17, 0x9E, 0xAC, 0xD9, 0xDF, 0x5B, 0x7F, 
+  0x93, 0x6B, 0xAA, 0x25, 0x03, 0xEB, 0x77, 0x60, 0xCA, 0x94, 0x67, 0x5A, 0xF4, 0x0B, 0x85, 0xE6, 0xA6, 0xD3, 0x98, 0x91, 
+  0x1E, 0x2C, 0xEA, 0x5C, 0x8A, 0xCC, 0x39, 0x4F, 0x53, 0x24, 0x26, 0x3C, 0x97, 0x59, 0x5A, 0xE3, 0x92, 0x85, 0x21, 0x7C, 
+  0xC1, 0xB6, 0xDE, 0x2B, 0x71, 0x79, 0xF5, 0xEF, 0xED, 0x4F, 0x45, 0x41, 0xD6, 0x8D, 0x50, 0x53, 0x54, 0x21, 0x02, 0x54, 
+  0x8C, 0x59, 0x4B, 0x5E, 0xD3, 0x9D, 0x67, 0x5D, 0x35, 0x55, 0x3D, 0x28, 0x0E, 0x7A, 0x89, 0xE2, 0x2C, 0x11, 0x7B, 0xF2, 
+  0xB8, 0x3B, 0x6B, 0x7D, 0xA2, 0x5F, 0x48, 0x8F, 0x8D, 0x2F, 0x0D, 0x77, 0xD5, 0x1E, 0xED, 0xB8, 0x2F, 0x97, 0x35, 0x4F, 
+  0x4F, 0xA3, 0xCD, 0x61, 0xBB, 0xCA, 0xC9, 0xB9, 0xA9, 0x94, 0xB7, 0xE0, 0xD5, 0xED, 0x97, 0x1E, 0x6C, 0x55, 0xE1, 0xC6, 
+  0x53, 0x30, 0xA1, 0xCB, 0xA6, 0xBE, 0xEC, 0x20, 0xEA, 0x18, 0x7A, 0x24, 0xC4, 0x21, 0xB5, 0x10, 0x97, 0x1B, 0xF2, 0x56, 
+  0xE7, 0x17, 0xB1, 0xF8, 0xFD, 0xFD, 0xBD, 0xCA, 0x4A, 0xF7, 0x1A, 0xE8, 0x6A, 0x06, 0x9A, 0xA1, 0xCC, 0x13, 0x4A, 0x0A, 
+  0x54, 0x71, 0x1E, 0x91, 0xAE, 0x3A, 0xF6, 0x9C, 0xEE, 0x14, 0xD5, 0x4C, 0x9E, 0xD5, 0x27, 0x4D, 0x74, 0xE3, 0xDA, 0x12, 
+  0x04, 0xA6, 0xD3, 0x4C, 0x55, 0x38, 0xF4, 0xF5, 0xD9, 0xAB, 0xB6, 0x0D, 0x95, 0xAE, 0x5A, 0x67, 0x68, 0xEA, 0x25, 0x9D, 
+  0x6A, 0x51, 0x28, 0xF4, 0xAD, 0x40, 0xB5, 0xE8, 0x57, 0xAD, 0x36, 0x8F, 0x16, 0xD6, 0x7E, 0x5B, 0x10, 0x95, 0x59, 0xA7, 
+  0xC1, 0xA8, 0x47, 0x8B, 0x51, 0xA8, 0xA5, 0x94, 0x2D, 0xD7, 0x52, 0xF3, 0xAD, 0xC6, 0x53, 0x9E, 0x4B, 0xCD, 0x53, 0x12, 
+  0xCB, 0x52, 0xE4, 0xBB, 0x24, 0xB8, 0x5F, 0x8F, 0xF4, 0x65, 0x42, 0x46, 0x66, 0x2A, 0x17, 0xCD, 0xA5, 0xF1, 0x10, 0xF2, 
+  0x5C, 0xCF, 0x1C, 0xF4, 0x57, 0x56, 0xDD, 0x68, 0xB3, 0x55, 0x15, 0x74, 0xFB, 0xD1, 0x3D, 0x28, 0x79, 0x11, 0x2E, 0x4D, 
+  0xD1, 0x33, 0x1A, 0xF3, 0xFB, 0xAF, 0x3E, 0x18, 0xEB, 0x74, 0x7A, 0xAD, 0x46, 0x7B, 0x8C, 0x34, 0xCC, 0x64, 0x4F, 0xA8, 
+  0x45, 0x50, 0x82, 0x2A, 0x13, 0xA4, 0xB6, 0xEC, 0x4E, 0x64, 0xF9, 0x2D, 0xB8, 0xE4, 0x44, 0x38, 0x63, 0xBA, 0xEA, 0xDF, 
+  0x53, 0x02, 0x3B, 0x2E, 0x08, 0xE7, 0xCA, 0x69, 0x2F, 0x37, 0x4F, 0x42, 0x65, 0xBF, 0xE7, 0xFE, 0x27, 0xF0, 0xA5, 0x6B, 
+  0x55, 0x16, 0x99, 0x9A, 0x41, 0x65, 0xE1, 0xA6, 0x3F, 0x73, 0x37, 0xF4, 0xF5, 0x76, 0xEB, 0xA7, 0x70, 0x23, 0xDE, 0xB6, 
+  0x52, 0x1C, 0xAC, 0x19, 0xB3, 0x03, 0x2D, 0xED, 0x05, 0xB5, 0x4C, 0x6A, 0x3A, 0x62, 0xEC, 0x62, 0xB0, 0xEB, 0x4A, 0x8C, 
+  0x3C, 0xE7, 0x1B, 0x1E, 0x73, 0x6E, 0xBA, 0xEA, 0x56, 0x16, 0x86, 0x94, 0xA7, 0x79, 0x46, 0x53, 0xC8, 0xB7, 0x08, 0x50, 
+  0x71, 0xB6, 0xD0, 0xDA, 0x81, 0x40, 0x23, 0x64, 0x27, 0xCC, 0xAF, 0xF0, 0xF1, 0x66, 0x68, 0xCC, 0x95, 0x17, 0x62, 0x2F, 
+  0xDE, 0x4B, 0x4D, 0xA0, 0xEC, 0x91, 0xAB, 0xC6, 0x6D, 0xEB, 0x9C, 0x4F, 0xF3, 0xDF, 0x58, 0xC7, 0xD3, 0x07, 0x70, 0x30, 
+  0x5B, 0x47, 0x92, 0xA5, 0x2D, 0xC3, 0xE6, 0x29, 0xD5, 0xF9, 0x4C, 0xF2, 0xF3, 0xCA, 0x0D, 0xA5, 0xA2, 0x84, 0xB2, 0x85, 
+  0xAD, 0x0D, 0xBB, 0x2B, 0xCE, 0x48, 0x61, 0x4F, 0xB2, 0x14, 0x1A, 0x0A, 0xE6, 0x35, 0x46, 0xC5, 0x49, 0x61, 0xAA, 0xAB, 
+  0x36, 0x16, 0x70, 0x90, 0x18, 0x9C, 0x37, 0xFD, 0xCD, 0x1C, 0x0E, 0x67, 0x11, 0x9F, 0x90, 0x2F, 0xC2, 0xDD, 0xFD, 0x6E, 
+  0xEF, 0x84, 0xAD, 0x16, 0x7E, 0xB5, 0xA8, 0x94, 0x8A, 0x64, 0xA8, 0xD1, 0x1E, 0x8F, 0x53, 0x90, 0xC2, 0x1B, 0x71, 0xE4, 
+  0xBA, 0xDD, 0x3D, 0xD6, 0x56, 0x03, 0xAF, 0xB0, 0xFB, 0x6D, 0xC5, 0x90, 0xA7, 0xE3, 0x36, 0x12, 0xE9, 0x96, 0x5B, 0x41, 
+  0x9D, 0xEC, 0xCD, 0x3E, 0xFC, 0x26, 0xFC, 0xF6, 0xD8, 0x4C, 0xBF, 0x53, 0xF0, 0x9B, 0x1F, 0x97, 0xED, 0x56, 0x5D, 0x22, 
+  0x92, 0x09, 0xA4, 0x62, 0x66, 0x26, 0xFC, 0x46, 0x42, 0x4C, 0xE3, 0x0D, 0xEA, 0xBA, 0x28, 0x6A, 0xF6, 0x86, 0xE5, 0xAD, 
+  0x50, 0x7A, 0x88, 0x8B, 0x08, 0x07, 0x74, 0x60, 0x35, 0xDB, 0xFD, 0x49, 0xA2, 0x78, 0x76, 0xF0, 0xED, 0x65, 0xC6, 0x63, 
+  0x57, 0xB5, 0x4E, 0xC5, 0xD3, 0x76, 0xE4, 0x25, 0xF9, 0x14, 0xF6, 0x2E, 0x1B, 0x8D, 0x98, 0x0E, 0x4A, 0x9C, 0xD7, 0x97, 
+  0x4F, 0x8D, 0xEC, 0x71, 0xBF, 0x65, 0x2E, 0x1C, 0x16, 0x16, 0x95, 0x42, 0x87, 0x10, 0x34, 0xA0, 0x21, 0x25, 0xDA, 0x95, 
+  0x40, 0xA1, 0xE9, 0x5E, 0xC8, 0xC7, 0x65, 0x7B, 0x94, 0x51, 0x2D, 0x4D, 0x34, 0x04, 0xCD, 0x55, 0x21, 0x19, 0xE5, 0xB0, 
+  0x67, 0x04, 0xBE, 0xBA, 0xF3, 0x4F, 0xCD, 0xDC, 0x5A, 0xA9, 0x14, 0xCD, 0x55, 0x16, 0x0E, 0x73, 0x55, 0xBD, 0x26, 0x15, 
+  0x10, 0x1C, 0xEB, 0x81, 0x7E, 0x31, 0x69, 0x0C, 0xDD, 0xD5, 0xBA, 0x3E, 0xA7, 0x5B, 0xD5, 0x6A, 0x2D, 0xEF, 0x46, 0x81, 
+  0x4B, 0x9B, 0x4B, 0xA3, 0xDE, 0xB6, 0xAC, 0xD6, 0x6A, 0xF4, 0x8B, 0xB3, 0x4F, 0xE3, 0x4C, 0x91, 0x54, 0x6A, 0x3F, 0xB5, 
+  0x44, 0x53, 0xA9, 0x15, 0xEB, 0x12, 0x5C, 0x9A, 0x84, 0xD5, 0xC1, 0x77, 0xCB, 0x95, 0x26, 0xD5, 0xAB, 0x54, 0x1C, 0x6D, 
+  0xA1, 0xF5, 0x12, 0x5A, 0x57, 0x93, 0xFF, 0x00, 0x10, 0x0D, 0xD6, 0x8D, 0xFA, 0x3A, 0x6A, 0xA6, 0x91, 0xA5, 0xDC, 0xA1, 
+  0xEA, 0xA6, 0xAA, 0x4B, 0xC0, 0x96, 0xEB, 0xA1, 0x6A, 0x43, 0x2D, 0x2B, 0x7B, 0x4E, 0xBB, 0xF6, 0x52, 0x3A, 0x59, 0xA1, 
+  0x8B, 0xD3, 0x84, 0x62, 0xC8, 0xCC, 0x34, 0xB7, 0xF4, 0x60, 0x9C, 0x85, 0x33, 0x61, 0xA6, 0x9C, 0x42, 0x4A, 0x4A, 0x14, 
+  0x92, 0x32, 0x08, 0xE5, 0x29, 0x52, 0x4E, 0xE1, 0x49, 0xC1, 0xC2, 0xB6, 0x3B, 0x28, 0x64, 0x11, 0x8D, 0xC8, 0x3C, 0x79, 
+  0xEB, 0x4F, 0xB2, 0x9D, 0x99, 0x96, 0xEB, 0xC3, 0x27, 0x7C, 0xFD, 0x6D, 0xAE, 0x99, 0xC6, 0x3E, 0x7F, 0x28, 0xB5, 0xE7, 
+  0x4B, 0x79, 0x48, 0x3B, 0x1C, 0x9E, 0x9B, 0x02, 0x13, 0xD0, 0x77, 0xDB, 0xB7, 0x7F, 0x86, 0x4F, 0x4E, 0x17, 0x53, 0xD8, 
+  0x5F, 0x8A, 0xFE, 0xAC, 0xE8, 0xCE, 0x38, 0x7C, 0x9F, 0xE4, 0xFD, 0x1D, 0x25, 0xE4, 0xA3, 0xF7, 0xFF, 0x00, 0x4E, 0x1F, 
+  0x53, 0xFF, 0x00, 0xEA, 0x7E, 0x46, 0x88, 0x3C, 0xFC, 0xDF, 0xE7, 0x4F, 0xC7, 0x64, 0x10, 0x9D, 0x8E, 0xE0, 0x7F, 0xD0, 
+  0xC1, 0xFE, 0xE1, 0xDB, 0xAF, 0x4D, 0x7F, 0x4F, 0x3A, 0x7F, 0x7F, 0x7F, 0xE1, 0xD3, 0x7C, 0x5C, 0xD1, 0xAD, 0xAA, 0xE5, 
+  0x2E, 0xB3, 0x56, 0xB7, 0x25, 0xDD, 0xB4, 0x78, 0xA9, 0x9C, 0x26, 0x51, 0xE9, 0xF3, 0x62, 0x53, 0xEA, 0x05, 0xE9, 0x10, 
+  0x5E, 0x8F, 0x02, 0xA5, 0x05, 0xFA, 0x8B, 0x6F, 0x40, 0x72, 0x55, 0x26, 0x5B, 0x8D, 0xCA, 0x62, 0x3C, 0xD6, 0xFC, 0x95, 
+  0x2D, 0x29, 0x79, 0x2A, 0x4B, 0xF1, 0xD8, 0x26, 0x3A, 0xA8, 0x2A, 0xA5, 0x68, 0x6A, 0xA4, 0xEA, 0xA5, 0x24, 0xBC, 0x8F, 
+  0x4A, 0x0B, 0x0F, 0x4B, 0xCB, 0x99, 0x7D, 0x35, 0x35, 0x2C, 0x7B, 0x22, 0xDE, 0x19, 0x41, 0xC0, 0xC9, 0x72, 0xCF, 0xA9, 
+  0x68, 0xCE, 0x9B, 0xAF, 0xDE, 0xD1, 0x27, 0x4A, 0x6C, 0xD9, 0x3A, 0x6E, 0xAB, 0x39, 0x48, 0x7C, 0xC9, 0x6E, 0xE5, 0xBD, 
+  0x2E, 0xC9, 0xD7, 0xED, 0xD7, 0x12, 0x41, 0x51, 0x57, 0xB5, 0xD1, 0xE1, 0xA9, 0x31, 0x6D, 0x8A, 0x3D, 0x49, 0x0B, 0xFD, 
+  0xA3, 0x15, 0x69, 0x11, 0xAB, 0xD3, 0xA2, 0x3C, 0x11, 0x22, 0x12, 0xA3, 0x49, 0x43, 0x4F, 0x36, 0xBA, 0xC5, 0xFF, 0x00, 
+  0x97, 0xB5, 0xD2, 0xDB, 0xDA, 0xAD, 0x6B, 0xAE, 0xD7, 0x50, 0xF7, 0x69, 0x78, 0x98, 0x6D, 0xE9, 0xA9, 0x29, 0xA9, 0x01, 
+  0xF6, 0x48, 0x84, 0x61, 0x5F, 0x58, 0x63, 0xC6, 0x5B, 0x5B, 0xD5, 0xC3, 0x4B, 0xC4, 0x78, 0xCD, 0x34, 0x0A, 0xD7, 0xE5, 
+  0xA4, 0x27, 0x2B, 0x52, 0x94, 0xE2, 0xF6, 0xC8, 0x2B, 0x52, 0xCA, 0x94, 0xA5, 0x91, 0x9E, 0x75, 0xAC, 0x95, 0xA9, 0x44, 
+  0xA9, 0x45, 0x4A, 0x24, 0x9A, 0xA7, 0xAB, 0xD9, 0x3D, 0x92, 0x94, 0x73, 0x33, 0x9A, 0x8E, 0xF6, 0xC2, 0xB9, 0x21, 0x6C, 
+  0x26, 0xB4, 0x24, 0xED, 0x80, 0xB7, 0xDE, 0x31, 0xAD, 0x9A, 0xD7, 0xCC, 0x83, 0x9E, 0xE7, 0x3B, 0x8D, 0xF6, 0xEB, 0xB0, 
+  0xEC, 0x00, 0x27, 0xFE, 0xFC, 0x3A, 0x9E, 0x9E, 0x7E, 0x4C, 0xDB, 0x9C, 0x77, 0x2D, 0xF1, 0xBD, 0xB4, 0xD6, 0xC7, 0x19, 
+  0x83, 0x31, 0xF1, 0xF3, 0x13, 0x1F, 0xCE, 0x9A, 0x75, 0x87, 0x21, 0xA5, 0x3F, 0xB6, 0x75, 0x09, 0x51, 0xD9, 0x09, 0x39, 
+  0x52, 0xD4, 0x54, 0x79, 0x40, 0x0D, 0xA4, 0x17, 0x09, 0x52, 0xF2, 0x94, 0xA4, 0x03, 0xCC, 0xAD, 0x80, 0x2A, 0xC6, 0x33, 
+  0x9A, 0x25, 0xF6, 0x5B, 0xF0, 0x22, 0x8D, 0xAC, 0x4D, 0xB1, 0x8C, 0x5E, 0xF1, 0x1A, 0x99, 0x08, 0xBE, 0x66, 0xF1, 0x6F, 
+  0x17, 0xFE, 0x4F, 0x8F, 0x72, 0x2D, 0x4D, 0x37, 0xA5, 0xDC, 0x57, 0x75, 0x2E, 0x99, 0xA9, 0x54, 0xEA, 0x85, 0xBF, 0x62, 
+  0x45, 0x61, 0xAB, 0x9A, 0xF3, 0x5D, 0x69, 0xA7, 0x2D, 0xB4, 0x0B, 0x2E, 0x23, 0xE8, 0x72, 0x64, 0xCA, 0xDD, 0x56, 0xA8, 
+  0x86, 0x5B, 0xB5, 0xAD, 0xAA, 0x82, 0x40, 0x86, 0xE5, 0x62, 0x4A, 0x17, 0x52, 0xAA, 0x21, 0xE5, 0x53, 0x6D, 0x7A, 0x7C, 
+  0xEA, 0x9C, 0x96, 0x9E, 0x8B, 0x5B, 0x5B, 0x45, 0x7B, 0x94, 0x1B, 0x83, 0x4D, 0x07, 0xB7, 0x5C, 0xD9, 0x28, 0xA5, 0x65, 
+  0xA9, 0x6D, 0x45, 0x32, 0x47, 0x53, 0x7A, 0x94, 0x29, 0x1D, 0x67, 0xB8, 0x85, 0x0A, 0x45, 0xC8, 0x2E, 0x5F, 0x96, 0xD3, 
+  0x0C, 0x3C, 0xB6, 0x2E, 0xBE, 0xCC, 0xCF, 0xA3, 0x2F, 0x0C, 0x1F, 0x4E, 0x0F, 0xD1, 0xF7, 0x22, 0xB5, 0x41, 0xD1, 0x8B, 
+  0xD9, 0xEA, 0xF5, 0x0A, 0x8F, 0x02, 0x64, 0x3A, 0x15, 0xB9, 0x7C, 0x55, 0x2D, 0xF9, 0x34, 0xEB, 0x1E, 0x33, 0x0C, 0xB6, 
+  0xDD, 0x22, 0x28, 0x69, 0xA5, 0x4E, 0x8F, 0x26, 0x1C, 0x16, 0x58, 0x75, 0x6D, 0xC7, 0x7A, 0xA6, 0xB8, 0xC9, 0x55, 0x39, 
+  0xA6, 0x61, 0x8F, 0x66, 0x0E, 0x3A, 0xF0, 0xF6, 0x28, 0xFC, 0x7F, 0xE1, 0xEB, 0x7A, 0x29, 0xAC, 0x16, 0xAF, 0x65, 0xAE, 
+  0x96, 0x8A, 0x53, 0x19, 0xE0, 0x70, 0x12, 0x36, 0xC1, 0x83, 0xCB, 0xAF, 0x69, 0xAA, 0xA6, 0xAA, 0x77, 0x69, 0x6B, 0x6E, 
+  0xD3, 0x28, 0xB5, 0x66, 0xCD, 0x41, 0x4B, 0x57, 0x6B, 0xB2, 0x31, 0x4C, 0xEB, 0xA9, 0x1A, 0xC5, 0xE0, 0xCB, 0x4F, 0xF5, 
+  0x86, 0x93, 0x4F, 0xBD, 0x74, 0xC1, 0xB7, 0xAA, 0x90, 0x2A, 0x6B, 0x4D, 0x55, 0xF9, 0xF1, 0x98, 0x75, 0xFB, 0x6A, 0x5D, 
+  0x3A, 0x7C, 0x90, 0xA8, 0xDE, 0xD0, 0xFB, 0x0A, 0x92, 0x86, 0x55, 0x3E, 0x24, 0xBC, 0x46, 0x89, 0x4F, 0x4A, 0x22, 0xC7, 
+  0x53, 0x71, 0x9A, 0x62, 0x3C, 0x96, 0x50, 0x24, 0xAB, 0xAC, 0xA8, 0x6C, 0x84, 0x8F, 0x7E, 0x08, 0x3C, 0x49, 0xC7, 0xCB, 
+  0x12, 0xCC, 0xED, 0xEE, 0xEE, 0x6D, 0xA9, 0x72, 0x31, 0xC5, 0x42, 0x99, 0x93, 0x9E, 0x6F, 0x1F, 0x3D, 0x50, 0x0A, 0xBF, 
+  0xD1, 0x9D, 0x70, 0x55, 0x5A, 0x7A, 0x48, 0xB6, 0xA2, 0xC5, 0x7A, 0x0C, 0xA6, 0xDC, 0x54, 0x97, 0x0A, 0x61, 0x2A, 0x5B, 
+  0xE8, 0x12, 0x42, 0x25, 0x46, 0xA9, 0x9F, 0x6D, 0xA7, 0x54, 0x1F, 0x8A, 0xB4, 0x49, 0x95, 0x36, 0x0B, 0x12, 0x18, 0x66, 
+  0x24, 0x4F, 0x2A, 0x3A, 0x22, 0x49, 0x9A, 0xCF, 0x2B, 0x29, 0xA2, 0x9A, 0xB8, 0x33, 0x9B, 0x0F, 0xAB, 0x9E, 0xF7, 0xF1, 
+  0x3E, 0x75, 0xD6, 0x7E, 0x39, 0xA7, 0x15, 0x29, 0x0F, 0x98, 0x01, 0xB2, 0x18, 0xEC, 0x66, 0x53, 0x9B, 0x1A, 0xD8, 0xD2, 
+  0xBE, 0x8B, 0x54, 0xDB, 0x0A, 0x55, 0x62, 0xEC, 0xFA, 0xB6, 0x0D, 0x11, 0xE9, 0x48, 0xF3, 0x65, 0xCD, 0xA8, 0xBF, 0x43, 
+  0x5C, 0xAF, 0x3D, 0x4A, 0x90, 0x1C, 0xA8, 0xAA, 0xAA, 0x89, 0x09, 0x7E, 0x95, 0x0E, 0xA5, 0x1C, 0x39, 0x29, 0xC7, 0xDD, 
+  0x61, 0x0A, 0x3C, 0xAE, 0xD5, 0xE3, 0x84, 0xA4, 0x40, 0x7C, 0x29, 0xA6, 0xF4, 0xE6, 0xF0, 0x96, 0x7B, 0x41, 0x78, 0xB4, 
+  0x62, 0x7F, 0x98, 0x97, 0xF1, 0xF5, 0xD5, 0x11, 0xC7, 0x00, 0x31, 0x21, 0x10, 0x4C, 0x8E, 0x12, 0x3F, 0x89, 0xB1, 0x36, 
+  0x17, 0x85, 0x8D, 0x39, 0xD1, 0x67, 0x60, 0x6A, 0x15, 0x26, 0xE4, 0xB4, 0x2E, 0x99, 0xF1, 0xE3, 0x35, 0x2A, 0x43, 0xCC, 
+  0xD7, 0x22, 0xCF, 0x08, 0x7E, 0x4C, 0x26, 0x82, 0xC2, 0xC5, 0x36, 0x5B, 0xE1, 0xC7, 0x98, 0x90, 0xCF, 0x94, 0x5C, 0x52, 
+  0xE1, 0xAE, 0x1A, 0x04, 0x61, 0xEC, 0xF5, 0x04, 0xB2, 0xE3, 0x6C, 0xD7, 0x3E, 0xCC, 0xF7, 0x64, 0x8F, 0x89, 0xC4, 0x7A, 
+  0x63, 0xBE, 0xB0, 0xAF, 0x76, 0xBD, 0xC3, 0xA2, 0xA1, 0x88, 0xE6, 0x99, 0x22, 0x66, 0x31, 0x97, 0xCA, 0xB6, 0xBB, 0xC9, 
+  0xE3, 0x67, 0xE9, 0x07, 0x99, 0x7B, 0x6B, 0x9F, 0x8D, 0x5D, 0x77, 0xAB, 0xEA, 0x2B, 0xF3, 0x93, 0x1E, 0xD9, 0xB9, 0xDB, 
+  0xB7, 0x6D, 0x3A, 0x0A, 0x9F, 0x92, 0x29, 0xF4, 0x8B, 0x6D, 0xAA, 0x5C, 0x09, 0x90, 0x57, 0x4E, 0x69, 0xE7, 0x56, 0xA4, 
+  0x31, 0x52, 0x4C, 0x9F, 0xAC, 0x56, 0xEA, 0x54, 0x95, 0x49, 0x75, 0xF5, 0xA9, 0xDC, 0xF2, 0x36, 0x86, 0xFE, 0x77, 0xF1, 
+  0xF5, 0x57, 0xB9, 0xF8, 0x9D, 0xCA, 0x27, 0xD9, 0xDB, 0xE9, 0x29, 0x2E, 0x04, 0xD2, 0x2B, 0x0A, 0xCC, 0xB5, 0x44, 0xC7, 
+  0x6D, 0x75, 0xED, 0xED, 0x15, 0x05, 0x3F, 0xD3, 0x4D, 0x14, 0x14, 0xDD, 0x85, 0x69, 0x9A, 0x95, 0x8B, 0xB2, 0xB0, 0xB1, 
+  0x62, 0xF6, 0x0D, 0x44, 0xDA, 0x2D, 0x74, 0x5E, 0xFA, 0x09, 0x59, 0x75, 0xDB, 0x65, 0x4E, 0x5C, 0x16, 0x35, 0x59, 0xE6, 
+  0x17, 0x75, 0xE9, 0xDD, 0x52, 0x5A, 0xFE, 0xAB, 0xAA, 0x96, 0x15, 0x96, 0x6A, 0x94, 0x87, 0x9C, 0x4B, 0xA9, 0xA2, 0x5C, 
+  0xF4, 0xF1, 0x95, 0xC0, 0xAA, 0xB6, 0xDA, 0xDB, 0x79, 0x21, 0x50, 0x6A, 0x01, 0xDA, 0x7B, 0xEE, 0xB6, 0x9E, 0x7D, 0x9D, 
+  0xDA, 0xF6, 0x2A, 0x90, 0x2A, 0xA5, 0x86, 0xBA, 0x24, 0xB9, 0xC3, 0x0C, 0xA2, 0x70, 0xC4, 0x87, 0x72, 0xDA, 0xD8, 0xD9, 
+  0xE8, 0x84, 0x9A, 0x86, 0xCD, 0x37, 0xF6, 0x67, 0x35, 0x51, 0x50, 0xC9, 0x1D, 0x99, 0x1C, 0x37, 0x84, 0x95, 0xDF, 0xAB, 
+  0x51, 0x2A, 0x15, 0xAA, 0xD4, 0xBB, 0x62, 0x9B, 0x52, 0xA3, 0x5B, 0x32, 0xAA, 0x2E, 0x48, 0xA1, 0xD2, 0xAA, 0xE8, 0x8A, 
+  0xCD, 0x42, 0x9D, 0x0E, 0x4B, 0x6C, 0xBC, 0xEC, 0x15, 0xB7, 0x12, 0x44, 0xB8, 0xED, 0xC6, 0x89, 0x35, 0x72, 0x99, 0x82, 
+  0x86, 0xE4, 0x38, 0x11, 0x4F, 0x44, 0x64, 0x92, 0x12, 0x94, 0x81, 0xA9, 0x15, 0x35, 0xB4, 0x52, 0xD3, 0x42, 0xF5, 0x05, 
+  0x44, 0xF4, 0xDF, 0xDD, 0x21, 0x8C, 0x62, 0x66, 0xC0, 0x78, 0xD6, 0xD9, 0xB3, 0x61, 0x32, 0xDF, 0xD2, 0x47, 0x9F, 0x5B, 
+  0x2D, 0xA7, 0x44, 0x17, 0x93, 0x8C, 0x13, 0x80, 0x7F, 0x7B, 0xAF, 0xBF, 0x7E, 0x87, 0xF9, 0x71, 0x45, 0x08, 0xCA, 0x54, 
+  0xB9, 0x3A, 0x69, 0x21, 0xED, 0x79, 0xB7, 0x17, 0xEF, 0x31, 0x36, 0xD5, 0x02, 0xD8, 0x15, 0xF1, 0x79, 0xEF, 0x62, 0x5F, 
+  0x9F, 0xEB, 0xAC, 0x7C, 0xC4, 0x7E, 0xF0, 0xE2, 0xE1, 0xEC, 0xFC, 0x9D, 0x57, 0x4D, 0x5D, 0xAA, 0xFF, 0x00, 0xB3, 0x73, 
+  0xFF, 0x00, 0x4D, 0x3B, 0x56, 0xBE, 0x6D, 0xB3, 0x8C, 0x93, 0x8C, 0x9C, 0x13, 0xD7, 0x6E, 0xA3, 0xD7, 0x24, 0x03, 0xF3, 
+  0xE2, 0x5A, 0xA0, 0x71, 0xD5, 0x0A, 0x81, 0x21, 0x38, 0x14, 0x23, 0x8C, 0x71, 0x99, 0x9D, 0x4D, 0xA1, 0x1B, 0xDB, 0x1D, 
+  0xBC, 0xC5, 0xE7, 0x1F, 0x1D, 0x6A, 0xE5, 0x46, 0x0E, 0x27, 0x04, 0x02, 0x37, 0x3D, 0x70, 0x73, 0xBF, 0x53, 0x92, 0x46, 
+  0x46, 0xDD, 0x70, 0x47, 0xE1, 0xC6, 0x4D, 0x4C, 0xCD, 0xAE, 0x44, 0x24, 0x89, 0x98, 0x47, 0x3A, 0x06, 0x7E, 0x69, 0xF7, 
+  0xEB, 0x9D, 0x00, 0xD4, 0x26, 0xD2, 0xBC, 0xF2, 0xE7, 0x07, 0x60, 0x72, 0x47, 0x6E, 0xD8, 0x1F, 0x68, 0x76, 0xEB, 0xD3, 
+  0x63, 0xC0, 0xAF, 0x6A, 0x49, 0x1C, 0x44, 0xDE, 0x2D, 0xCC, 0x1D, 0xFE, 0x1A, 0x3E, 0xFE, 0xFE, 0xFB, 0x6B, 0x6E, 0xDA, 
+  0x54, 0xD8, 0x03, 0xB8, 0x3D, 0x48, 0x1E, 0x9D, 0xF6, 0x1D, 0x7A, 0xED, 0x8C, 0xF0, 0x0D, 0x3C, 0xD2, 0xB3, 0xDA, 0xA8, 
+  0x0F, 0xAA, 0xCF, 0xE9, 0xA5, 0x6B, 0xC8, 0xCE, 0x08, 0x62, 0xDD, 0xF0, 0xDE, 0xF6, 0x19, 0xF0, 0x0E, 0x85, 0x99, 0x29, 
+  0x4D, 0xB4, 0xB2, 0x14, 0x09, 0xC7, 0xDD, 0x1B, 0x76, 0xEC, 0x46, 0x08, 0x1E, 0xF0, 0x31, 0x93, 0x92, 0x30, 0x0F, 0x0E, 
+  0x69, 0x6C, 0x51, 0x60, 0x66, 0x6F, 0x62, 0x59, 0x66, 0xC3, 0x29, 0x0E, 0x4B, 0x04, 0xB1, 0xA7, 0x63, 0x12, 0x7C, 0x6D, 
+  0xF2, 0xE6, 0xA5, 0x73, 0xE6, 0xDA, 0xD2, 0xD2, 0xB5, 0xB6, 0xD5, 0xB1, 0x23, 0x52, 0xA4, 0xC7, 0xB2, 0xF5, 0x69, 0xFD, 
+  0x48, 0xA3, 0xA2, 0xA7, 0x15, 0x52, 0xED, 0x5B, 0xA2, 0x89, 0x6B, 0x5B, 0x35, 0x59, 0x12, 0x6A, 0x12, 0x9E, 0x8F, 0x5A, 
+  0x72, 0xE3, 0xF6, 0x39, 0xF7, 0x14, 0x07, 0x97, 0x4F, 0x76, 0x24, 0x15, 0xB7, 0x05, 0x86, 0x27, 0xD3, 0x99, 0x89, 0xE4, 
+  0x53, 0x64, 0x36, 0x87, 0x4B, 0xEE, 0xBA, 0x77, 0x76, 0xA8, 0xA6, 0x91, 0xA3, 0x72, 0xAD, 0xCA, 0x67, 0x15, 0x14, 0x52, 
+  0xB2, 0xBD, 0x56, 0xA5, 0xAA, 0x5E, 0x21, 0x12, 0xF7, 0xE3, 0x59, 0x54, 0xD5, 0x82, 0x8A, 0x95, 0x8F, 0xF4, 0xA6, 0x0C, 
+  0xAD, 0x5F, 0xAB, 0x4A, 0x91, 0x9B, 0xC6, 0xA2, 0x2B, 0xD2, 0xE1, 0xBF, 0x35, 0x70, 0xBA, 0xD5, 0xDA, 0xF4, 0x5A, 0x35, 
+  0xB0, 0xEC, 0xFF, 0x00, 0xAD, 0x93, 0x65, 0x50, 0xDE, 0xAA, 0x3B, 0x4C, 0x97, 0x55, 0x00, 0xA5, 0x15, 0x9B, 0xA6, 0xB1, 
+  0x59, 0x99, 0x3E, 0xE4, 0xBF, 0x2E, 0x34, 0xA1, 0x45, 0xB1, 0x5B, 0xBA, 0xEA, 0x93, 0x9C, 0x8C, 0x95, 0x38, 0x8A, 0x6C, 
+  0x68, 0x0C, 0xAC, 0xB4, 0x72, 0xAE, 0xBA, 0xF7, 0x24, 0x62, 0x8A, 0x66, 0x7A, 0x29, 0xB8, 0xF9, 0x6F, 0x55, 0x55, 0x3E, 
+  0x6A, 0x55, 0x4E, 0xDA, 0x5F, 0x96, 0xD5, 0x7D, 0xC6, 0x7B, 0x50, 0x41, 0x44, 0x18, 0x9B, 0x7B, 0x49, 0xDD, 0xB1, 0xC1, 
+  0xA8, 0xB2, 0xE2, 0xD3, 0x58, 0x32, 0x20, 0x18, 0x34, 0xDA, 0x49, 0x7E, 0xA3, 0x2D, 0x6D, 0xC3, 0xA6, 0x46, 0x85, 0x18, 
+  0x2A, 0x6C, 0xAA, 0x94, 0xA7, 0x13, 0x1E, 0x04, 0x48, 0x8D, 0xB4, 0x8F, 0x35, 0xD9, 0x32, 0x65, 0x2D, 0xA6, 0x1A, 0x65, 
+  0x20, 0xF9, 0xAB, 0x58, 0x47, 0x2F, 0x29, 0x56, 0x32, 0x69, 0xBC, 0x0A, 0xAA, 0x01, 0x08, 0xAB, 0xC7, 0xD2, 0x0D, 0x45, 
+  0x7B, 0x54, 0xF4, 0xA7, 0x4D, 0xED, 0x70, 0x09, 0xB5, 0xA3, 0xCF, 0x1C, 0xF3, 0x3A, 0xBE, 0x9A, 0x27, 0xF4, 0xC1, 0x78, 
+  0xF5, 0xF0, 0x89, 0x67, 0x41, 0xF0, 0xF5, 0xA7, 0x97, 0x04, 0x39, 0xF0, 0x34, 0xFD, 0x08, 0xB7, 0xA6, 0xC4, 0xBA, 0x45, 
+  0x42, 0xBD, 0x0E, 0x2B, 0xB4, 0xF7, 0xDA, 0x78, 0xD3, 0x53, 0x18, 0x4F, 0x89, 0x15, 0x2D, 0x53, 0xA6, 0xB0, 0xDB, 0x49, 
+  0x79, 0xC7, 0x1D, 0x79, 0xE5, 0xC7, 0x29, 0x0A, 0xF2, 0x42, 0x10, 0x3B, 0x28, 0xFC, 0x76, 0xFE, 0xD0, 0x6D, 0xD4, 0x6D, 
+  0xD7, 0xD1, 0x34, 0xFB, 0x54, 0xAD, 0x51, 0x38, 0xEA, 0x11, 0xB7, 0x0F, 0xC7, 0x5C, 0xD5, 0x53, 0x4D, 0x4F, 0x4B, 0xB7, 
+  0x55, 0x55, 0x81, 0xD5, 0x51, 0x52, 0x4A, 0x52, 0x13, 0x87, 0x18, 0x97, 0x2E, 0xBA, 0x63, 0xA5, 0x5F, 0xE1, 0x4D, 0x6B, 
+  0x9D, 0x36, 0xDE, 0x16, 0xC7, 0x88, 0x0D, 0x1A, 0xA3, 0xD7, 0x6B, 0x94, 0xD8, 0x25, 0x30, 0xEE, 0x8B, 0x62, 0xA2, 0xEC, 
+  0x75, 0x48, 0x9C, 0xC4, 0x09, 0xF1, 0x61, 0xBF, 0x26, 0x85, 0x57, 0x62, 0x62, 0x61, 0xB8, 0x91, 0x26, 0x3B, 0x2D, 0xC8, 
+  0xA6, 0x54, 0x92, 0x84, 0x43, 0x61, 0xE6, 0x59, 0x0D, 0x2E, 0x4B, 0xCE, 0x1E, 0x8A, 0x7F, 0xE2, 0x54, 0x7F, 0x5E, 0xC7, 
+  0x2A, 0xF4, 0x57, 0x12, 0xDE, 0x33, 0x4A, 0x99, 0xE1, 0xFE, 0x0C, 0x1D, 0x9D, 0xB9, 0x47, 0xAB, 0x6E, 0xE3, 0xD2, 0x8D, 
+  0x45, 0x91, 0x49, 0x21, 0xB8, 0x5B, 0x8F, 0x3C, 0x6B, 0x8E, 0x1E, 0x2B, 0x3E, 0x91, 0x0F, 0x16, 0xDE, 0x3C, 0x2F, 0x1A, 
+  0xA5, 0x52, 0xE4, 0xD4, 0x2B, 0x9A, 0xCB, 0xD3, 0x34, 0xD4, 0xA5, 0x3D, 0x6F, 0x69, 0xD5, 0xB9, 0x70, 0x56, 0x62, 0xD0, 
+  0xE1, 0x34, 0xF3, 0xE5, 0xD5, 0x7B, 0x5A, 0xDA, 0x96, 0xC4, 0x8A, 0xCC, 0xB5, 0x3A, 0x4B, 0xCE, 0x3B, 0x31, 0xC3, 0x0E, 
+  0x2B, 0xAA, 0x2D, 0x43, 0x8A, 0x95, 0x05, 0xB8, 0xE7, 0x2E, 0xF7, 0xE3, 0x77, 0xF7, 0xB1, 0x53, 0xB7, 0x41, 0xC5, 0x0A, 
+  0x4C, 0x63, 0xAE, 0xA2, 0x1A, 0x93, 0x89, 0xC4, 0xEB, 0x6D, 0xBD, 0xB9, 0x22, 0x81, 0xA2, 0x8A, 0x5F, 0x7A, 0x26, 0xBA, 
+  0x9B, 0x73, 0x3E, 0x1B, 0x16, 0x3C, 0xA0, 0xEA, 0xBC, 0xE9, 0xCE, 0xAB, 0x6B, 0xC7, 0x87, 0xAB, 0x92, 0x9F, 0x79, 0x59, 
+  0x57, 0xFD, 0xD3, 0x2A, 0x14, 0x09, 0x51, 0xDF, 0xAC, 0xD0, 0x5D, 0xAC, 0xD4, 0x9D, 0xA7, 0x55, 0xE9, 0xCD, 0x14, 0xA6, 
+  0x54, 0x49, 0x50, 0x9E, 0x94, 0xFC, 0x77, 0x02, 0xE2, 0x05, 0xB2, 0x97, 0x9B, 0x43, 0x52, 0x19, 0x49, 0x1C, 0x85, 0x6D, 
+  0xA5, 0x4D, 0xAB, 0x2D, 0xBF, 0xC4, 0xFE, 0x23, 0x66, 0xA2, 0xA3, 0x72, 0xBB, 0x27, 0x50, 0xD6, 0xB4, 0xAF, 0x66, 0x6C, 
+  0xCC, 0xC7, 0xCC, 0x7B, 0x6B, 0x4A, 0xB6, 0xEB, 0xA2, 0x55, 0x6B, 0xA4, 0xBB, 0x4D, 0x43, 0x30, 0x8D, 0xC9, 0xC2, 0x66, 
+  0x4B, 0xE7, 0x5D, 0x0B, 0xF1, 0x59, 0x32, 0x85, 0x7E, 0xDD, 0xF6, 0x3E, 0xB6, 0xDB, 0xEB, 0x6D, 0xD8, 0x3A, 0x9D, 0x60, 
+  0xDA, 0x8B, 0xAC, 0xF2, 0x29, 0x2A, 0x52, 0x65, 0x9A, 0x73, 0xD2, 0xED, 0x8A, 0x93, 0xBC, 0xA7, 0x74, 0xCF, 0xA4, 0xAA, 
+  0xA1, 0x42, 0x75, 0xD3, 0xB7, 0xD6, 0x36, 0xCA, 0x98, 0x59, 0x0E, 0x3C, 0xD2, 0x0F, 0x67, 0xE3, 0x22, 0xBA, 0xE8, 0xDF, 
+  0xA4, 0x1A, 0x77, 0x68, 0x3A, 0xE6, 0xCA, 0xD3, 0x2D, 0x1D, 0xC9, 0xA8, 0x9A, 0x67, 0x1D, 0x54, 0x46, 0x43, 0x5B, 0xEC, 
+  0x09, 0xD4, 0x5A, 0xC9, 0x10, 0xD9, 0x18, 0xB8, 0xC6, 0x01, 0x8B, 0x48, 0xBA, 0xAE, 0x88, 0xA7, 0xB4, 0x12, 0x95, 0x72, 
+  0x8E, 0xBD, 0x48, 0x00, 0x1F, 0xC3, 0x3D, 0x73, 0x93, 0x8D, 0xFB, 0x63, 0xAE, 0x39, 0x03, 0x80, 0xB1, 0x6B, 0x4B, 0x07, 
+  0x1C, 0x1F, 0x43, 0xD3, 0x5D, 0x11, 0x38, 0x2E, 0xDA, 0xD9, 0x5E, 0x23, 0xCF, 0x6D, 0x1E, 0xD3, 0x61, 0x18, 0xE5, 0x04, 
+  0x01, 0x9E, 0xA3, 0x1F, 0x01, 0x83, 0xD8, 0x0D, 0x86, 0xDD, 0xBA, 0x71, 0xB5, 0x34, 0xB4, 0xF5, 0x5C, 0x1B, 0x49, 0x9B, 
+  0x0E, 0x1E, 0x99, 0x89, 0xB8, 0x4C, 0x43, 0x7D, 0x0E, 0x13, 0x86, 0xC9, 0xF7, 0x7F, 0xBB, 0xE8, 0x8E, 0x62, 0x91, 0xD7, 
+  0x03, 0xDF, 0xBF, 0xBF, 0x6C, 0xFE, 0x83, 0x8B, 0x59, 0x67, 0xEF, 0xC6, 0x9E, 0x59, 0x82, 0xEF, 0x07, 0xCB, 0xE3, 0x6F, 
+  0x8E, 0xBE, 0x79, 0xBF, 0xED, 0x7E, 0x5F, 0xDD, 0xC2, 0xD5, 0x74, 0xBF, 0xE9, 0x3E, 0x6F, 0xFE, 0xDA, 0x77, 0x29, 0xC1, 
+  0xBE, 0xE4, 0x9E, 0xDB, 0x0C, 0x7C, 0xF0, 0x47, 0xC7, 0xBF, 0x5E, 0xBC, 0x60, 0xB6, 0x80, 0x03, 0xC7, 0x3E, 0xAF, 0x3A, 
+  0x83, 0x49, 0x95, 0xAB, 0x27, 0x7E, 0xBB, 0x74, 0x1D, 0x31, 0x8E, 0xF9, 0xED, 0xDB, 0x85, 0xA3, 0x5F, 0x3C, 0xD0, 0x37, 
+  0xD8, 0x9D, 0xBA, 0x0D, 0xCF, 0x6E, 0xA3, 0x6D, 0xBD, 0xFB, 0xF7, 0xDF, 0x87, 0x0C, 0x4F, 0x13, 0x1F, 0x1F, 0xBF, 0xBB, 
+  0x9A, 0x35, 0xF0, 0xBA, 0x0F, 0xAA, 0x71, 0x9C, 0x01, 0xDF, 0xE7, 0x9E, 0xDF, 0x9E, 0x76, 0xF7, 0xAE, 0xFF, 0x00, 0x3F, 
+  0xDB, 0xF7, 0xD2, 0xBF, 0x3F, 0xC1, 0x8E, 0xD2, 0xCF, 0xC7, 0xBD, 0xB5, 0xAF, 0x95, 0xFB, 0x40, 0x40, 0x19, 0xEB, 0x90, 
+  0x4E, 0xDD, 0x37, 0x19, 0xEF, 0xD3, 0x1E, 0xBF, 0x3C, 0xF1, 0x45, 0x4D, 0x89, 0xE9, 0x18, 0x14, 0x3C, 0xE5, 0xEF, 0xE6, 
+  0xF1, 0xA7, 0xA6, 0xCC, 0x8A, 0x63, 0x4F, 0x2C, 0xA8, 0xB4, 0x0A, 0x89, 0x56, 0xE4, 0x02, 0x46, 0x4E, 0xC3, 0x9B, 0xAE, 
+  0x3A, 0x63, 0x20, 0x10, 0x76, 0x27, 0x6C, 0xF0, 0x55, 0x44, 0x66, 0x11, 0x27, 0xCB, 0xE0, 0x09, 0x64, 0x6D, 0xA5, 0x11, 
+  0xCE, 0x3E, 0x1F, 0x3E, 0xEE, 0x6F, 0xCE, 0x62, 0x74, 0x8A, 0xE3, 0x47, 0x8A, 0xDA, 0x96, 0xE8, 0x4A, 0x12, 0xD9, 0xCF, 
+  0xBF, 0x9B, 0x20, 0x72, 0x80, 0x01, 0x52, 0x8A, 0x94, 0x79, 0x52, 0x94, 0x82, 0xA5, 0x28, 0x80, 0x9C, 0xA8, 0x80, 0x53, 
+  0x49, 0x4C, 0x76, 0x73, 0x07, 0x1E, 0x1E, 0x7F, 0x5D, 0x38, 0xB3, 0x9B, 0xCC, 0x2F, 0xCA, 0xC1, 0x04, 0x63, 0x96, 0xF9, 
+  0x8E, 0x5F, 0xD4, 0xBB, 0x6E, 0xB9, 0xA6, 0xD3, 0x28, 0x5A, 0x97, 0x73, 0x41, 0x34, 0x96, 0x29, 0x76, 0xE4, 0x8D, 0x47, 
+  0x8B, 0x4F, 0x7D, 0x3C, 0xB5, 0x83, 0x6C, 0xA1, 0xE4, 0xD2, 0xAD, 0x62, 0xC3, 0x2E, 0x24, 0x9A, 0x74, 0xBD, 0x49, 0xBA, 
+  0x24, 0xC3, 0xB6, 0xA8, 0x35, 0x07, 0x31, 0x2A, 0x4D, 0x21, 0xCA, 0xCC, 0xEA, 0x3A, 0x44, 0x06, 0x9F, 0xAA, 0x3F, 0xAD, 
+  0x03, 0xB6, 0x9B, 0xAF, 0xF4, 0x53, 0xF9, 0x95, 0x52, 0xF1, 0x48, 0xC5, 0x00, 0x47, 0xBD, 0xB9, 0x5C, 0x03, 0x76, 0x26, 
+  0x31, 0xA9, 0xAD, 0x69, 0x07, 0x33, 0x70, 0x3C, 0x49, 0x33, 0xD9, 0xAA, 0x0F, 0x84, 0x43, 0xCD, 0x62, 0x8B, 0x6D, 0x48, 
+  0x96, 0xEC, 0xFA, 0xD5, 0x54, 0xA2, 0x55, 0x6E, 0xBB, 0x51, 0x9B, 0x5B, 0xAC, 0x49, 0x09, 0xFF, 0x00, 0x49, 0xAA, 0xD5, 
+  0xA4, 0xBB, 0x36, 0xA0, 0xE0, 0xD8, 0xE1, 0xB5, 0x48, 0x7D, 0xC4, 0xB0, 0x93, 0xF7, 0x18, 0x4B, 0x4D, 0xA7, 0x01, 0x03, 
+  0x8E, 0x56, 0x95, 0x5A, 0xAD, 0x28, 0xB8, 0xE6, 0xA6, 0x62, 0xF8, 0xEC, 0x39, 0x02, 0xF7, 0x6F, 0x06, 0xD8, 0x43, 0x79, 
+  0x57, 0xA9, 0x9C, 0xAF, 0x3F, 0x3F, 0x91, 0x63, 0x4C, 0xBB, 0xA3, 0x4B, 0x9B, 0xAE, 0x3C, 0xC3, 0xC1, 0x4E, 0x46, 0x71, 
+  0xA5, 0x14, 0xF9, 0x8D, 0x25, 0x25, 0x4A, 0x69, 0x5B, 0xA9, 0xB3, 0x90, 0x46, 0xC4, 0x65, 0x0A, 0xDC, 0xA0, 0xE7, 0x1C, 
+  0xC0, 0xA8, 0x11, 0xDB, 0xBD, 0x9B, 0x5F, 0x8C, 0x76, 0xE6, 0xFA, 0x8D, 0xCD, 0x8A, 0x6B, 0x7D, 0xE8, 0x8F, 0x3F, 0xA7, 
+  0x3E, 0x2E, 0xCD, 0xDE, 0xCD, 0x9F, 0xF6, 0xE5, 0xA1, 0x1E, 0x95, 0x11, 0x98, 0xAD, 0x34, 0x10, 0x86, 0x5B, 0x4A, 0x00, 
+  0xC0, 0x24, 0x01, 0xD7, 0x72, 0x0F, 0x53, 0xF7, 0x8E, 0x09, 0x51, 0x24, 0xF1, 0x54, 0xD2, 0x07, 0x37, 0x59, 0xF3, 0xC4, 
+  0x7A, 0x72, 0x7C, 0xF5, 0xAD, 0x14, 0x53, 0x48, 0x74, 0xF6, 0x2F, 0x8E, 0xDF, 0x73, 0x9F, 0xA6, 0x9C, 0x52, 0xE8, 0x4D, 
+  0x2D, 0x95, 0x21, 0x48, 0x0A, 0x0A, 0x04, 0x6C, 0x31, 0x81, 0xD0, 0x8C, 0x7D, 0xDC, 0x8D, 0xBA, 0xFA, 0x1E, 0xC3, 0x81, 
+  0x2C, 0x04, 0x45, 0xED, 0xC5, 0xCB, 0x3F, 0x30, 0xC5, 0xFE, 0x5A, 0x7D, 0x23, 0x32, 0x67, 0xCC, 0xC7, 0xA3, 0x02, 0x6A, 
+  0x79, 0xD0, 0x7B, 0x7E, 0x81, 0xA8, 0x54, 0x7A, 0x0E, 0x9C, 0x5E, 0x77, 0x42, 0x6D, 0x0A, 0x5E, 0x9F, 0xDC, 0x28, 0xB6, 
+  0x26, 0xDD, 0x72, 0x50, 0xEC, 0x88, 0x36, 0xC6, 0x97, 0x6A, 0xAD, 0x61, 0xBF, 0xF1, 0x72, 0xE9, 0xAC, 0xC5, 0x63, 0x9A, 
+  0x4C, 0x9B, 0x63, 0x4D, 0x35, 0x58, 0x32, 0xCD, 0x7D, 0xC8, 0xA1, 0x53, 0x28, 0xF6, 0xF5, 0xCD, 0x0A, 0xA1, 0x08, 0xF9, 
+  0xB4, 0xF6, 0x9B, 0x7B, 0x6D, 0xA0, 0xAE, 0x82, 0x8A, 0xAA, 0x87, 0x65, 0x85, 0x9C, 0x6D, 0xEE, 0x27, 0x4B, 0x39, 0xE9, 
+  0xA3, 0x70, 0x07, 0x92, 0x44, 0x85, 0x9D, 0x67, 0x40, 0x53, 0x55, 0x54, 0x44, 0x80, 0xB4, 0x78, 0x9B, 0x84, 0xB3, 0x6A, 
+  0x59, 0xB4, 0xCD, 0xCC, 0x11, 0xA7, 0x46, 0xB2, 0xE8, 0x96, 0xA4, 0x78, 0x75, 0xD5, 0x0B, 0xBB, 0x45, 0xF5, 0x82, 0x84, 
+  0x6D, 0xFB, 0xF6, 0xCC, 0x96, 0xDB, 0x32, 0x9B, 0x43, 0x8D, 0xCD, 0xA4, 0xD7, 0x69, 0x33, 0x18, 0x6E, 0x65, 0x0E, 0xEB, 
+  0xB5, 0xEA, 0xCC, 0x7F, 0x9A, 0x57, 0x6D, 0x6B, 0x9A, 0x95, 0x22, 0x25, 0x66, 0x83, 0x5A, 0x80, 0xA5, 0xC5, 0xA8, 0x53, 
+  0xA5, 0xB0, 0xF3, 0x65, 0x0A, 0x52, 0x9A, 0x6A, 0x6A, 0xA6, 0xBD, 0xAA, 0x9A, 0x6A, 0x3A, 0x5A, 0x61, 0x2A, 0x96, 0x1E, 
+  0x54, 0x7B, 0x4E, 0x73, 0xE7, 0x99, 0xD4, 0x1C, 0xCD, 0x8E, 0x4C, 0x4A, 0xB1, 0x1F, 0x0E, 0x39, 0xF2, 0x9A, 0x88, 0xD6, 
+  0x42, 0x41, 0x1D, 0x14, 0x37, 0x19, 0x39, 0xDB, 0x24, 0x7C, 0xF7, 0x1D, 0x7A, 0x1E, 0xA3, 0x6E, 0xAD, 0x89, 0x56, 0xC3, 
+  0x16, 0x12, 0xEC, 0x0F, 0xC9, 0x97, 0x05, 0xB8, 0xE1, 0x5D, 0xB2, 0xCB, 0x72, 0x41, 0xBB, 0x79, 0xFD, 0x79, 0x7E, 0x76, 
+  0xB8, 0x81, 0x50, 0xC9, 0xC9, 0xC9, 0xC7, 0xA1, 0xEF, 0xFC, 0xBF, 0x4D, 0xC0, 0xE9, 0xC2, 0xEB, 0x62, 0x00, 0x31, 0x73, 
+  0x2C, 0x62, 0xED, 0xCE, 0xD6, 0xE3, 0xE3, 0xAA, 0x6B, 0xA8, 0x22, 0x9A, 0x4A, 0x0E, 0x2A, 0x63, 0xDA, 0xBB, 0xC4, 0x32, 
+  0xCB, 0x13, 0x33, 0xFA, 0xE9, 0x3F, 0x33, 0xDD, 0xF9, 0xFF, 0x00, 0x77, 0x0A, 0x5E, 0xEF, 0xCD, 0xD3, 0xEA, 0x7F, 0xD4, 
+  0x7C, 0x9F, 0xFD, 0x74, 0xEC, 0x2E, 0xFF, 0x00, 0xB4, 0x3E, 0x5B, 0xFE, 0x99, 0xFC, 0xF8, 0x21, 0xC6, 0x3D, 0x6D, 0xF5, 
+  0xD4, 0x6B, 0x12, 0xE0, 0xF7, 0x9F, 0xC7, 0x19, 0xF9, 0x9F, 0xD0, 0x70, 0x3D, 0xE4, 0x78, 0xB7, 0x62, 0xC4, 0xD8, 0xE3, 
+  0x46, 0xB1, 0x2E, 0x74, 0xC6, 0x07, 0xA9, 0x27, 0x61, 0xFF, 0x00, 0x5E, 0xBF, 0x97, 0x0A, 0x0B, 0xB0, 0xA8, 0x4E, 0x24, 
+  0xCF, 0x6B, 0xF0, 0x1C, 0x66, 0x2F, 0xA3, 0x49, 0x29, 0xCF, 0x53, 0x9D, 0xCE, 0xC3, 0xF9, 0x8C, 0x8C, 0x63, 0xB9, 0xCF, 
+  0xCF, 0xA7, 0x15, 0xD2, 0xC4, 0xB0, 0x66, 0xED, 0xAF, 0xDA, 0x33, 0xF0, 0xD1, 0xA4, 0x94, 0xE0, 0xC6, 0x09, 0x19, 0xEF, 
+  0xF1, 0xCF, 0x40, 0x37, 0x39, 0xEF, 0xEE, 0x00, 0xEF, 0x9E, 0x28, 0xA7, 0x98, 0x93, 0x8A, 0x5C, 0xB8, 0xBB, 0x68, 0x0B, 
+  0xE5, 0xE6, 0x02, 0x73, 0xA1, 0xB1, 0x92, 0xF3, 0x12, 0xC7, 0xCD, 0xE0, 0xF2, 0xFF, 0x00, 0x12, 0x13, 0x8E, 0x73, 0x02, 
+  0x33, 0x90, 0x49, 0x24, 0xE7, 0xA7, 0x62, 0x01, 0xF4, 0xF5, 0xF7, 0xFB, 0xC6, 0xD7, 0x05, 0x25, 0xDE, 0x98, 0x11, 0xE2, 
+  0x56, 0xE4, 0x9F, 0xEA, 0x6C, 0x5D, 0xC6, 0x0E, 0xE1, 0x03, 0x72, 0xDE, 0xD2, 0x86, 0x54, 0x3F, 0x5E, 0x5B, 0x66, 0x2D, 
+  0x9D, 0x11, 0x48, 0x69, 0x6D, 0x4B, 0xA1, 0xD6, 0x5D, 0xA1, 0x3F, 0x71, 0x26, 0x7D, 0x72, 0x45, 0x3A, 0x83, 0x42, 0x69, 
+  0x0E, 0x2B, 0xEB, 0x99, 0x14, 0x9F, 0x20, 0xD5, 0x9F, 0x78, 0xA0, 0x73, 0x08, 0x62, 0x6C, 0x98, 0x96, 0xFB, 0x0B, 0x49, 
+  0x49, 0x2E, 0x39, 0x5D, 0x79, 0x0A, 0x4C, 0x8A, 0x74, 0x75, 0xA6, 0x6F, 0x53, 0x4D, 0x45, 0x35, 0x56, 0x55, 0x5F, 0x4D, 
+  0x14, 0x91, 0x90, 0xBD, 0x56, 0x58, 0xA5, 0x64, 0x2F, 0x13, 0x53, 0x10, 0x94, 0xA2, 0x5B, 0xDE, 0x20, 0x65, 0x25, 0xB8, 
+  0xDA, 0x3C, 0xE1, 0x9E, 0xF6, 0x3C, 0xEB, 0x7B, 0xE2, 0x12, 0xE0, 0xAE, 0x4C, 0xBB, 0x63, 0x69, 0xFD, 0x7E, 0xA8, 0x2B, 
+  0x17, 0x73, 0x4F, 0x52, 0xEF, 0xFD, 0x67, 0xAA, 0x34, 0x53, 0xEC, 0xEE, 0xDE, 0xD2, 0xA9, 0x42, 0x35, 0x91, 0x60, 0xC2, 
+  0x43, 0x67, 0xCA, 0x8D, 0x6F, 0xE9, 0x75, 0x9C, 0xEA, 0x19, 0xA7, 0xD2, 0x58, 0x08, 0x8B, 0x0E, 0xA1, 0x59, 0x05, 0xB6, 
+  0x92, 0xE4, 0x26, 0xCA, 0x5F, 0xE2, 0x2A, 0x4A, 0x8D, 0xA1, 0x3A, 0x87, 0xF3, 0x37, 0x13, 0x9D, 0xC6, 0x90, 0xA6, 0x88, 
+  0xC7, 0x4E, 0xD8, 0xC8, 0x44, 0x8D, 0xFC, 0x6B, 0x31, 0x2B, 0xA9, 0x59, 0x8A, 0x6F, 0x49, 0xC8, 0x37, 0xA6, 0xD9, 0x6D, 
+  0x73, 0x37, 0xCD, 0xF5, 0x1C, 0x45, 0x8E, 0x0A, 0x53, 0xB0, 0xC7, 0xA7, 0x5C, 0x7C, 0x07, 0x73, 0xD3, 0x72, 0x06, 0xE7, 
+  0x8C, 0x02, 0x00, 0x75, 0xAE, 0x8B, 0x30, 0xDB, 0x27, 0x74, 0x8F, 0x7E, 0xD8, 0xC7, 0x7C, 0x63, 0xE5, 0xBE, 0x7D, 0x3B, 
+  0xF0, 0xF4, 0xA3, 0x16, 0x96, 0xDE, 0xBF, 0x05, 0xD6, 0x69, 0x8E, 0xDA, 0x3A, 0x0C, 0x7A, 0x63, 0x18, 0xFE, 0x3D, 0x7A, 
+  0xFC, 0x7A, 0x75, 0xE0, 0xD3, 0x44, 0x71, 0xEB, 0xF2, 0xFF, 0x00, 0x06, 0x85, 0x92, 0x94, 0x80, 0x52, 0x06, 0x33, 0xD8, 
+  0xE3, 0x62, 0x76, 0x00, 0xEF, 0xEB, 0x92, 0x08, 0xDB, 0x18, 0xC6, 0xFC, 0x1D, 0xDF, 0xF1, 0xF2, 0xC1, 0xA3, 0xE9, 0x07, 
+  0x8C, 0xE4, 0x8F, 0x1A, 0xD6, 0x5B, 0xD7, 0xCB, 0x7A, 0x5B, 0x7C, 0x51, 0x2F, 0xA9, 0x94, 0xD3, 0x5A, 0xB6, 0xDB, 0x6A, 
+  0xA3, 0x6D, 0xEA, 0x0D, 0xBA, 0x51, 0xCC, 0xDD, 0xC9, 0xA7, 0x37, 0x33, 0x02, 0x9D, 0x77, 0x52, 0x94, 0xD9, 0xCF, 0x99, 
+  0x21, 0xA8, 0x65, 0xAA, 0xCD, 0x38, 0x9C, 0x96, 0xAA, 0x94, 0x98, 0x2E, 0x36, 0x42, 0xB0, 0x41, 0x46, 0xE7, 0xE5, 0x6E, 
+  0x53, 0x52, 0x7B, 0x37, 0xA2, 0xAA, 0x5F, 0xEA, 0xA2, 0xA2, 0xE5, 0xF2, 0x24, 0xA1, 0x8B, 0x5A, 0x35, 0x8E, 0xE8, 0x81, 
+  0x58, 0xC7, 0x4A, 0x2A, 0x67, 0xA5, 0xB2, 0x72, 0x41, 0xEF, 0x36, 0x64, 0x22, 0xDC, 0xF4, 0xE3, 0x5E, 0xF5, 0x56, 0x97, 
+  0xA8, 0x7A, 0x0F, 0xA7, 0xBA, 0x69, 0xAA, 0xF5, 0x17, 0x2E, 0x7A, 0xD6, 0x94, 0x51, 0x5A, 0x57, 0x84, 0xCF, 0x12, 0xAD, 
+  0xE6, 0x74, 0x8B, 0xCF, 0x43, 0x65, 0xAD, 0xC9, 0xAD, 0xE8, 0xB5, 0xFF, 0x00, 0x3F, 0xED, 0x39, 0x32, 0x75, 0x9B, 0xED, 
+  0x2B, 0x97, 0x67, 0x48, 0x98, 0xF2, 0x9E, 0x8C, 0xA1, 0x3E, 0x88, 0x54, 0xDC, 0x5A, 0xB2, 0xD4, 0xDF, 0x66, 0xF7, 0x4B, 
+  0xB7, 0x41, 0x54, 0xA1, 0x4C, 0xEC, 0x6F, 0x12, 0x8D, 0x08, 0x7B, 0x1B, 0x93, 0x07, 0x5D, 0x17, 0xB5, 0xD7, 0x0A, 0xE4, 
+  0xBA, 0x6A, 0xEA, 0x51, 0x71, 0x68, 0xB2, 0x46, 0x4A, 0xA6, 0x2F, 0xD4, 0x5E, 0x62, 0x29, 0xC0, 0xCE, 0x39, 0xC4, 0xEB, 
+  0xEE, 0x21, 0xE7, 0x58, 0x7C, 0x25, 0xB9, 0x2C, 0x29, 0x01, 0xE4, 0xB6, 0xAF, 0x31, 0xB5, 0xA1, 0xD6, 0x5B, 0x7D, 0x89, 
+  0x11, 0xDD, 0xCE, 0x1F, 0x89, 0x36, 0x2B, 0xAC, 0x4B, 0x84, 0xF8, 0xD9, 0xE8, 0xAF, 0xB4, 0xE0, 0x09, 0x51, 0x52, 0x53, 
+  0xC6, 0xC8, 0xA6, 0x52, 0x32, 0x91, 0x7C, 0x43, 0xDB, 0xA6, 0x11, 0x89, 0x86, 0x32, 0x6A, 0x86, 0x6F, 0xCD, 0xC8, 0xE4, 
+  0xBF, 0xF8, 0x9D, 0x21, 0xE7, 0x0E, 0xCA, 0xFC, 0x32, 0x7E, 0x43, 0x39, 0x03, 0x7F, 0x4C, 0x6F, 0xC1, 0xA7, 0xAF, 0x9C, 
+  0xE7, 0xD1, 0x7F, 0x9F, 0xF3, 0xE0, 0xD1, 0xA7, 0x49, 0x78, 0x76, 0x3F, 0x0C, 0x0D, 0x8F, 0x4E, 0xE7, 0xA6, 0x7F, 0x3C, 
+  0x71, 0xA9, 0x45, 0xA7, 0xA6, 0x93, 0xBF, 0x55, 0x5C, 0x79, 0x84, 0x8F, 0xD2, 0x22, 0xFA, 0x70, 0xC3, 0x8B, 0x74, 0xFF, 
+  0x00, 0x55, 0x3C, 0xCC, 0xDA, 0x7C, 0x66, 0x7E, 0x0E, 0xB1, 0x2E, 0x93, 0xD3, 0x98, 0x9E, 0x9E, 0x9D, 0xFF, 0x00, 0xEF, 
+  0xEB, 0x9E, 0xDC, 0x28, 0x8B, 0x4D, 0x07, 0x92, 0xFE, 0x73, 0x29, 0xE0, 0xE3, 0xD1, 0xD2, 0xF5, 0x63, 0x33, 0x71, 0x23, 
+  0xBB, 0x6F, 0x89, 0x11, 0xE4, 0xC6, 0xB0, 0x53, 0xBE, 0xA4, 0x0F, 0xEB, 0x1C, 0xFC, 0x7D, 0x3F, 0xBB, 0xDF, 0xC3, 0xF5, 
+  0xAE, 0xAB, 0xD8, 0x29, 0x33, 0xE0, 0xB8, 0x3E, 0x9E, 0x9A, 0x0B, 0xC4, 0x3D, 0x44, 0x33, 0x02, 0x19, 0xF3, 0x2D, 0xBB, 
+  0xE3, 0x58, 0x17, 0x7A, 0xFD, 0xAC, 0x82, 0x31, 0xCA, 0x9D, 0x81, 0x1B, 0x77, 0xC1, 0xCF, 0xC7, 0x27, 0xBE, 0xDE, 0xA2, 
+  0x65, 0x69, 0x4A, 0x96, 0xF5, 0xD4, 0x92, 0x4C, 0x3E, 0xEA, 0x47, 0x07, 0x7E, 0xD2, 0x5A, 0x1F, 0x4B, 0xE9, 0x6B, 0x35, 
+  0x39, 0xF5, 0x7B, 0xF3, 0x82, 0x7E, 0x6E, 0x87, 0x53, 0xBD, 0x40, 0x38, 0xEF, 0x84, 0x83, 0xF8, 0x67, 0x1D, 0xF7, 0x2A, 
+  0x3B, 0xE0, 0xEC, 0x06, 0x0F, 0x14, 0x54, 0x52, 0x37, 0x73, 0x3E, 0xD3, 0xD3, 0x26, 0x15, 0x0B, 0x84, 0xCF, 0x48, 0x65, 
+  0x6F, 0xE0, 0x2D, 0x4B, 0x13, 0xDF, 0x80, 0x38, 0x26, 0xD3, 0xE8, 0x41, 0xFE, 0xAB, 0xF3, 0xA5, 0xA8, 0x4D, 0x31, 0xDA, 
+  0x52, 0xB3, 0x92, 0x90, 0x4F, 0x5E, 0xB8, 0x23, 0x60, 0x01, 0xC0, 0x1B, 0x9C, 0x67, 0xA0, 0x07, 0xD7, 0x3C, 0x65, 0x55, 
+  0x52, 0xA9, 0x61, 0x6D, 0xF0, 0xC5, 0xF3, 0x3E, 0x74, 0x99, 0x6D, 0x24, 0x2F, 0x24, 0xB1, 0x11, 0x13, 0xFC, 0xDB, 0xC5, 
+  0xB5, 0x2B, 0xE9, 0xF7, 0x8C, 0xDD, 0x2A, 0xD3, 0x6D, 0x29, 0xB5, 0xA3, 0xB9, 0x6B, 0x35, 0x50, 0xD4, 0xAB, 0x52, 0x8B, 
+  0x51, 0xA4, 0x32, 0xA9, 0x0D, 0xA5, 0xD5, 0x8A, 0xBF, 0xD6, 0xF5, 0x59, 0x8A, 0x53, 0x6D, 0xA8, 0x73, 0x07, 0x66, 0x4E, 
+  0x98, 0x5E, 0x52, 0xC2, 0x47, 0x32, 0x9D, 0xE6, 0x2A, 0x38, 0x2A, 0xE3, 0xA3, 0x6F, 0xF1, 0x9B, 0x7B, 0x7B, 0x54, 0x05, 
+  0x0B, 0xB9, 0x45, 0x31, 0x3C, 0x2F, 0x53, 0x55, 0x8C, 0x11, 0x33, 0xE7, 0xE1, 0x1A, 0xE5, 0x6B, 0xA5, 0x16, 0xAA, 0x98, 
+  0x73, 0x41, 0x6A, 0xBA, 0x85, 0xF6, 0x56, 0x66, 0x38, 0x00, 0x9F, 0x31, 0x1A, 0xAD, 0x76, 0xEC, 0xBA, 0xC5, 0x6E, 0x45, 
+  0x4E, 0xE7, 0xB8, 0xE4, 0x19, 0x97, 0x15, 0xD1, 0x55, 0xA8, 0x5C, 0x15, 0xE9, 0x4E, 0x12, 0xA5, 0xBF, 0x54, 0xAB, 0x48, 
+  0x5C, 0xB9, 0x23, 0x27, 0x7E, 0x46, 0x4A, 0x91, 0x15, 0x84, 0x92, 0x42, 0x23, 0xC7, 0x6D, 0x09, 0xC0, 0x48, 0x1C, 0x71, 
+  0x13, 0x52, 0xD6, 0xD4, 0xAD, 0x55, 0x35, 0x2C, 0xF2, 0xD9, 0xF8, 0x29, 0x7E, 0xC9, 0x6D, 0x6B, 0x45, 0x27, 0x4D, 0xFD, 
+  0xEA, 0x9E, 0xA5, 0xC5, 0xF8, 0x88, 0xEC, 0x20, 0x7A, 0x46, 0xA4, 0x58, 0xC4, 0x25, 0x03, 0x20, 0x60, 0xF5, 0xDF, 0x04, 
+  0x01, 0xD0, 0x1C, 0x7B, 0xC0, 0x3E, 0xFD, 0xB7, 0x39, 0xE2, 0xF5, 0xAF, 0x6F, 0x53, 0xCA, 0xDF, 0x1D, 0xEE, 0x73, 0xC6, 
+  0x74, 0xB7, 0x9A, 0x9E, 0xC7, 0xE3, 0x91, 0xB0, 0xEB, 0xD7, 0x23, 0x23, 0xE1, 0x8E, 0xB8, 0x1B, 0xEC, 0x78, 0x35, 0x51, 
+  0x50, 0xC9, 0xEC, 0xD2, 0xDD, 0x1A, 0x81, 0x0B, 0xC1, 0x76, 0x99, 0xC3, 0xC3, 0x3E, 0x2D, 0xAF, 0xDC, 0xE4, 0xFB, 0xC9, 
+  0xF8, 0xFE, 0x5B, 0xE4, 0xFF, 0x00, 0x0F, 0xD0, 0xD4, 0x11, 0x92, 0x61, 0xBF, 0x1D, 0xFD, 0x54, 0xC4, 0xC7, 0x97, 0x9D, 
+  0x08, 0xF9, 0xC8, 0x29, 0x39, 0xE9, 0x93, 0xF1, 0x38, 0xEF, 0x8E, 0xBD, 0x3B, 0xFE, 0x1B, 0xF0, 0x69, 0xF3, 0xFB, 0x7D, 
+  0xFD, 0xDB, 0x4C, 0xCA, 0xDB, 0x1E, 0xD2, 0xC3, 0xAD, 0xA9, 0x29, 0x21, 0x68, 0x29, 0x39, 0xDD, 0x3D, 0x30, 0x08, 0xFC, 
+  0x40, 0xEA, 0x7B, 0xE7, 0x19, 0xC7, 0x13, 0x54, 0xC4, 0x03, 0x7B, 0x4F, 0x07, 0x79, 0xD0, 0xE1, 0xF4, 0xF1, 0xFB, 0xDB, 
+  0xE7, 0x6D, 0x63, 0xA4, 0xBE, 0x26, 0xAA, 0x3A, 0x23, 0x4F, 0x9D, 0xA5, 0x5A, 0x87, 0x6C, 0x35, 0xA8, 0x5A, 0x3B, 0x50, 
+  0x96, 0xFC, 0xAA, 0x65, 0x2A, 0x7A, 0x03, 0xD2, 0xAD, 0xE7, 0x9F, 0x59, 0x5B, 0xE8, 0xA5, 0x3C, 0xBC, 0xA9, 0x84, 0xA1, 
+  0x6A, 0x52, 0xDB, 0x65, 0xA2, 0x95, 0x25, 0x2A, 0xFB, 0x00, 0xA3, 0x21, 0x1A, 0xEC, 0xFE, 0x25, 0xDA, 0x1D, 0xBA, 0xE9, 
+  0x37, 0x36, 0x97, 0xDD, 0xAB, 0xFA, 0x72, 0x4D, 0x3D, 0xBC, 0x84, 0x6B, 0x8D, 0xAC, 0xDB, 0xA8, 0x2B, 0x9E, 0x91, 0x4A, 
+  0x2B, 0xA5, 0xC1, 0x96, 0x96, 0xF7, 0x0F, 0xE9, 0x9C, 0x5A, 0x3B, 0x69, 0xC7, 0x76, 0xEA, 0x86, 0x9C, 0xDF, 0x97, 0x2D, 
+  0x1D, 0xCD, 0x2A, 0xA4, 0xD4, 0xE9, 0x56, 0xED, 0x22, 0xD3, 0x8D, 0x4A, 0x9A, 0x2A, 0x7C, 0xEA, 0x71, 0x53, 0xC5, 0x56, 
+  0xA5, 0x3A, 0x2C, 0x36, 0xDD, 0x50, 0x0A, 0x75, 0xBA, 0x5C, 0x19, 0x9E, 0xCC, 0x95, 0x9C, 0x94, 0x34, 0xA6, 0x23, 0xE7, 
+  0x91, 0x96, 0xD0, 0x95, 0xBB, 0xBB, 0x45, 0x6D, 0x3F, 0x95, 0x47, 0x48, 0x53, 0x0C, 0xCA, 0xC0, 0xA9, 0x3E, 0x93, 0x05, 
+  0xAC, 0x45, 0x38, 0x0D, 0x6F, 0x45, 0x65, 0x72, 0x53, 0x54, 0xC1, 0xEF, 0x04, 0x02, 0xB2, 0x17, 0x99, 0x7C, 0xE1, 0xBC, 
+  0xCF, 0x09, 0x37, 0x20, 0xAB, 0x24, 0x13, 0xEF, 0x38, 0xF8, 0x60, 0x0D, 0xC7, 0x4F, 0x5E, 0xBC, 0x67, 0x3C, 0xB3, 0xE9, 
+  0x09, 0x16, 0xBB, 0xCA, 0x92, 0xC4, 0xD8, 0xB7, 0x9D, 0x6A, 0x11, 0xF7, 0xF7, 0xFA, 0x69, 0x4F, 0x37, 0xDE, 0xAF, 0xC7, 
+  0xFB, 0xF8, 0xAD, 0x1A, 0x79, 0x70, 0x68, 0x71, 0x4F, 0xFB, 0xAA, 0xFF, 0x00, 0xC7, 0x58, 0xAF, 0xEE, 0x9F, 0x97, 0xEA, 
+  0x38, 0xBA, 0x32, 0xFA, 0x7E, 0xE6, 0xA7, 0x6F, 0xDD, 0xAB, 0xEF, 0x9A, 0x74, 0x81, 0xE9, 0xF3, 0x4F, 0xEA, 0x38, 0xD5, 
+  0xF7, 0x6B, 0xFF, 0x00, 0x6B, 0xF5, 0x35, 0xB5, 0x3E, 0xE5, 0x5F, 0x1F, 0xA1, 0xAC, 0x87, 0x5F, 0x92, 0xBF, 0x43, 0xC7, 
+  0x3E, 0xEF, 0xBA, 0x7F, 0xB6, 0x9F, 0xAE, 0xA7, 0x73, 0xDF, 0x3F, 0xDA, 0xFD, 0x4D, 0x0A, 0xAE, 0x87, 0xE0, 0x7F, 0x4E, 
+  0x1D, 0x7F, 0xFD, 0xDD, 0xCF, 0x53, 0xE9, 0xA2, 0xAC, 0xD7, 0xFE, 0xEA, 0x7F, 0xF0, 0xD3, 0x6A, 0xB5, 0xFE, 0x8C, 0xEF, 
+  0xF5, 0x57, 0xFA, 0x2B, 0x85, 0xA9, 0xD5, 0x23, 0xA8, 0x7F, 0xEA, 0x03, 0xDF, 0xFE, 0xF3, 0x7F, 0xDA, 0x47, 0x1C, 0xFA, 
+  0xF2, 0xEB, 0xFF, 0x00, 0xF2, 0x7F, 0xFE, 0x94, 0xFD, 0x6A, 0xD5, 0xBE, 0xB7, 0xFF, 0x00, 0xD1, 0xA3, 0x7C, 0xBF, 0x44, 
+  0xF1, 0xAD, 0x18, 0x7D, 0x7F, 0x63, 0x5E, 0x91, 0x8A, 0x3E, 0x1F, 0xF8, 0xBA, 0x7A, 0x23, 0xFF, 0x00, 0x28, 0x7F, 0x58, 
+  0xFF, 0x00, 0x1E, 0x2F, 0x5A, 0xD1, 0x97, 0xD3, 0xF7, 0x34, 0x07, 0xFE, 0xE8, 0xBF, 0xFE, 0xB0, 0xFF, 0x00, 0x88, 0x78, 
+  0x0F, 0x78, 0xFF, 0x00, 0x6D, 0x7F, 0x43, 0x58, 0xF3, 0x57, 0xAD, 0x1F, 0x53, 0x5B, 0x14, 0x7D, 0xE1, 0xF3, 0xFD, 0x0F, 
+  0x06, 0xAF, 0x49, 0xBB, 0xD1, 0x5F, 0xD6, 0x1F, 0xDB, 0x1C, 0x1A, 0x34, 0xDB, 0xA8, 0x7D, 0xC5, 0x7C, 0xBF, 0xE2, 0x0E, 
+  0x0D, 0x1A, 0xAF, 0x7A, 0x9B, 0xFE, 0xAF, 0x7F, 0xFF, 0x00, 0x99, 0xBF, 0xED, 0xAB, 0x8E, 0x63, 0x1F, 0x1A, 0xBE, 0xAE, 
+  0xB8, 0x37, 0x7D, 0xCF, 0x8D, 0x5F, 0xF9, 0x1A, 0xDB, 0x69, 0x47, 0xFA, 0xA9, 0x8F, 0xEB, 0x3B, 0xFD, 0xA5, 0x71, 0xAD, 
+  0x3E, 0xE5, 0x5F, 0x1F, 0xA1, 0xAD, 0xF6, 0x3D, 0xDA, 0x7F, 0xDB, 0xFB, 0x9A, 0x9C, 0xD9, 0xE8, 0x9F, 0x8A, 0xFF, 0x00, 
+  0x55, 0x70, 0x51, 0x93, 0xFD, 0xAF, 0xFE, 0x4E, 0xBA, 0x34, 0x4F, 0x1D, 0x9A, 0x35, 0xFF, 0xD9
+};
+
+NPT_UInt8 Platinum_120x120_png[26577] =
+{
+  0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x81, 
+  0x00, 0x00, 0x00, 0x81, 0x08, 0x02, 0x00, 0x00, 0x00, 0x68, 0xC2, 0x4E, 0x07, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 
+  0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 
+  0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 
+  0xFA, 0x00, 0x00, 0x00, 0x80, 0xE8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xEA, 0x60, 0x00, 0x00, 0x3A, 0x98, 0x00, 0x00, 
+  0x17, 0x70, 0x9C, 0xBA, 0x51, 0x3C, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x12, 0x00, 0x00, 
+  0x0B, 0x12, 0x01, 0xD2, 0xDD, 0x7E, 0xFC, 0x00, 0x00, 0x67, 0x3A, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0x9D, 0xBD, 0x05, 
+  0x98, 0x9D, 0xD5, 0xD5, 0xF7, 0x3D, 0x68, 0x21, 0x68, 0x84, 0x84, 0xE8, 0x44, 0x67, 0x26, 0xE3, 0xEE, 0xEE, 0xEE, 0xEE, 
+  0x92, 0xF1, 0x89, 0x4D, 0xDC, 0x85, 0xB8, 0x13, 0x08, 0x10, 0xDC, 0xDD, 0x9D, 0x42, 0xA1, 0x58, 0xA1, 0x2D, 0xA5, 0x50, 
+  0xA1, 0x85, 0xB6, 0xB4, 0x94, 0xEA, 0x5B, 0x6F, 0xE9, 0x53, 0x8A, 0xE5, 0xFD, 0xAD, 0xBD, 0xEE, 0x7B, 0xCF, 0x3D, 0x93, 
+  0xC0, 0xF3, 0xBD, 0xDF, 0x5C, 0xFB, 0x3A, 0xD7, 0x7D, 0xCE, 0x9C, 0x39, 0x73, 0xCE, 0x92, 0xFF, 0xB2, 0xFF, 0xDE, 0xE7, 
+  0xB4, 0xC1, 0xAE, 0x61, 0x9F, 0x91, 0x9F, 0x2F, 0xB8, 0x3C, 0x71, 0xE2, 0x34, 0xCF, 0x23, 0xCE, 0xE5, 0x89, 0x13, 0x9F, 
+  0xFB, 0xF8, 0x9C, 0x3E, 0xFA, 0x99, 0x72, 0xF7, 0x8B, 0xCF, 0x4F, 0x9C, 0xE6, 0x79, 0x98, 0x3F, 0x3D, 0xED, 0x84, 0x3C, 
+  0xAC, 0xCF, 0x3C, 0x71, 0x42, 0xEE, 0x98, 0x9F, 0xD3, 0x3D, 0xD7, 0xA3, 0x7E, 0x7B, 0xDA, 0x69, 0x67, 0x98, 0x5F, 0xF1, 
+  0xA0, 0xBC, 0x10, 0xFF, 0xE8, 0xB4, 0xD3, 0x9C, 0x37, 0xA0, 0x7F, 0xA2, 0x77, 0xB9, 0xD5, 0x9F, 0xD3, 0x4F, 0x3F, 0xFD, 
+  0x8C, 0x33, 0xCE, 0xE0, 0xF6, 0xCC, 0x33, 0xCF, 0x3C, 0xFD, 0x74, 0x1F, 0xAE, 0x4F, 0x3B, 0xFD, 0xC4, 0xE9, 0xA7, 0x9D, 
+  0xC9, 0xDB, 0xFE, 0xFC, 0xF3, 0xCF, 0x4F, 0xF8, 0x7C, 0xFA, 0xF9, 0x67, 0x27, 0xBE, 0xF8, 0xE2, 0x8B, 0x13, 0x9F, 0x9D, 
+  0xF8, 0xE4, 0xF3, 0xCF, 0x7C, 0x3E, 0xFB, 0xFC, 0xD3, 0x13, 0x5F, 0xF0, 0x3A, 0x3C, 0x72, 0xFA, 0x17, 0x27, 0x3E, 0xF9, 
+  0xE2, 0x73, 0x1F, 0x9E, 0xFA, 0x85, 0xBC, 0x31, 0x1E, 0xD5, 0x77, 0x28, 0xAF, 0xEF, 0xBE, 0xB9, 0xD3, 0xCF, 0xE0, 0x21, 
+  0x7D, 0x1B, 0xCE, 0xBF, 0xE6, 0xC2, 0xF9, 0x25, 0x8F, 0x9C, 0x76, 0x1A, 0xAF, 0x63, 0x3F, 0xD8, 0xE7, 0x3C, 0xF5, 0xC4, 
+  0xC8, 0x33, 0xF5, 0x4A, 0x5F, 0xD0, 0xFE, 0xD5, 0x17, 0xA7, 0x7D, 0x71, 0x26, 0x22, 0x39, 0xF1, 0xF9, 0x17, 0x3E, 0xE6, 
+  0x53, 0xF0, 0x17, 0xA7, 0x8D, 0xFA, 0xF8, 0xF2, 0x47, 0x03, 0x9D, 0xCB, 0xCD, 0x5A, 0xCA, 0x6D, 0x7F, 0xC7, 0x32, 0xBD, 
+  0x30, 0xB7, 0x4B, 0xB9, 0xEB, 0x59, 0x4B, 0xFA, 0x3B, 0x96, 0xF4, 0xB5, 0x2F, 0x75, 0xD7, 0x62, 0xEF, 0x75, 0x6F, 0xDB, 
+  0x50, 0x6F, 0xDB, 0x12, 0x59, 0xAD, 0x4B, 0x9D, 0x8B, 0xB6, 0x25, 0x3D, 0xAD, 0x8B, 0xCD, 0x1A, 0x74, 0x2F, 0xFA, 0xB9, 
+  0xEE, 0x6E, 0x19, 0xEA, 0x6E, 0x19, 0xD0, 0xD5, 0xD5, 0xD4, 0xB7, 0xA8, 0xB9, 0x9F, 0x8B, 0x45, 0xCD, 0x83, 0x5C, 0xF4, 
+  0x34, 0xF5, 0x73, 0xAB, 0x0F, 0xEA, 0xD2, 0x6B, 0x6E, 0x79, 0x8E, 0x79, 0x9D, 0xC1, 0xBE, 0xF6, 0xC5, 0x43, 0x1D, 0x4B, 
+  0x97, 0xF4, 0xAC, 0x58, 0xDE, 0xBF, 0x7A, 0xD5, 0xE2, 0xF5, 0xEB, 0x96, 0x6F, 0xDC, 0xB0, 0x62, 0xF3, 0xDA, 0xE5, 0xEB, 
+  0xD6, 0xAF, 0xD8, 0xB0, 0x71, 0xE5, 0x96, 0xCD, 0x6B, 0xB6, 0x70, 0xBB, 0x76, 0xD9, 0x86, 0x15, 0x83, 0xAB, 0x97, 0xF5, 
+  0xAD, 0x5A, 0xBA, 0x68, 0x78, 0xA8, 0x9D, 0xB7, 0x31, 0xD8, 0xD5, 0xD2, 0xDF, 0xDD, 0xD0, 0xDB, 0x55, 0xDF, 0xD3, 0x51, 
+  0xBB, 0xA8, 0xB5, 0xB6, 0xAB, 0xB3, 0xBA, 0xAB, 0xBD, 0xBA, 0xB3, 0xAD, 0xAA, 0xA3, 0x95, 0x55, 0xD9, 0xCE, 0xAD, 0x73, 
+  0xCD, 0x05, 0x8F, 0x57, 0x77, 0xCA, 0x23, 0x35, 0xED, 0xED, 0xB5, 0x1D, 0x9D, 0xB5, 0x9D, 0xDC, 0xB6, 0xD7, 0xB6, 0xB5, 
+  0x56, 0xB7, 0xF1, 0x78, 0x4B, 0x65, 0x7B, 0x73, 0x45, 0x47, 0x73, 0x79, 0xAB, 0xAC, 0x8A, 0xB6, 0xA6, 0xF2, 0xD6, 0x86, 
+  0x92, 0xA6, 0x86, 0xD2, 0xE6, 0xC6, 0xE2, 0xA6, 0xFA, 0xA2, 0xE6, 0xFA, 0x92, 0x16, 0x59, 0xC5, 0x8D, 0x75, 0x25, 0xF5, 
+  0x75, 0xDC, 0x16, 0x37, 0xF3, 0xA0, 0x5C, 0x14, 0xD5, 0xD5, 0x16, 0x35, 0xC8, 0x2A, 0xAE, 0xAB, 0x2D, 0xAE, 0xA9, 0x29, 
+  0xAA, 0x95, 0x8B, 0xC2, 0x5A, 0x2E, 0xAA, 0x0B, 0x6B, 0x58, 0x3E, 0x56, 0xCA, 0x7C, 0x3C, 0x73, 0x2D, 0x82, 0xE6, 0xA2, 
+  0xAF, 0x6D, 0x99, 0x47, 0xCA, 0x2A, 0x7A, 0x91, 0x3B, 0x02, 0x45, 0xCA, 0x5C, 0x1B, 0xB9, 0x0F, 0x99, 0x8B, 0x25, 0x3D, 
+  0x2D, 0xA2, 0x00, 0x2B, 0x74, 0x34, 0xE1, 0x5E, 0x2F, 0xF6, 0x0A, 0x5D, 0x45, 0x6F, 0xE4, 0xDB, 0xEB, 0x15, 0xB4, 0x48, 
+  0xB9, 0xD1, 0x59, 0x9D, 0x8D, 0xBD, 0x2C, 0x1E, 0xB1, 0xCB, 0x3E, 0xB3, 0xBB, 0xCD, 0xE8, 0x60, 0xD1, 0xD2, 0xA5, 0xBD, 
+  0xC3, 0x2B, 0x87, 0xD6, 0xAC, 0x59, 0xBC, 0x76, 0x79, 0xFF, 0xCA, 0xE5, 0x03, 0xC3, 0xDB, 0x37, 0xED, 0xD8, 0xBB, 0x63, 
+  0xFF, 0xC6, 0x35, 0x9B, 0x56, 0x2E, 0x5D, 0xBD, 0x69, 0xF5, 0x66, 0xD6, 0xDA, 0x65, 0x9B, 0x56, 0x0C, 0xAD, 0x1C, 0xEE, 
+  0x5B, 0xBE, 0xA4, 0x6B, 0x79, 0x6F, 0xF3, 0x50, 0x67, 0x63, 0x7F, 0x77, 0x7D, 0x3F, 0x02, 0xED, 0xAC, 0x5D, 0xD4, 0x51, 
+  0xD3, 0xD5, 0x52, 0xD3, 0xD9, 0x54, 0xD5, 0x8E, 0xF4, 0x8D, 0x4C, 0xDB, 0x74, 0x71, 0xCD, 0x72, 0x54, 0x62, 0x14, 0xC0, 
+  0xEA, 0xA8, 0xEB, 0x64, 0x71, 0x81, 0x4A, 0x58, 0xAD, 0x95, 0x22, 0xFD, 0xA6, 0xB2, 0x16, 0x56, 0x23, 0xA2, 0x2F, 0x6D, 
+  0x46, 0x07, 0x35, 0x25, 0x8D, 0xC8, 0xBD, 0xBE, 0xB8, 0x5E, 0x44, 0xAF, 0xD2, 0x97, 0x8B, 0x5A, 0x11, 0x7A, 0x61, 0xBD, 
+  0x91, 0x7B, 0x9D, 0xC8, 0xDD, 0x08, 0xBD, 0xA6, 0xA8, 0x1A, 0xA1, 0x9B, 0x0B, 0xD1, 0x04, 0xD7, 0x55, 0x05, 0xD5, 0xA2, 
+  0x83, 0xD1, 0xD6, 0x8D, 0xA0, 0x47, 0xD9, 0xB8, 0x2B, 0x6E, 0xA4, 0x3C, 0x60, 0x6C, 0x5C, 0x44, 0xCF, 0xF2, 0x18, 0xF8, 
+  0x20, 0x3A, 0xB0, 0xA6, 0x6A, 0x04, 0x3D, 0x62, 0xEC, 0x6A, 0xE3, 0x1E, 0x89, 0x0F, 0xA8, 0xB8, 0x8D, 0x88, 0x7B, 0x54, 
+  0xD0, 0x56, 0xEE, 0x8B, 0x1A, 0x44, 0x01, 0xCE, 0xDD, 0xFA, 0x1E, 0xBD, 0xCB, 0xDF, 0x1A, 0xAD, 0xF4, 0x74, 0xB6, 0x0D, 
+  0x0C, 0xB6, 0x0D, 0x2E, 0x59, 0xB4, 0x74, 0x59, 0xDF, 0x8A, 0x95, 0x03, 0x2B, 0x10, 0xF1, 0x65, 0x5B, 0x77, 0xBF, 0xFD, 
+  0xFD, 0x1F, 0xFC, 0xF5, 0xAF, 0x7F, 0xFD, 0xC7, 0x3F, 0xFE, 0xF5, 0xBB, 0xDF, 0xFC, 0xFE, 0x89, 0x47, 0x9F, 0xD9, 0xB8, 
+  0x6A, 0xD3, 0x86, 0xE5, 0xEB, 0x37, 0xAC, 0xDE, 0x24, 0xDE, 0x80, 0x86, 0xBA, 0x97, 0x0F, 0x76, 0x0C, 0xC9, 0x7F, 0x6F, 
+  0xEC, 0xEE, 0xAC, 0xEB, 0x6E, 0xAF, 0xE9, 0x62, 0x61, 0xE6, 0x22, 0x71, 0x0C, 0xB9, 0xCA, 0x51, 0x03, 0x16, 0x6D, 0xD5, 
+  0xA0, 0x1E, 0xA0, 0xD2, 0x6F, 0xAB, 0xEB, 0xEC, 0xAA, 0xEB, 0x52, 0x7D, 0xB4, 0x57, 0xB7, 0xB7, 0x55, 0xA1, 0xAD, 0x8E, 
+  0xA6, 0xB2, 0x26, 0x91, 0x7E, 0x29, 0x86, 0xDF, 0xC4, 0x32, 0x26, 0x2F, 0x6A, 0x40, 0xE8, 0xAA, 0x00, 0x84, 0x6B, 0x6F, 
+  0xAB, 0x8A, 0xB8, 0x5B, 0x53, 0x57, 0xE4, 0xC8, 0x5D, 0x0D, 0x5F, 0x17, 0xD2, 0x67, 0x95, 0xE7, 0x57, 0xF9, 0x9C, 0x6C, 
+  0xEC, 0x16, 0x4C, 0xDC, 0x8B, 0x21, 0x35, 0x73, 0x5D, 0x2E, 0xBC, 0x38, 0x08, 0x83, 0x88, 0x79, 0x44, 0x85, 0xBE, 0xA8, 
+  0x55, 0x16, 0xD7, 0x8A, 0x30, 0xAE, 0xC9, 0xA3, 0x83, 0x41, 0x8B, 0x30, 0x5E, 0xA1, 0x5B, 0x89, 0x77, 0x34, 0xF4, 0xE8, 
+  0x42, 0xD6, 0xDC, 0xB6, 0xD7, 0x77, 0xEB, 0x6D, 0x5B, 0xDD, 0x22, 0x7D, 0x1C, 0x18, 0xE1, 0x57, 0x3D, 0xCD, 0xBD, 0x03, 
+  0xED, 0xFD, 0xE8, 0x60, 0x71, 0xD7, 0x92, 0x65, 0x3D, 0x4B, 0xB6, 0xAE, 0xDB, 0xF6, 0xA7, 0x3F, 0xFE, 0x19, 0x3C, 0xFD, 
+  0xF8, 0xE3, 0xFF, 0xF9, 0xF8, 0xE3, 0x8F, 0x3F, 0xFB, 0xE4, 0x53, 0xAE, 0x7F, 0xFA, 0xD3, 0xF7, 0xB6, 0xAC, 0xDF, 0xB6, 
+  0x6E, 0x78, 0x3D, 0xE8, 0xB4, 0x7A, 0x68, 0xE5, 0xD2, 0xEE, 0x25, 0xFC, 0x49, 0x37, 0xCA, 0x6E, 0x10, 0x90, 0xE9, 0xA8, 
+  0x12, 0x08, 0x72, 0xCC, 0xBF, 0xBC, 0xB5, 0xB1, 0xB2, 0x4D, 0x8C, 0x1A, 0xD3, 0x36, 0xF0, 0x82, 0x56, 0x5A, 0xAA, 0x5A, 
+  0x81, 0x9D, 0x96, 0xDA, 0xD6, 0x8E, 0x1A, 0x11, 0x7A, 0x43, 0x59, 0x63, 0x59, 0x4E, 0x79, 0x43, 0x49, 0x43, 0x73, 0x65, 
+  0x8B, 0xFE, 0x8A, 0x67, 0x36, 0x96, 0x37, 0x18, 0xD8, 0x71, 0xA4, 0x8F, 0x2B, 0xA8, 0xB1, 0x8B, 0xBD, 0x1B, 0x05, 0x28, 
+  0xE6, 0x00, 0x41, 0x18, 0x7B, 0x15, 0xAB, 0xA0, 0x5A, 0x0C, 0xBF, 0x60, 0x44, 0xF4, 0x95, 0xF9, 0x55, 0x15, 0x46, 0x01, 
+  0x5C, 0x8C, 0xE8, 0xC0, 0x35, 0x70, 0x31, 0xF3, 0x93, 0x70, 0x5C, 0x80, 0xB8, 0xA7, 0x55, 0xD0, 0xDC, 0x8A, 0x5B, 0x44, 
+  0xDC, 0xAC, 0xA2, 0x47, 0xE2, 0x6A, 0xE9, 0x22, 0x68, 0x90, 0x57, 0xEF, 0x8E, 0x11, 0x7A, 0x57, 0x93, 0xA0, 0x7F, 0x27, 
+  0xC6, 0xE8, 0x9A, 0xB9, 0x88, 0xBB, 0xA9, 0xDF, 0x4A, 0x7F, 0x94, 0xE8, 0x1B, 0xBA, 0xDB, 0x1A, 0xBA, 0x55, 0x07, 0xBA, 
+  0xC0, 0xF1, 0x45, 0xA2, 0x86, 0xEE, 0xFE, 0xB6, 0x3E, 0x64, 0x3A, 0xD0, 0x3E, 0xB8, 0xAC, 0x67, 0xE9, 0x83, 0xF7, 0x3C, 
+  0x84, 0xD0, 0x3F, 0xFA, 0xE8, 0xA3, 0xFF, 0x9A, 0x1F, 0x34, 0xF1, 0xEF, 0x7F, 0xFF, 0x9B, 0x47, 0x5E, 0x7F, 0xFD, 0x3B, 
+  0xAB, 0x96, 0xAD, 0x5E, 0xBB, 0x62, 0xDD, 0xAA, 0x25, 0xAB, 0x89, 0x1C, 0x3C, 0x19, 0x1D, 0x88, 0x21, 0xE3, 0x01, 0x2E, 
+  0xFE, 0x08, 0x94, 0x03, 0x26, 0x8A, 0x2A, 0xEE, 0x6A, 0xA9, 0x40, 0xD0, 0xCD, 0x66, 0xB5, 0x36, 0x54, 0x36, 0x56, 0xE6, 
+  0x56, 0x82, 0x30, 0x9B, 0x56, 0x6D, 0x6D, 0xAA, 0x68, 0xAE, 0xC8, 0x29, 0xAB, 0x2F, 0xAD, 0xE3, 0xA2, 0xB9, 0x5C, 0xF0, 
+  0xA7, 0xA1, 0x44, 0x2C, 0xDD, 0x2E, 0x47, 0xE8, 0xE0, 0x4F, 0x71, 0x8D, 0x62, 0xBD, 0xEA, 0x80, 0x0B, 0x07, 0x79, 0x8C, 
+  0x02, 0x44, 0xE2, 0x85, 0xD5, 0x48, 0x9F, 0x8B, 0xAA, 0xDC, 0x72, 0x75, 0x02, 0xAE, 0x7D, 0x8C, 0x69, 0xAB, 0x94, 0x91, 
+  0x29, 0xA1, 0x4F, 0x03, 0xA9, 0x77, 0x11, 0x48, 0x35, 0x8A, 0x8A, 0xC4, 0xDD, 0xA5, 0x81, 0x54, 0x6D, 0x7C, 0x00, 0xC0, 
+  0x15, 0x87, 0x68, 0x32, 0x16, 0x27, 0xF0, 0x22, 0x12, 0x77, 0x4D, 0x1E, 0xB9, 0xA3, 0x12, 0x9E, 0x03, 0xB0, 0x88, 0x0E, 
+  0x3C, 0x72, 0xEF, 0x43, 0xD0, 0xBA, 0xC4, 0x09, 0xEA, 0x44, 0xE8, 0xC4, 0x4C, 0x15, 0x3A, 0xC0, 0xDD, 0x55, 0x23, 0xB7, 
+  0xD8, 0x2F, 0xE2, 0x13, 0x28, 0x6F, 0xEC, 0xC4, 0x15, 0x3A, 0xEB, 0xDB, 0xB1, 0xEE, 0x25, 0x3D, 0xCB, 0x1F, 0x7D, 0xE8, 
+  0x49, 0x72, 0x9B, 0x4F, 0x3E, 0xF9, 0xF8, 0x33, 0x7E, 0xBE, 0xF8, 0x94, 0x9B, 0x4F, 0x3F, 0xFD, 0x54, 0x7D, 0xE2, 0xD8, 
+  0xA1, 0x63, 0xC3, 0x83, 0x2B, 0x56, 0x2E, 0x5E, 0x45, 0xE4, 0x40, 0x07, 0xBD, 0x4D, 0xFC, 0x95, 0x04, 0xDE, 0x96, 0xF2, 
+  0x0E, 0x81, 0x20, 0x83, 0xE9, 0x88, 0x1E, 0x35, 0xA8, 0x26, 0x04, 0x58, 0x4A, 0x1B, 0x1A, 0x4A, 0xB1, 0xF1, 0xA6, 0xA6, 
+  0x8A, 0x46, 0x2C, 0xBD, 0x32, 0xBF, 0xA2, 0x2A, 0xAF, 0xEA, 0x95, 0x97, 0x5F, 0xFF, 0xE4, 0xD3, 0xCF, 0xBF, 0xF3, 0xFA, 
+  0xF7, 0xEA, 0x0B, 0xEB, 0xCA, 0x73, 0x51, 0x43, 0x43, 0x63, 0xA9, 0x22, 0x4F, 0xAD, 0xA2, 0x8D, 0x22, 0xBB, 0x77, 0x21, 
+  0x6B, 0xD1, 0x41, 0x51, 0x03, 0x1E, 0x50, 0x59, 0x58, 0x83, 0xD0, 0xB9, 0x15, 0xA1, 0x1B, 0xD1, 0xEB, 0x05, 0xA2, 0xAF, 
+  0xC8, 0x2B, 0xE7, 0xB6, 0x34, 0x97, 0x8B, 0x4A, 0x1F, 0xD7, 0xC0, 0x55, 0x0D, 0x62, 0xEF, 0xAE, 0x75, 0x0B, 0x88, 0x8F, 
+  0x81, 0x14, 0x2B, 0x77, 0x0B, 0x2F, 0x08, 0x57, 0xD5, 0xC0, 0x12, 0xA0, 0x57, 0x40, 0x6F, 0x50, 0x89, 0xCB, 0x52, 0x84, 
+  0x41, 0x0D, 0x1D, 0x0D, 0x7D, 0xAC, 0xF6, 0xFA, 0xDE, 0xF6, 0xC6, 0x1E, 0x59, 0x22, 0xFA, 0x5E, 0xAF, 0xB1, 0xB7, 0xD5, 
+  0xF5, 0x38, 0x78, 0x5D, 0x2B, 0xA8, 0x8D, 0xC8, 0x24, 0x7B, 0x71, 0x17, 0x20, 0xDE, 0x51, 0xD7, 0xBE, 0xA8, 0xBE, 0x13, 
+  0x1B, 0x5C, 0xBD, 0x74, 0xCD, 0x40, 0xD7, 0xE0, 0xD5, 0x57, 0x5E, 0xF7, 0xD1, 0x47, 0xFF, 0x83, 0xE1, 0x93, 0x91, 0x92, 
+  0x32, 0x92, 0x98, 0xF2, 0xF3, 0xDF, 0x4F, 0x3F, 0xE6, 0x91, 0x27, 0x1F, 0x7F, 0x6A, 0xD5, 0xE0, 0xCA, 0x15, 0xFD, 0xC3, 
+  0xC3, 0x3D, 0xCB, 0xAC, 0x1F, 0x34, 0x55, 0x99, 0x64, 0x46, 0xAD, 0xDE, 0x44, 0x54, 0xF0, 0x44, 0x61, 0xBD, 0xAE, 0x08, 
+  0x78, 0x01, 0xDC, 0x5B, 0x54, 0xCA, 0x35, 0x05, 0x55, 0x39, 0x89, 0x99, 0x5B, 0xD6, 0x6F, 0xFD, 0xF8, 0xE3, 0x4F, 0x7E, 
+  0xFD, 0xC1, 0x2F, 0xFF, 0xF5, 0xAF, 0x7F, 0xAD, 0xE8, 0x5D, 0x9E, 0x97, 0x92, 0x5B, 0x99, 0x5B, 0x2E, 0xD6, 0xED, 0xE2, 
+  0x8C, 0x57, 0xF4, 0x6A, 0xF2, 0xDE, 0x05, 0xF8, 0x38, 0x26, 0x5F, 0x50, 0x5D, 0x9D, 0x2F, 0xE6, 0x2F, 0x2B, 0xAF, 0x52, 
+  0x6D, 0xBF, 0x22, 0x47, 0xA4, 0x5F, 0x9A, 0x5B, 0x51, 0x96, 0x5F, 0xEE, 0xA3, 0x06, 0x6E, 0x70, 0x7C, 0xA0, 0xB7, 0x59, 
+  0x96, 0x1B, 0x3F, 0xC5, 0xC6, 0x7B, 0x9A, 0x9C, 0x88, 0xDA, 0xD5, 0x32, 0xD8, 0xD5, 0x28, 0xB2, 0x36, 0x38, 0x23, 0x86, 
+  0xEF, 0x45, 0x76, 0xEE, 0x9A, 0xD5, 0xAB, 0x10, 0x6F, 0x2D, 0x5D, 0xD2, 0x41, 0x01, 0xF4, 0xBE, 0xF6, 0x46, 0x16, 0x96, 
+  0x8E, 0xD0, 0xE5, 0xB7, 0x22, 0x6E, 0x03, 0x35, 0x6A, 0xF5, 0x8E, 0xED, 0x9B, 0x80, 0xA9, 0x56, 0x6F, 0x45, 0xAF, 0xD8, 
+  0x8D, 0xF1, 0x72, 0xDB, 0x56, 0x25, 0x58, 0x51, 0x95, 0x57, 0xB1, 0x61, 0xD5, 0xB6, 0xDE, 0xF6, 0xBE, 0x0D, 0x2B, 0x37, 
+  0x7E, 0xF7, 0x3B, 0xDF, 0xD7, 0x4C, 0x1C, 0x1D, 0x98, 0x1F, 0x71, 0x09, 0x94, 0xF2, 0xE6, 0xF7, 0x7E, 0xB0, 0x7E, 0xD9, 
+  0x3A, 0xF0, 0x6A, 0x69, 0xE7, 0x50, 0x7F, 0x4B, 0x2F, 0xC1, 0xA0, 0xB5, 0xBA, 0x45, 0xA0, 0xA6, 0xCC, 0x11, 0xBD, 0xEB, 
+  0x04, 0x24, 0x97, 0x0D, 0x62, 0xD1, 0xE8, 0xA0, 0xD8, 0x81, 0x72, 0xA4, 0x5C, 0x9A, 0x59, 0x9C, 0x1D, 0x9F, 0x79, 0x60, 
+  0xF7, 0x21, 0x20, 0xEE, 0x9F, 0x7F, 0xFF, 0xC7, 0xCF, 0xDE, 0xFB, 0x65, 0x73, 0x4D, 0x4B, 0x61, 0x7A, 0x41, 0x49, 0x7A, 
+  0x21, 0xD2, 0x44, 0x43, 0x55, 0x05, 0x95, 0x1A, 0x51, 0x59, 0x56, 0xEE, 0xD8, 0x3B, 0x77, 0x55, 0xD6, 0xF6, 0xB7, 0x62, 
+  0xF5, 0x05, 0x15, 0x88, 0xBB, 0x4C, 0xA4, 0x5F, 0x63, 0x56, 0x15, 0x72, 0xE7, 0xAE, 0xAC, 0xFC, 0xF2, 0xD2, 0xBC, 0x32, 
+  0x1F, 0x91, 0x69, 0x8B, 0x23, 0xE8, 0xCE, 0x66, 0x81, 0x91, 0xEE, 0x16, 0xCD, 0xCA, 0x07, 0x10, 0x7A, 0x67, 0xB3, 0xA0, 
+  0x8A, 0x49, 0x63, 0xC4, 0xD2, 0x55, 0xD0, 0x8E, 0x81, 0x37, 0x01, 0xE8, 0xB2, 0xAC, 0xBD, 0x7B, 0xC1, 0xDD, 0xB9, 0xAE, 
+  0x5D, 0xA4, 0xF6, 0x0E, 0xBE, 0x1B, 0x84, 0x21, 0x43, 0x97, 0x24, 0x1D, 0x84, 0xC1, 0xC6, 0x2D, 0xCE, 0xA8, 0xC4, 0x35, 
+  0x63, 0x91, 0xA4, 0xA5, 0x46, 0x32, 0x74, 0xC1, 0x6E, 0xC5, 0x0D, 0x85, 0x8E, 0xF2, 0x06, 0x56, 0x43, 0x59, 0x7D, 0x51, 
+  0x7A, 0xFE, 0xA6, 0x35, 0x97, 0x2D, 0xEE, 0x5E, 0xD6, 0xDF, 0xD6, 0x7B, 0xFD, 0xD5, 0x37, 0x7E, 0xF8, 0xE1, 0x6F, 0xAD, 
+  0x0E, 0xB8, 0x30, 0x3A, 0x38, 0xF1, 0xEE, 0xBB, 0x3F, 0xDB, 0xB4, 0x62, 0x23, 0x90, 0xD5, 0xD3, 0xB8, 0xA8, 0xB7, 0xA5, 
+  0x07, 0x07, 0x22, 0xA8, 0x36, 0x95, 0xB6, 0x39, 0xC9, 0x4C, 0xA9, 0xC8, 0x1D, 0x93, 0x37, 0x90, 0x22, 0x08, 0x6E, 0x53, 
+  0x75, 0x8C, 0x97, 0x30, 0x90, 0x9B, 0x98, 0x5B, 0x94, 0x56, 0x84, 0xF2, 0xBE, 0xFB, 0x9D, 0xB7, 0xBE, 0xF3, 0xDA, 0x9B, 
+  0x3B, 0xB7, 0xEE, 0xCE, 0x49, 0xCA, 0xE6, 0xF1, 0x9C, 0xB8, 0xEC, 0x8A, 0x9C, 0x8A, 0xCA, 0xFC, 0x72, 0xC4, 0x6A, 0x64, 
+  0x2A, 0x11, 0x55, 0xE3, 0xAA, 0x48, 0x56, 0x1F, 0x01, 0x7C, 0x3C, 0xC8, 0xC3, 0x23, 0xAA, 0x18, 0x15, 0xBA, 0xFC, 0x21, 
+  0x0A, 0x30, 0xA2, 0x2F, 0xC9, 0x2D, 0x2D, 0xC9, 0x2D, 0xC1, 0x15, 0xC4, 0x0F, 0x14, 0x73, 0x3C, 0x08, 0x3E, 0x92, 0x20, 
+  0x1A, 0xAD, 0x38, 0xB9, 0xA3, 0xCA, 0x1A, 0x4B, 0x17, 0xD1, 0x9B, 0x74, 0xA5, 0xB5, 0xC9, 0xC9, 0x67, 0xD4, 0xDE, 0x15, 
+  0xD9, 0x91, 0xB5, 0x45, 0xF9, 0x96, 0xC6, 0x91, 0xE8, 0x8A, 0xE8, 0x91, 0xB2, 0x73, 0x6B, 0x92, 0x74, 0x91, 0xBB, 0x5B, 
+  0x13, 0x8D, 0x14, 0x4D, 0x9A, 0x38, 0x1A, 0xF3, 0x37, 0xE9, 0x4A, 0x33, 0xB9, 0x20, 0xF9, 0x09, 0x21, 0x11, 0xC1, 0x55, 
+  0x17, 0x56, 0x65, 0xC6, 0xA5, 0xE1, 0x07, 0x9B, 0xD6, 0x6C, 0x5B, 0xD4, 0xD2, 0xBD, 0x71, 0xD5, 0xC6, 0x47, 0x1F, 0x78, 
+  0xEC, 0xFF, 0xFC, 0xF1, 0xAF, 0x56, 0x0D, 0x9F, 0x7D, 0xF6, 0x09, 0xD7, 0xEF, 0xFC, 0xE8, 0xDD, 0x75, 0x2B, 0x37, 0x90, 
+  0xBC, 0x52, 0x5E, 0x2D, 0x6A, 0x44, 0xDF, 0x02, 0xF4, 0x0A, 0xFA, 0x9A, 0xBC, 0x4B, 0xFE, 0x6E, 0x93, 0x99, 0x42, 0x5E, 
+  0x56, 0xCC, 0x53, 0x05, 0x84, 0x13, 0xA4, 0x45, 0xA4, 0x22, 0xC7, 0xCC, 0x98, 0xB4, 0xE1, 0xBE, 0x15, 0x4B, 0xBB, 0x97, 
+  0x25, 0x87, 0x25, 0x94, 0x67, 0x96, 0x15, 0xA7, 0x17, 0x67, 0xC4, 0xA4, 0x89, 0xEC, 0xF2, 0x4B, 0x49, 0x96, 0x14, 0x46, 
+  0x54, 0xFA, 0xE5, 0x5C, 0x17, 0x38, 0x9A, 0x50, 0xD0, 0xAF, 0xC8, 0x15, 0xA1, 0x03, 0xF7, 0xDC, 0x12, 0x5A, 0x04, 0x76, 
+  0xF2, 0xCA, 0xCC, 0x23, 0x15, 0xBA, 0xE4, 0x3A, 0xAF, 0x4C, 0x97, 0x8F, 0x06, 0x4C, 0x37, 0x8A, 0x5A, 0x1C, 0x17, 0x7B, 
+  0x17, 0x28, 0x6F, 0x76, 0x14, 0xE0, 0xDA, 0xB8, 0x44, 0x51, 0x27, 0x5F, 0x6C, 0x02, 0xDF, 0x47, 0x44, 0xAF, 0xD2, 0x27, 
+  0x72, 0x4A, 0xF0, 0xAC, 0x75, 0xF2, 0x19, 0x1B, 0x5D, 0x15, 0xE8, 0xB5, 0x4C, 0xB5, 0xD7, 0xAA, 0x06, 0xC1, 0xFD, 0x4A, 
+  0x53, 0xB2, 0xAA, 0x13, 0xB8, 0x15, 0x93, 0x93, 0xBA, 0x20, 0xBB, 0x32, 0x6C, 0xD6, 0xC9, 0x31, 0x30, 0xC6, 0x84, 0xD0, 
+  0xD8, 0xA1, 0x9E, 0x65, 0xFB, 0x76, 0x5D, 0x49, 0x48, 0x18, 0x68, 0xEF, 0xDB, 0xB6, 0x65, 0xC7, 0x73, 0xCF, 0x7C, 0xF3, 
+  0xAF, 0x7F, 0xFD, 0xFB, 0x17, 0x9F, 0x7D, 0x2E, 0x2D, 0x8A, 0x13, 0x9F, 0x7F, 0xF2, 0xC9, 0x27, 0x18, 0xEF, 0xEA, 0xA1, 
+  0x55, 0x4B, 0xFB, 0x96, 0xF1, 0x87, 0x24, 0xF5, 0x2D, 0x15, 0x64, 0xF4, 0x1A, 0x48, 0x9D, 0x58, 0x2A, 0x17, 0x45, 0x75, 
+  0x26, 0x7D, 0x74, 0x92, 0x74, 0x63, 0x9B, 0xA5, 0xC5, 0x39, 0x25, 0x05, 0x69, 0xF9, 0xF1, 0x21, 0x31, 0xD5, 0x25, 0x35, 
+  0xF1, 0x81, 0x71, 0xC9, 0x11, 0x71, 0x71, 0xC1, 0xD1, 0xE1, 0x73, 0xC3, 0xF8, 0xA4, 0x49, 0x61, 0x09, 0x19, 0x71, 0x69, 
+  0x85, 0x59, 0x45, 0xC5, 0x3C, 0x2D, 0xAF, 0x54, 0xC4, 0x87, 0x34, 0x91, 0x2C, 0x7F, 0x68, 0x64, 0x6A, 0x57, 0x69, 0x81, 
+  0xA3, 0x1B, 0x07, 0x6D, 0x0A, 0x0C, 0xF2, 0xE4, 0x97, 0x97, 0xE4, 0xC8, 0x73, 0xB0, 0xFD, 0xB2, 0x7C, 0x44, 0x2F, 0xAF, 
+  0xA0, 0xAE, 0x80, 0x0E, 0x24, 0x60, 0x7A, 0x03, 0x29, 0xF0, 0xED, 0x86, 0x50, 0x8F, 0x99, 0x1B, 0x54, 0x31, 0xC6, 0x2E, 
+  0x98, 0x2E, 0x12, 0x17, 0x78, 0x11, 0x64, 0x57, 0x34, 0xB7, 0x0A, 0x50, 0x1D, 0x88, 0xB8, 0xEB, 0x47, 0x24, 0x2E, 0x0A, 
+  0x30, 0xF8, 0x63, 0xB1, 0x9E, 0x6B, 0x2B, 0x77, 0xA7, 0x68, 0x32, 0xE0, 0x63, 0x93, 0x77, 0x0D, 0x9E, 0x6A, 0xB9, 0x54, 
+  0x3A, 0x82, 0xB0, 0x79, 0x15, 0x65, 0x59, 0x65, 0xB1, 0x81, 0xD1, 0xA4, 0x28, 0x57, 0x5C, 0x71, 0xD3, 0x9A, 0xE5, 0x9B, 
+  0x86, 0xBA, 0x17, 0x53, 0x27, 0x5F, 0xB1, 0xF7, 0xE8, 0x37, 0xBE, 0xFE, 0xE2, 0x07, 0xBF, 0xFA, 0x2D, 0xB9, 0xE9, 0xFF, 
+  0xFC, 0xCF, 0xC7, 0xBF, 0xFF, 0xDD, 0x9F, 0x9E, 0x79, 0xF2, 0x1B, 0x43, 0x9D, 0x03, 0xCB, 0x7B, 0x97, 0x01, 0xDF, 0x88, 
+  0x9E, 0xD5, 0x50, 0x54, 0xAF, 0x21, 0x14, 0x4F, 0x92, 0x34, 0xB1, 0xD8, 0xA4, 0x8F, 0x05, 0x92, 0xB6, 0x0B, 0x50, 0x28, 
+  0x38, 0xE4, 0x94, 0x23, 0xE2, 0xFC, 0xD4, 0xDC, 0xA8, 0x85, 0x11, 0x35, 0xA5, 0xB5, 0xC9, 0x91, 0x49, 0x41, 0x73, 0x16, 
+  0x06, 0xCD, 0xF5, 0xCF, 0x4E, 0xCB, 0x69, 0xAE, 0x6D, 0x0F, 0x99, 0x17, 0x94, 0x9E, 0x94, 0x99, 0x9F, 0x51, 0x50, 0x94, 
+  0x5D, 0x8C, 0xAA, 0x10, 0x9F, 0x5A, 0xB1, 0x60, 0x3D, 0x0E, 0xA1, 0xA6, 0xAD, 0xCA, 0x70, 0xD0, 0xA6, 0xD4, 0x5C, 0x94, 
+  0xF1, 0x64, 0xF1, 0x1B, 0xD7, 0xEA, 0xF5, 0x42, 0x5F, 0x41, 0x97, 0x8F, 0xD8, 0x72, 0x7D, 0xBF, 0x09, 0x95, 0x5E, 0xBB, 
+  0x16, 0x29, 0x8B, 0xD0, 0x6B, 0x25, 0x90, 0xB2, 0xD4, 0xB4, 0x79, 0x04, 0xC9, 0x5A, 0x4B, 0x57, 0x59, 0x93, 0x53, 0xEA, 
+  0x85, 0x00, 0x7A, 0xAD, 0x80, 0x8C, 0x37, 0xBD, 0x91, 0xDE, 0x8B, 0x27, 0xB7, 0xD1, 0xCE, 0x8C, 0x74, 0x05, 0xAC, 0xE1, 
+  0x1B, 0xE4, 0xB1, 0x6D, 0x03, 0x9B, 0xAD, 0x6B, 0xE2, 0x48, 0x22, 0x08, 0x68, 0x20, 0x26, 0x80, 0xA2, 0x24, 0xBF, 0xAC, 
+  0x28, 0xA3, 0x30, 0x29, 0x34, 0x3E, 0xDA, 0x3F, 0x62, 0xFF, 0x9E, 0xCB, 0xF7, 0xEE, 0xBA, 0x7C, 0xE5, 0xD0, 0xBA, 0x81, 
+  0xCE, 0xC5, 0xAB, 0x97, 0xAC, 0x3B, 0x76, 0xE4, 0xEA, 0x67, 0x9E, 0x7E, 0xFE, 0xC7, 0x3F, 0x7A, 0xF7, 0x67, 0x3F, 0xFD, 
+  0xE5, 0x9B, 0xDF, 0xFB, 0xE1, 0x6D, 0xB7, 0xDF, 0xD3, 0xD5, 0xD0, 0x31, 0xD8, 0xB5, 0xA4, 0x32, 0xBB, 0xA2, 0x3C, 0xBB, 
+  0xB4, 0x26, 0xBF, 0xB2, 0xA2, 0xB0, 0xD2, 0x80, 0x72, 0x75, 0x65, 0x5E, 0x0D, 0xC1, 0x53, 0x32, 0x16, 0x7A, 0x06, 0x46, 
+  0x01, 0x0E, 0x04, 0x19, 0xB9, 0xA0, 0x83, 0x9C, 0xD4, 0xDC, 0x08, 0xFF, 0x30, 0x55, 0x49, 0xD8, 0x82, 0x90, 0xE8, 0x90, 
+  0x68, 0x3A, 0x2B, 0xD9, 0x29, 0xD9, 0x21, 0xFE, 0x41, 0x59, 0xC9, 0xD9, 0x79, 0xE9, 0xF9, 0x04, 0x67, 0xD4, 0x60, 0x25, 
+  0x68, 0xF5, 0x67, 0x3D, 0xC3, 0xB9, 0x50, 0xD8, 0xF1, 0x88, 0xDE, 0xF9, 0x93, 0x9C, 0x72, 0xFB, 0xB7, 0x38, 0x01, 0xFF, 
+  0x14, 0x1D, 0x48, 0xCA, 0x28, 0x9A, 0x68, 0x12, 0x4D, 0x18, 0x03, 0xEF, 0x6D, 0xAB, 0xD5, 0x28, 0xDA, 0xD9, 0x59, 0xDF, 
+  0x85, 0x88, 0xAD, 0x94, 0x55, 0xD0, 0xDA, 0x75, 0x41, 0xDC, 0x0A, 0x2C, 0xA3, 0xA4, 0x6F, 0x2C, 0x5D, 0xEC, 0x7D, 0x74, 
+  0x5A, 0x89, 0xC4, 0x9B, 0xAB, 0x65, 0x61, 0xE9, 0x9A, 0x74, 0x6A, 0xB9, 0xC4, 0xF5, 0x48, 0xC7, 0xA6, 0xA2, 0xCD, 0x2A, 
+  0xA0, 0xAE, 0xAC, 0xD9, 0xC4, 0x00, 0xE9, 0x73, 0x49, 0x96, 0x6D, 0x90, 0x9A, 0x77, 0x8C, 0x08, 0xD2, 0x62, 0x52, 0xE7, 
+  0x4C, 0x9A, 0x35, 0xB0, 0x68, 0xC9, 0xD1, 0x23, 0xD7, 0x11, 0x9C, 0x07, 0x16, 0x2D, 0xA3, 0x8D, 0xB1, 0x6E, 0x78, 0x1D, 
+  0xA9, 0xEA, 0xE3, 0x8F, 0x3D, 0x83, 0x43, 0xD0, 0xB1, 0x38, 0x72, 0xF0, 0xAA, 0xFA, 0xA2, 0x1A, 0x92, 0x8B, 0xD2, 0xAC, 
+  0xA2, 0xBC, 0x84, 0x5C, 0x92, 0x71, 0x1B, 0x09, 0x79, 0xA9, 0xF2, 0xA2, 0x0A, 0xCD, 0xD6, 0x35, 0x69, 0x51, 0x21, 0x96, 
+  0xE5, 0x94, 0x22, 0x59, 0xCC, 0x3C, 0x27, 0x35, 0x27, 0x32, 0x38, 0x3C, 0x2D, 0x3E, 0x9D, 0x4F, 0x17, 0x1F, 0x11, 0x5F, 
+  0x94, 0x5B, 0xD2, 0xD3, 0x3E, 0xB4, 0x70, 0xDE, 0x82, 0xF8, 0xA8, 0x84, 0x9C, 0xA4, 0x2C, 0x90, 0xAA, 0x20, 0xB3, 0x50, 
+  0x10, 0x29, 0x47, 0xC4, 0xE7, 0x75, 0x08, 0xC5, 0x25, 0x7D, 0x35, 0x6B, 0xEC, 0xB8, 0x2C, 0xB0, 0xA3, 0x42, 0x77, 0xC1, 
+  0x47, 0xAE, 0xED, 0xDF, 0x8A, 0x1F, 0xA8, 0xBD, 0xAB, 0x94, 0x25, 0x4D, 0xAC, 0x1F, 0x29, 0x4D, 0x91, 0xB5, 0x15, 0xB1, 
+  0x35, 0x6D, 0x95, 0xBB, 0x1A, 0xBB, 0xB4, 0x18, 0x01, 0x22, 0x1A, 0x8A, 0x20, 0x3B, 0x6D, 0x16, 0x23, 0x7A, 0x6F, 0x74, 
+  0xF5, 0xA2, 0x8D, 0x9A, 0x3F, 0x12, 0xD7, 0x84, 0x67, 0x4C, 0xCB, 0x4C, 0xF3, 0x1F, 0x4D, 0x19, 0xE5, 0xB6, 0x44, 0x10, 
+  0x1C, 0xB8, 0xA0, 0xD2, 0x51, 0xAC, 0x40, 0x58, 0xC8, 0x28, 0x37, 0x2D, 0x2F, 0x3D, 0x31, 0x75, 0xEE, 0x14, 0xDF, 0x94, 
+  0xA8, 0xD4, 0x03, 0xFB, 0xAE, 0xDE, 0xB3, 0xE3, 0xE8, 0xB2, 0xA1, 0xF5, 0xE4, 0x14, 0xF4, 0xB2, 0xD6, 0x0F, 0x6F, 0x3A, 
+  0xB2, 0xE7, 0x8A, 0x9B, 0xAE, 0xBF, 0xED, 0xDA, 0xAB, 0x6F, 0xDE, 0x34, 0xBC, 0x35, 0x3F, 0x29, 0xA7, 0xB5, 0xB6, 0xA3, 
+  0x34, 0xB3, 0x34, 0x2D, 0x32, 0xB9, 0x24, 0x0B, 0xF4, 0x10, 0xCB, 0x55, 0xA4, 0xE6, 0xD5, 0x24, 0x4F, 0x77, 0x53, 0x14, 
+  0xC4, 0xA4, 0x42, 0x29, 0xC8, 0x2E, 0x2A, 0xC8, 0x2C, 0xC0, 0xD8, 0x13, 0x22, 0x13, 0xB0, 0xFA, 0xDE, 0x8E, 0xC1, 0x92, 
+  0xBC, 0x8A, 0x9E, 0xF6, 0x01, 0x14, 0xEF, 0x3F, 0x67, 0x41, 0x6A, 0x5C, 0x2A, 0xBF, 0xCA, 0x49, 0x71, 0x74, 0xC0, 0x9B, 
+  0x61, 0x95, 0x66, 0x97, 0x10, 0xA2, 0x2D, 0x2E, 0x59, 0x29, 0x7B, 0xC5, 0x3D, 0x46, 0x01, 0x56, 0x79, 0xF6, 0xC2, 0xC7, 
+  0x81, 0x72, 0x8C, 0xDD, 0xC5, 0x13, 0x07, 0xBB, 0x4D, 0x14, 0xB5, 0x6B, 0x4C, 0xDA, 0xAE, 0xC6, 0x6E, 0x41, 0x46, 0xB2, 
+  0x4C, 0xB7, 0x15, 0xAC, 0x17, 0x72, 0xAB, 0x6D, 0xC8, 0x0A, 0x07, 0xF7, 0x15, 0x70, 0x58, 0xDA, 0x20, 0xB3, 0xDD, 0x4A, 
+  0xCD, 0x7F, 0xB4, 0x6D, 0xA0, 0x71, 0xD8, 0x55, 0x83, 0x38, 0x81, 0x93, 0xD8, 0xE5, 0x97, 0x4B, 0x18, 0xCC, 0x2E, 0x41, 
+  0x07, 0x29, 0xB1, 0x29, 0xC1, 0x0B, 0x82, 0x27, 0x5F, 0x34, 0x79, 0xD5, 0xD2, 0x0D, 0x07, 0xF7, 0x1F, 0xDF, 0xBE, 0x65, 
+  0x1F, 0xAE, 0x40, 0xEA, 0x89, 0xD5, 0xAF, 0x5E, 0xB6, 0xFE, 0xF0, 0xDE, 0x63, 0x7B, 0xB6, 0x1E, 0xA4, 0x9C, 0x4E, 0x09, 
+  0x4F, 0x20, 0xE4, 0x16, 0x67, 0x97, 0xC5, 0x85, 0xC4, 0x08, 0x80, 0x64, 0x15, 0xCA, 0x67, 0xD6, 0x58, 0x6A, 0xC2, 0xA9, 
+  0x86, 0x50, 0x2E, 0x54, 0x46, 0x0A, 0x44, 0xB9, 0xD9, 0x05, 0xD9, 0x29, 0x39, 0x88, 0x3B, 0x70, 0x7E, 0x40, 0x5A, 0x62, 
+  0xFA, 0x60, 0xF7, 0x72, 0x82, 0xB3, 0xDF, 0xEC, 0xF9, 0x71, 0xE1, 0x71, 0x29, 0xB1, 0xA9, 0x04, 0x06, 0x5E, 0x0A, 0x5F, 
+  0xE1, 0x99, 0x2C, 0x1B, 0x18, 0xAC, 0x0E, 0x3C, 0x20, 0xE3, 0xD8, 0xBE, 0x7D, 0xE4, 0x64, 0xD1, 0xAB, 0x16, 0x59, 0xA2, 
+  0x03, 0xB5, 0x77, 0x07, 0xCD, 0xEB, 0x1C, 0x1B, 0xD7, 0x07, 0x9D, 0x66, 0xBA, 0x2B, 0x6E, 0xC0, 0x44, 0x13, 0x4A, 0x6B, 
+  0xE0, 0xC8, 0x5A, 0xBB, 0x60, 0x4E, 0x56, 0xA3, 0x08, 0xE3, 0xB4, 0xDA, 0x4D, 0x4F, 0xD8, 0xD3, 0x19, 0x76, 0xD2, 0x4D, 
+  0x83, 0x39, 0x4E, 0xE2, 0xAF, 0xE9, 0xBF, 0xEB, 0x01, 0xAA, 0x00, 0x4A, 0xD6, 0xDA, 0xD2, 0x26, 0x6D, 0x06, 0xA0, 0x03, 
+  0x45, 0x55, 0x47, 0x46, 0x69, 0x79, 0xA9, 0x71, 0x69, 0xB1, 0xE1, 0x91, 0x17, 0x8E, 0x3B, 0x17, 0xE0, 0xBE, 0xFC, 0xF0, 
+  0xF5, 0x3B, 0x77, 0x5E, 0xBE, 0xB8, 0x7F, 0x4D, 0x43, 0x45, 0x2B, 0x4D, 0x1E, 0x1A, 0x18, 0x6B, 0x87, 0x37, 0xD2, 0x55, 
+  0x25, 0xA3, 0x8D, 0xF2, 0x0B, 0x27, 0x92, 0xF3, 0x09, 0xC3, 0x02, 0xC2, 0x78, 0x26, 0x82, 0xE3, 0x15, 0x00, 0x16, 0xD5, 
+  0x81, 0x82, 0x86, 0xBA, 0x97, 0x8A, 0xA9, 0x28, 0xB7, 0x18, 0xB1, 0x22, 0x62, 0x9E, 0x0C, 0x10, 0x25, 0x45, 0x24, 0x04, 
+  0xCC, 0x09, 0x08, 0x5C, 0xB0, 0xD0, 0x7F, 0xCE, 0xBC, 0xA8, 0x90, 0xB0, 0xE4, 0x98, 0x94, 0x8C, 0xA4, 0x9C, 0x9C, 0xF4, 
+  0x3C, 0x9E, 0xA0, 0x58, 0x34, 0x46, 0x07, 0x56, 0x91, 0x27, 0xCB, 0xFA, 0x2B, 0xA4, 0xEF, 0xE8, 0xC0, 0x49, 0x57, 0x4C, 
+  0xC5, 0x04, 0xA4, 0x08, 0xC8, 0x28, 0xA4, 0xB8, 0x0A, 0x50, 0x99, 0xAA, 0xAC, 0xED, 0xAC, 0x63, 0x24, 0xAE, 0x1A, 0xBB, 
+  0xB6, 0x41, 0xD5, 0x1A, 0xBB, 0xB5, 0xF4, 0x31, 0x17, 0xA7, 0x14, 0xBD, 0x86, 0x01, 0xAB, 0x00, 0xDB, 0x82, 0xE7, 0x02, 
+  0xD4, 0xB6, 0xD8, 0x5A, 0x9C, 0x59, 0x84, 0x1F, 0xA4, 0xC5, 0x65, 0x26, 0x44, 0xC5, 0xCD, 0x98, 0x36, 0xFD, 0xD2, 0x89, 
+  0x53, 0xD6, 0x0E, 0x6F, 0xC5, 0x15, 0xD6, 0xAD, 0xBA, 0xAC, 0xA1, 0xAA, 0xA3, 0x2C, 0xBB, 0x12, 0xE4, 0xA1, 0x88, 0x6D, 
+  0x2C, 0x6E, 0xC8, 0x4B, 0xCC, 0x0E, 0xF4, 0xF5, 0xAF, 0x29, 0x6B, 0xC8, 0xCF, 0x2A, 0x00, 0x55, 0xB2, 0x13, 0xB3, 0xF8, 
+  0xC3, 0xFC, 0x4C, 0x31, 0x3A, 0x8B, 0x0C, 0x64, 0x2C, 0x2C, 0xAB, 0x03, 0x1E, 0x47, 0xB8, 0xAA, 0x03, 0x30, 0x07, 0x4D, 
+  0x27, 0x44, 0x26, 0xC6, 0x84, 0xC6, 0x80, 0x4B, 0x78, 0x40, 0x46, 0x62, 0x86, 0x04, 0xE4, 0x94, 0x5C, 0x79, 0x9D, 0xAC, 
+  0x42, 0x55, 0x83, 0xFA, 0x81, 0x17, 0xD9, 0xFF, 0x7F, 0x28, 0x80, 0xD7, 0xF1, 0x31, 0x68, 0xBE, 0xA8, 0xB9, 0xBA, 0x8B, 
+  0xA5, 0x56, 0x6F, 0x96, 0x8B, 0x2D, 0x6E, 0xC5, 0xE4, 0xCD, 0x64, 0x2C, 0xB2, 0x7B, 0xA7, 0x1F, 0x5E, 0x59, 0x8F, 0x54, 
+  0x58, 0x2E, 0xE6, 0x58, 0x63, 0xB7, 0x51, 0x57, 0x5D, 0xC1, 0x8A, 0x5E, 0x15, 0xE0, 0x74, 0x6F, 0xDC, 0x2E, 0x3C, 0xA9, 
+  0x24, 0x3A, 0x10, 0x83, 0xCD, 0x71, 0xB0, 0x22, 0x3F, 0x23, 0x3F, 0x33, 0x29, 0x53, 0xF0, 0x3A, 0x20, 0xF8, 0x6B, 0x67, 
+  0x9D, 0x8D, 0x8B, 0xEC, 0xDB, 0x73, 0xD5, 0xE6, 0xF5, 0x7B, 0x69, 0xE2, 0x66, 0xC6, 0xE5, 0x25, 0x85, 0x25, 0xE5, 0xA6, 
+  0x16, 0x90, 0xB7, 0xC4, 0x87, 0xC6, 0xFA, 0xCD, 0xF7, 0xAF, 0x2B, 0x6B, 0xCC, 0xCD, 0xC8, 0x0B, 0x5A, 0xB0, 0x30, 0x3D, 
+  0x21, 0x03, 0x84, 0x11, 0x44, 0xCA, 0x2C, 0x19, 0x93, 0x59, 0x2A, 0x70, 0x3B, 0x7E, 0x96, 0x53, 0x8C, 0x7C, 0x0B, 0x53, 
+  0xF3, 0x79, 0x32, 0x12, 0x4F, 0x4F, 0x48, 0xC7, 0x21, 0xD2, 0xE2, 0xD3, 0x32, 0x12, 0x33, 0xB9, 0xCB, 0x83, 0xF9, 0xA9, 
+  0x79, 0xF8, 0x13, 0x0A, 0x50, 0x38, 0xF2, 0xEA, 0xE0, 0x94, 0xD2, 0xB7, 0x68, 0x73, 0xF2, 0x85, 0x7A, 0x92, 0x2E, 0x1F, 
+  0xB1, 0xEE, 0xEA, 0x45, 0x2D, 0x95, 0x48, 0xDF, 0x69, 0x15, 0xC8, 0x23, 0x06, 0xC4, 0xAD, 0x51, 0x9F, 0x7C, 0xA1, 0x71, 
+  0x55, 0x71, 0xC6, 0xBB, 0xAC, 0xAC, 0xAD, 0xBD, 0x5B, 0xB8, 0xF7, 0x4A, 0x5F, 0x11, 0x7F, 0x8C, 0x02, 0xA4, 0x6B, 0x46, 
+  0xFF, 0x80, 0xF9, 0x9F, 0xA0, 0x90, 0xB4, 0x10, 0x00, 0x74, 0x89, 0x07, 0xB4, 0x18, 0x35, 0x66, 0x66, 0x16, 0x60, 0x86, 
+  0x99, 0x49, 0x59, 0x49, 0xD1, 0x49, 0x58, 0xE8, 0xF8, 0x8B, 0x2E, 0xF6, 0x9B, 0xB3, 0x60, 0xC3, 0x9A, 0x9D, 0xDB, 0xB6, 
+  0x1D, 0xEC, 0xEF, 0x5E, 0x91, 0x9F, 0x5E, 0x94, 0x14, 0x91, 0x9C, 0x14, 0x9B, 0x92, 0x18, 0x93, 0x44, 0x42, 0xE9, 0x37, 
+  0xC7, 0xBF, 0xBE, 0xB2, 0x99, 0xE7, 0x2F, 0x9C, 0xE7, 0x8F, 0x28, 0x11, 0x22, 0xD7, 0xDE, 0x94, 0x66, 0x0C, 0x76, 0x0B, 
+  0x16, 0xE5, 0x18, 0x84, 0x49, 0x2B, 0x20, 0xF9, 0xC1, 0xE4, 0xB3, 0x92, 0x72, 0xB3, 0x52, 0x73, 0xE4, 0x16, 0x05, 0xA4, 
+  0x01, 0x44, 0xB9, 0x68, 0xD1, 0xC5, 0xA2, 0xB1, 0x7E, 0x20, 0x40, 0xE7, 0xE2, 0xFB, 0xFF, 0x47, 0xD1, 0x8F, 0xE8, 0xC0, 
+  0x89, 0x9C, 0x0A, 0xEB, 0xA6, 0x44, 0xE2, 0x11, 0x1D, 0x2A, 0xE9, 0xAF, 0x4E, 0x16, 0xB4, 0x83, 0xF2, 0x66, 0xE8, 0xE1, 
+  0x0C, 0x40, 0x6C, 0x63, 0xC7, 0x98, 0xB6, 0x85, 0x7B, 0x6F, 0x7F, 0x78, 0x8C, 0xD0, 0x75, 0x14, 0xE5, 0xF4, 0x8D, 0xDD, 
+  0xFE, 0xA5, 0x54, 0x64, 0x66, 0x2C, 0x65, 0xDB, 0xC2, 0x9A, 0x14, 0x09, 0x5E, 0x67, 0x17, 0x23, 0xC1, 0x82, 0xB4, 0x3C, 
+  0x24, 0x42, 0x58, 0x46, 0x07, 0xF3, 0x7D, 0xE7, 0x8D, 0x3B, 0xE7, 0x5C, 0x42, 0xF1, 0xDE, 0x5D, 0x57, 0x0F, 0x2F, 0xDB, 
+  0x44, 0xD9, 0x15, 0x1B, 0x11, 0x07, 0xFA, 0x93, 0x50, 0x86, 0x2F, 0x0C, 0x27, 0x90, 0xD6, 0x96, 0x37, 0x62, 0xBC, 0x01, 
+  0x73, 0xE7, 0x63, 0xCB, 0x59, 0xC9, 0x59, 0x1A, 0x15, 0xBE, 0x02, 0xC7, 0x89, 0x16, 0xFC, 0x56, 0xCD, 0x1C, 0x59, 0xA3, 
+  0x33, 0xFE, 0x44, 0x57, 0x6E, 0x5A, 0xAE, 0x64, 0xA5, 0x6E, 0x62, 0xCA, 0x73, 0xBC, 0x82, 0x56, 0x27, 0xF8, 0x6A, 0x1D, 
+  0x78, 0x0D, 0x5F, 0xAF, 0xE5, 0xE3, 0x98, 0xE5, 0xE3, 0x88, 0xDB, 0x9B, 0xA7, 0x8F, 0x1E, 0xB4, 0x5A, 0x33, 0x1F, 0x03, 
+  0xE5, 0x84, 0x41, 0xFB, 0x48, 0x7D, 0xB9, 0x93, 0x53, 0xDA, 0x47, 0x46, 0x4B, 0x9C, 0x6C, 0xA7, 0x55, 0x67, 0x4F, 0x32, 
+  0x08, 0x94, 0xD6, 0x8D, 0x3C, 0x62, 0xD3, 0x50, 0x9D, 0x8C, 0xEB, 0x68, 0x50, 0xEA, 0x32, 0x1A, 0x6A, 0x8C, 0x67, 0xCD, 
+  0xFC, 0x8F, 0xE2, 0xC0, 0xAB, 0x83, 0xBC, 0xF4, 0x3C, 0xC4, 0x4A, 0xCF, 0x20, 0x21, 0x2C, 0x2E, 0x6C, 0x61, 0xC8, 0xB9, 
+  0xE7, 0x9C, 0x9D, 0x14, 0x9D, 0xBC, 0x75, 0xE3, 0xBE, 0x55, 0x2B, 0xB6, 0xD5, 0x55, 0xB4, 0x88, 0x0E, 0xFC, 0x82, 0xC8, 
+  0xEE, 0xC3, 0x16, 0x06, 0xF9, 0xCF, 0x9A, 0x07, 0x16, 0x65, 0xA5, 0x66, 0x13, 0x54, 0x0D, 0xA0, 0x67, 0x22, 0x4A, 0x93, 
+  0x20, 0x09, 0x86, 0x78, 0x8B, 0x2C, 0x27, 0x9C, 0xE6, 0x95, 0x14, 0xE4, 0x22, 0x47, 0xA4, 0x23, 0x72, 0x31, 0xB5, 0x98, 
+  0xA8, 0x21, 0x37, 0x03, 0xDB, 0x97, 0x50, 0xEC, 0x66, 0x44, 0xFC, 0xD6, 0x51, 0xA4, 0x57, 0xE8, 0x56, 0xC4, 0xA7, 0x7C, 
+  0x50, 0x25, 0x6E, 0x9F, 0xA3, 0x6A, 0x1E, 0xD1, 0x81, 0x62, 0x0E, 0x53, 0x3D, 0x64, 0xAD, 0xB7, 0x63, 0x64, 0xED, 0xB5, 
+  0x74, 0x06, 0x7E, 0xDE, 0x3A, 0x76, 0xCC, 0x18, 0xC4, 0x62, 0xBA, 0x17, 0xDC, 0xC9, 0x70, 0x90, 0xBE, 0xF6, 0xCB, 0xB8, 
+  0x90, 0xAE, 0x7D, 0x69, 0x9D, 0x36, 0xEB, 0x1B, 0x8A, 0x45, 0x2B, 0x2C, 0x6D, 0xE5, 0xEB, 0x54, 0xD6, 0x19, 0xC9, 0x32, 
+  0x0D, 0x2F, 0x94, 0x4E, 0x8E, 0x69, 0xC1, 0x4B, 0xD5, 0xA3, 0x79, 0x11, 0x82, 0x50, 0xA4, 0x4E, 0x8E, 0x4C, 0x8C, 0x0C, 
+  0x8A, 0x9A, 0x3C, 0xE9, 0x92, 0x4B, 0x26, 0x4E, 0xA6, 0x44, 0x58, 0xBF, 0x7A, 0x27, 0xAD, 0xAD, 0xE4, 0x84, 0x74, 0x14, 
+  0x10, 0x1B, 0x1C, 0x83, 0x7A, 0xFC, 0x66, 0xCF, 0xAD, 0x28, 0xAD, 0xCB, 0x4C, 0xCF, 0xC1, 0x21, 0xC0, 0x2E, 0xFE, 0x04, 
+  0xE5, 0x29, 0x1C, 0xA9, 0x98, 0xBC, 0xB1, 0x54, 0x5E, 0x3F, 0x8F, 0xD4, 0xA8, 0xA4, 0x24, 0xAB, 0x54, 0x75, 0xA0, 0x0B, 
+  0x49, 0x89, 0xEB, 0xA4, 0xCB, 0xAD, 0x2B, 0x44, 0x44, 0x59, 0x48, 0x76, 0x30, 0xC6, 0x15, 0xAC, 0xE8, 0x4F, 0xB6, 0x77, 
+  0xAF, 0xE8, 0xED, 0x2B, 0xDB, 0xD7, 0xE7, 0x13, 0xF9, 0x78, 0x2D, 0xF7, 0xE4, 0xA4, 0x65, 0xAC, 0xED, 0x33, 0x69, 0x72, 
+  0x27, 0x7F, 0x1E, 0x89, 0x3B, 0x49, 0xBD, 0xDA, 0xB5, 0xDA, 0xB2, 0x6B, 0xD7, 0x46, 0xCA, 0x46, 0xB2, 0xD2, 0x7A, 0xB3, 
+  0x13, 0x70, 0xD7, 0xE4, 0xF1, 0x00, 0x79, 0x7E, 0xB1, 0x51, 0x92, 0x7A, 0x83, 0x27, 0x20, 0x4B, 0x63, 0x27, 0xAF, 0x46, 
+  0x5B, 0x8C, 0x58, 0xAB, 0x48, 0x27, 0x2D, 0x3F, 0x37, 0x39, 0x27, 0x3D, 0x29, 0x23, 0x39, 0x26, 0x39, 0x26, 0x08, 0xD0, 
+  0x5F, 0x70, 0xD6, 0x59, 0x67, 0x81, 0x39, 0xBB, 0xB6, 0x5C, 0xDE, 0xB7, 0x68, 0x38, 0x23, 0x39, 0x2B, 0xC4, 0x2F, 0x24, 
+  0xD4, 0x3F, 0x34, 0xD8, 0x2F, 0xD0, 0x6F, 0xC6, 0xFC, 0xC2, 0xBC, 0x4A, 0x70, 0x7C, 0x81, 0xEF, 0x1C, 0x74, 0x80, 0xEB, 
+  0x00, 0x47, 0x36, 0xBB, 0x1F, 0xD1, 0xC1, 0xA8, 0xCE, 0x41, 0x69, 0x91, 0xAB, 0x03, 0xFE, 0x97, 0x2A, 0x43, 0x2F, 0xDC, 
+  0x35, 0x12, 0x48, 0x6D, 0x7A, 0xAA, 0xD2, 0xF7, 0xFA, 0x81, 0xD7, 0xE4, 0xF5, 0x71, 0xAF, 0xD5, 0x7B, 0xB5, 0xAB, 0x8F, 
+  0xFB, 0xD8, 0xFC, 0xC4, 0xD6, 0xA8, 0x63, 0x2C, 0x5D, 0xEE, 0x96, 0x37, 0xE9, 0xD3, 0x90, 0x11, 0x95, 0x94, 0xC8, 0x5A, 
+  0x99, 0x1D, 0xBA, 0x30, 0xE4, 0x62, 0x43, 0xB3, 0x51, 0x3C, 0x31, 0xA4, 0x1A, 0x2E, 0x18, 0x70, 0x2B, 0xBB, 0xC6, 0x3B, 
+  0x7A, 0x55, 0xF6, 0x87, 0xCC, 0x63, 0xE5, 0xB6, 0x41, 0x56, 0x71, 0x4B, 0x23, 0x3A, 0x28, 0x6B, 0x94, 0x97, 0xE2, 0x5A, 
+  0x5F, 0xC4, 0x74, 0xAA, 0x69, 0x6A, 0x6A, 0xA3, 0xC2, 0xD6, 0x50, 0x0C, 0x0F, 0x88, 0x96, 0x84, 0xE5, 0x94, 0xF8, 0x54, 
+  0xEA, 0xA6, 0xD0, 0x80, 0xE0, 0xF3, 0xCE, 0x1D, 0x17, 0x11, 0x16, 0xB9, 0x69, 0xDD, 0x9E, 0x25, 0x03, 0x6B, 0x29, 0x74, 
+  0x83, 0xFD, 0x43, 0x28, 0xAF, 0x42, 0x03, 0x02, 0xE7, 0xCE, 0x98, 0x2D, 0x30, 0x92, 0x99, 0xBF, 0xC0, 0x77, 0x1E, 0x78, 
+  0x45, 0x58, 0xE6, 0xAF, 0xB2, 0xD3, 0x0C, 0x1C, 0x65, 0x8A, 0x4B, 0x8D, 0x24, 0x48, 0xD9, 0x4E, 0x7E, 0x69, 0x73, 0x1B, 
+  0x57, 0xBE, 0x82, 0x4B, 0xBA, 0x8A, 0x1D, 0x65, 0x88, 0x40, 0x71, 0x02, 0xAF, 0xB1, 0xAB, 0x0E, 0xAC, 0xDC, 0xBD, 0x96, 
+  0x7E, 0xB2, 0xE8, 0xAD, 0x6F, 0xA9, 0x87, 0xE9, 0x12, 0x1D, 0x78, 0xB1, 0xDB, 0x5E, 0x8F, 0x0D, 0xA1, 0x65, 0x0C, 0x40, 
+  0x64, 0x06, 0x22, 0x9D, 0x1C, 0xCF, 0x14, 0x50, 0x3B, 0xFB, 0xCE, 0x20, 0x10, 0x33, 0x77, 0xE9, 0x4D, 0x1A, 0x5A, 0x2D, 
+  0xC5, 0x43, 0xE9, 0x37, 0xF2, 0x4C, 0x77, 0x12, 0x5B, 0x5B, 0x04, 0xF8, 0x38, 0x42, 0x17, 0x05, 0x57, 0x34, 0x33, 0xE7, 
+  0x6A, 0x2E, 0x55, 0xEA, 0x4E, 0x23, 0x4B, 0x27, 0x5C, 0x84, 0x04, 0x74, 0xA0, 0x7E, 0x80, 0x91, 0x6A, 0x6A, 0xC4, 0x44, 
+  0x05, 0x88, 0x4F, 0x8C, 0x8E, 0x07, 0x79, 0xA6, 0x5D, 0x32, 0x75, 0xD2, 0x84, 0x4B, 0x96, 0xF6, 0xAF, 0x5A, 0xB1, 0x74, 
+  0x33, 0x4D, 0xBD, 0xB0, 0xC0, 0xF0, 0xC0, 0xD9, 0x01, 0xE4, 0x42, 0x73, 0x67, 0xF9, 0xA6, 0x27, 0xA5, 0x91, 0x6B, 0xCE, 
+  0x9F, 0x8D, 0x1F, 0x88, 0x0E, 0xB4, 0xD3, 0x20, 0x89, 0x8D, 0x80, 0xBE, 0x13, 0x15, 0x24, 0x96, 0xE6, 0x38, 0xBD, 0x0A, 
+  0x47, 0x07, 0xD9, 0x65, 0xA3, 0x81, 0x65, 0x04, 0xC7, 0xFF, 0x9F, 0x70, 0xE6, 0x14, 0xB0, 0x93, 0xE9, 0x08, 0xDD, 0xC9, 
+  0x6E, 0xD3, 0x9D, 0xC8, 0xEF, 0x33, 0x06, 0xC4, 0x2D, 0x92, 0xB8, 0x78, 0x22, 0xB1, 0xD4, 0x44, 0x54, 0x49, 0x1C, 0x47, 
+  0x40, 0xC6, 0x60, 0xB7, 0xA2, 0xB9, 0xFC, 0x09, 0xE6, 0x5C, 0x64, 0x84, 0x5E, 0x2C, 0x11, 0xB5, 0x86, 0xA9, 0x08, 0x13, 
+  0x92, 0xA2, 0x06, 0x87, 0x53, 0xE6, 0x0E, 0xAA, 0x34, 0xDB, 0x71, 0xA6, 0x86, 0x85, 0x32, 0xC9, 0x72, 0x66, 0xE8, 0x55, 
+  0x4D, 0xCD, 0x95, 0x4D, 0x4A, 0x68, 0x68, 0xAB, 0x90, 0xB9, 0x0D, 0x2F, 0x68, 0xFA, 0x45, 0x75, 0xD5, 0xC5, 0x0D, 0x36, 
+  0x35, 0xD2, 0x96, 0x4E, 0x1E, 0x3D, 0xFC, 0xE4, 0x6C, 0x52, 0x1D, 0x10, 0x26, 0x2A, 0x54, 0xE0, 0xE8, 0xEC, 0xB3, 0xCF, 
+  0xAC, 0x2E, 0xAD, 0x5F, 0xBF, 0x72, 0x7B, 0x6D, 0x79, 0x73, 0x64, 0x48, 0x14, 0xF9, 0x52, 0xC0, 0x3C, 0xFF, 0x39, 0x33, 
+  0x66, 0x27, 0xC5, 0x26, 0x17, 0xE6, 0x14, 0xA3, 0x8C, 0xC4, 0xA8, 0x44, 0xF5, 0x03, 0x70, 0x4C, 0xB2, 0xA3, 0xAC, 0x82, 
+  0x11, 0x35, 0x10, 0x87, 0x4D, 0xF3, 0xF2, 0xA4, 0xC4, 0xC6, 0xD1, 0xD3, 0x29, 0xE5, 0x6E, 0x5D, 0xE1, 0x94, 0xE6, 0x3F, 
+  0xC6, 0x15, 0xAC, 0xBD, 0xE7, 0x19, 0x1D, 0xA8, 0x02, 0xA4, 0xD6, 0x4B, 0x95, 0xBC, 0x8B, 0x0B, 0x47, 0x07, 0xA3, 0x41, 
+  0x7C, 0x24, 0x4B, 0x71, 0x72, 0x76, 0x9D, 0x77, 0xAB, 0x1A, 0x4A, 0x64, 0xF4, 0x6A, 0x96, 0x63, 0xAA, 0x9A, 0x4A, 0xBA, 
+  0x1E, 0x20, 0xD7, 0xD2, 0x9A, 0x97, 0x21, 0x09, 0x0D, 0x1F, 0x67, 0x52, 0xE8, 0x10, 0xCD, 0x0A, 0xC5, 0xAE, 0xAB, 0x0B, 
+  0x1C, 0xDE, 0x99, 0x0E, 0x63, 0xC9, 0x7F, 0x18, 0x52, 0x32, 0xEF, 0x85, 0xCF, 0x03, 0xAB, 0x07, 0x36, 0x5C, 0x6B, 0x35, 
+  0x3E, 0x21, 0xFC, 0x06, 0x69, 0x5A, 0x98, 0xBE, 0xA9, 0x36, 0x23, 0x25, 0x2C, 0xE7, 0xD8, 0xB0, 0x4C, 0x48, 0x48, 0x89, 
+  0x0D, 0x8F, 0x0E, 0x0F, 0x0C, 0x05, 0x8E, 0x50, 0xC6, 0xFA, 0x95, 0x5B, 0x69, 0x38, 0xC6, 0x84, 0xC7, 0xA2, 0x15, 0xE0, 
+  0x68, 0xDE, 0xCC, 0x39, 0x09, 0xD1, 0x89, 0x78, 0xC6, 0xBC, 0x59, 0x73, 0xD1, 0x01, 0x75, 0x2F, 0xA9, 0x11, 0x61, 0x99, 
+  0x7E, 0x83, 0x11, 0x8A, 0x24, 0x48, 0x92, 0xAE, 0xA0, 0x80, 0x3C, 0x51, 0x83, 0xF5, 0x0C, 0xD7, 0x09, 0xBE, 0x4A, 0x07, 
+  0x5E, 0xC5, 0x8C, 0xB1, 0x77, 0x3C, 0x75, 0x0C, 0xE2, 0xF3, 0xBF, 0xCC, 0x12, 0xAB, 0xD7, 0x94, 0xD7, 0x2E, 0xBD, 0xEB, 
+  0xE3, 0xA5, 0x8C, 0x69, 0xB7, 0x52, 0xA4, 0xEC, 0x30, 0xC8, 0x4C, 0x9A, 0xE8, 0xE6, 0xEC, 0x16, 0x5E, 0xEC, 0x85, 0x2A, 
+  0x43, 0x53, 0x49, 0xB1, 0x6E, 0x43, 0x34, 0x53, 0xDB, 0xB7, 0x9C, 0x03, 0x1D, 0x79, 0x33, 0x2D, 0xB1, 0xCC, 0x32, 0xEC, 
+  0x9A, 0x6B, 0xA6, 0x31, 0xC4, 0x5B, 0x78, 0x3B, 0xF9, 0xA9, 0x05, 0xCC, 0x6F, 0xCB, 0x33, 0x2B, 0x84, 0xD3, 0xE9, 0x70, 
+  0xDC, 0x20, 0x16, 0xB6, 0x42, 0x2C, 0x04, 0xA0, 0x4C, 0xFB, 0x9A, 0x59, 0x39, 0xE3, 0x40, 0x99, 0x73, 0x01, 0xE5, 0xF2, 
+  0xBE, 0x13, 0xB3, 0xB3, 0x13, 0x33, 0x4D, 0x48, 0x88, 0x8F, 0x0C, 0x8A, 0xBC, 0x74, 0xD2, 0x25, 0x53, 0xA7, 0x5C, 0x3A, 
+  0xBC, 0x64, 0xE3, 0xA2, 0xF6, 0x25, 0x74, 0x98, 0x49, 0x84, 0xA8, 0x8D, 0xE7, 0xCD, 0xF4, 0x8D, 0x8B, 0x8C, 0x2F, 0x2B, 
+  0xAC, 0xE0, 0x82, 0xBA, 0x3A, 0xC9, 0x94, 0xBB, 0xF8, 0x81, 0x18, 0x20, 0x73, 0x18, 0xB7, 0x50, 0x10, 0x89, 0x3B, 0x0A, 
+  0x00, 0x9D, 0x1C, 0x80, 0x32, 0x6A, 0x18, 0x05, 0xFA, 0xE2, 0x7F, 0x63, 0x1E, 0x71, 0x73, 0xA7, 0x93, 0x30, 0x47, 0xC4, 
+  0x3D, 0x66, 0x9D, 0x2C, 0x7D, 0xAB, 0x06, 0x5C, 0xC1, 0x07, 0x03, 0x57, 0x5C, 0xB6, 0x8C, 0x49, 0x2E, 0x14, 0x8B, 0x35, 
+  0xB4, 0x8E, 0x30, 0x58, 0x9D, 0xAC, 0xC6, 0xF0, 0x58, 0xDD, 0x52, 0xD6, 0x78, 0x80, 0x4C, 0xA9, 0x0C, 0x9F, 0xB2, 0x1A, 
+  0x14, 0xB2, 0xDC, 0x4A, 0x2F, 0xA9, 0x4F, 0x19, 0x4E, 0x3A, 0xDA, 0x26, 0xD7, 0xA4, 0xF7, 0x40, 0xC2, 0x87, 0x0E, 0xBA, 
+  0x1A, 0x16, 0x7D, 0xFB, 0x5B, 0xDF, 0x7B, 0xEC, 0x91, 0x27, 0xE1, 0x22, 0xD2, 0xE8, 0x6F, 0xAD, 0x6C, 0x66, 0xFE, 0x0E, 
+  0x17, 0x48, 0x18, 0x86, 0x35, 0xC2, 0xA2, 0x50, 0x35, 0xC8, 0xD0, 0xB1, 0x00, 0x6F, 0x10, 0x57, 0x40, 0x1C, 0x54, 0x4C, 
+  0x00, 0x0B, 0xDD, 0x4D, 0x46, 0x5D, 0x94, 0xC4, 0x20, 0xFE, 0xF9, 0xE3, 0xCE, 0xEB, 0x6E, 0xEB, 0x5F, 0xD2, 0xB7, 0x32, 
+  0x39, 0x2E, 0x15, 0x1D, 0x90, 0x17, 0x05, 0xCC, 0xF5, 0x23, 0x3E, 0x57, 0x95, 0xD4, 0x2D, 0x98, 0x33, 0x9B, 0xAA, 0x0D, 
+  0x3F, 0x40, 0x6D, 0x1A, 0x93, 0x09, 0xD4, 0xC0, 0xD1, 0x29, 0x33, 0x7A, 0x42, 0x8E, 0xC7, 0x0F, 0x46, 0x45, 0x02, 0xF0, 
+  0xA7, 0x38, 0xDD, 0x24, 0xAC, 0x9E, 0xE4, 0xD5, 0x9A, 0xBC, 0x26, 0x3F, 0xBA, 0x4C, 0xF6, 0x25, 0x8B, 0xC2, 0x82, 0xB7, 
+  0xEA, 0x35, 0x7C, 0xAF, 0xE8, 0x6D, 0x0D, 0xE8, 0xA3, 0x48, 0x62, 0x15, 0x00, 0x83, 0xD5, 0x31, 0x73, 0x37, 0xA2, 0x0A, 
+  0xB6, 0x18, 0x03, 0x77, 0xC8, 0xC3, 0x5C, 0x1B, 0x16, 0x31, 0xE2, 0x36, 0x78, 0x2D, 0x90, 0xCD, 0x35, 0x62, 0x12, 0x4B, 
+  0x2F, 0x32, 0x0E, 0x61, 0xC8, 0x36, 0x60, 0x08, 0xB0, 0x03, 0xCF, 0x00, 0xB9, 0x1B, 0x72, 0x47, 0xB5, 0xE9, 0xBE, 0x49, 
+  0x73, 0x86, 0x14, 0x13, 0x1D, 0x30, 0x68, 0x64, 0xBD, 0xF7, 0x93, 0x5F, 0x31, 0x05, 0xFE, 0xDB, 0xDF, 0xFE, 0xB6, 0x67, 
+  0xFB, 0x81, 0xDC, 0xA4, 0xAC, 0xD6, 0xAA, 0xA6, 0xEE, 0xA6, 0x45, 0xB0, 0x51, 0xA0, 0x12, 0x09, 0xE3, 0xB3, 0xA6, 0xB5, 
+  0xB9, 0x52, 0xF2, 0x5A, 0x5E, 0x93, 0xE0, 0xCC, 0x18, 0x00, 0x88, 0x47, 0x88, 0x84, 0x04, 0xEC, 0x9A, 0x0C, 0x95, 0x6A, 
+  0x20, 0x30, 0x60, 0xE1, 0xB8, 0x73, 0xBF, 0x56, 0x98, 0x57, 0xBA, 0x6E, 0xC5, 0x96, 0x8C, 0xE4, 0x4C, 0x12, 0x21, 0x32, 
+  0x54, 0x4A, 0x65, 0xFF, 0xB9, 0x7E, 0x55, 0xA5, 0x35, 0x81, 0xF3, 0xFD, 0xC8, 0xA0, 0x88, 0x1F, 0x34, 0x9A, 0x32, 0x52, 
+  0xF3, 0x0A, 0x92, 0x51, 0x03, 0xAE, 0x90, 0xCF, 0x48, 0x6E, 0x94, 0x1A, 0x46, 0xA4, 0xEF, 0xE4, 0x9A, 0xA0, 0x8A, 0x9B, 
+  0x74, 0x4A, 0x5E, 0x04, 0xB1, 0x45, 0x25, 0xCE, 0x1F, 0x8E, 0x29, 0x20, 0x2C, 0xCA, 0x8B, 0x0E, 0xD2, 0x51, 0x86, 0x2A, 
+  0x20, 0x9F, 0xE6, 0x15, 0x82, 0xB6, 0xF8, 0x63, 0xAB, 0x6E, 0x4F, 0xF9, 0x2D, 0x21, 0x41, 0x74, 0x50, 0x53, 0xC8, 0x32, 
+  0x48, 0x22, 0x04, 0xA6, 0x3A, 0x8C, 0x5A, 0xB9, 0x92, 0xC8, 0xDA, 0x06, 0x55, 0xD5, 0xC4, 0x08, 0x8B, 0xD8, 0x25, 0x25, 
+  0x8C, 0xE1, 0x9A, 0x19, 0x82, 0x5F, 0xBD, 0x0E, 0x0B, 0x45, 0x25, 0xF9, 0xD2, 0x74, 0x33, 0xC4, 0x02, 0xE8, 0x08, 0xDA, 
+  0x1D, 0x73, 0xE6, 0xE6, 0x89, 0x21, 0x71, 0x8C, 0x21, 0x53, 0x22, 0x92, 0x0A, 0x52, 0x0A, 0x5E, 0xFE, 0xE6, 0x6B, 0x42, 
+  0xD5, 0x3A, 0xF1, 0xC5, 0xDD, 0xB7, 0xDE, 0xCF, 0x27, 0xA4, 0xF1, 0xD9, 0xD7, 0xDC, 0xD3, 0xDB, 0xD4, 0xAD, 0x3C, 0x51, 
+  0x82, 0x04, 0xD1, 0x82, 0x98, 0x41, 0xE4, 0xC0, 0x87, 0x98, 0xA6, 0x91, 0x2C, 0x62, 0x5F, 0xE8, 0x20, 0x35, 0x3A, 0x05, 
+  0x1B, 0x8F, 0x08, 0x0E, 0xA7, 0x77, 0x84, 0x43, 0x6C, 0x5E, 0xBB, 0x3D, 0x27, 0x2B, 0x9F, 0x00, 0x10, 0x15, 0x12, 0x91, 
+  0x1C, 0x9B, 0xE8, 0x3F, 0x67, 0x4E, 0x79, 0x51, 0x65, 0x68, 0x70, 0x08, 0x61, 0x83, 0xB6, 0x1D, 0xF5, 0x81, 0xC6, 0x64, 
+  0x45, 0x86, 0x12, 0x4F, 0xE1, 0xAA, 0xCA, 0xB0, 0x91, 0x76, 0x54, 0xF6, 0x99, 0x63, 0x1E, 0x4F, 0x1F, 0x29, 0x6B, 0x6D, 
+  0x9B, 0x61, 0x34, 0xE0, 0x38, 0x85, 0xB4, 0xED, 0x73, 0x8C, 0xC1, 0xFD, 0x31, 0x0A, 0x90, 0xC8, 0x94, 0x9A, 0xAB, 0xB7, 
+  0x3E, 0x0A, 0x26, 0x2A, 0x6B, 0x3E, 0xA4, 0xC3, 0x98, 0x14, 0x9A, 0xBC, 0x61, 0xAA, 0x16, 0x55, 0x6B, 0xEF, 0xCC, 0xD5, 
+  0x8A, 0x4B, 0x9F, 0x77, 0x29, 0xDD, 0x3C, 0x0E, 0x0F, 0x50, 0x7F, 0xAB, 0x14, 0x57, 0x99, 0xD0, 0xE6, 0x57, 0x01, 0x1D, 
+  0xA6, 0xDD, 0x26, 0x94, 0x1B, 0xA1, 0x11, 0x14, 0x94, 0x79, 0xC7, 0x55, 0xBC, 0x3F, 0x46, 0xF3, 0x99, 0xF1, 0x19, 0x5B, 
+  0xD6, 0xED, 0xE6, 0x96, 0x11, 0xF1, 0x03, 0x77, 0x3F, 0x84, 0x0E, 0xD0, 0xC4, 0xAB, 0x2F, 0xBF, 0xD2, 0x5C, 0xDD, 0xC6, 
+  0x10, 0xB8, 0xA7, 0x79, 0x11, 0xEC, 0xD2, 0xEE, 0x56, 0x51, 0x06, 0x3E, 0x81, 0x43, 0x34, 0x95, 0x89, 0x1A, 0x08, 0x21, 
+  0x4C, 0x28, 0x69, 0x24, 0x64, 0xA6, 0x64, 0xF3, 0xB7, 0xC9, 0x51, 0xF1, 0xD1, 0xA1, 0x91, 0xB3, 0xA6, 0x4D, 0x9F, 0x3B, 
+  0x73, 0xCE, 0xFA, 0xB5, 0x3B, 0x4B, 0xF3, 0x2B, 0xE7, 0xCF, 0x9C, 0x9F, 0x16, 0x93, 0x52, 0x5D, 0x58, 0x19, 0xEE, 0x1F, 
+  0x5C, 0x90, 0x55, 0x92, 0x48, 0xFB, 0x39, 0x24, 0x82, 0x71, 0x3C, 0x33, 0x61, 0x6D, 0x19, 0x49, 0x40, 0x46, 0xA6, 0x19, 
+  0x23, 0x85, 0x95, 0x88, 0x55, 0xE1, 0x5E, 0x4A, 0x87, 0xB1, 0x10, 0x54, 0x92, 0xE1, 0xB4, 0x77, 0x9C, 0x82, 0xCB, 0x60, 
+  0xD1, 0x28, 0xDB, 0x37, 0x79, 0x8E, 0x9A, 0xFC, 0xC9, 0xD0, 0xFF, 0x65, 0xD2, 0x47, 0x01, 0xBA, 0x7C, 0x14, 0xBE, 0xD5, 
+  0x9C, 0xAD, 0x28, 0x9D, 0x88, 0x6A, 0xC0, 0xDD, 0x5D, 0xD5, 0x34, 0x0F, 0xBC, 0x91, 0xD6, 0xA5, 0x29, 0x38, 0x34, 0x6E, 
+  0x05, 0x1F, 0x9D, 0x95, 0x6B, 0x24, 0x50, 0x0F, 0x90, 0x94, 0xA6, 0x40, 0x9A, 0x6E, 0x26, 0xFF, 0x2B, 0x36, 0x55, 0x7E, 
+  0x01, 0xB8, 0x4C, 0xB2, 0x38, 0xEF, 0xD2, 0x59, 0xB9, 0xC9, 0x79, 0xFB, 0x77, 0x1E, 0x26, 0x14, 0xC7, 0x2C, 0x8C, 0x3A, 
+  0xB8, 0xF3, 0x88, 0x92, 0x76, 0x7F, 0xF7, 0x9B, 0xDF, 0x5E, 0xB6, 0x79, 0x07, 0x41, 0x18, 0xA1, 0xF7, 0xB5, 0x2D, 0x82, 
+  0xC0, 0xD2, 0xD7, 0xDA, 0x0B, 0x40, 0x75, 0xD6, 0xD2, 0x40, 0x14, 0xBE, 0x2D, 0x04, 0x0B, 0x58, 0x40, 0x78, 0x3A, 0xAE, 
+  0x40, 0xFF, 0x2E, 0x3E, 0x32, 0x36, 0x60, 0xFE, 0x82, 0xC9, 0x17, 0x4F, 0x58, 0xB7, 0x62, 0x1B, 0xC9, 0x6E, 0xB0, 0x6F, 
+  0x40, 0x59, 0x4E, 0x09, 0xD4, 0x20, 0xC6, 0x99, 0x39, 0x09, 0x59, 0x3C, 0x2D, 0x22, 0x20, 0x44, 0xFA, 0xCF, 0x19, 0xA6, 
+  0xFB, 0x6F, 0x52, 0x14, 0xB9, 0x95, 0x0C, 0xD5, 0x88, 0xDB, 0xB4, 0x4B, 0x35, 0x2F, 0x52, 0x1B, 0x37, 0x15, 0x19, 0x8F, 
+  0x8F, 0x52, 0x92, 0x94, 0xCD, 0xD9, 0x8A, 0x42, 0x23, 0x3E, 0xE1, 0x8D, 0x01, 0xDE, 0x9C, 0xE7, 0x2B, 0xF0, 0xC7, 0x8A, 
+  0x5E, 0x3B, 0xE4, 0x2C, 0x1F, 0x61, 0xE8, 0xE5, 0x3B, 0xDB, 0x13, 0x54, 0x0D, 0x22, 0xEB, 0x82, 0x2A, 0x51, 0x8C, 0x59, 
+  0x4A, 0xDA, 0xC6, 0xC0, 0x55, 0xB2, 0x4A, 0x49, 0xB3, 0x1C, 0x3F, 0x21, 0xB4, 0x16, 0x4B, 0x67, 0xCD, 0x28, 0x80, 0x0B, 
+  0x89, 0x0A, 0xA0, 0xBC, 0xA1, 0xB5, 0x3A, 0x33, 0x5B, 0xAD, 0xB0, 0x4C, 0x02, 0x2E, 0x7E, 0x0D, 0xDA, 0xD0, 0x42, 0x48, 
+  0x4D, 0x48, 0x63, 0x14, 0x33, 0x7D, 0xC2, 0x14, 0x5A, 0x0E, 0x3B, 0xB7, 0xEC, 0x67, 0x3A, 0x9F, 0x1C, 0x9E, 0xD8, 0xD7, 
+  0xD1, 0x6F, 0x78, 0x73, 0x9F, 0x7F, 0xFE, 0xC5, 0x7F, 0x5F, 0x7D, 0xF9, 0x5B, 0xC3, 0x4B, 0x57, 0xF3, 0x6A, 0x50, 0x1C, 
+  0xE1, 0x5A, 0x0F, 0xB5, 0x0F, 0xA0, 0x09, 0x1C, 0xA2, 0xB5, 0xAE, 0xAD, 0xB1, 0xB4, 0x1E, 0xAA, 0x44, 0x59, 0x66, 0x31, 
+  0x29, 0x36, 0xF3, 0x19, 0xAC, 0x3E, 0x26, 0x28, 0x6A, 0xD6, 0xC4, 0xE9, 0x2B, 0x97, 0x6D, 0x66, 0x36, 0x0E, 0x3B, 0x68, 
+  0x71, 0xD7, 0xD0, 0x55, 0x97, 0x5F, 0x03, 0xBF, 0x88, 0x0C, 0x8A, 0x72, 0x3D, 0x2E, 0x30, 0xBA, 0x30, 0x51, 0xC7, 0x90, 
+  0x4C, 0xC1, 0xC4, 0x03, 0x78, 0x0F, 0xA4, 0x46, 0xC4, 0x58, 0x2E, 0x78, 0x4B, 0x25, 0x02, 0x44, 0x25, 0xD8, 0x3B, 0xD2, 
+  0x57, 0x20, 0x92, 0xC8, 0x4C, 0x84, 0xC8, 0x35, 0xDD, 0x3D, 0xC6, 0xD1, 0x04, 0x64, 0xD3, 0x23, 0x52, 0xA8, 0xD1, 0xB6, 
+  0x9D, 0xA7, 0xE8, 0xD5, 0xD4, 0xD3, 0x71, 0x85, 0x93, 0x71, 0x5F, 0x61, 0xE7, 0x64, 0xE9, 0x3B, 0x3A, 0x18, 0xC5, 0x54, 
+  0x2D, 0x10, 0x09, 0x8A, 0x56, 0x8C, 0xA0, 0x2B, 0xC0, 0x5F, 0xB5, 0x68, 0xE7, 0x11, 0x61, 0x90, 0x29, 0xAB, 0x52, 0x39, 
+  0xF5, 0x68, 0x48, 0x08, 0x0A, 0xE6, 0x39, 0xC4, 0x5E, 0x21, 0xFE, 0x19, 0x4D, 0x08, 0xE7, 0xB2, 0x50, 0xF8, 0x65, 0x78, 
+  0x80, 0x77, 0x48, 0x22, 0x35, 0x7D, 0xB6, 0x33, 0xAB, 0x02, 0xA0, 0x29, 0xB2, 0x00, 0xF1, 0x69, 0xE3, 0x27, 0x4F, 0xBF, 
+  0x68, 0x6A, 0x7F, 0xC7, 0xD0, 0x91, 0x03, 0xD7, 0x4A, 0x7B, 0x2E, 0xA3, 0xE8, 0x95, 0x17, 0x5E, 0x35, 0x6C, 0x2D, 0x36, 
+  0x16, 0x7C, 0xFC, 0xF2, 0xF3, 0x2F, 0xC1, 0x2B, 0x6D, 0xAE, 0x68, 0xE8, 0xA8, 0x6B, 0x5B, 0xDC, 0x35, 0x08, 0x6B, 0x08, 
+  0xEE, 0x22, 0x35, 0x04, 0x0E, 0x41, 0xC9, 0x5D, 0x0D, 0xE3, 0x28, 0xB3, 0xB8, 0x30, 0x25, 0x0F, 0x59, 0x87, 0x2F, 0x08, 
+  0x59, 0xBF, 0x72, 0x73, 0x5F, 0x6B, 0x3F, 0xFD, 0x8C, 0x2B, 0x0E, 0x5C, 0xF9, 0x8D, 0xAF, 0xBF, 0x7C, 0xFC, 0xAA, 0x1B, 
+  0xAA, 0xF3, 0x2B, 0xDB, 0xEB, 0xBB, 0x32, 0x63, 0x52, 0x79, 0x4E, 0x31, 0x83, 0x01, 0x14, 0x20, 0x83, 0xFB, 0x42, 0xA4, 
+  0xCF, 0x42, 0xB8, 0x44, 0x5A, 0x02, 0x03, 0xD2, 0x97, 0xEB, 0x0C, 0xA7, 0x13, 0xA7, 0xFD, 0x41, 0x5C, 0x8D, 0x37, 0xCC, 
+  0xAD, 0x66, 0x44, 0x2C, 0xC6, 0x3B, 0x6E, 0x30, 0x30, 0xA5, 0x96, 0x1B, 0x7E, 0xA5, 0x52, 0x4B, 0x77, 0xE0, 0xC8, 0xAB, 
+  0x00, 0xCD, 0x7C, 0x2C, 0xF4, 0xAB, 0xE1, 0x5B, 0xF3, 0x57, 0x05, 0x88, 0x1F, 0xA8, 0x0E, 0xB4, 0x43, 0x29, 0x66, 0x6E, 
+  0x28, 0x37, 0x27, 0x2F, 0x11, 0xBA, 0x81, 0x78, 0x31, 0x70, 0x23, 0x77, 0x25, 0x76, 0x3B, 0x7B, 0x19, 0xCC, 0x5D, 0xC5, 
+  0x22, 0x79, 0x02, 0x64, 0x9E, 0x42, 0x71, 0x02, 0x6D, 0x33, 0x78, 0xFC, 0x80, 0xBE, 0x8A, 0x64, 0x6F, 0x60, 0x91, 0x49, 
+  0x2E, 0xD3, 0x48, 0xF0, 0x63, 0x43, 0x22, 0x7D, 0x2F, 0xF5, 0x1D, 0x77, 0xE6, 0x39, 0xBC, 0xDD, 0x23, 0x07, 0xAF, 0x59, 
+  0xDC, 0xBB, 0x22, 0x3D, 0x2A, 0xE5, 0xFA, 0x63, 0xD7, 0x7F, 0xFA, 0x5F, 0x61, 0x2D, 0xF2, 0x03, 0x6F, 0xEE, 0xB5, 0x57, 
+  0xBF, 0xB3, 0x71, 0xCD, 0x66, 0x32, 0x57, 0x5C, 0x61, 0xA8, 0x13, 0x7A, 0x1D, 0x24, 0xFB, 0x45, 0x86, 0xCE, 0x4E, 0x6F, 
+  0x83, 0xB2, 0x51, 0x7C, 0x37, 0x2B, 0x2E, 0x63, 0xE7, 0x96, 0xBD, 0xB0, 0xAC, 0x07, 0x5B, 0x7B, 0x9F, 0xFB, 0xFA, 0x0B, 
+  0xEF, 0xFF, 0xE2, 0xC3, 0x57, 0x5F, 0xFA, 0xEE, 0xB2, 0x9E, 0xE5, 0xE8, 0x4C, 0xDE, 0x40, 0x66, 0x21, 0x31, 0xA6, 0x24, 
+  0x83, 0x41, 0x50, 0x61, 0x41, 0x56, 0x0E, 0x12, 0xB7, 0x49, 0x91, 0x20, 0x8C, 0xAD, 0x0C, 0x28, 0xD9, 0x72, 0x49, 0x9D, 
+  0xA5, 0x6C, 0x86, 0x42, 0x20, 0xB4, 0x09, 0x74, 0x23, 0x4F, 0x16, 0x80, 0x62, 0xBC, 0x63, 0x13, 0x53, 0x1C, 0xC8, 0x9B, 
+  0x02, 0x49, 0x95, 0x43, 0x48, 0xD0, 0x5B, 0x57, 0xF4, 0x63, 0x6C, 0xDF, 0x2B, 0x7D, 0xFD, 0x15, 0x0A, 0x40, 0x0E, 0xA2, 
+  0x03, 0x2B, 0x71, 0x35, 0x70, 0x21, 0xDE, 0xE4, 0x19, 0xD2, 0x64, 0x1E, 0xEC, 0x62, 0xCC, 0x59, 0x99, 0x94, 0x66, 0x0B, 
+  0x83, 0xAB, 0x00, 0xBD, 0x50, 0xB6, 0xA5, 0xEA, 0xCF, 0x3A, 0x84, 0xF3, 0x6A, 0x85, 0x96, 0x6E, 0xE6, 0xE8, 0xC0, 0xA0, 
+  0x2D, 0xF6, 0x22, 0x51, 0x4B, 0x67, 0xB6, 0x0C, 0x69, 0x25, 0xB9, 0x0C, 0x8F, 0xA6, 0xED, 0x43, 0x52, 0x7F, 0xEE, 0xE9, 
+  0xE7, 0x06, 0xCC, 0xF2, 0xDB, 0xB6, 0x61, 0x27, 0xA2, 0x24, 0x97, 0x67, 0x03, 0xC1, 0xEF, 0x7E, 0xF7, 0x07, 0xDC, 0x81, 
+  0x5D, 0x05, 0x42, 0xE6, 0xFD, 0xE4, 0xD3, 0x6F, 0x3C, 0xF7, 0x22, 0xAC, 0x3A, 0x44, 0xBF, 0xBC, 0x7B, 0x29, 0x9C, 0xEA, 
+  0x25, 0x9D, 0x43, 0x83, 0x6D, 0xFD, 0x03, 0x2D, 0xBD, 0x7D, 0xAD, 0xA4, 0x4F, 0x74, 0xE0, 0x1B, 0x2F, 0xDF, 0x7F, 0x0C, 
+  0x34, 0x3B, 0x7E, 0xF4, 0xDA, 0xDF, 0x7C, 0xF8, 0x87, 0xFF, 0xFC, 0xE7, 0x3F, 0xBF, 0xFD, 0xCD, 0x1F, 0xAF, 0x3A, 0x74, 
+  0x9C, 0xED, 0x53, 0xDD, 0x4D, 0x5D, 0x15, 0xB9, 0xA5, 0xE8, 0xA9, 0x92, 0x69, 0x7E, 0x96, 0x0C, 0x5B, 0x0A, 0x73, 0x0A, 
+  0x24, 0x0C, 0xB8, 0x88, 0xAF, 0xF6, 0xCE, 0xAF, 0xCA, 0xB2, 0x8B, 0x79, 0x26, 0x61, 0x9F, 0x0C, 0x82, 0xE1, 0x1D, 0x75, 
+  0x0C, 0x6A, 0xD0, 0x36, 0x06, 0xCF, 0x27, 0xC2, 0x6B, 0xE8, 0x76, 0xCB, 0x02, 0xA7, 0x00, 0xB6, 0x01, 0x59, 0x4D, 0x9E, 
+  0xBB, 0xD6, 0xE4, 0xF5, 0x93, 0x9E, 0x72, 0x21, 0x7D, 0x5D, 0x3E, 0xCA, 0x1C, 0xB6, 0xF2, 0x35, 0x35, 0xD4, 0xC8, 0x23, 
+  0x50, 0x59, 0x0D, 0x47, 0x55, 0x76, 0x2B, 0x28, 0x6F, 0xBB, 0xBC, 0xA0, 0xBC, 0xA2, 0xB0, 0x82, 0xA5, 0x66, 0x2E, 0xD2, 
+  0x37, 0xB9, 0x10, 0x86, 0x5F, 0x55, 0x5C, 0xCD, 0xAA, 0x2C, 0xAA, 0xAA, 0x28, 0x16, 0x57, 0x30, 0x04, 0x1E, 0x61, 0x30, 
+  0xB8, 0xC1, 0x40, 0x8A, 0x4F, 0x49, 0x27, 0x52, 0xCC, 0x1C, 0x26, 0x31, 0x13, 0x38, 0xC2, 0x15, 0x68, 0xBD, 0xC5, 0x87, 
+  0x45, 0x86, 0x07, 0x06, 0xC3, 0xA3, 0x3A, 0xFF, 0xEC, 0x71, 0xE3, 0xC7, 0x8D, 0x5F, 0xD2, 0x37, 0x7C, 0xEC, 0xF0, 0x75, 
+  0x55, 0xC5, 0x55, 0xB5, 0x65, 0x75, 0xAF, 0xBF, 0xF6, 0x06, 0x0A, 0x40, 0x0D, 0x9F, 0x7E, 0xFA, 0x5F, 0x2E, 0xFE, 0xF2, 
+  0xD7, 0xBF, 0x1F, 0x3F, 0x7A, 0x1C, 0xD3, 0x5E, 0xDE, 0xBB, 0x74, 0xED, 0x92, 0xD5, 0x2B, 0x97, 0xAE, 0x5A, 0xB1, 0x64, 
+  0xD5, 0xAA, 0x25, 0xAB, 0x96, 0xF4, 0x2E, 0x81, 0xE6, 0x75, 0x68, 0xF7, 0xE1, 0xAD, 0xEB, 0xB6, 0xBE, 0xF3, 0xC3, 0xF7, 
+  0x3E, 0x63, 0xCB, 0xEE, 0x89, 0xCF, 0xFF, 0xFD, 0x3F, 0x1F, 0x3F, 0xFF, 0xEC, 0x4B, 0x6B, 0xD8, 0x1C, 0x38, 0xB8, 0x82, 
+  0x84, 0xAA, 0xA9, 0x82, 0x4D, 0x7A, 0xD5, 0xC8, 0xD7, 0xDB, 0x1D, 0xC2, 0xC6, 0xCB, 0x32, 0x05, 0x76, 0x10, 0x3D, 0x12, 
+  0x47, 0xEE, 0x6C, 0x32, 0x90, 0x2A, 0xD2, 0xE4, 0x72, 0x0E, 0x87, 0x2E, 0x5F, 0x83, 0x99, 0x43, 0x45, 0x31, 0x3A, 0x10, 
+  0x58, 0x73, 0x9A, 0x10, 0x99, 0xB9, 0xAE, 0xF9, 0x3B, 0x43, 0x37, 0x85, 0x23, 0x6B, 0xE9, 0x27, 0x2B, 0x00, 0xB9, 0xF3, 
+  0xF1, 0x47, 0xE9, 0x00, 0xAB, 0xD7, 0x1A, 0xCA, 0x0C, 0x4C, 0x1C, 0x03, 0x1F, 0x21, 0xB1, 0x1A, 0x39, 0x96, 0xE6, 0xBA, 
+  0xCC, 0x64, 0x23, 0x7D, 0x15, 0x31, 0xB2, 0xD6, 0x60, 0x80, 0x1A, 0x24, 0x56, 0x9B, 0x92, 0x4D, 0x62, 0x89, 0x70, 0x52, 
+  0x84, 0x5B, 0xE8, 0xC0, 0x91, 0xC9, 0x8B, 0x9C, 0xC9, 0x09, 0x91, 0x2D, 0xAD, 0x90, 0xF7, 0x47, 0x66, 0xC9, 0xFB, 0xA0, 
+  0x74, 0xC2, 0x15, 0x08, 0x0C, 0xB1, 0x61, 0xB1, 0x34, 0x9C, 0xA9, 0xA7, 0x2E, 0xBA, 0xE0, 0xC2, 0x0B, 0xCF, 0x38, 0x17, 
+  0xBE, 0xF4, 0x35, 0x57, 0xDD, 0x02, 0x99, 0x0E, 0x04, 0xB8, 0xFB, 0xB6, 0x7B, 0xD8, 0xDC, 0x41, 0x84, 0x00, 0x94, 0x34, 
+  0x4E, 0xBC, 0xFA, 0xEA, 0x6B, 0x6B, 0x86, 0xD7, 0xE2, 0x13, 0x5B, 0x56, 0x6D, 0xDA, 0xBE, 0x61, 0x3B, 0xFB, 0x32, 0x37, 
+  0xAE, 0x5E, 0xBF, 0x77, 0xC7, 0xBE, 0x43, 0x7B, 0x0F, 0xBF, 0xFD, 0xC6, 0x0F, 0x3F, 0xFF, 0x82, 0x98, 0x2E, 0xCF, 0x47, 
+  0x13, 0xBF, 0xF9, 0xF5, 0xEF, 0x0F, 0xEE, 0x3A, 0xC8, 0x46, 0xC1, 0x45, 0x8D, 0xD4, 0x19, 0x6D, 0x2D, 0xE5, 0x8D, 0xA8, 
+  0xC1, 0x64, 0xC9, 0x2A, 0x53, 0xE9, 0x4F, 0x94, 0x66, 0x17, 0x03, 0x3E, 0x48, 0x1F, 0xF5, 0x90, 0x8C, 0x11, 0x42, 0x6A, 
+  0xCD, 0x0E, 0x03, 0xFD, 0x8C, 0x92, 0xD4, 0x51, 0xD9, 0x18, 0x22, 0x97, 0xD5, 0x84, 0x19, 0x2D, 0x48, 0xC3, 0x43, 0x8B, 
+  0x61, 0x37, 0x0B, 0xB2, 0x3A, 0x70, 0xC2, 0xAF, 0x4A, 0xDF, 0x62, 0x8E, 0x15, 0xBA, 0xF7, 0x02, 0x21, 0xF8, 0xE8, 0x0E, 
+  0x05, 0x87, 0x9C, 0xAD, 0xCC, 0x7A, 0x97, 0x7B, 0xA3, 0x8C, 0x62, 0x97, 0x5D, 0x8C, 0x5D, 0x94, 0x94, 0x15, 0x1A, 0x9E, 
+  0x9A, 0xC9, 0xFA, 0x25, 0xEA, 0x16, 0x09, 0x7F, 0x56, 0x2A, 0x64, 0x53, 0x64, 0x08, 0xB5, 0xB6, 0x44, 0xEA, 0x38, 0x65, 
+  0x96, 0x0B, 0xCA, 0xE9, 0xC7, 0x70, 0x43, 0x82, 0xFA, 0x3E, 0xEF, 0x3B, 0x37, 0x5D, 0xDE, 0x99, 0xEB, 0x0A, 0xA9, 0xE8, 
+  0x20, 0x3E, 0x22, 0x21, 0x26, 0x2C, 0x8A, 0xF9, 0xD7, 0xC2, 0xF9, 0x01, 0x93, 0x2E, 0x1E, 0x7F, 0xB6, 0xCF, 0x99, 0xD0, 
+  0xB3, 0xAE, 0xBE, 0xF2, 0xA6, 0xCD, 0xAB, 0x2F, 0x43, 0x0D, 0x87, 0xF7, 0x1C, 0xFE, 0xF7, 0xBF, 0xFF, 0xA3, 0x0E, 0x21, 
+  0x1B, 0xC1, 0x4F, 0x9C, 0xF8, 0xE3, 0x1F, 0xFF, 0x74, 0xCB, 0xF5, 0xB7, 0xB2, 0xFF, 0x72, 0xCB, 0xCA, 0x8D, 0xF0, 0xE0, 
+  0x77, 0x6F, 0xDD, 0x83, 0xAA, 0x3E, 0xFC, 0xF0, 0x43, 0xB3, 0x2D, 0xE7, 0x53, 0x91, 0xBF, 0xE1, 0x60, 0xB3, 0x91, 0xE6, 
+  0x89, 0xC7, 0x9E, 0xDE, 0xBE, 0x76, 0x1B, 0xDB, 0x72, 0x16, 0x35, 0xD0, 0x02, 0x61, 0x57, 0x65, 0x03, 0x59, 0x1F, 0xB1, 
+  0x81, 0xA5, 0x74, 0x0D, 0x14, 0x40, 0xE5, 0x88, 0xF9, 0x23, 0x77, 0xEA, 0x21, 0xF9, 0x20, 0xA5, 0x75, 0xC4, 0x98, 0x86, 
+  0x62, 0xD3, 0x7D, 0x29, 0x00, 0x15, 0xA4, 0x55, 0x85, 0x1A, 0x24, 0xB7, 0x36, 0xD9, 0x9D, 0x3B, 0xE1, 0x71, 0x5C, 0xC1, 
+  0x19, 0x3E, 0xA7, 0x08, 0xC6, 0x9E, 0x12, 0x88, 0xC6, 0x48, 0x9F, 0x0F, 0xAE, 0x9F, 0x9D, 0x65, 0x74, 0x90, 0x6B, 0x09, 
+  0x4F, 0x42, 0x90, 0x1F, 0x21, 0x70, 0x8F, 0xE6, 0xAB, 0x1A, 0x5E, 0x94, 0x87, 0x1A, 0x55, 0x54, 0x49, 0x09, 0x8A, 0x0E, 
+  0x4C, 0x11, 0x57, 0xC3, 0x3B, 0x96, 0xD9, 0x40, 0x69, 0x6D, 0x63, 0x79, 0xBD, 0xEC, 0xD4, 0x90, 0xC1, 0x0E, 0x1F, 0x83, 
+  0x32, 0x9B, 0x38, 0x2F, 0xDA, 0x72, 0xAC, 0x29, 0x4B, 0x66, 0x1D, 0xD2, 0xC2, 0x4D, 0x96, 0x71, 0x98, 0x4C, 0x25, 0xE3, 
+  0x4D, 0xDB, 0x27, 0x26, 0x45, 0xD4, 0x10, 0x19, 0xEB, 0xA8, 0x61, 0xDE, 0xBC, 0x4B, 0xC6, 0x4F, 0x38, 0xDD, 0xE7, 0x34, 
+  0xF8, 0xFE, 0x57, 0x1E, 0xBA, 0x66, 0xDF, 0xEE, 0xA3, 0xBC, 0x08, 0xE2, 0x46, 0xEE, 0x46, 0xC4, 0x9F, 0xEB, 0x66, 0x1B, 
+  0x4A, 0xBA, 0x5F, 0xFD, 0xEA, 0xD7, 0x2F, 0xBF, 0xFC, 0xEA, 0xCB, 0x2F, 0xBD, 0xF6, 0xF3, 0x9F, 0xBF, 0xAF, 0xBB, 0x3F, 
+  0x8C, 0x86, 0x44, 0x49, 0xB2, 0x3B, 0xCA, 0x6C, 0xCF, 0xF9, 0xE0, 0x57, 0xBF, 0xBB, 0x7C, 0xDF, 0xE5, 0xB8, 0x0B, 0x7B, 
+  0x46, 0x06, 0x5A, 0x07, 0x28, 0x32, 0x9A, 0x8D, 0x37, 0x60, 0xEF, 0x86, 0xB1, 0x51, 0x46, 0xFE, 0x86, 0xA0, 0x01, 0x2B, 
+  0x3A, 0x22, 0xE0, 0x95, 0xD9, 0x7F, 0xD9, 0x42, 0xEF, 0xB6, 0xB5, 0xA2, 0x89, 0x67, 0xD6, 0x95, 0xCB, 0x64, 0x9B, 0x8A, 
+  0x44, 0xBC, 0x47, 0xBC, 0x41, 0x74, 0xA0, 0xB1, 0x4D, 0xFD, 0x80, 0x3A, 0x63, 0x0C, 0x01, 0xC0, 0x86, 0x62, 0x44, 0xAF, 
+  0x3D, 0x95, 0x31, 0x86, 0xAF, 0x3A, 0xB0, 0x4B, 0xE2, 0x81, 0x97, 0xA6, 0x6A, 0xF9, 0xAA, 0x5E, 0x8E, 0xAA, 0x7D, 0x02, 
+  0x5E, 0xE9, 0x78, 0x09, 0x21, 0x01, 0xE0, 0x12, 0x1D, 0x08, 0xA9, 0x1F, 0xB9, 0xEB, 0x00, 0x00, 0x7F, 0xE7, 0x03, 0x38, 
+  0x94, 0x7F, 0x94, 0x41, 0xEF, 0x4F, 0xF8, 0x29, 0x86, 0x7D, 0x8F, 0x47, 0x4B, 0x02, 0xEE, 0x84, 0x04, 0xEC, 0x45, 0xDF, 
+  0x1F, 0x21, 0x81, 0x3A, 0x0B, 0x44, 0x4A, 0x8C, 0x4A, 0x8A, 0x8B, 0x88, 0xA1, 0xCD, 0xC0, 0x44, 0x3E, 0x60, 0xEE, 0xDC, 
+  0x4B, 0x2E, 0x9E, 0xC4, 0xE1, 0x02, 0x89, 0xA1, 0xF1, 0x44, 0xDA, 0xA3, 0x87, 0xAF, 0x69, 0xAC, 0x6A, 0x5A, 0xBD, 0x74, 
+  0xB5, 0xEE, 0xBA, 0x31, 0xE1, 0x41, 0x02, 0xB5, 0xF7, 0x47, 0x6C, 0xFF, 0x33, 0x91, 0xBE, 0xFD, 0x31, 0xAE, 0x20, 0x7B, 
+  0x05, 0x9F, 0x7F, 0xEE, 0xC5, 0x9D, 0x5B, 0x77, 0xAD, 0x5B, 0xBA, 0x86, 0x30, 0x3E, 0xD0, 0xDA, 0x87, 0x37, 0x68, 0xAD, 
+  0x87, 0x70, 0x59, 0xB8, 0x2F, 0xCE, 0x41, 0xD2, 0x45, 0x29, 0x4E, 0x6B, 0x84, 0xDF, 0x22, 0x7A, 0x1A, 0x85, 0x7C, 0x96, 
+  0x8E, 0xFA, 0x16, 0x50, 0x11, 0xC5, 0xF0, 0x64, 0xEC, 0x80, 0x58, 0x88, 0x43, 0x88, 0xDF, 0x18, 0x1D, 0x90, 0x50, 0x15, 
+  0xCB, 0xB4, 0xD9, 0xE9, 0x48, 0xD3, 0x04, 0x93, 0x30, 0x90, 0x46, 0x24, 0x10, 0x2F, 0x17, 0xBC, 0x75, 0x71, 0x7F, 0x8C, 
+  0xD0, 0xBD, 0x77, 0x71, 0x05, 0x9F, 0x11, 0x72, 0xB6, 0xCB, 0xBC, 0xFC, 0x32, 0xD2, 0xA4, 0xFC, 0x7B, 0x41, 0x46, 0x29, 
+  0xB8, 0x94, 0x25, 0x28, 0xA5, 0x1C, 0x4E, 0x50, 0x56, 0xDF, 0x52, 0xD5, 0xC4, 0x7B, 0x95, 0x0F, 0xD0, 0xC0, 0x26, 0x56, 
+  0xF9, 0x18, 0xB4, 0x3F, 0xB5, 0xFF, 0xCC, 0x40, 0x46, 0x1A, 0xD7, 0x6C, 0x8A, 0xCB, 0x33, 0xC1, 0xD9, 0xD4, 0x68, 0x3A, 
+  0xC4, 0x60, 0xAA, 0xA5, 0xEF, 0x92, 0xA8, 0x80, 0x1A, 0x98, 0x76, 0x11, 0x9F, 0x69, 0x38, 0xA3, 0x86, 0x10, 0xFF, 0x85, 
+  0x0C, 0xE5, 0x27, 0x5C, 0x3C, 0x1E, 0x35, 0x24, 0x84, 0xC4, 0xE1, 0x0D, 0xA8, 0xA1, 0xB5, 0xAE, 0x95, 0x20, 0xFC, 0xDE, 
+  0x4F, 0x7F, 0x31, 0xB2, 0xEB, 0xE6, 0x0B, 0x7C, 0xE2, 0x13, 0xA4, 0xAC, 0x1B, 0x02, 0x35, 0x5A, 0xA8, 0xA3, 0xC8, 0x5E, 
+  0x4D, 0xF3, 0xC3, 0x23, 0xE0, 0xD8, 0xCD, 0xD7, 0xDD, 0xB2, 0x6D, 0xFD, 0xF6, 0xE1, 0xC1, 0xE1, 0x15, 0xFD, 0xCB, 0x69, 
+  0x81, 0xB0, 0x47, 0x0A, 0x11, 0x93, 0xDA, 0x8A, 0xE8, 0xAB, 0x5A, 0x78, 0xC3, 0xBD, 0xCD, 0x8B, 0x06, 0x5B, 0xFB, 0x06, 
+  0xDB, 0xFB, 0xDA, 0xEB, 0x9A, 0x77, 0x6F, 0xDD, 0xCD, 0xF3, 0x7B, 0x5B, 0xBA, 0xD9, 0xC3, 0x43, 0xFC, 0xE7, 0x56, 0x3B, 
+  0x25, 0x92, 0x59, 0x49, 0xE6, 0x5A, 0x4A, 0x06, 0x25, 0x6A, 0xA0, 0xAC, 0x23, 0x6D, 0x95, 0x89, 0xBF, 0x43, 0x84, 0x11, 
+  0xD1, 0xA7, 0x3A, 0x56, 0x4F, 0x7B, 0x8A, 0x2E, 0xA1, 0x7E, 0x40, 0x32, 0x40, 0xF7, 0xC2, 0x31, 0x7F, 0x05, 0x22, 0x5D, 
+  0x3E, 0x8E, 0xC4, 0x19, 0x6D, 0x8F, 0x9E, 0x6E, 0xEB, 0x5D, 0x2F, 0xF9, 0x00, 0xFD, 0xF3, 0xEF, 0x65, 0x0B, 0x15, 0xF8, 
+  0xCE, 0xDE, 0x92, 0x7C, 0x09, 0x5F, 0x8A, 0x45, 0x14, 0xAE, 0x92, 0x78, 0x94, 0xD7, 0x77, 0xD6, 0xB5, 0xE1, 0xF2, 0x7C, 
+  0x48, 0x3E, 0x00, 0x29, 0x3C, 0x85, 0x15, 0x1F, 0x92, 0xFE, 0x81, 0xC4, 0x0C, 0xE3, 0xCE, 0xDA, 0x0F, 0x00, 0x8E, 0x58, 
+  0x9A, 0xB7, 0xF1, 0xE6, 0x78, 0x1F, 0x66, 0x2E, 0x86, 0x2B, 0x24, 0x32, 0x00, 0x88, 0x0D, 0x8B, 0x63, 0x2A, 0x10, 0xB4, 
+  0xC0, 0x7F, 0xFE, 0xAC, 0xD9, 0x17, 0x5E, 0x78, 0x21, 0x6A, 0xC8, 0x8C, 0x4F, 0x27, 0x44, 0x1F, 0xDA, 0x7F, 0x65, 0x67, 
+  0x53, 0xD7, 0x9A, 0x65, 0x6B, 0xBF, 0xF7, 0xFA, 0x9B, 0x8A, 0x3C, 0xBA, 0x0F, 0x90, 0x65, 0xF0, 0x47, 0x9C, 0x80, 0xB8, 
+  0xFD, 0xD1, 0xBF, 0xFF, 0xF3, 0xCF, 0x7F, 0x7E, 0xF4, 0xCF, 0x7F, 0xFE, 0x93, 0x12, 0x8F, 0x5F, 0x69, 0xFC, 0x20, 0xCD, 
+  0x3D, 0xB8, 0xE7, 0xF0, 0xFA, 0x55, 0x1B, 0x70, 0x26, 0x34, 0xB1, 0xB4, 0x6B, 0xF1, 0x50, 0x5B, 0x7F, 0x5F, 0x4B, 0x37, 
+  0x05, 0xC7, 0x40, 0x5B, 0xEF, 0xE0, 0xA2, 0x21, 0x36, 0x8C, 0xAC, 0xEE, 0x5F, 0x31, 0xD8, 0xD1, 0xBF, 0x77, 0xFB, 0x5E, 
+  0x12, 0x2A, 0xFE, 0xE4, 0xBE, 0x3B, 0xEF, 0xE7, 0x23, 0x2C, 0xED, 0x5E, 0xBC, 0x64, 0xD1, 0x62, 0x9E, 0x46, 0x4E, 0x6C, 
+  0xF6, 0xF3, 0xD0, 0xC1, 0xAD, 0xE7, 0xB3, 0x88, 0x32, 0xB2, 0x44, 0x07, 0x04, 0x67, 0xFA, 0xB8, 0x2C, 0x87, 0x89, 0x44, 
+  0x10, 0x4E, 0xCC, 0xC9, 0x4C, 0x84, 0x8B, 0xE6, 0x28, 0xC3, 0x8B, 0xFE, 0x5E, 0xD1, 0x8F, 0xE8, 0x40, 0x73, 0x47, 0x2B, 
+  0x6E, 0x2F, 0x81, 0x92, 0x6B, 0xFB, 0xB8, 0x4E, 0xC0, 0x35, 0x97, 0x90, 0xC7, 0xF3, 0x49, 0xE3, 0xCA, 0xA4, 0x7D, 0x96, 
+  0x59, 0xCC, 0x76, 0x67, 0x2E, 0xD8, 0x28, 0xC9, 0x07, 0x83, 0x6E, 0x4E, 0xDB, 0x15, 0xD1, 0x0F, 0x75, 0xF4, 0xF3, 0x08, 
+  0xED, 0x36, 0x4C, 0x0C, 0x74, 0xC2, 0x57, 0x04, 0x94, 0x72, 0xD8, 0x09, 0x24, 0x09, 0x12, 0xDE, 0x20, 0x9D, 0x83, 0xD4, 
+  0x3C, 0xA2, 0x82, 0x62, 0x25, 0xED, 0x23, 0x02, 0x03, 0x3A, 0x80, 0xE5, 0x99, 0x18, 0x9E, 0x10, 0x43, 0xD1, 0x10, 0x14, 
+  0x19, 0x38, 0x7F, 0xFE, 0x3C, 0xDF, 0xD9, 0xE7, 0x9E, 0x37, 0x8E, 0xE3, 0x59, 0x40, 0xBC, 0xEB, 0x8F, 0xDF, 0x4E, 0xE9, 
+  0xD0, 0xD5, 0xDC, 0x45, 0x3E, 0xCA, 0x26, 0x83, 0xDF, 0xFF, 0xFE, 0x8F, 0x9F, 0x7C, 0x22, 0x22, 0x26, 0xFF, 0x31, 0x3B, 
+  0x93, 0x3F, 0x61, 0x47, 0x14, 0x60, 0xF5, 0xE1, 0x6F, 0xFE, 0xC0, 0xFA, 0xC3, 0x6F, 0xFF, 0xFC, 0xB7, 0xBF, 0xFD, 0x43, 
+  0x53, 0x29, 0x75, 0x07, 0xB6, 0xF0, 0xEF, 0xDA, 0xB6, 0x7B, 0xE3, 0xF0, 0xFA, 0x4D, 0x2B, 0x36, 0xAC, 0x59, 0xB6, 0x66, 
+  0xF5, 0x00, 0x9B, 0x67, 0x97, 0x73, 0xE6, 0xC2, 0xAA, 0xC1, 0x15, 0xE8, 0x95, 0x7D, 0xFD, 0x64, 0xB7, 0x6C, 0xF0, 0xFF, 
+  0xE0, 0x03, 0x02, 0xFB, 0xA7, 0xFF, 0xFD, 0xEF, 0x7F, 0xFE, 0xFC, 0xE7, 0x3F, 0x6F, 0x5E, 0xB3, 0x99, 0xDF, 0xAE, 0x5C, 
+  0xBC, 0x92, 0xB6, 0x07, 0xB5, 0x61, 0x4F, 0x73, 0x37, 0xFE, 0x2D, 0x25, 0xBA, 0xEE, 0xCD, 0x22, 0x9D, 0x11, 0x09, 0x94, 
+  0x12, 0x18, 0xF2, 0x52, 0x72, 0xA0, 0xCF, 0xD0, 0xC7, 0x4D, 0x8B, 0x4D, 0x72, 0xA5, 0x3F, 0x82, 0xF8, 0xA7, 0x14, 0xBD, 
+  0xB1, 0x3C, 0xE1, 0x52, 0xFA, 0xA8, 0x64, 0xBD, 0x74, 0x49, 0x91, 0x7B, 0xB6, 0x24, 0xD1, 0x36, 0x23, 0xD6, 0x0B, 0x5B, 
+  0x34, 0xA2, 0x7C, 0xD3, 0xF9, 0x29, 0x64, 0xEA, 0x42, 0x37, 0xA6, 0xBE, 0xBC, 0xE9, 0xA5, 0x6F, 0xBC, 0xCC, 0x89, 0x11, 
+  0x7F, 0xFB, 0xDB, 0x5F, 0x7E, 0xF5, 0xC1, 0x87, 0x8F, 0x3D, 0xF8, 0x38, 0xF9, 0x38, 0xEF, 0xB2, 0xAF, 0x49, 0xDA, 0x6D, 
+  0xD2, 0xF5, 0x04, 0x7F, 0xAB, 0xD8, 0xD3, 0x51, 0x0F, 0x76, 0x91, 0x86, 0x4B, 0xF5, 0x9F, 0x6E, 0x48, 0x54, 0xB0, 0x7D, 
+  0x4C, 0x1E, 0xAD, 0x6A, 0xE0, 0x33, 0x98, 0xC0, 0x90, 0xC2, 0xD8, 0x8B, 0x8E, 0x34, 0x4C, 0xBA, 0x88, 0xA0, 0xB0, 0x85, 
+  0x0B, 0xFC, 0xE6, 0xCC, 0x9C, 0x71, 0xD6, 0x99, 0xA7, 0x53, 0x37, 0xAC, 0x59, 0xBA, 0x1E, 0x6F, 0x60, 0xEF, 0x0D, 0x71, 
+  0x95, 0x2D, 0xCA, 0xB7, 0xDC, 0x78, 0xC7, 0x0B, 0xCF, 0xBD, 0xFC, 0x83, 0xB7, 0xDF, 0x79, 0xEF, 0xDD, 0xF7, 0x7F, 0xFA, 
+  0x93, 0x5F, 0xBC, 0xFD, 0xE6, 0x8F, 0x19, 0x07, 0xBD, 0xF1, 0xDD, 0xB7, 0xDF, 0xFA, 0xFE, 0x8F, 0x7F, 0xF8, 0x83, 0x9F, 
+  0xFC, 0xF4, 0x27, 0x3F, 0xFF, 0xD5, 0x2F, 0x7F, 0x83, 0x1A, 0x34, 0x47, 0xB2, 0xFB, 0x35, 0x77, 0x6D, 0xDB, 0xB3, 0x61, 
+  0xE5, 0x86, 0x6D, 0xEB, 0xB7, 0x6D, 0x59, 0xBB, 0x45, 0x0E, 0x18, 0x59, 0xBB, 0x85, 0x92, 0x62, 0xC7, 0xA6, 0x1D, 0xBB, 
+  0xB7, 0xED, 0xDC, 0xBC, 0x72, 0xE3, 0x8B, 0xCF, 0xBD, 0xA4, 0xCE, 0xF4, 0xDF, 0x4F, 0xA5, 0x4A, 0x7F, 0xEA, 0xD1, 0xA7, 
+  0x51, 0xCF, 0xF6, 0xB5, 0x5B, 0xD7, 0xAF, 0x58, 0x2F, 0x9A, 0xE0, 0xE4, 0x85, 0x36, 0x8E, 0x6C, 0x58, 0xD4, 0x56, 0x6F, 
+  0x34, 0x41, 0xA3, 0x8C, 0x62, 0x28, 0xAB, 0x3C, 0x2B, 0x36, 0x3D, 0x3E, 0x28, 0x26, 0x35, 0x3A, 0xB9, 0xA2, 0xB8, 0x12, 
+  0x7A, 0x36, 0x33, 0x54, 0xC0, 0x67, 0xB4, 0xDC, 0x45, 0xD6, 0x5F, 0xB6, 0xC6, 0xEA, 0xC0, 0xCA, 0x7D, 0x24, 0x17, 0x76, 
+  0x8B, 0x49, 0xE5, 0x77, 0x48, 0x20, 0x32, 0xBD, 0xCF, 0xD4, 0xA8, 0x24, 0xBA, 0x17, 0x78, 0x03, 0x01, 0xE0, 0xEF, 0x7F, 
+  0xFF, 0x27, 0x9F, 0xF3, 0x5F, 0xFF, 0xFC, 0x3B, 0xE6, 0xC3, 0x5B, 0x07, 0x07, 0x1E, 0xBA, 0xF7, 0x61, 0x52, 0x72, 0x69, 
+  0x7C, 0x0A, 0x28, 0x71, 0x54, 0x01, 0x9B, 0xB3, 0x19, 0x04, 0x49, 0x54, 0x00, 0x49, 0xA5, 0x5F, 0x46, 0xDD, 0x6F, 0x86, 
+  0xDA, 0x9E, 0xF4, 0x39, 0x33, 0x2D, 0x21, 0x25, 0x25, 0x2E, 0x09, 0x50, 0xC2, 0x1B, 0x48, 0x93, 0xA2, 0xC9, 0x56, 0x03, 
+  0x43, 0x19, 0xD0, 0x4F, 0x9F, 0x72, 0x29, 0x87, 0x02, 0xB1, 0x03, 0xE7, 0xD8, 0x15, 0x37, 0x6F, 0x5C, 0xB7, 0x03, 0x63, 
+  0x6C, 0x6F, 0xE0, 0x8C, 0x99, 0xE5, 0x6C, 0x21, 0xBE, 0xF6, 0xE8, 0x0D, 0xF7, 0xDD, 0xF3, 0xE0, 0x83, 0xF7, 0x3D, 0x7A, 
+  0xFF, 0x3D, 0x0F, 0xB3, 0x73, 0xFF, 0xEB, 0x4F, 0x3D, 0xFF, 0xEC, 0xD3, 0x2F, 0xB0, 0x5E, 0x7D, 0xE9, 0xDB, 0xE8, 0x03, 
+  0x35, 0xE0, 0x1F, 0x72, 0x7C, 0x90, 0xD9, 0x44, 0x4E, 0x2A, 0xF5, 0xE1, 0x6F, 0x7E, 0x77, 0xF4, 0xE0, 0x95, 0x1C, 0xB1, 
+  0xB3, 0x6B, 0xCB, 0xAE, 0xFD, 0x3B, 0x77, 0x1F, 0xD8, 0xB5, 0xE7, 0xE0, 0xAE, 0x43, 0x07, 0x76, 0x1E, 0xD8, 0xB1, 0x79, 
+  0xFB, 0xA3, 0x0F, 0x3F, 0x61, 0xE3, 0x8A, 0x22, 0xD8, 0xBF, 0xFE, 0xFD, 0xD1, 0xB5, 0x57, 0x5C, 0x7B, 0xD9, 0x3A, 0x72, 
+  0xDF, 0xDD, 0xA8, 0x6D, 0xC3, 0xF2, 0x75, 0xB8, 0xC5, 0x50, 0xEF, 0xE2, 0xDE, 0xF6, 0x5E, 0x82, 0x04, 0x6A, 0x28, 0x4A, 
+  0xCD, 0x67, 0x10, 0x42, 0x55, 0x3F, 0xD4, 0xB9, 0x18, 0xD1, 0xB1, 0x65, 0x81, 0xE9, 0x69, 0x54, 0x70, 0x14, 0xF6, 0xA4, 
+  0x3A, 0x30, 0x96, 0x2E, 0x0A, 0xC0, 0xCB, 0xF5, 0x62, 0xCC, 0xE2, 0x71, 0x47, 0x07, 0x63, 0x4C, 0x5E, 0xEF, 0x8E, 0x74, 
+  0xD2, 0x73, 0xA4, 0xD7, 0x46, 0x12, 0xC6, 0x16, 0x09, 0xAD, 0x4A, 0x90, 0x1D, 0x83, 0x2A, 0x76, 0x12, 0xEA, 0x46, 0x49, 
+  0xAC, 0xF2, 0x5D, 0x13, 0x2A, 0x39, 0xB9, 0x80, 0x5D, 0xED, 0x06, 0x88, 0xBF, 0xF8, 0xE0, 0x83, 0x0F, 0x76, 0x6C, 0xD9, 
+  0x45, 0xD1, 0xC7, 0x68, 0x8C, 0xDC, 0x9C, 0xC4, 0x49, 0xE8, 0x8B, 0xF9, 0x95, 0xF8, 0x93, 0xB4, 0x68, 0xB2, 0x84, 0x46, 
+  0x68, 0x5B, 0x2B, 0x9A, 0x23, 0x69, 0xE5, 0x9C, 0x12, 0x93, 0x9E, 0x14, 0x93, 0x00, 0x2E, 0x25, 0x86, 0xC7, 0x47, 0x87, 
+  0xC4, 0x30, 0xB5, 0x0F, 0x9A, 0xED, 0xC7, 0xE0, 0x7E, 0xEA, 0x84, 0xA9, 0xBB, 0xB6, 0x1E, 0xDA, 0x75, 0xD9, 0x21, 0xC6, 
+  0x96, 0xE4, 0x2A, 0xCC, 0xD7, 0x68, 0x5A, 0x70, 0x3E, 0x0B, 0x00, 0xB2, 0x6D, 0xE3, 0xF6, 0xBD, 0xDB, 0xF7, 0x5D, 0xBE, 
+  0xF7, 0xCA, 0x5B, 0x6F, 0xBA, 0x93, 0x4D, 0xCB, 0x40, 0xF9, 0x3D, 0x77, 0x3F, 0x4C, 0x6F, 0xE3, 0xED, 0x1F, 0xBC, 0xF3, 
+  0xBB, 0xDF, 0xFE, 0x1F, 0x4D, 0xA2, 0x4C, 0xEC, 0x10, 0xC9, 0xFE, 0xE3, 0x5F, 0xFF, 0x7C, 0xFC, 0xD1, 0xA7, 0xA8, 0xDD, 
+  0x76, 0x6E, 0xDE, 0x09, 0x3A, 0xED, 0xBB, 0x6C, 0x1F, 0x67, 0x2B, 0xBC, 0xF2, 0xD2, 0xAB, 0x94, 0xE2, 0x60, 0x96, 0x86, 
+  0x71, 0x7D, 0x3E, 0xB7, 0x20, 0xDE, 0xF1, 0x2B, 0xAF, 0xDD, 0xB9, 0xE5, 0x32, 0x74, 0x46, 0x54, 0xA7, 0xDC, 0x23, 0x9C, 
+  0xE0, 0x0D, 0xF5, 0x25, 0x35, 0xE0, 0x01, 0x9A, 0xB8, 0xF1, 0xF8, 0xCD, 0xBF, 0xFB, 0xFD, 0x1F, 0x69, 0x11, 0x62, 0x22, 
+  0xE4, 0xEB, 0xA4, 0x76, 0x8C, 0xED, 0x8C, 0xC4, 0x47, 0xC4, 0xCD, 0x87, 0x62, 0x9D, 0x2C, 0x7D, 0x9E, 0x76, 0x0A, 0x1D, 
+  0xD8, 0x4E, 0x16, 0xBD, 0x5C, 0x77, 0x9C, 0x24, 0x35, 0xA1, 0x36, 0xCA, 0x45, 0x64, 0xCA, 0xF8, 0x4C, 0xC8, 0x5E, 0x30, 
+  0x7B, 0x7E, 0x4B, 0x23, 0x87, 0x4E, 0xAD, 0xA4, 0xEE, 0x4D, 0x0A, 0x8F, 0x27, 0x32, 0xDF, 0x71, 0xD3, 0x3D, 0x7F, 0xFE, 
+  0xB3, 0x6E, 0x15, 0xFE, 0xEC, 0x3F, 0xFF, 0xF9, 0xB7, 0xB1, 0xA9, 0x13, 0x94, 0x48, 0x75, 0x95, 0x0D, 0x18, 0x3E, 0x11, 
+  0x9B, 0x52, 0x4E, 0x0A, 0x72, 0xE9, 0xBA, 0xB8, 0x69, 0x75, 0xAA, 0x44, 0x66, 0xEB, 0x0D, 0x44, 0x33, 0x36, 0xC8, 0xAB, 
+  0xF9, 0x08, 0x83, 0x28, 0x2A, 0x51, 0xD2, 0xA4, 0xB0, 0xF0, 0x30, 0xBF, 0x85, 0xD3, 0x26, 0x4F, 0xB9, 0x68, 0xDC, 0xC5, 
+  0x1B, 0xD7, 0xEF, 0xDC, 0xB1, 0xF5, 0x10, 0x84, 0x4C, 0x3E, 0x3F, 0x69, 0x31, 0x31, 0xB3, 0xA9, 0xB2, 0x8E, 0x70, 0xBA, 
+  0x69, 0xC5, 0x66, 0x4E, 0x08, 0xE1, 0x7C, 0x8F, 0xCD, 0xAB, 0xB7, 0xED, 0xDB, 0x79, 0xE0, 0x9A, 0x2B, 0xAE, 0x45, 0x19, 
+  0x0F, 0xDD, 0xFF, 0x04, 0xEB, 0x7B, 0x6F, 0xFC, 0xE0, 0x8F, 0x7F, 0xF8, 0x8B, 0xD9, 0x39, 0xEB, 0x64, 0x4A, 0x2A, 0xDC, 
+  0x3F, 0xFD, 0xE9, 0x4F, 0xDF, 0x7B, 0xE3, 0x6D, 0x4A, 0xEE, 0x37, 0xDF, 0x7C, 0xEB, 0x2F, 0x7F, 0xF9, 0x8B, 0xCD, 0xB5, 
+  0xAC, 0x0E, 0x34, 0xC5, 0x12, 0x9D, 0xFD, 0xE3, 0x1F, 0x4F, 0x3F, 0xF9, 0xEC, 0xD1, 0xFD, 0x47, 0xB7, 0xAC, 0xDD, 0x2A, 
+  0x67, 0x60, 0x0C, 0x2C, 0xE7, 0x7F, 0x1D, 0xDE, 0x77, 0x84, 0xFE, 0x2E, 0x1E, 0xCF, 0x13, 0x5E, 0xFF, 0xD6, 0x77, 0xD9, 
+  0x39, 0xAB, 0xF4, 0x56, 0xC0, 0x33, 0x29, 0x36, 0x11, 0xFA, 0x37, 0xC2, 0x85, 0x75, 0xC0, 0x6D, 0x7A, 0x2C, 0xB7, 0xE2, 
+  0x07, 0x5F, 0xB6, 0x1C, 0x3F, 0x38, 0x25, 0x8B, 0xC6, 0xA1, 0x22, 0x19, 0x96, 0xA7, 0x2D, 0x43, 0x14, 0xBE, 0xE9, 0xFE, 
+  0xCF, 0x9E, 0x36, 0x0D, 0xCE, 0xE1, 0xB6, 0xCD, 0x7B, 0xD7, 0xAE, 0xDA, 0xDA, 0xDB, 0xB1, 0x98, 0x94, 0x89, 0xEC, 0x05, 
+  0x88, 0xB8, 0xFD, 0xD6, 0xBB, 0x68, 0x99, 0xA9, 0x29, 0x99, 0x1D, 0xDB, 0x9F, 0x53, 0xBE, 0xAE, 0x5B, 0xB9, 0x3E, 0x2D, 
+  0x2A, 0x85, 0x6C, 0x5A, 0x72, 0x09, 0x13, 0x0C, 0x64, 0xB0, 0x6E, 0x62, 0xB2, 0x6D, 0xF6, 0x42, 0x34, 0xE7, 0x11, 0x61, 
+  0x62, 0x39, 0x51, 0x3A, 0x0D, 0x68, 0x02, 0x64, 0x13, 0xC2, 0xE2, 0x19, 0x0F, 0xCC, 0x9F, 0x36, 0x77, 0xE6, 0xE4, 0x99, 
+  0x97, 0x6D, 0x39, 0xB8, 0x74, 0x70, 0x1D, 0xE9, 0x60, 0x46, 0x5C, 0x3A, 0x1E, 0x46, 0x29, 0x8E, 0x7B, 0x41, 0xBD, 0x5E, 
+  0xD2, 0xB9, 0x84, 0xB0, 0xC9, 0x81, 0x5E, 0x1B, 0x97, 0x6D, 0xDC, 0xB6, 0x61, 0x37, 0xA3, 0xE9, 0x23, 0xFB, 0x8F, 0xDE, 
+  0x76, 0xE3, 0x1D, 0x0F, 0x3F, 0xF0, 0xE4, 0xE3, 0x8F, 0x3C, 0xFD, 0x9D, 0x6F, 0x7F, 0xFF, 0x2F, 0x7F, 0xFE, 0x87, 0x1A, 
+  0x87, 0x00, 0x92, 0x04, 0xF2, 0x4F, 0x1D, 0x6B, 0x77, 0xAB, 0x09, 0x9B, 0xDA, 0x7A, 0xFD, 0xC0, 0x20, 0x18, 0x55, 0xB7, 
+  0x3C, 0xF7, 0xA3, 0x8F, 0xFE, 0xF9, 0xFE, 0xFB, 0xBF, 0xFA, 0xF1, 0x0F, 0xDF, 0xF9, 0xD9, 0xCF, 0x7E, 0xF1, 0xF7, 0x8F, 
+  0x64, 0xD6, 0xA4, 0x8F, 0x43, 0x48, 0x88, 0x0F, 0x8E, 0xE5, 0x5C, 0x09, 0xDA, 0x79, 0x73, 0x2E, 0x9D, 0x9E, 0x18, 0x11, 
+  0x8B, 0xE9, 0x10, 0xD5, 0x44, 0x07, 0xB1, 0x29, 0x2C, 0x8F, 0xE8, 0x4F, 0xAD, 0x09, 0x9F, 0x31, 0xD2, 0xD7, 0x8E, 0xA0, 
+  0x6D, 0x0D, 0x2A, 0x70, 0x1B, 0xC4, 0x10, 0x56, 0x88, 0x66, 0x93, 0x88, 0x1E, 0xFA, 0x54, 0xC0, 0xFC, 0x79, 0x34, 0x15, 
+  0xB0, 0x71, 0xBA, 0xF6, 0x3B, 0xB6, 0x1F, 0xDE, 0xB7, 0xE3, 0xC8, 0x9A, 0xE5, 0x1B, 0xEA, 0x2B, 0x1A, 0xA8, 0x59, 0x68, 
+  0x54, 0x90, 0xE1, 0x11, 0x21, 0x0D, 0x16, 0x1B, 0x65, 0x7C, 0xF1, 0x39, 0xBD, 0x04, 0x68, 0x10, 0x29, 0xE1, 0x89, 0x05, 
+  0x09, 0xD9, 0xB4, 0xFB, 0x65, 0xAE, 0x9B, 0xA2, 0x8D, 0x2D, 0xB9, 0x16, 0xC6, 0x03, 0x19, 0x1E, 0xD3, 0xF6, 0xD4, 0x3C, 
+  0xDA, 0xF4, 0xE0, 0x2C, 0x8B, 0xF9, 0x3B, 0x0D, 0x3E, 0x22, 0x1E, 0xFA, 0x9B, 0x37, 0xD9, 0x97, 0x82, 0x76, 0xE7, 0x96, 
+  0x83, 0xE5, 0x39, 0x55, 0xE9, 0xD1, 0xA9, 0xD4, 0x6E, 0x3C, 0xC8, 0x89, 0x06, 0x38, 0x04, 0xE7, 0x17, 0x70, 0x18, 0x06, 
+  0x8C, 0x3F, 0xB6, 0x6A, 0xA1, 0x95, 0x8E, 0x86, 0x45, 0xC3, 0x03, 0xAB, 0xD6, 0x2C, 0xDD, 0xB8, 0x79, 0xC3, 0x8E, 0xAB, 
+  0x0F, 0x5F, 0xFF, 0xF0, 0x43, 0x4F, 0x3D, 0xF6, 0xE8, 0xD3, 0xAF, 0xBF, 0xFA, 0x06, 0xDB, 0xF9, 0x8D, 0xD4, 0x14, 0xF3, 
+  0xE9, 0x79, 0x48, 0xF9, 0x86, 0x95, 0xA8, 0xF4, 0x4F, 0xF9, 0xE3, 0x82, 0x92, 0xA6, 0xBF, 0xF6, 0xC7, 0x34, 0xA3, 0x3E, 
+  0x97, 0xFC, 0xF5, 0x81, 0xBB, 0x1F, 0x4C, 0x89, 0x4C, 0x04, 0x0F, 0x79, 0x0F, 0x53, 0x2F, 0x9A, 0x12, 0x11, 0x16, 0x4D, 
+  0x36, 0x41, 0xCD, 0x4F, 0x48, 0xA3, 0xEA, 0x64, 0xE1, 0xCD, 0xAA, 0x09, 0xB3, 0x4E, 0xE1, 0x0A, 0x3C, 0xEE, 0xE8, 0xC0, 
+  0x72, 0x34, 0xC6, 0xB0, 0x65, 0x64, 0x6A, 0x91, 0x3A, 0xC2, 0xC4, 0x37, 0x4D, 0x1E, 0xC9, 0xE5, 0x49, 0x5D, 0xD8, 0xA5, 
+  0x25, 0xFD, 0xB5, 0x71, 0xE7, 0xD2, 0x79, 0xA6, 0x5D, 0xBA, 0x7C, 0x70, 0xD5, 0xEE, 0x1D, 0x07, 0xAF, 0x38, 0x72, 0xDD, 
+  0xDE, 0xDD, 0x47, 0x07, 0xFB, 0x96, 0x92, 0x5C, 0x31, 0xE1, 0x22, 0x5C, 0xDF, 0x7C, 0xFC, 0x66, 0xAA, 0x2A, 0x45, 0xE4, 
+  0x37, 0xBE, 0xF7, 0x7D, 0x86, 0x97, 0x30, 0x21, 0x78, 0x73, 0x24, 0x70, 0x23, 0x0D, 0x45, 0x14, 0x9C, 0x21, 0x53, 0x46, 
+  0xE6, 0x59, 0x54, 0x21, 0xA4, 0xDE, 0x24, 0xE0, 0x14, 0x1F, 0xD2, 0x42, 0xCF, 0x2D, 0x2F, 0xCF, 0x29, 0xC9, 0x8C, 0x15, 
+  0x68, 0x62, 0x53, 0x78, 0x61, 0x7A, 0x11, 0x46, 0x97, 0x1A, 0x9E, 0x42, 0x1E, 0x92, 0x18, 0x9A, 0x58, 0x9C, 0x5E, 0x9A, 
+  0x12, 0x91, 0x92, 0x15, 0x9F, 0x0B, 0x11, 0x9F, 0x13, 0x8A, 0x84, 0x99, 0x50, 0x58, 0x0F, 0x4D, 0x86, 0xD3, 0x67, 0xD8, 
+  0x9C, 0xBC, 0x6A, 0xE9, 0xBA, 0x6D, 0x6B, 0xB6, 0x6F, 0x5D, 0xBF, 0xE3, 0xE8, 0xE1, 0xAB, 0xEE, 0xBD, 0xEB, 0x41, 0x92, 
+  0xA8, 0x5F, 0xBC, 0xFF, 0xE1, 0x7F, 0xFF, 0xEB, 0x14, 0xD8, 0x5A, 0x3A, 0x78, 0x45, 0xAF, 0xC8, 0xA3, 0x75, 0x86, 0x5E, 
+  0xD8, 0xDF, 0xDA, 0xA8, 0xCE, 0x23, 0x9F, 0x7C, 0x26, 0x9E, 0x81, 0x32, 0xEF, 0xBF, 0xE3, 0x7E, 0x62, 0xD8, 0xCE, 0x0D, 
+  0x3B, 0x1A, 0x6B, 0x9A, 0x2F, 0x19, 0x37, 0x21, 0x22, 0x28, 0x88, 0x94, 0x9A, 0xE1, 0x20, 0x7E, 0x60, 0xD4, 0x90, 0xA4, 
+  0xED, 0x48, 0x57, 0x19, 0x56, 0x13, 0x63, 0x2F, 0x7C, 0x4E, 0xA6, 0x45, 0x7A, 0xE9, 0x02, 0xC2, 0x73, 0x76, 0xB7, 0x42, 
+  0x68, 0x02, 0x63, 0xBA, 0x0B, 0xA9, 0xE4, 0x2D, 0x44, 0x7F, 0xFF, 0x79, 0xF3, 0xCF, 0x39, 0xE7, 0x1C, 0x0E, 0x66, 0x64, 
+  0x2F, 0xC6, 0xAC, 0x4B, 0xA7, 0x31, 0x5B, 0xA7, 0x64, 0x43, 0x19, 0x74, 0x78, 0x98, 0xC6, 0x6C, 0xD9, 0xB8, 0xBB, 0xA9, 
+  0xA6, 0x03, 0xE6, 0x04, 0x43, 0xCA, 0xAE, 0x96, 0x8E, 0xDB, 0xAF, 0xBD, 0xF5, 0x77, 0xBF, 0xFD, 0xD3, 0x6D, 0x37, 0xDF, 
+  0x87, 0xA5, 0x10, 0xB8, 0x28, 0x89, 0x51, 0x27, 0x7A, 0x82, 0x3C, 0x0A, 0x5F, 0x9A, 0xFF, 0xC2, 0x84, 0x84, 0x74, 0x9B, 
+  0xFC, 0x95, 0x17, 0xA1, 0x37, 0x40, 0x1E, 0x45, 0x0B, 0xA4, 0xB6, 0xA8, 0x8A, 0xF1, 0x4B, 0x56, 0x7C, 0x3A, 0x6A, 0xC6, 
+  0x7B, 0x32, 0xD8, 0x1C, 0x09, 0x43, 0x22, 0x26, 0x93, 0x44, 0x80, 0x6D, 0x7B, 0x40, 0x22, 0x64, 0x16, 0xCA, 0xC9, 0x9A, 
+  0xB2, 0xA6, 0xFA, 0xF2, 0xB6, 0xAA, 0xA2, 0xC6, 0xA2, 0x4C, 0xFA, 0xBE, 0xB5, 0x15, 0xB9, 0xB5, 0x1C, 0x35, 0x30, 0xD8, 
+  0xCD, 0x01, 0x87, 0x43, 0xAB, 0x87, 0xD6, 0xB0, 0x6D, 0xF6, 0xD0, 0x9E, 0xA3, 0xD7, 0x5E, 0x7D, 0xE3, 0x03, 0xF7, 0x3E, 
+  0x06, 0x87, 0x83, 0x2E, 0x13, 0x27, 0x4F, 0x69, 0xB6, 0xEA, 0x5A, 0xBA, 0x24, 0xAF, 0x9C, 0xD2, 0x42, 0x18, 0xFB, 0x1F, 
+  0xB6, 0xFA, 0xFF, 0xE7, 0x33, 0xD2, 0x53, 0x3D, 0x92, 0x67, 0x0C, 0x64, 0xA9, 0x86, 0x78, 0xE6, 0xDD, 0xB7, 0xDD, 0x45, 
+  0xEB, 0x65, 0xCB, 0xBA, 0xCB, 0xD6, 0x2F, 0x59, 0x3F, 0xF9, 0xBC, 0xF1, 0xA1, 0xF3, 0x64, 0xDF, 0x03, 0xB3, 0x90, 0x84, 
+  0xE8, 0x78, 0x3E, 0x9A, 0x24, 0x14, 0x31, 0x8E, 0x1A, 0x54, 0x07, 0xA0, 0x93, 0xC7, 0x21, 0x46, 0x5D, 0x3B, 0x3A, 0xF0, 
+  0xCA, 0x5D, 0xD1, 0xDF, 0xE1, 0x2A, 0x01, 0xD9, 0xEE, 0x54, 0xC8, 0x56, 0xDB, 0xBC, 0x16, 0xFF, 0x83, 0x6E, 0x33, 0x6D, 
+  0x4E, 0xC8, 0x9D, 0x17, 0x5C, 0x70, 0xC1, 0xE9, 0x67, 0x72, 0x26, 0xA5, 0xFC, 0x70, 0xCE, 0xE5, 0x05, 0xE7, 0x8E, 0x9B, 
+  0x37, 0x75, 0x0E, 0x41, 0x95, 0x3D, 0xC3, 0x3B, 0x36, 0xEF, 0xDB, 0xBD, 0xE3, 0xF0, 0x60, 0xFF, 0xEA, 0xCC, 0xC4, 0x1C, 
+  0xBF, 0x69, 0xF3, 0xC3, 0x16, 0x84, 0xD2, 0x22, 0xA6, 0x15, 0x01, 0x33, 0x85, 0x77, 0x9C, 0x1C, 0x97, 0xA2, 0x8D, 0x43, 
+  0xD4, 0xC0, 0x14, 0x2C, 0x27, 0x3E, 0x53, 0x02, 0x72, 0x74, 0x2A, 0x65, 0x07, 0x05, 0x84, 0x54, 0x7F, 0x79, 0x15, 0xA8, 
+  0x01, 0x6A, 0xC5, 0x65, 0x1B, 0x77, 0xDC, 0x72, 0xED, 0xAD, 0xE0, 0x3B, 0xD9, 0x7D, 0x4F, 0x63, 0x0F, 0xC7, 0x77, 0x70, 
+  0xAC, 0x47, 0x6A, 0x74, 0x5A, 0x42, 0x74, 0x12, 0xEF, 0x84, 0xBD, 0x37, 0x4C, 0x57, 0x8A, 0x0B, 0xCA, 0xD3, 0xE2, 0xB2, 
+  0xB3, 0xE2, 0xF3, 0x7B, 0x3B, 0x96, 0xB2, 0x45, 0xB0, 0xA6, 0x84, 0x53, 0x80, 0x96, 0x41, 0x88, 0xE7, 0x0C, 0x42, 0x8E, 
+  0x18, 0xDC, 0xB2, 0x6A, 0x2B, 0x99, 0xFE, 0xEE, 0x9D, 0xFB, 0x8E, 0x5D, 0x71, 0xD5, 0x9D, 0xB7, 0xDD, 0x4B, 0xF2, 0x4A, 
+  0xAC, 0x7E, 0xE7, 0xC7, 0x3F, 0x23, 0x9D, 0xA3, 0xBC, 0xE0, 0x74, 0x9C, 0x77, 0xDF, 0xF9, 0x05, 0xEB, 0x27, 0xEF, 0xFC, 
+  0xEC, 0xED, 0xB7, 0xDE, 0x31, 0x8F, 0xBF, 0x4F, 0xB3, 0x8F, 0xEA, 0xFA, 0x5F, 0xFF, 0xFA, 0xB7, 0x56, 0x82, 0xC6, 0x41, 
+  0xBE, 0xA0, 0x6F, 0xFB, 0xDB, 0x0F, 0xFF, 0x70, 0xDB, 0x8D, 0xB7, 0x93, 0x62, 0x0C, 0x75, 0x0F, 0x5D, 0x71, 0xF8, 0x86, 
+  0xD0, 0xB9, 0xC1, 0xF3, 0x2E, 0x9D, 0x1D, 0x11, 0x14, 0x12, 0x1D, 0x1A, 0x8E, 0x6D, 0xE1, 0x07, 0x9C, 0x72, 0xC1, 0xF6, 
+  0x08, 0x29, 0x36, 0x8D, 0x43, 0xB8, 0x3A, 0x38, 0xB5, 0x1A, 0xF8, 0xAD, 0xE8, 0xE0, 0xCB, 0xB8, 0x79, 0xAA, 0x0C, 0x8D, 
+  0x99, 0xDA, 0x54, 0x30, 0x6A, 0x20, 0x7D, 0x94, 0x6E, 0x33, 0x19, 0x58, 0x74, 0x50, 0x38, 0xFC, 0x11, 0x08, 0xFE, 0x53, 
+  0x2F, 0x99, 0x74, 0xE1, 0xF9, 0x17, 0x7C, 0xED, 0x6B, 0x5F, 0x63, 0x37, 0x80, 0x3D, 0x9D, 0xF4, 0x8C, 0xD3, 0xCE, 0xBE, 
+  0x74, 0xC2, 0x64, 0x32, 0x84, 0xBE, 0xF6, 0xC1, 0xED, 0x1B, 0xF7, 0xAC, 0x5E, 0xB9, 0x8D, 0x8D, 0x92, 0x64, 0xB4, 0x91, 
+  0x61, 0xB1, 0x6D, 0x0D, 0x5D, 0x6C, 0xEA, 0x8B, 0x0F, 0xE7, 0xFD, 0xA5, 0xA0, 0x2D, 0x3C, 0x23, 0x2D, 0x3A, 0x19, 0xC0, 
+  0xC1, 0xF6, 0x8F, 0xEC, 0xBB, 0xF2, 0x91, 0xFB, 0x1F, 0xFD, 0xE6, 0xB3, 0x2F, 0x40, 0x72, 0x79, 0xEB, 0xAD, 0x1F, 0xFC, 
+  0xFA, 0xD7, 0xBF, 0xA6, 0xF7, 0xA0, 0xE6, 0x48, 0xDB, 0x87, 0x0A, 0x80, 0xE3, 0x1C, 0x81, 0xA9, 0xA2, 0xB4, 0x12, 0x8C, 
+  0x80, 0xB0, 0xC4, 0xDB, 0x60, 0x14, 0x91, 0x12, 0x97, 0x91, 0x1A, 0x9F, 0x99, 0x40, 0x00, 0x8C, 0xCD, 0xC8, 0x4F, 0x29, 
+  0xAD, 0x2B, 0x6B, 0xED, 0x6C, 0x1D, 0x6A, 0xAD, 0xEF, 0xC1, 0x11, 0xE5, 0x78, 0xB7, 0xD6, 0x01, 0x0E, 0x55, 0xE3, 0x70, 
+  0x0B, 0x80, 0x9B, 0xBA, 0x6C, 0xFF, 0xAE, 0x83, 0x87, 0xF6, 0x1E, 0x39, 0x76, 0xE8, 0x2A, 0xB2, 0x58, 0x0A, 0x3D, 0x60, 
+  0xEA, 0x81, 0x7B, 0x1F, 0xB9, 0xEF, 0xEE, 0x87, 0xEE, 0xB9, 0xFD, 0xBE, 0x07, 0xEF, 0x79, 0x98, 0xBB, 0x4F, 0x3D, 0xF9, 
+  0xFC, 0x37, 0x5F, 0x78, 0x95, 0xF9, 0xCF, 0x8B, 0xDF, 0x7C, 0x95, 0x21, 0xD2, 0x0F, 0x7E, 0xF8, 0xD3, 0xF7, 0xDE, 0xFD, 
+  0xE5, 0x7B, 0x3F, 0xFB, 0xE5, 0x4F, 0x7F, 0xFC, 0xF3, 0x17, 0xBF, 0xF9, 0xAD, 0x6B, 0xAF, 0xBC, 0x91, 0x7E, 0x0C, 0x2D, 
+  0xB2, 0x03, 0x7B, 0x8F, 0xA2, 0x60, 0x50, 0x28, 0x74, 0x41, 0x20, 0x26, 0x15, 0x1F, 0x16, 0x1D, 0x13, 0x1A, 0xCB, 0x74, 
+  0x96, 0x3A, 0x1F, 0x1D, 0x8C, 0xB8, 0x42, 0x2C, 0x21, 0xDA, 0x09, 0x0F, 0x63, 0x2E, 0x54, 0x43, 0x3E, 0x1E, 0x05, 0xC8, 
+  0x64, 0x6E, 0x0C, 0x19, 0xCF, 0x4E, 0x47, 0x6D, 0x0F, 0x56, 0x2A, 0x72, 0x74, 0x10, 0x9B, 0x4C, 0x35, 0x88, 0x14, 0x28, 
+  0x65, 0x83, 0xFD, 0x69, 0x73, 0xCE, 0xA7, 0xB7, 0x33, 0xE3, 0xD2, 0xA9, 0x53, 0x26, 0x4F, 0x9A, 0x38, 0xE1, 0x62, 0x9A, 
+  0x3C, 0xE3, 0xC6, 0x8D, 0x83, 0x0E, 0x2D, 0xA7, 0xC3, 0x9E, 0x26, 0xCE, 0x31, 0x6B, 0xEA, 0x4C, 0x68, 0x9D, 0x4B, 0xFB, 
+  0x57, 0xB0, 0xB1, 0x7B, 0x71, 0xFF, 0x5A, 0x30, 0x84, 0xE7, 0xAB, 0x99, 0xE0, 0xBF, 0xB8, 0x2D, 0xCA, 0xA6, 0x3B, 0x86, 
+  0xD1, 0xD9, 0x7C, 0xC3, 0x8B, 0xCB, 0x92, 0x5F, 0x7D, 0xF1, 0xD9, 0xDF, 0xFF, 0xF6, 0x11, 0x49, 0x0E, 0x10, 0x4F, 0xDB, 
+  0xA3, 0x3C, 0xBB, 0x9C, 0xCA, 0x08, 0xF4, 0xE3, 0x45, 0x80, 0x32, 0x34, 0x4D, 0x0B, 0xAB, 0x30, 0xB3, 0xAC, 0xA4, 0xB0, 
+  0xA2, 0x20, 0xB7, 0xA2, 0xBA, 0xA4, 0x6D, 0xF3, 0xFA, 0x3D, 0x9C, 0xFE, 0x00, 0x8D, 0xB3, 0xA3, 0x65, 0x90, 0x19, 0x35, 
+  0x34, 0xC8, 0xA1, 0x9E, 0xE1, 0xB5, 0xC3, 0x9B, 0x09, 0x2A, 0xCC, 0x1B, 0x08, 0x12, 0x7B, 0xB7, 0x1D, 0x38, 0xB4, 0xE7, 
+  0x4A, 0x5A, 0x81, 0xD7, 0x1C, 0xBB, 0xF1, 0xFA, 0xE3, 0x37, 0xDF, 0x70, 0xFD, 0xED, 0x80, 0xD5, 0xF5, 0xC7, 0x6E, 0xB8, 
+  0xE1, 0xDA, 0xDB, 0x6E, 0xBE, 0xF9, 0xEE, 0xDB, 0x6F, 0xB9, 0xFB, 0x96, 0xEB, 0x6F, 0xBB, 0xEB, 0xD6, 0x7B, 0x50, 0xCC, 
+  0xC3, 0x0F, 0x3C, 0x7E, 0xDB, 0xCD, 0x77, 0xDD, 0x7B, 0xD7, 0xC3, 0xDC, 0xEE, 0xDF, 0x75, 0x60, 0xD5, 0xC0, 0x30, 0x50, 
+  0xC9, 0x21, 0x16, 0x57, 0x5E, 0x7E, 0x3D, 0x19, 0xDA, 0x94, 0xF3, 0x2F, 0x0E, 0x5D, 0x18, 0x12, 0x15, 0x1A, 0x89, 0x34, 
+  0xE8, 0x74, 0xA1, 0x03, 0xF2, 0x69, 0xAC, 0x8A, 0x37, 0x96, 0x12, 0x65, 0xE3, 0x81, 0x34, 0x86, 0x4F, 0xB9, 0x90, 0x80, 
+  0xE8, 0xC0, 0xDA, 0xFB, 0xC9, 0xCC, 0x48, 0xEF, 0x58, 0x4E, 0xB1, 0x08, 0x1D, 0xB0, 0xA7, 0x25, 0x39, 0x31, 0x2D, 0x2E, 
+  0x46, 0x4A, 0x59, 0xA2, 0x50, 0x44, 0x48, 0x28, 0xA0, 0x44, 0x8B, 0x8D, 0x82, 0x16, 0xCE, 0xF3, 0xFC, 0x59, 0x73, 0xFD, 
+  0x66, 0xCE, 0x9E, 0x33, 0xDD, 0x77, 0xE6, 0xD4, 0x69, 0x6C, 0x0E, 0x98, 0x3C, 0x61, 0xE2, 0x79, 0x17, 0x9C, 0xCF, 0x69, 
+  0xBC, 0x20, 0xD5, 0xB8, 0x73, 0xCE, 0x9B, 0x76, 0xE9, 0xF4, 0x4B, 0x27, 0x4F, 0x99, 0x36, 0x69, 0x12, 0xC3, 0x4B, 0xDE, 
+  0x34, 0x6F, 0x74, 0xE1, 0xDC, 0x85, 0xA0, 0x39, 0x21, 0x97, 0x4D, 0xC5, 0x77, 0xDC, 0x7A, 0xCF, 0x2F, 0x7F, 0xF9, 0xC1, 
+  0xC9, 0x7D, 0x69, 0x14, 0x03, 0x4C, 0x93, 0xCE, 0xDF, 0x70, 0xF5, 0x2D, 0xEB, 0x96, 0x6C, 0x84, 0x79, 0x97, 0x93, 0x90, 
+  0x03, 0x93, 0x2E, 0x3E, 0x26, 0xB9, 0xA4, 0xB0, 0x86, 0x29, 0x7C, 0x5C, 0x64, 0x2C, 0x4E, 0x56, 0x9C, 0x2D, 0xE7, 0x08, 
+  0xF5, 0x2E, 0x5A, 0xCA, 0xB9, 0x49, 0x83, 0xBD, 0xAB, 0x16, 0x19, 0x57, 0xE0, 0x08, 0x31, 0x0E, 0xE4, 0xE0, 0x9C, 0x2C, 
+  0x36, 0x89, 0x2C, 0x5F, 0xBC, 0x61, 0xE5, 0x92, 0xF5, 0x6B, 0x57, 0x6F, 0xE3, 0x04, 0xDA, 0x65, 0x03, 0xAB, 0x57, 0x2C, 
+  0x5E, 0x43, 0xFF, 0x83, 0x53, 0x6A, 0x77, 0x6C, 0xDC, 0xBD, 0x73, 0xD3, 0xBE, 0xDD, 0xDB, 0xF7, 0x72, 0xEA, 0xD1, 0xC1, 
+  0xDD, 0x97, 0xD3, 0x95, 0xDA, 0xBA, 0x61, 0xFB, 0xDE, 0xCB, 0x0E, 0x62, 0xE9, 0xFB, 0xB6, 0x1F, 0x3C, 0x7C, 0xE0, 0xD8, 
+  0x15, 0x87, 0x8E, 0x5D, 0x71, 0xE4, 0xF8, 0x65, 0x9B, 0x76, 0xAF, 0x59, 0xBC, 0x8A, 0xD3, 0x90, 0x00, 0x49, 0x36, 0x72, 
+  0x1F, 0xD8, 0x77, 0x0D, 0x86, 0x38, 0x65, 0xFC, 0xC4, 0x88, 0xC0, 0x08, 0x00, 0x96, 0xE6, 0x0A, 0x4E, 0x89, 0x4C, 0x50, 
+  0x00, 0x23, 0x29, 0x5C, 0x41, 0x23, 0xB3, 0x0D, 0x0C, 0xA3, 0x71, 0x69, 0x44, 0x25, 0x3E, 0x9A, 0x74, 0x4A, 0xAA, 0x6E, 
+  0x08, 0x01, 0xF9, 0xD0, 0x31, 0xD9, 0x16, 0x9A, 0x31, 0x76, 0x34, 0xAA, 0x39, 0x8C, 0x36, 0xD7, 0xB4, 0xF2, 0x16, 0x57, 
+  0x88, 0x4C, 0xE0, 0xBF, 0xF2, 0xBF, 0xE9, 0xAF, 0x71, 0xDE, 0x0C, 0xBB, 0xB1, 0xD9, 0x18, 0x03, 0xE7, 0x19, 0xEA, 0x39, 
+  0x3B, 0xDC, 0x45, 0x25, 0xB3, 0xE7, 0x53, 0xCA, 0xC1, 0xC9, 0xA5, 0xF5, 0xE6, 0x3B, 0x7D, 0xC6, 0xB4, 0xA9, 0x53, 0xD0, 
+  0x0A, 0x44, 0x68, 0xC6, 0x96, 0xBC, 0x6F, 0x9C, 0x37, 0x21, 0x2A, 0x6A, 0xF6, 0x74, 0x5F, 0x32, 0xEB, 0x25, 0x7D, 0xAB, 
+  0xA3, 0x16, 0x46, 0x86, 0xCD, 0x0D, 0xA6, 0xCE, 0x80, 0xE0, 0xF5, 0xE4, 0x63, 0x5F, 0x7F, 0xEF, 0xBD, 0x9F, 0xFF, 0xE5, 
+  0x2F, 0x7F, 0xA3, 0x3E, 0xA2, 0x13, 0xF7, 0xFE, 0xCF, 0x3F, 0x00, 0xC1, 0x8F, 0x1D, 0x3E, 0xCE, 0x11, 0x2D, 0x14, 0x04, 
+  0x32, 0x13, 0x4E, 0x2F, 0x4E, 0x4D, 0x48, 0x47, 0x85, 0xC5, 0xB9, 0x95, 0x7C, 0xE0, 0xF4, 0x14, 0x32, 0x66, 0x46, 0x13, 
+  0x15, 0x04, 0x06, 0xF8, 0x4E, 0x54, 0xE0, 0xCC, 0xEC, 0x2A, 0x8A, 0xEA, 0x0A, 0x32, 0x4A, 0xEB, 0x4B, 0x5A, 0x09, 0xD7, 
+  0xAC, 0xC6, 0xDA, 0x45, 0x95, 0xC5, 0x74, 0x18, 0x06, 0x87, 0x7A, 0x56, 0xEA, 0xB1, 0xA9, 0x9C, 0xDF, 0xC7, 0x2D, 0x30, 
+  0x85, 0x7F, 0x0C, 0x0F, 0xAD, 0x25, 0x9B, 0x58, 0xDC, 0x3D, 0xBC, 0x7A, 0xC9, 0xA6, 0x95, 0x03, 0xAB, 0x88, 0x1F, 0x1B, 
+  0x56, 0x6C, 0xA5, 0x2A, 0xA6, 0x08, 0xDD, 0xB8, 0x72, 0xDB, 0x96, 0x35, 0xDB, 0xB7, 0xAD, 0xDB, 0x45, 0xCA, 0x8B, 0xB3, 
+  0xD2, 0x71, 0x41, 0x4A, 0x1C, 0x87, 0xB3, 0x6D, 0xD3, 0x01, 0xA8, 0xF3, 0x93, 0x2E, 0xBE, 0x88, 0x8F, 0x0F, 0x95, 0x4F, 
+  0xFC, 0x20, 0x3C, 0x9C, 0x78, 0xA0, 0xFD, 0x2E, 0xD3, 0x7F, 0x4C, 0xB0, 0x6A, 0xA0, 0x9D, 0x47, 0xC2, 0xAA, 0x77, 0xC7, 
+  0x2C, 0x1F, 0x41, 0x7C, 0x43, 0x4E, 0x92, 0xA1, 0x8A, 0x69, 0x42, 0x90, 0xAA, 0x8F, 0x61, 0xC5, 0xD8, 0x96, 0x8E, 0xFA, 
+  0x81, 0x56, 0x1F, 0x40, 0xB9, 0xFE, 0x1B, 0x3A, 0x0A, 0xFC, 0x7B, 0x9A, 0x0A, 0x64, 0x4A, 0x51, 0x81, 0x61, 0x20, 0x3E, 
+  0xDD, 0x05, 0x3C, 0x03, 0x7D, 0xA0, 0x15, 0x56, 0xB0, 0x5F, 0x00, 0x8A, 0x91, 0xE5, 0x17, 0x18, 0xE2, 0x17, 0x4A, 0x0B, 
+  0x88, 0xA7, 0xC1, 0x2C, 0x32, 0x6F, 0x3A, 0x3A, 0xC0, 0xCF, 0x7F, 0xCA, 0x84, 0xC9, 0x1C, 0x73, 0xB0, 0x7D, 0xF3, 0x01, 
+  0x4E, 0x19, 0x66, 0xA6, 0x04, 0x39, 0x0E, 0x96, 0x51, 0x67, 0x4B, 0x17, 0x0D, 0x35, 0x3A, 0x42, 0x57, 0x1F, 0xBE, 0x96, 
+  0xC3, 0x40, 0xE8, 0xF0, 0x0C, 0x0F, 0xAC, 0xA1, 0x37, 0xC0, 0x1E, 0x50, 0x80, 0x88, 0x6E, 0x55, 0x44, 0x70, 0x14, 0x15, 
+  0x5C, 0x5A, 0x62, 0x06, 0xBE, 0x08, 0xDD, 0x3A, 0x3B, 0x35, 0x1F, 0x10, 0xE0, 0x42, 0x76, 0x18, 0x64, 0x15, 0x56, 0x31, 
+  0xC5, 0xAB, 0x6A, 0xCD, 0x48, 0x85, 0xAE, 0xDD, 0x52, 0x96, 0x57, 0x5B, 0x98, 0x59, 0xC1, 0x49, 0x87, 0x9C, 0xB6, 0xC4, 
+  0x86, 0xF8, 0xEA, 0xD2, 0x66, 0x9C, 0xA3, 0xBF, 0x6B, 0x79, 0x57, 0xDB, 0xE2, 0xBE, 0xCE, 0x65, 0xEC, 0xE1, 0x31, 0xC7, 
+  0xD6, 0xF4, 0x0E, 0x2D, 0x5A, 0x41, 0x85, 0xB1, 0xA4, 0x67, 0xD5, 0xFA, 0xD5, 0x3B, 0xE4, 0xA8, 0xE9, 0x9E, 0xE5, 0xAB, 
+  0x86, 0x37, 0xE0, 0x2E, 0x12, 0xDB, 0x3B, 0xFA, 0xF1, 0x3F, 0x52, 0x5E, 0x08, 0xE7, 0xE4, 0x0B, 0x99, 0xD1, 0x19, 0xA9, 
+  0x11, 0x49, 0xEC, 0x42, 0xA4, 0x6B, 0x82, 0xA3, 0xF3, 0x89, 0x60, 0xE8, 0xC4, 0x85, 0x46, 0xB1, 0x5B, 0x54, 0x04, 0x12, 
+  0x25, 0x99, 0x82, 0x66, 0x47, 0x9A, 0x0E, 0x59, 0x14, 0x1A, 0x23, 0x7D, 0x45, 0x63, 0x1F, 0x27, 0xF5, 0x34, 0xD2, 0x77, 
+  0x90, 0x27, 0xCD, 0xEC, 0x8A, 0x76, 0x49, 0xA9, 0x96, 0x15, 0xE3, 0x74, 0x37, 0xE3, 0x9D, 0x3E, 0xB3, 0x99, 0xBA, 0x18, 
+  0x5F, 0xA3, 0xE9, 0x1F, 0x81, 0x1A, 0xC4, 0x21, 0x00, 0x68, 0x6E, 0x51, 0x06, 0x66, 0x3E, 0x76, 0x05, 0x84, 0x10, 0x3C, 
+  0x88, 0x5D, 0x2C, 0x14, 0xC0, 0xD8, 0x52, 0xFF, 0x84, 0x07, 0x2F, 0x99, 0x48, 0x48, 0xBF, 0xA8, 0xB1, 0xAA, 0x71, 0xD7, 
+  0xD6, 0x03, 0x38, 0xF8, 0xA6, 0x0D, 0x7B, 0xA0, 0x7C, 0xD5, 0x57, 0xC9, 0xB9, 0x2D, 0xB4, 0x48, 0xDB, 0x9B, 0xE4, 0x08, 
+  0x1F, 0x33, 0x5F, 0x6C, 0x29, 0x97, 0xE1, 0x49, 0x59, 0x76, 0x42, 0x1E, 0x2A, 0xAF, 0xAE, 0x68, 0x84, 0x31, 0x47, 0xC1, 
+  0x98, 0x97, 0x51, 0x44, 0x8D, 0x2D, 0x5B, 0x04, 0x32, 0x0B, 0x68, 0x5B, 0xB2, 0xB7, 0x09, 0x1D, 0x70, 0x91, 0x97, 0x5D, 
+  0x52, 0x55, 0xDE, 0x20, 0x47, 0x24, 0xD0, 0x61, 0xCE, 0xAF, 0xCC, 0xCF, 0x2C, 0x2F, 0xCE, 0xAD, 0x46, 0x01, 0x00, 0x54, 
+  0x7F, 0xD7, 0x52, 0x92, 0x57, 0x9C, 0x6F, 0xB0, 0x7B, 0x05, 0x4A, 0xC5, 0x2D, 0x9A, 0x6B, 0x17, 0xA1, 0x12, 0x74, 0x83, 
+  0x67, 0xC8, 0x59, 0x30, 0x4C, 0x3D, 0x9B, 0x07, 0x28, 0x3B, 0xE4, 0x80, 0xAD, 0xE6, 0x3E, 0x39, 0x42, 0xA2, 0xBE, 0x5B, 
+  0xCF, 0x37, 0x85, 0xA4, 0x94, 0x1C, 0x9A, 0x04, 0xA5, 0x8C, 0x37, 0x4F, 0xA4, 0x81, 0x87, 0xC0, 0xF6, 0xDB, 0xE8, 0x70, 
+  0xF1, 0x03, 0x8C, 0xC0, 0xD6, 0x07, 0x28, 0xC3, 0xA4, 0x6D, 0x52, 0xAF, 0x25, 0x46, 0xCA, 0xCE, 0x75, 0x90, 0x23, 0x39, 
+  0x5A, 0xC7, 0x24, 0x49, 0x26, 0x6B, 0x92, 0xDF, 0xB2, 0xC0, 0x22, 0x53, 0xAF, 0x1A, 0xDB, 0x77, 0x0B, 0x57, 0x99, 0xC3, 
+  0x79, 0xE9, 0x79, 0x36, 0x29, 0x32, 0x6A, 0x90, 0xA9, 0x90, 0x99, 0x7C, 0xA5, 0x82, 0xC8, 0xEA, 0x5F, 0xAA, 0x06, 0x70, 
+  0x89, 0xE4, 0x8C, 0x77, 0x26, 0xCA, 0x08, 0x89, 0x46, 0x1F, 0xA0, 0x24, 0xB7, 0x5C, 0x8B, 0x56, 0xC2, 0xA2, 0x55, 0xF4, 
+  0x24, 0x0F, 0x26, 0x7C, 0x49, 0x04, 0xE3, 0xAE, 0xB4, 0xE4, 0x16, 0xF8, 0x5F, 0x70, 0xDE, 0xF9, 0x9C, 0xC8, 0x4E, 0x82, 
+  0x41, 0x12, 0x05, 0xE1, 0xEE, 0x8A, 0xCB, 0x6F, 0xDC, 0xB9, 0xF3, 0x30, 0x87, 0x81, 0x00, 0x17, 0x8D, 0xD5, 0xAD, 0x28, 
+  0x83, 0x23, 0x19, 0x39, 0xDA, 0x90, 0xBD, 0xAB, 0xC5, 0x19, 0x32, 0xF7, 0x26, 0xA9, 0xAD, 0xAB, 0x68, 0x22, 0x23, 0x42, 
+  0xDC, 0x20, 0x0F, 0x9F, 0x16, 0x2C, 0x22, 0x30, 0x70, 0x17, 0x5C, 0x2A, 0xCC, 0x2E, 0xCD, 0x4A, 0x11, 0x6F, 0x90, 0x3D, 
+  0x23, 0x6C, 0x61, 0x4B, 0x2D, 0xA0, 0x1B, 0x5F, 0x56, 0x50, 0x83, 0x3E, 0xC0, 0x2E, 0xC2, 0x4F, 0x6D, 0x79, 0x2B, 0xB1, 
+  0x1A, 0x65, 0x40, 0xD8, 0x21, 0x8B, 0x05, 0xAF, 0xAA, 0x0B, 0x1A, 0xB8, 0xDB, 0x5C, 0xD3, 0x5D, 0x9E, 0x5F, 0xD7, 0x5A, 
+  0xD3, 0xC3, 0x36, 0xE1, 0xC2, 0xB4, 0x32, 0xF2, 0x2B, 0x8A, 0x4A, 0x98, 0xE1, 0xED, 0x35, 0xDD, 0x55, 0x79, 0x35, 0x8C, 
+  0x0A, 0x38, 0x61, 0x88, 0x52, 0x3C, 0x2D, 0x2A, 0x8D, 0x33, 0x01, 0x38, 0x50, 0x87, 0x46, 0x69, 0x4D, 0x79, 0x9D, 0xEF, 
+  0xE4, 0xE9, 0x7C, 0x4C, 0xD5, 0x41, 0x52, 0xA4, 0xD4, 0x68, 0x22, 0x5C, 0x53, 0x1F, 0x18, 0x1D, 0xC8, 0x35, 0x91, 0x83, 
+  0x65, 0xE5, 0xAE, 0x17, 0xC9, 0xE8, 0x46, 0x75, 0x60, 0x03, 0x2F, 0xDD, 0x1B, 0x3B, 0x8F, 0xD6, 0x44, 0x68, 0x0C, 0x37, 
+  0xC6, 0x3B, 0x20, 0xD5, 0x01, 0xA4, 0x82, 0x12, 0xFF, 0x46, 0x41, 0x50, 0xB2, 0x82, 0xB0, 0x44, 0x94, 0xA1, 0x38, 0xE3, 
+  0xCA, 0xDA, 0x0A, 0x5D, 0x2E, 0xE4, 0x39, 0x68, 0xCB, 0x3C, 0x27, 0x26, 0x2C, 0x02, 0xB7, 0x60, 0xCB, 0xC6, 0x82, 0x39, 
+  0x73, 0x2F, 0x38, 0x7F, 0x1C, 0x71, 0xFB, 0x82, 0x73, 0xCE, 0xE7, 0x3D, 0x6C, 0x5D, 0xB7, 0xF7, 0xF8, 0xD5, 0xB7, 0xA3, 
+  0x09, 0x32, 0xDA, 0xC5, 0xBD, 0xAB, 0xC4, 0x5A, 0x4B, 0x5A, 0xCA, 0x0B, 0x6B, 0x31, 0x4C, 0x4E, 0x85, 0xE3, 0x09, 0xD8, 
+  0x14, 0xE9, 0x10, 0xA1, 0x18, 0x56, 0x40, 0xA2, 0xB4, 0x04, 0x52, 0xD0, 0x81, 0xF0, 0x65, 0xD8, 0x8F, 0x9F, 0x9E, 0x87, 
+  0xE1, 0xA3, 0x03, 0xDA, 0xC8, 0x28, 0x83, 0xD2, 0x44, 0x4E, 0xA0, 0xCB, 0x2E, 0x93, 0x1A, 0x22, 0xB7, 0x9C, 0x23, 0x89, 
+  0xA0, 0x07, 0xB2, 0x4F, 0xA2, 0x30, 0xB7, 0xBA, 0xB4, 0xB0, 0xBE, 0x9C, 0xAD, 0x2E, 0x35, 0xED, 0x75, 0x55, 0x1D, 0x64, 
+  0xB1, 0xC0, 0x97, 0x90, 0xF5, 0x8B, 0xEB, 0x0B, 0xB3, 0xCB, 0x2B, 0x0B, 0x1B, 0xC8, 0xB2, 0xD0, 0x47, 0x7E, 0x4A, 0x49, 
+  0x79, 0x56, 0x4D, 0x5D, 0x69, 0x1B, 0xFD, 0x44, 0x94, 0x51, 0x90, 0x51, 0x2E, 0x03, 0xE4, 0x94, 0x1C, 0xFA, 0xCA, 0xBC, 
+  0x0D, 0x9C, 0x80, 0xFF, 0x98, 0x12, 0x9F, 0xCC, 0x96, 0x13, 0x0E, 0xC9, 0xA0, 0xB5, 0x45, 0x70, 0x02, 0x85, 0xE8, 0xFB, 
+  0x3A, 0x2B, 0x4A, 0x3A, 0x8F, 0x02, 0x4A, 0x52, 0x31, 0x48, 0x33, 0x58, 0x94, 0x81, 0x8B, 0x44, 0xC5, 0xC9, 0x33, 0xC3, 
+  0xE5, 0x91, 0x51, 0x3A, 0xF0, 0x2A, 0x60, 0x8C, 0xF4, 0x4F, 0x9E, 0x4A, 0x2B, 0x35, 0xC8, 0x8B, 0x74, 0xEA, 0x0D, 0xD2, 
+  0xFA, 0x97, 0x5B, 0x51, 0x89, 0x68, 0x25, 0x8C, 0x14, 0x36, 0x0E, 0x03, 0x89, 0x8B, 0x4C, 0x88, 0xE5, 0xAE, 0xF1, 0x56, 
+  0xE7, 0x57, 0xE1, 0xF1, 0xE2, 0x16, 0x61, 0x0C, 0xF1, 0xD9, 0xD0, 0xEA, 0xC7, 0xE6, 0x3D, 0xCA, 0x3D, 0xAD, 0xF5, 0x62, 
+  0x42, 0xE2, 0xB7, 0x6D, 0xD8, 0x7B, 0xE3, 0x8D, 0xF7, 0x72, 0x6E, 0x1D, 0xFB, 0x5E, 0x49, 0xF6, 0x85, 0x3D, 0x56, 0x58, 
+  0x93, 0x9B, 0x54, 0xC4, 0xAF, 0x48, 0x04, 0x81, 0xD0, 0x78, 0xF3, 0xD9, 0x52, 0xE2, 0xD3, 0x18, 0x7F, 0xF2, 0xB2, 0x31, 
+  0x64, 0x07, 0x9C, 0x32, 0x14, 0x2F, 0x6D, 0x7A, 0xBC, 0x24, 0x33, 0x39, 0x97, 0x12, 0x9A, 0x4F, 0x84, 0xBF, 0xA2, 0x9E, 
+  0x9C, 0x74, 0x51, 0x0F, 0x7E, 0x80, 0x0E, 0xE0, 0x25, 0x02, 0x5C, 0x65, 0xC5, 0x35, 0xC5, 0x05, 0xD5, 0x00, 0x00, 0xEE, 
+  0x82, 0xD5, 0x67, 0xA6, 0xD1, 0xCA, 0x95, 0xDD, 0x86, 0xF1, 0x31, 0xE9, 0x39, 0x69, 0x05, 0x59, 0x29, 0x05, 0xDC, 0xE2, 
+  0x07, 0x29, 0x91, 0xE9, 0xEC, 0x8B, 0x29, 0xCD, 0xAF, 0xA6, 0xF2, 0x80, 0x4B, 0x48, 0xF8, 0x2C, 0xCF, 0xAE, 0xD4, 0x0D, 
+  0x2F, 0x1C, 0x86, 0x49, 0x7D, 0xC0, 0xF1, 0x0D, 0x7C, 0x40, 0xA2, 0x20, 0x15, 0x8F, 0xE4, 0x45, 0x44, 0x63, 0x53, 0x2A, 
+  0x1B, 0x90, 0x30, 0x81, 0x41, 0xC3, 0x03, 0xD2, 0x57, 0xB9, 0x0B, 0x10, 0x25, 0xE8, 0xD2, 0xB9, 0xA1, 0x8F, 0x95, 0xFB, 
+  0xC9, 0xBC, 0x30, 0xCC, 0x6A, 0x0C, 0x45, 0x69, 0xF4, 0x68, 0x94, 0x8F, 0xEA, 0x0C, 0x25, 0x54, 0x13, 0xDE, 0x80, 0xA3, 
+  0xFA, 0xD0, 0xA0, 0x6D, 0x7C, 0xD0, 0xE8, 0x5F, 0x4D, 0x20, 0x5A, 0x1C, 0x85, 0x77, 0x63, 0xD4, 0x13, 0x8B, 0x40, 0x71, 
+  0x05, 0x02, 0x38, 0xFC, 0xF5, 0x39, 0xD3, 0x67, 0x5E, 0x74, 0xDE, 0xF9, 0x5A, 0xE5, 0x61, 0xDD, 0x5B, 0xD6, 0xEE, 0xD9, 
+  0xBF, 0xFF, 0xD8, 0xA1, 0x43, 0xD7, 0x2A, 0xA1, 0xBA, 0x22, 0xB7, 0x0E, 0xAA, 0x19, 0x66, 0x8E, 0x8D, 0xF3, 0x5B, 0x29, 
+  0x12, 0x43, 0xA2, 0x89, 0x3A, 0x5C, 0x80, 0x45, 0x1C, 0x94, 0xC0, 0x86, 0x40, 0x0A, 0x05, 0xAE, 0x93, 0x63, 0xD3, 0x91, 
+  0xBB, 0x9C, 0x1F, 0x12, 0x95, 0x44, 0xFA, 0x94, 0x10, 0x95, 0x42, 0xE8, 0x96, 0x2D, 0x08, 0x12, 0xEA, 0x04, 0x4E, 0xF9, 
+  0x15, 0x52, 0x46, 0x7F, 0x74, 0x95, 0xA9, 0x8A, 0x38, 0x0F, 0x04, 0x8F, 0x41, 0x49, 0x54, 0x79, 0x70, 0xDD, 0x48, 0x70, 
+  0xF9, 0xEC, 0x3C, 0x82, 0xCE, 0x50, 0x0C, 0xDC, 0xE7, 0xEC, 0x8C, 0x7C, 0x22, 0x0A, 0x2E, 0x48, 0x4B, 0x9F, 0x03, 0x6E, 
+  0x68, 0x87, 0xB0, 0xDD, 0xA8, 0xBF, 0x75, 0xE8, 0xC0, 0xAE, 0x2B, 0x1F, 0xBC, 0xEF, 0x49, 0xB2, 0x58, 0xBC, 0x64, 0xDE, 
+  0x8C, 0x79, 0x24, 0x84, 0x26, 0x43, 0x8D, 0xC7, 0x2C, 0x10, 0xAE, 0x11, 0xB4, 0x48, 0x59, 0x96, 0xFB, 0xD9, 0x8D, 0x75, 
+  0x3A, 0x06, 0xAA, 0x6A, 0x18, 0xA5, 0x03, 0xAF, 0xED, 0xD3, 0x3F, 0xA0, 0x99, 0xA3, 0x71, 0xD8, 0x5E, 0x68, 0x6B, 0xC1, 
+  0x3B, 0xA5, 0xB3, 0xA9, 0xAA, 0x8B, 0x4B, 0x02, 0x0B, 0x56, 0x1F, 0x63, 0x14, 0x63, 0x95, 0xA4, 0xBA, 0xC1, 0x78, 0x05, 
+  0xAC, 0x82, 0x4D, 0xB4, 0x08, 0x8C, 0x24, 0x83, 0x02, 0x61, 0x51, 0x03, 0x9B, 0xCB, 0xD0, 0x01, 0xB7, 0x04, 0xC6, 0x2B, 
+  0x2E, 0xBF, 0x69, 0xDB, 0x96, 0x03, 0x6B, 0x56, 0x6C, 0x27, 0x66, 0x12, 0x51, 0x49, 0x7E, 0x08, 0xBF, 0xA8, 0x21, 0x31, 
+  0x2E, 0x15, 0x89, 0xE3, 0x0A, 0x48, 0x33, 0x9C, 0xCC, 0x38, 0x34, 0x3A, 0x2E, 0x22, 0x89, 0x0B, 0x5C, 0x21, 0x32, 0x44, 
+  0x8A, 0x3E, 0x3E, 0x33, 0xBF, 0x65, 0xC5, 0x1A, 0x5F, 0x91, 0xBA, 0xC9, 0x3C, 0x19, 0xE5, 0xA1, 0x24, 0x8A, 0x6A, 0xF4, 
+  0x44, 0xB3, 0x44, 0xD4, 0x60, 0x94, 0x24, 0xE7, 0x43, 0xB1, 0x31, 0x22, 0x39, 0x0F, 0xD1, 0x13, 0x60, 0xC2, 0x83, 0x22, 
+  0x50, 0x9B, 0x6C, 0x33, 0x49, 0xE6, 0x14, 0xBD, 0x0A, 0x39, 0xC0, 0x25, 0xBD, 0x40, 0xF6, 0xB6, 0x14, 0xD5, 0x72, 0x7C, 
+  0x1C, 0xBD, 0x5B, 0x68, 0x3B, 0x90, 0x48, 0xB6, 0xAE, 0xDD, 0xF9, 0xC0, 0xFD, 0x8F, 0x7F, 0xF8, 0x9B, 0x3F, 0xFE, 0xFC, 
+  0x67, 0x1F, 0xEE, 0xDA, 0xB6, 0x13, 0x05, 0xCC, 0x98, 0x32, 0x9D, 0xC6, 0x01, 0x9E, 0x4D, 0xC2, 0xCA, 0x5D, 0x00, 0xCA, 
+  0x40, 0x6E, 0x94, 0x64, 0x2B, 0xA4, 0x21, 0x21, 0xDC, 0xB2, 0x73, 0x48, 0x3A, 0x66, 0x60, 0x35, 0xDA, 0x42, 0x0E, 0x3E, 
+  0xCA, 0x43, 0xB2, 0xC9, 0x8F, 0x4D, 0x43, 0x69, 0x90, 0xC9, 0xAF, 0x52, 0x9D, 0x16, 0x05, 0xA8, 0x6A, 0xFB, 0x45, 0xEA, 
+  0xEC, 0x76, 0xD9, 0xF1, 0x90, 0x6D, 0x94, 0x7B, 0x9B, 0x53, 0x16, 0xAC, 0x4C, 0xA2, 0xE6, 0x04, 0x70, 0x1B, 0xC6, 0x4D, 
+  0x42, 0x15, 0xCB, 0xFB, 0x93, 0x83, 0x3E, 0x08, 0xCE, 0x7E, 0x81, 0xFE, 0xB3, 0xE6, 0x50, 0xDC, 0xD1, 0xF6, 0x40, 0x0D, 
+  0xBC, 0xE0, 0x86, 0x75, 0xBB, 0xB7, 0x6D, 0x39, 0xB8, 0x7C, 0xE9, 0xA6, 0xD6, 0xC6, 0x3E, 0xAA, 0x30, 0xE4, 0xC5, 0x56, 
+  0x56, 0xCC, 0x13, 0x01, 0x21, 0x77, 0x19, 0x95, 0x90, 0x2B, 0x27, 0xA4, 0x0B, 0x1B, 0x43, 0xFC, 0x20, 0x4E, 0x84, 0x1E, 
+  0xC1, 0x2D, 0xAC, 0x3D, 0x1E, 0x89, 0x89, 0x0E, 0x8B, 0x21, 0x73, 0xC7, 0xD5, 0x78, 0x32, 0xBF, 0xE5, 0x57, 0x2C, 0x50, 
+  0x11, 0x85, 0x19, 0x25, 0x89, 0x1D, 0x44, 0x61, 0xB9, 0xC4, 0xD2, 0xD8, 0x64, 0xF2, 0x2B, 0x56, 0x66, 0x8A, 0xCC, 0xF2, 
+  0x04, 0xCD, 0x52, 0xB2, 0xC9, 0xBB, 0x08, 0x12, 0xF8, 0x41, 0x51, 0x56, 0x39, 0x3D, 0xA8, 0x82, 0x9C, 0xAA, 0x9C, 0x94, 
+  0xE2, 0xCC, 0xD8, 0x6C, 0x2A, 0xC4, 0x8A, 0xAC, 0x4A, 0x4A, 0x19, 0xE6, 0xE4, 0x94, 0x14, 0x14, 0x71, 0x6F, 0x7C, 0xF7, 
+  0x87, 0xFF, 0xFD, 0xF8, 0x8B, 0xDF, 0xBC, 0xFF, 0x87, 0xA3, 0x87, 0xAF, 0xE5, 0xF9, 0x86, 0x90, 0x10, 0x10, 0xE0, 0x2B, 
+  0xED, 0x03, 0x36, 0x08, 0x2D, 0x98, 0xE1, 0x4B, 0xA9, 0x84, 0x85, 0x41, 0x9D, 0xE2, 0x98, 0x0D, 0x98, 0x3B, 0x78, 0xB0, 
+  0x4C, 0xDC, 0xD0, 0x44, 0x58, 0x9C, 0x8F, 0x97, 0x13, 0xE9, 0x45, 0x1E, 0xEB, 0x07, 0xA0, 0xAA, 0xC3, 0x14, 0x4B, 0x94, 
+  0xC6, 0xB5, 0x5B, 0x2D, 0x3B, 0xC3, 0x52, 0x4B, 0x0E, 0xD0, 0xC2, 0x6D, 0xCC, 0x3A, 0xA5, 0x32, 0x54, 0x2B, 0x02, 0x8B, 
+  0x06, 0x94, 0x30, 0x07, 0x0C, 0x84, 0x0C, 0x8A, 0x2A, 0xCF, 0x04, 0x06, 0xB6, 0x16, 0xFB, 0x72, 0x18, 0x08, 0x3A, 0xA0, 
+  0xA4, 0xE0, 0x4C, 0x96, 0x1D, 0xDB, 0x8F, 0x74, 0xB5, 0x0F, 0x72, 0x42, 0x11, 0x1B, 0xC1, 0x81, 0x7B, 0xAC, 0x98, 0x15, 
+  0xBA, 0x30, 0x9C, 0x3F, 0x47, 0xAC, 0xD8, 0x35, 0x0E, 0x11, 0xE4, 0x17, 0x1C, 0x46, 0x36, 0x8C, 0x3F, 0x51, 0xA3, 0x84, 
+  0x46, 0x87, 0x87, 0x44, 0x87, 0x07, 0x70, 0x4D, 0xE9, 0x14, 0x15, 0x41, 0x47, 0x39, 0x28, 0x92, 0xC5, 0x16, 0x7E, 0xC9, 
+  0xD0, 0x42, 0xA3, 0xC9, 0x86, 0xB9, 0x95, 0x43, 0x5E, 0x78, 0x24, 0x2C, 0x96, 0x57, 0x13, 0x8F, 0xE1, 0x5D, 0xF1, 0xFE, 
+  0x63, 0x33, 0xB8, 0xD5, 0x12, 0x4F, 0x55, 0x82, 0x82, 0x09, 0x1E, 0xD9, 0xA9, 0xC5, 0xE5, 0x85, 0xF5, 0x72, 0xF2, 0x74, 
+  0xCB, 0x60, 0x4F, 0x9B, 0xF4, 0x04, 0x81, 0xAC, 0xDC, 0xD4, 0xA2, 0xBC, 0x94, 0x7C, 0xC6, 0x18, 0x30, 0xA0, 0x68, 0xA4, 
+  0xD3, 0xAE, 0x87, 0x2D, 0x70, 0xCB, 0x75, 0x77, 0xDC, 0x7A, 0xFD, 0xBD, 0xA0, 0x13, 0xDF, 0x54, 0x42, 0xB4, 0x18, 0x1E, 
+  0xE2, 0x5B, 0x49, 0xB6, 0x1F, 0xD8, 0x75, 0x84, 0xBE, 0xC8, 0x8A, 0x65, 0xEB, 0x30, 0xF1, 0xB8, 0x88, 0x28, 0xA4, 0xC4, 
+  0x49, 0x02, 0x7C, 0x64, 0x30, 0x80, 0xB7, 0xE4, 0xE8, 0xC0, 0xD3, 0x92, 0xB3, 0x14, 0xA5, 0xEC, 0xAC, 0x84, 0x4C, 0x5D, 
+  0xE2, 0x92, 0x0E, 0x57, 0x69, 0x84, 0x28, 0xF9, 0xD5, 0xAE, 0xA0, 0x03, 0x55, 0xAB, 0x12, 0x4F, 0x12, 0x35, 0x02, 0x56, 
+  0x82, 0x18, 0xA6, 0xD2, 0x36, 0x25, 0x1E, 0xC8, 0x1E, 0x49, 0x64, 0x93, 0xC0, 0x30, 0x27, 0x00, 0x44, 0xA2, 0xCB, 0x04, 
+  0xF7, 0x74, 0xCB, 0x86, 0x7D, 0x9B, 0x37, 0xEE, 0x93, 0xB3, 0xFD, 0x4A, 0x1B, 0x01, 0x74, 0x72, 0x1B, 0xFA, 0x42, 0xB4, 
+  0x9B, 0x10, 0x22, 0xF0, 0x1D, 0x16, 0x10, 0xCE, 0x05, 0xE6, 0x8C, 0xAC, 0x41, 0x8F, 0xF0, 0xC0, 0x68, 0x2C, 0x9A, 0x0B, 
+  0x76, 0xC5, 0x86, 0x2E, 0x0C, 0x43, 0xC4, 0xB2, 0x02, 0xC2, 0x28, 0x0C, 0xD9, 0xA9, 0xC9, 0x2D, 0x07, 0x97, 0xF2, 0x48, 
+  0xA8, 0x7F, 0x58, 0x48, 0x40, 0x28, 0x4F, 0xE0, 0xDF, 0xA1, 0x27, 0xFC, 0x00, 0x45, 0xE2, 0x52, 0xBC, 0x14, 0x3A, 0x4E, 
+  0x8A, 0xA1, 0x1D, 0x9B, 0x88, 0xE8, 0x15, 0x8B, 0x78, 0x9C, 0x3A, 0x23, 0x27, 0xAD, 0x84, 0x1C, 0x89, 0xD5, 0x56, 0xDF, 
+  0x07, 0x2A, 0xB6, 0x37, 0x0F, 0x74, 0x77, 0x2C, 0x2D, 0xC9, 0xAB, 0xA9, 0x2A, 0x69, 0x22, 0x78, 0x14, 0xA5, 0x97, 0x02, 
+  0x92, 0x29, 0x49, 0xE9, 0xD8, 0x04, 0xF1, 0x89, 0x4A, 0x4D, 0x3C, 0x29, 0x31, 0x15, 0x14, 0x61, 0x1A, 0xC6, 0x79, 0xF3, 
+  0x03, 0xDD, 0x43, 0x74, 0x0C, 0x5B, 0x6A, 0x5B, 0xE8, 0xB7, 0x4F, 0xB9, 0x64, 0x32, 0xA0, 0x87, 0xA6, 0x49, 0xA5, 0x68, 
+  0xB5, 0x02, 0x00, 0x82, 0x45, 0xA7, 0x5C, 0x7C, 0x60, 0xC9, 0x4D, 0x13, 0x0C, 0x49, 0x26, 0x59, 0xC9, 0x62, 0xA7, 0xE0, 
+  0x88, 0xB9, 0xEC, 0x01, 0x06, 0xD6, 0x02, 0x50, 0x8A, 0x4B, 0x98, 0xFF, 0x28, 0x05, 0xC4, 0x39, 0x84, 0x46, 0x3B, 0xDE, 
+  0xB3, 0x31, 0x43, 0x92, 0x28, 0x00, 0xC1, 0x69, 0x78, 0x44, 0x45, 0x2C, 0x14, 0x23, 0xC5, 0xFC, 0x81, 0xD4, 0xB3, 0xCF, 
+  0x3A, 0x03, 0xD1, 0x6C, 0xDA, 0xB8, 0x8F, 0xF3, 0xA1, 0xBA, 0xBB, 0x96, 0x61, 0x98, 0x44, 0xD4, 0xDC, 0xF4, 0x42, 0xF6, 
+  0xB7, 0x12, 0x39, 0x29, 0xCD, 0x30, 0x7F, 0xC4, 0x0D, 0xB0, 0x00, 0x38, 0x48, 0x96, 0x30, 0x80, 0x40, 0xB9, 0x10, 0x89, 
+  0x2F, 0x08, 0x97, 0xFA, 0x7C, 0x41, 0x30, 0xA2, 0x0F, 0x9A, 0x1F, 0x4C, 0x4B, 0x4A, 0xAF, 0x17, 0xCE, 0x87, 0xDA, 0x1D, 
+  0x10, 0x34, 0x3F, 0x28, 0xC8, 0x2F, 0x24, 0x78, 0x01, 0x27, 0xBC, 0x84, 0xF1, 0x38, 0x4A, 0xE2, 0x6F, 0x79, 0x29, 0xD2, 
+  0x36, 0xCC, 0x42, 0x70, 0x2C, 0x28, 0x4A, 0x52, 0xAC, 0x58, 0x69, 0x0F, 0x03, 0x65, 0x31, 0x61, 0x49, 0x24, 0xAC, 0xB5, 
+  0x00, 0x4F, 0x51, 0x23, 0x55, 0xC5, 0xD2, 0xC1, 0xF5, 0x1B, 0xD6, 0xEC, 0xE2, 0x78, 0x8C, 0x55, 0x2B, 0xB6, 0xEE, 0xDE, 
+  0x79, 0x74, 0xDF, 0x9E, 0x63, 0x87, 0xF6, 0x5F, 0x7F, 0x60, 0xCF, 0xD5, 0xE4, 0x6F, 0x14, 0x34, 0x8B, 0x5A, 0xFB, 0x5A, 
+  0xEA, 0xDB, 0xA8, 0x5D, 0x38, 0x45, 0xAC, 0xA6, 0xB2, 0x89, 0x3C, 0x38, 0x23, 0x35, 0x87, 0x57, 0x13, 0x9B, 0x08, 0xA0, 
+  0xC7, 0x19, 0xC3, 0x28, 0x9E, 0xEF, 0x81, 0x88, 0x8A, 0x88, 0x06, 0xA6, 0xCC, 0x51, 0x4B, 0x21, 0xA7, 0xD0, 0x81, 0x57, 
+  0xDC, 0x96, 0xB5, 0xAA, 0x70, 0xE4, 0xC9, 0x8B, 0x54, 0xE2, 0x96, 0xC1, 0x21, 0x3A, 0x30, 0x3C, 0xAD, 0x53, 0xB2, 0x07, 
+  0xE4, 0x41, 0xE3, 0x13, 0x72, 0xAB, 0x25, 0x85, 0xCC, 0xF9, 0xA4, 0x48, 0x19, 0xE5, 0x0A, 0xC0, 0x28, 0x25, 0x1B, 0xAE, 
+  0x30, 0x7F, 0xB6, 0x2F, 0x31, 0x99, 0xFE, 0xC1, 0x86, 0xB5, 0x7B, 0x07, 0x7A, 0x56, 0x02, 0xCA, 0x84, 0x4A, 0xD9, 0xBD, 
+  0x43, 0x3B, 0xCB, 0x40, 0x84, 0x86, 0x59, 0x84, 0x8E, 0xEC, 0x70, 0x02, 0xF4, 0x81, 0x69, 0xB3, 0xC2, 0x17, 0x46, 0x20, 
+  0x59, 0xA4, 0x2C, 0xA7, 0x32, 0xCE, 0x0B, 0xE4, 0x36, 0x60, 0xDE, 0x42, 0x6E, 0xFD, 0x67, 0xFB, 0xFB, 0xCF, 0x0D, 0x60, 
+  0xC7, 0xB2, 0x2C, 0x73, 0xCD, 0xE3, 0x81, 0x0B, 0x82, 0x64, 0xCD, 0x0B, 0x14, 0x0D, 0x05, 0x84, 0x82, 0x63, 0x68, 0x1D, 
+  0xE9, 0xF0, 0xCA, 0xE4, 0xBE, 0x60, 0x14, 0xF5, 0x44, 0x43, 0x55, 0x4B, 0x43, 0x65, 0x67, 0x6E, 0x7A, 0x69, 0x05, 0xE7, 
+  0xF3, 0x57, 0x77, 0x2E, 0x5F, 0xBC, 0x11, 0xD7, 0x5C, 0xB7, 0x66, 0xE7, 0x91, 0x43, 0xD7, 0xEF, 0xDD, 0x7F, 0xCD, 0x2D, 
+  0xB7, 0x3C, 0x70, 0xFC, 0xF8, 0x1D, 0x00, 0x26, 0xC5, 0x1A, 0x47, 0x97, 0xF0, 0x75, 0x61, 0xFA, 0x35, 0x62, 0xF4, 0xF0, 
+  0x69, 0x1E, 0xD3, 0x2D, 0xA6, 0x32, 0x2D, 0xC8, 0xE3, 0x6B, 0xA3, 0x3A, 0x38, 0x2D, 0xB5, 0xBF, 0x8B, 0x2F, 0x1A, 0x1A, 
+  0xE4, 0xA0, 0x76, 0x5E, 0x7F, 0xCA, 0xC4, 0x09, 0x98, 0x1A, 0x0A, 0xA0, 0x36, 0xF2, 0x51, 0xE1, 0x6A, 0x45, 0x66, 0x57, 
+  0x9A, 0xC7, 0xF0, 0x35, 0x17, 0x3A, 0x49, 0x07, 0x63, 0x39, 0x4C, 0x99, 0xF1, 0x59, 0xCC, 0xD9, 0x69, 0xA9, 0xB2, 0xD4, 
+  0x1B, 0xBC, 0x40, 0xA4, 0xD7, 0x78, 0xBA, 0x2C, 0x33, 0x59, 0x95, 0x9C, 0x24, 0x5A, 0x13, 0x64, 0x49, 0xD4, 0xB4, 0x5E, 
+  0x63, 0x3E, 0x6A, 0xDA, 0x4D, 0xC1, 0x33, 0x26, 0x5F, 0x8A, 0x5C, 0xD6, 0xAF, 0xDD, 0x45, 0x24, 0x20, 0xC4, 0x09, 0xA7, 
+  0x3C, 0xB5, 0x00, 0x59, 0xE3, 0xDD, 0x54, 0xB9, 0xE4, 0xA6, 0x20, 0x06, 0xF2, 0x02, 0x2E, 0x78, 0xD0, 0x04, 0xDE, 0x28, 
+  0xE9, 0x44, 0x05, 0x84, 0x61, 0x6E, 0x18, 0x7E, 0xE0, 0x1C, 0x3F, 0xCE, 0xB3, 0x43, 0xD0, 0x0B, 0x66, 0x8B, 0xD0, 0xA5, 
+  0x6F, 0xE8, 0x3B, 0x8F, 0x86, 0x2E, 0xB7, 0x7A, 0x4D, 0x7F, 0x97, 0x0B, 0x6E, 0xD1, 0x04, 0x5E, 0x82, 0x1A, 0xD4, 0x93, 
+  0xD0, 0x44, 0x64, 0xB0, 0x94, 0xBB, 0x44, 0x0B, 0x66, 0x12, 0x14, 0xD5, 0x60, 0x60, 0x5E, 0x46, 0x59, 0x6B, 0x5D, 0x6F, 
+  0x4B, 0x43, 0x6F, 0x7F, 0xF7, 0xCA, 0x81, 0x1E, 0xCE, 0x9C, 0x3F, 0xB0, 0x63, 0xDB, 0xD1, 0x43, 0x07, 0x8E, 0xDF, 0x7A, 
+  0xEB, 0x83, 0xB7, 0xDC, 0xF1, 0xC8, 0x50, 0xDF, 0xEA, 0xD9, 0xD3, 0xE7, 0x68, 0x59, 0x73, 0xD6, 0x19, 0x67, 0x5E, 0x78, 
+  0xC1, 0x79, 0x90, 0xC6, 0xA7, 0x4C, 0x9C, 0xC4, 0x62, 0xD6, 0xCB, 0xC1, 0x87, 0x3C, 0xC8, 0x2D, 0xDC, 0x9C, 0x89, 0xE3, 
+  0x27, 0x4D, 0x1C, 0x3F, 0x81, 0xAE, 0xFE, 0xC5, 0x17, 0x5D, 0x80, 0xA3, 0xA3, 0x03, 0xAC, 0x8D, 0x66, 0x9A, 0xE8, 0xC0, 
+  0x0B, 0x32, 0x7A, 0x9D, 0x96, 0x02, 0x0A, 0x65, 0xB0, 0xFB, 0x97, 0x45, 0x21, 0xFA, 0x25, 0x28, 0x94, 0xEE, 0xCD, 0x53, 
+  0x5D, 0x32, 0x93, 0x7A, 0x83, 0x48, 0x7C, 0xB4, 0x26, 0x1C, 0x0F, 0xB0, 0x70, 0x64, 0x72, 0x24, 0x21, 0xF9, 0x6A, 0xE5, 
+  0x62, 0x72, 0xB5, 0x48, 0x6D, 0x34, 0x71, 0x1E, 0xDA, 0x94, 0xF1, 0xE3, 0x99, 0xBD, 0xD0, 0x3C, 0xC8, 0x4C, 0xA1, 0x0C, 
+  0x26, 0xC7, 0x4F, 0x03, 0x97, 0xC9, 0xEB, 0x1B, 0xAB, 0xDB, 0xAB, 0xCA, 0x9B, 0x10, 0xBD, 0xA9, 0x4E, 0xD3, 0x90, 0x1A, 
+  0x81, 0x84, 0x68, 0x8C, 0x04, 0x5D, 0xE4, 0x91, 0x04, 0x97, 0x24, 0x44, 0x5A, 0xB6, 0xB3, 0x16, 0xB0, 0x67, 0x9F, 0xD2, 
+  0x8F, 0x33, 0x5C, 0x38, 0x42, 0x84, 0x25, 0x6A, 0x98, 0x35, 0x57, 0xAE, 0xCD, 0xAD, 0x51, 0x86, 0x3F, 0x4F, 0x43, 0x07, 
+  0x68, 0x8E, 0x96, 0x09, 0x93, 0x00, 0xB0, 0x08, 0x87, 0x10, 0x1D, 0xB0, 0xB5, 0x1F, 0x52, 0x41, 0x56, 0x59, 0x4D, 0x45, 
+  0x1B, 0x2D, 0x58, 0xEC, 0xB7, 0xB7, 0x6B, 0xF9, 0xD0, 0xD0, 0xDA, 0xCB, 0xB6, 0x1D, 0x3E, 0x7A, 0xE4, 0xC6, 0x5B, 0x6E, 
+  0xBA, 0xFF, 0xF6, 0xDB, 0x1F, 0xE6, 0x54, 0x49, 0xFE, 0x10, 0xE9, 0x9F, 0x79, 0xFA, 0x19, 0x48, 0x9C, 0xB6, 0x3C, 0x43, 
+  0x94, 0xD9, 0xD3, 0x66, 0x10, 0xCF, 0x58, 0x73, 0x67, 0xCC, 0xE2, 0x76, 0xF6, 0x8C, 0x99, 0x33, 0x2F, 0x9D, 0x31, 0x6D, 
+  0xD2, 0x64, 0x0E, 0x03, 0xBD, 0x74, 0xCA, 0x25, 0xF4, 0x89, 0x79, 0x6F, 0xC4, 0x64, 0xB0, 0x71, 0xC4, 0x0F, 0x4E, 0x81, 
+  0xF5, 0x49, 0x8E, 0x02, 0x44, 0x07, 0x9E, 0x34, 0x54, 0xAF, 0x47, 0x97, 0x08, 0x23, 0x95, 0x9A, 0x11, 0xBA, 0x43, 0x2B, 
+  0x3B, 0x39, 0x61, 0x3D, 0x39, 0x73, 0xD5, 0x0C, 0x55, 0x9A, 0x5C, 0xD2, 0xBD, 0x80, 0xCE, 0x25, 0x1C, 0x53, 0x74, 0x30, 
+  0x6D, 0xD2, 0xA5, 0x30, 0x9A, 0xEA, 0x2B, 0x5B, 0x11, 0x2E, 0xB2, 0xE0, 0x91, 0xC4, 0x84, 0x34, 0x0E, 0xE5, 0xA2, 0xAC, 
+  0x6D, 0x6F, 0xE9, 0xCB, 0x61, 0xEF, 0x6A, 0xBE, 0xEC, 0x08, 0x8B, 0x0D, 0x4F, 0x4C, 0x4D, 0xCA, 0x24, 0x07, 0x37, 0x85, 
+  0x1E, 0x9A, 0x08, 0x07, 0x73, 0x34, 0x05, 0x44, 0xF4, 0x6A, 0xF8, 0x9C, 0x24, 0xC5, 0x62, 0x98, 0xE1, 0x3B, 0x6D, 0x16, 
+  0x0B, 0x3E, 0x8E, 0x91, 0x8E, 0x2F, 0x4B, 0x7E, 0x65, 0xD4, 0xC0, 0x93, 0x09, 0x8F, 0x00, 0x14, 0x4E, 0x40, 0x30, 0x27, 
+  0x6D, 0xD5, 0x12, 0x04, 0x30, 0xC0, 0x15, 0xB2, 0x93, 0x8B, 0x5A, 0xAA, 0xBB, 0x7B, 0xDA, 0x97, 0x74, 0xB4, 0x0C, 0xAD, 
+  0x59, 0xB1, 0x8D, 0x03, 0x9E, 0x39, 0x51, 0x95, 0xAA, 0xE5, 0xA6, 0x9B, 0xEE, 0xA3, 0x9B, 0xC2, 0x29, 0x07, 0x67, 0x9C, 
+  0xC6, 0xD7, 0x15, 0x9E, 0x0E, 0xC5, 0x44, 0xA5, 0x8F, 0x6A, 0x61, 0x8C, 0xEB, 0x32, 0xD6, 0x30, 0x17, 0x93, 0xA7, 0x7B, 
+  0xCF, 0xF2, 0xF3, 0xF5, 0xE3, 0x1F, 0x21, 0x7D, 0x3C, 0x00, 0x08, 0xC2, 0x09, 0xD0, 0x01, 0x71, 0xCB, 0xC7, 0x93, 0xE6, 
+  0x7B, 0xB2, 0xFE, 0xA4, 0x4C, 0x8E, 0x72, 0xFD, 0x12, 0x89, 0x3B, 0x4C, 0xD5, 0xAF, 0x20, 0x50, 0x9E, 0x42, 0x01, 0xF1, 
+  0xC9, 0x0E, 0x16, 0xC5, 0x25, 0x09, 0xE5, 0x26, 0x5E, 0x82, 0x81, 0x5B, 0x31, 0x4A, 0xF7, 0x5B, 0x92, 0xF7, 0xE0, 0x18, 
+  0xC4, 0x8D, 0x99, 0x24, 0xC7, 0x25, 0x51, 0x16, 0x21, 0x41, 0xCC, 0x13, 0xB9, 0x20, 0xDF, 0xE4, 0xD8, 0xCC, 0x84, 0x88, 
+  0x54, 0x92, 0x10, 0x42, 0x62, 0x3E, 0x1C, 0xDB, 0x9C, 0xB2, 0xF4, 0xC4, 0x6C, 0x62, 0x80, 0x6C, 0x67, 0x8B, 0x91, 0x73, 
+  0x36, 0xD1, 0x5F, 0xD0, 0xC2, 0x50, 0x50, 0x85, 0x4F, 0x28, 0x6B, 0xF6, 0x82, 0xB9, 0xB3, 0xE7, 0xA9, 0xED, 0x8B, 0x0E, 
+  0x66, 0xCC, 0x9E, 0x3D, 0x0D, 0x93, 0xF4, 0x55, 0x0B, 0x9D, 0x3B, 0x55, 0xAE, 0x55, 0x3D, 0xEA, 0x1C, 0xFE, 0x33, 0x17, 
+  0x00, 0x5C, 0xA4, 0xED, 0x20, 0x21, 0x80, 0x46, 0x5E, 0x84, 0x1A, 0x48, 0x5B, 0x49, 0x58, 0x61, 0x50, 0xD3, 0x5C, 0x22, 
+  0x0B, 0xEA, 0xEF, 0x1C, 0x1E, 0xE8, 0x5A, 0xC1, 0xE9, 0x30, 0xDB, 0xB7, 0x1E, 0xBC, 0xE6, 0xAA, 0xDB, 0x6F, 0xBC, 0xE1, 
+  0x3E, 0x94, 0x11, 0x1D, 0x18, 0x83, 0x13, 0x4C, 0xB8, 0xF0, 0x22, 0xDF, 0xA9, 0xD3, 0xB1, 0x7A, 0xB1, 0x80, 0x79, 0xF3, 
+  0x29, 0xF8, 0xE5, 0x3D, 0xCC, 0x97, 0xA3, 0xAC, 0x74, 0x94, 0x22, 0x89, 0x80, 0xE9, 0xDE, 0x23, 0x7A, 0x96, 0x0E, 0x5A, 
+  0x54, 0x07, 0x12, 0x93, 0x4F, 0x32, 0x73, 0xB1, 0x6B, 0x77, 0x59, 0x71, 0x7F, 0x15, 0x65, 0x75, 0x94, 0x32, 0x60, 0x65, 
+  0x19, 0x71, 0x8F, 0x58, 0xBD, 0x34, 0x70, 0xD2, 0x34, 0x0C, 0xA4, 0xC3, 0x7C, 0x32, 0xC4, 0x1B, 0xC7, 0x03, 0xA8, 0x92, 
+  0x4C, 0xDF, 0x2A, 0x3E, 0x14, 0xA2, 0xB5, 0x30, 0x04, 0x30, 0x49, 0x9E, 0xCC, 0x5B, 0x9A, 0x3B, 0x1D, 0x3B, 0x92, 0x23, 
+  0x70, 0x82, 0x03, 0x39, 0xC0, 0x31, 0x31, 0x3B, 0xA9, 0xB8, 0x34, 0xA3, 0xB2, 0x3C, 0xA7, 0x06, 0x63, 0xAC, 0xAF, 0xE8, 
+  0x20, 0x31, 0x27, 0xBB, 0x90, 0xF6, 0x4E, 0x6A, 0x0E, 0x88, 0x81, 0x07, 0x00, 0x62, 0x84, 0x04, 0xF9, 0xB4, 0x7E, 0xFE, 
+  0xF3, 0xE7, 0xFA, 0x2B, 0xD4, 0x70, 0xAB, 0x4E, 0x80, 0x02, 0x58, 0xF3, 0xA6, 0xCD, 0xF4, 0x9D, 0x2A, 0x10, 0x01, 0x38, 
+  0xA0, 0x69, 0x79, 0xC4, 0xF8, 0x81, 0x0C, 0xFE, 0x08, 0x0C, 0x73, 0x04, 0x9D, 0xD1, 0x01, 0xD6, 0x20, 0x9D, 0x8F, 0xB0, 
+  0x38, 0xAA, 0xB6, 0xCA, 0xB2, 0xFA, 0x76, 0xB8, 0xCB, 0x35, 0x1D, 0x64, 0x41, 0x4B, 0x06, 0xD6, 0x11, 0x8D, 0x37, 0xAE, 
+  0xDD, 0x45, 0x3C, 0xB8, 0xEA, 0xCA, 0x5B, 0xAF, 0xBF, 0xFE, 0xEE, 0x5D, 0xDB, 0x2F, 0x5F, 0x30, 0x33, 0x80, 0x08, 0x4C, 
+  0x51, 0x49, 0x4D, 0xC3, 0x40, 0x17, 0x92, 0x1D, 0x4B, 0xE5, 0xEE, 0x8C, 0x4C, 0x5C, 0xB9, 0xAB, 0xF4, 0x4D, 0x00, 0x30, 
+  0x1E, 0x40, 0xE8, 0x32, 0x3A, 0x00, 0xFD, 0xD0, 0x81, 0x93, 0xE1, 0x7C, 0x19, 0x23, 0xF5, 0x94, 0xF6, 0x7E, 0x12, 0xDC, 
+  0x7F, 0x29, 0x91, 0xCF, 0x06, 0x00, 0x76, 0xD3, 0x33, 0xB8, 0x67, 0x8D, 0xE8, 0xC0, 0x69, 0xB5, 0xC6, 0xC5, 0x87, 0x44, 
+  0xE9, 0x84, 0x07, 0x94, 0xA7, 0x5E, 0xD3, 0xCF, 0x03, 0x38, 0x90, 0x54, 0x10, 0x06, 0x40, 0x83, 0xC6, 0x8A, 0xCE, 0xDA, 
+  0xAA, 0x56, 0x92, 0xD4, 0xC5, 0x83, 0xEB, 0xA0, 0x4D, 0x70, 0x56, 0x64, 0x75, 0x71, 0x53, 0x7E, 0x4E, 0x39, 0x0A, 0x20, 
+  0x4A, 0x83, 0x8D, 0x64, 0xB7, 0x68, 0x82, 0x1C, 0x09, 0xF7, 0x27, 0x20, 0xD3, 0xD0, 0x47, 0x9D, 0x12, 0x0C, 0x8C, 0xA5, 
+  0x8B, 0xD5, 0x4F, 0xC5, 0x03, 0xA6, 0x1B, 0x3F, 0x10, 0xE9, 0xAB, 0x6E, 0xF4, 0x96, 0xA7, 0x89, 0xBE, 0xFD, 0x82, 0xD1, 
+  0x22, 0x21, 0x9D, 0x08, 0xCF, 0x3F, 0x25, 0x65, 0xA0, 0x10, 0xA9, 0xE4, 0xEC, 0xB8, 0x8A, 0x36, 0x3A, 0xDB, 0x1D, 0x8D, 
+  0x03, 0xD4, 0xEA, 0xE8, 0x60, 0xEB, 0xE6, 0x03, 0x5B, 0x36, 0xED, 0x23, 0x1E, 0x5C, 0x75, 0xD5, 0xAD, 0xBB, 0x76, 0x5C, 
+  0x3E, 0xDF, 0xD7, 0xEF, 0xBC, 0xB3, 0xCF, 0x30, 0x6F, 0xD8, 0x4F, 0x3E, 0xC2, 0xFC, 0x20, 0x14, 0x10, 0x32, 0xDF, 0x4C, 
+  0xAB, 0xFC, 0x83, 0x08, 0x6C, 0x3A, 0xC5, 0x32, 0x86, 0xEF, 0x80, 0x8F, 0xB4, 0x31, 0x16, 0x4A, 0xEE, 0x17, 0x1E, 0x14, 
+  0xC6, 0x21, 0x0E, 0xA2, 0x03, 0xF8, 0x84, 0x5F, 0x81, 0x2A, 0x46, 0xD6, 0x92, 0x71, 0xBA, 0xEB, 0xAB, 0x64, 0x7D, 0xEA, 
+  0x22, 0xD9, 0x80, 0x8F, 0xF5, 0x00, 0x53, 0x21, 0x4B, 0x43, 0xD1, 0xED, 0x75, 0xC7, 0x41, 0xAE, 0x26, 0x75, 0x01, 0xD3, 
+  0xA9, 0x21, 0xF9, 0x24, 0xA0, 0x2A, 0xB6, 0x49, 0x22, 0x0F, 0x20, 0x90, 0x8C, 0x56, 0x73, 0x22, 0x79, 0x5D, 0x4F, 0x67, 
+  0xEB, 0xE2, 0xA5, 0x8B, 0x37, 0x1C, 0x39, 0x72, 0xFD, 0x8A, 0xE5, 0x9B, 0x69, 0x5A, 0x70, 0x66, 0x5A, 0x71, 0x56, 0x75, 
+  0x71, 0x46, 0x05, 0xE7, 0xAA, 0xE1, 0x34, 0xD4, 0x3B, 0x88, 0x4F, 0x1B, 0x7F, 0x66, 0x6C, 0x17, 0x28, 0x15, 0xC6, 0xEC, 
+  0xF9, 0x48, 0x9F, 0x53, 0x4E, 0x0D, 0x1C, 0x61, 0xF2, 0xBE, 0xD8, 0x3B, 0xA0, 0x64, 0xB4, 0x22, 0xF1, 0xC0, 0x6F, 0xA6, 
+  0x0D, 0xCB, 0x0B, 0x78, 0x1A, 0x38, 0x16, 0x1E, 0x4E, 0xEF, 0x53, 0x26, 0x80, 0xE4, 0x69, 0x58, 0x03, 0x09, 0x71, 0x75, 
+  0x51, 0x33, 0x27, 0x03, 0xA1, 0x06, 0x2A, 0x64, 0x38, 0x96, 0x4B, 0x86, 0xD6, 0xAF, 0x5D, 0xBB, 0x03, 0x2C, 0x42, 0x13, 
+  0x87, 0x2F, 0xBF, 0xE1, 0xEA, 0x63, 0xB7, 0x05, 0x05, 0x84, 0x5D, 0x74, 0xDE, 0x38, 0xB4, 0x8E, 0xE8, 0xD5, 0xD2, 0x65, 
+  0x39, 0x42, 0x17, 0xB4, 0xD1, 0xB7, 0x64, 0x30, 0x67, 0x21, 0x69, 0xB7, 0x2E, 0x6A, 0x20, 0xA4, 0x8F, 0x2B, 0xE8, 0x5D, 
+  0x9F, 0xD1, 0xF4, 0x60, 0x27, 0x9F, 0x39, 0xB9, 0xEB, 0xA0, 0xB9, 0xA6, 0xB2, 0x27, 0xDD, 0xDB, 0x91, 0xBB, 0x52, 0x94, 
+  0x61, 0xE6, 0xEE, 0x3A, 0x99, 0xCC, 0x64, 0xB9, 0x7F, 0x38, 0xB8, 0xA3, 0x80, 0x70, 0xC3, 0x8E, 0x09, 0x89, 0x46, 0xEE, 
+  0x20, 0x95, 0x1C, 0xFE, 0x67, 0x72, 0x47, 0x1E, 0x01, 0x61, 0xAA, 0x2B, 0x0C, 0x1F, 0x62, 0x70, 0xF5, 0xA6, 0x0D, 0x7B, 
+  0x0F, 0x1F, 0xBE, 0x6E, 0xEF, 0x9E, 0xAB, 0xF8, 0xD8, 0x7B, 0x77, 0x1F, 0xEB, 0x6A, 0x5B, 0xB2, 0xA8, 0x65, 0x31, 0xDF, 
+  0x92, 0x51, 0x5F, 0xD9, 0x5E, 0x5B, 0xD2, 0x9A, 0x97, 0x56, 0x2C, 0xFC, 0xB0, 0x0C, 0x99, 0x62, 0x46, 0x9B, 0x32, 0x3B, 
+  0x32, 0x20, 0x9C, 0x8F, 0x67, 0xD2, 0x7F, 0x7F, 0x0D, 0xD1, 0xEA, 0x10, 0x26, 0x48, 0x4A, 0xB2, 0xA4, 0x79, 0x11, 0xB7, 
+  0x6A, 0xFE, 0x80, 0x06, 0x17, 0x8A, 0xDD, 0x08, 0x8B, 0x82, 0x23, 0x34, 0x38, 0x82, 0x5E, 0x3F, 0x2D, 0x29, 0x46, 0x05, 
+  0xA0, 0x5F, 0x5B, 0x53, 0x3F, 0xFC, 0xA8, 0xBE, 0x8E, 0xE5, 0x2B, 0x96, 0x6E, 0x05, 0x91, 0x28, 0xC4, 0xF6, 0xEC, 0x3E, 
+  0xB6, 0x6B, 0xC7, 0xD1, 0xBD, 0xBB, 0xAF, 0x24, 0x32, 0x97, 0xE4, 0x55, 0xD1, 0xE8, 0x55, 0x05, 0x40, 0xF3, 0x09, 0xF7, 
+  0x0B, 0xE5, 0x64, 0x4F, 0x05, 0x19, 0x67, 0xA6, 0x2B, 0x52, 0x0E, 0x8E, 0x5C, 0xC8, 0x51, 0x87, 0x22, 0x7A, 0xA9, 0xCC, 
+  0x51, 0x40, 0x50, 0x88, 0x73, 0x57, 0xAE, 0xC3, 0xA4, 0x2F, 0xA6, 0x23, 0xE2, 0x31, 0xCB, 0xCD, 0x2C, 0x8D, 0xE8, 0x0D, 
+  0x7F, 0xD8, 0xDB, 0x19, 0x85, 0xE7, 0xCD, 0x90, 0x1A, 0x96, 0x15, 0xDD, 0x92, 0xF4, 0xA8, 0x64, 0x99, 0xEB, 0xBA, 0x3C, 
+  0x32, 0xC4, 0x3D, 0x46, 0x07, 0x27, 0x8F, 0x19, 0xAC, 0x13, 0x00, 0xDF, 0x5C, 0xD3, 0x97, 0xA6, 0x2B, 0x40, 0x49, 0xD9, 
+  0xC6, 0x37, 0x62, 0xF6, 0x0E, 0xAF, 0x5A, 0xBA, 0x89, 0x53, 0x70, 0xB6, 0x6F, 0x3D, 0xB4, 0x6F, 0xEF, 0xD5, 0xD7, 0x5E, 
+  0x7B, 0xE7, 0x9D, 0x77, 0x3E, 0xBA, 0x7F, 0xEF, 0xD5, 0x7B, 0x76, 0x5D, 0x09, 0x14, 0xE0, 0x07, 0xD4, 0x47, 0xCB, 0x86, 
+  0x36, 0x30, 0x07, 0xA6, 0x8D, 0x4A, 0xE1, 0x4A, 0x3F, 0x99, 0x7E, 0x00, 0xEF, 0x56, 0x46, 0xA7, 0x48, 0xD0, 0x5F, 0xE6, 
+  0xD5, 0x7C, 0x42, 0x84, 0x82, 0x68, 0xD8, 0x77, 0xAE, 0x81, 0x11, 0x4D, 0x83, 0x6F, 0x66, 0x49, 0x72, 0xC2, 0x52, 0xC1, 
+  0xE9, 0x35, 0x7F, 0x25, 0x88, 0xE1, 0x17, 0x22, 0x0C, 0x09, 0xD3, 0xB1, 0x20, 0x29, 0xE0, 0x58, 0x27, 0x26, 0x39, 0x75, 
+  0xE5, 0xED, 0x8C, 0x36, 0x01, 0xA2, 0xCD, 0x1B, 0xF7, 0xEE, 0xBC, 0xEC, 0x08, 0x5D, 0xF4, 0xD5, 0x2B, 0xB7, 0xD3, 0xC7, 
+  0x5D, 0xB1, 0x7C, 0xCB, 0x8E, 0xAD, 0x87, 0x21, 0x6A, 0x90, 0x11, 0xF1, 0x0A, 0xC4, 0x73, 0x31, 0xF6, 0x00, 0x29, 0x86, 
+  0x45, 0x01, 0x6A, 0xEC, 0x08, 0xDD, 0xBC, 0x19, 0x1E, 0xE4, 0x95, 0x35, 0xEB, 0xD3, 0x69, 0x2E, 0x4B, 0x9E, 0xC0, 0x7B, 
+  0x56, 0x1D, 0x7C, 0xD9, 0x62, 0x3B, 0x86, 0x1A, 0x38, 0x48, 0xC2, 0xAD, 0x15, 0xA5, 0x14, 0xBA, 0x71, 0x52, 0xEB, 0x6A, 
+  0xA9, 0x65, 0xAE, 0x9D, 0x61, 0xCE, 0x58, 0xFA, 0x86, 0x4B, 0x6F, 0x1A, 0x19, 0x2D, 0xC4, 0xC8, 0xEC, 0x02, 0x02, 0x88, 
+  0x14, 0x65, 0xA1, 0x31, 0xA0, 0x04, 0xF9, 0x38, 0xDF, 0xA3, 0x0D, 0x73, 0x5B, 0x76, 0x33, 0x94, 0xD5, 0xE2, 0x10, 0xD4, 
+  0x04, 0xA4, 0x86, 0x74, 0xE8, 0x60, 0xA9, 0x1C, 0x3E, 0x74, 0xFD, 0xCD, 0xB7, 0x3E, 0x74, 0xC7, 0x1D, 0x8F, 0xDC, 0x7B, 
+  0xFF, 0xD3, 0x77, 0xDF, 0xF9, 0xD8, 0x0D, 0xD7, 0xDD, 0x7D, 0xFC, 0x9A, 0x3B, 0xF7, 0xEC, 0xBC, 0x6A, 0xE5, 0xF0, 0x16, 
+  0x8A, 0xA3, 0xC1, 0xCE, 0x15, 0x32, 0x66, 0x89, 0x93, 0xEE, 0xBA, 0x76, 0x00, 0x69, 0x84, 0xF1, 0xC1, 0x40, 0x64, 0x64, 
+  0x6A, 0x44, 0x23, 0x19, 0x88, 0xEA, 0xC3, 0x50, 0x0B, 0x4C, 0xD6, 0x24, 0xD9, 0xA1, 0x7F, 0xF0, 0xBC, 0x00, 0xC1, 0x6E, 
+  0xCE, 0xA4, 0x0D, 0x90, 0x3A, 0x59, 0x08, 0x09, 0xF4, 0x56, 0x99, 0x85, 0x45, 0x26, 0x02, 0x6E, 0xC5, 0xD9, 0x55, 0xAD, 
+  0x7C, 0xE3, 0x6F, 0xF7, 0x72, 0x3A, 0x13, 0x28, 0x60, 0xA0, 0x6F, 0x15, 0x86, 0x4F, 0x35, 0x40, 0x1F, 0x77, 0xE5, 0xF0, 
+  0x56, 0xBA, 0x14, 0x14, 0xCC, 0x83, 0xBD, 0xAB, 0x77, 0x6C, 0x3A, 0x08, 0xA0, 0x73, 0x7A, 0x12, 0x8A, 0xE7, 0x02, 0x88, 
+  0x57, 0xE9, 0x4B, 0xA1, 0x63, 0x74, 0x60, 0x25, 0xCE, 0x05, 0xEF, 0x4D, 0x44, 0x8F, 0x9A, 0x83, 0x4D, 0x77, 0x2B, 0x48, 
+  0xDE, 0x2A, 0xB7, 0x63, 0x75, 0x60, 0xD1, 0xC6, 0xDA, 0xB2, 0xF6, 0x15, 0xA4, 0xB5, 0xC0, 0x10, 0x3F, 0x16, 0x93, 0xB7, 
+  0x42, 0x97, 0x24, 0x47, 0x1F, 0xF4, 0x92, 0x5B, 0xB5, 0x47, 0xCD, 0x14, 0xE9, 0x64, 0x32, 0x81, 0x33, 0xD2, 0x71, 0x0B, 
+  0x63, 0xDE, 0x13, 0x20, 0x70, 0xF1, 0x85, 0x17, 0x49, 0xD8, 0x9C, 0x31, 0xFB, 0xE2, 0x71, 0xE7, 0x53, 0xE9, 0x68, 0xC1, 
+  0xC9, 0x0F, 0xFB, 0x93, 0x2F, 0x3E, 0xFF, 0x82, 0xA8, 0xE0, 0x68, 0x80, 0xF8, 0xE1, 0x87, 0x9F, 0xFB, 0xCE, 0x77, 0xDE, 
+  0x79, 0xF4, 0xD1, 0xE7, 0xEF, 0xBA, 0xEB, 0xB1, 0x6B, 0xAE, 0xBC, 0x0D, 0x28, 0xD8, 0xBA, 0x71, 0xFF, 0xB2, 0x25, 0x1B, 
+  0x97, 0xF6, 0xAF, 0x81, 0x2D, 0xC1, 0x40, 0x98, 0x2D, 0x9E, 0xA6, 0xA9, 0x95, 0x41, 0x17, 0x4F, 0x1B, 0x1E, 0x2C, 0xF9, 
+  0xA8, 0xA0, 0x53, 0xB0, 0x14, 0xDE, 0x9A, 0x05, 0x22, 0x7A, 0x96, 0xDA, 0xA9, 0x93, 0x9C, 0x98, 0x43, 0x81, 0x69, 0x17, 
+  0x92, 0x98, 0x89, 0x98, 0xE8, 0x87, 0x47, 0x27, 0xD3, 0x17, 0xA9, 0x2C, 0x68, 0x04, 0xEE, 0x40, 0x1E, 0xB2, 0x20, 0xF4, 
+  0xBD, 0x7B, 0xE7, 0x15, 0xC7, 0x8E, 0xDE, 0x76, 0xD9, 0xF6, 0x23, 0x07, 0x0F, 0x1E, 0xDF, 0xBB, 0xF7, 0xD8, 0xD6, 0xAD, 
+  0x07, 0x48, 0x93, 0x80, 0x44, 0xCA, 0x66, 0x6E, 0xA1, 0x18, 0xA1, 0x00, 0x5E, 0x96, 0x13, 0xC5, 0x14, 0x70, 0x84, 0xED, 
+  0xC2, 0x32, 0xF6, 0xCE, 0x47, 0x70, 0xEE, 0xEA, 0x83, 0xA3, 0x17, 0x6A, 0xF0, 0xF9, 0x32, 0x22, 0xAA, 0x45, 0x1E, 0xAB, 
+  0x00, 0x11, 0x34, 0x68, 0xEE, 0x2E, 0x77, 0x66, 0x6D, 0x06, 0x8A, 0x26, 0xD9, 0xE7, 0x48, 0x2D, 0xEF, 0x28, 0xED, 0xE4, 
+  0x01, 0x8E, 0xDB, 0x99, 0x30, 0x4D, 0x3A, 0xA6, 0x98, 0xC1, 0x42, 0x49, 0x22, 0x42, 0x52, 0xDF, 0x9B, 0x2F, 0x66, 0xF7, 
+  0x7E, 0x57, 0x3C, 0x4A, 0x38, 0x4D, 0x96, 0x8F, 0xCF, 0xAC, 0x29, 0xBE, 0x6B, 0x96, 0x6F, 0x79, 0xF0, 0xE1, 0xE7, 0x9E, 
+  0x79, 0xEA, 0xD5, 0xEB, 0x6F, 0xBC, 0x0F, 0x7B, 0x3C, 0x7C, 0xF0, 0x3A, 0xBE, 0xF3, 0x60, 0x68, 0x60, 0x0D, 0x4C, 0xA1, 
+  0x2E, 0xBE, 0xA2, 0xBA, 0x79, 0xA0, 0x20, 0xB5, 0x8C, 0x7D, 0xE7, 0xD4, 0x19, 0xEA, 0x88, 0xF2, 0x66, 0x62, 0x52, 0xEC, 
+  0xA0, 0xCD, 0xD8, 0xA3, 0x98, 0x27, 0x98, 0xC3, 0x85, 0xF4, 0xC9, 0x83, 0xE9, 0xB5, 0x26, 0x0A, 0xF1, 0x20, 0x30, 0x92, 
+  0xC7, 0x85, 0x6C, 0x60, 0xE8, 0x20, 0xE8, 0x80, 0xB6, 0x4D, 0x41, 0x56, 0x45, 0x4B, 0x6D, 0x0F, 0xF2, 0x05, 0x73, 0xB6, 
+  0x6D, 0x3D, 0x74, 0x60, 0xFF, 0xF1, 0xDB, 0x6E, 0x7D, 0x98, 0x8C, 0xE0, 0x8A, 0xCB, 0xAF, 0xBF, 0xFA, 0xEA, 0xDB, 0xAE, 
+  0x3C, 0x7A, 0x33, 0xEF, 0x01, 0xC5, 0x34, 0x56, 0x75, 0x51, 0x45, 0xD3, 0xCE, 0x0A, 0x0B, 0x09, 0x9F, 0x3B, 0x63, 0xC6, 
+  0x08, 0xBC, 0x04, 0x22, 0xE8, 0x28, 0x49, 0x97, 0x83, 0xF9, 0x77, 0xA2, 0x0F, 0x79, 0x65, 0xFE, 0xA9, 0xBB, 0x84, 0xE7, 
+  0xE0, 0x2E, 0x7E, 0x7B, 0x0A, 0x1D, 0x78, 0xE1, 0xDB, 0x4B, 0x60, 0xD1, 0xC1, 0xB4, 0xCE, 0xA6, 0xE9, 0xC1, 0xDA, 0x45, 
+  0xF3, 0x5D, 0x67, 0x72, 0xC2, 0x2C, 0x8B, 0x90, 0xE9, 0x9D, 0x25, 0x33, 0x69, 0x0A, 0xA4, 0x9B, 0x5E, 0xBD, 0x4E, 0x40, 
+  0x67, 0x82, 0x73, 0x42, 0x78, 0x1F, 0xB8, 0x30, 0x29, 0x90, 0xDF, 0xDC, 0x79, 0xB3, 0x66, 0xCC, 0x64, 0xD3, 0x19, 0x5C, 
+  0x9D, 0x89, 0x17, 0x5D, 0x0C, 0xC7, 0x82, 0x19, 0x8E, 0x68, 0x45, 0xDA, 0x5F, 0xA2, 0x86, 0xD8, 0xD0, 0x84, 0x2D, 0x9B, 
+  0xF6, 0xDF, 0x7D, 0xF7, 0xE3, 0xB4, 0x07, 0xF0, 0x09, 0xF2, 0xC2, 0x63, 0x57, 0xDC, 0x82, 0x3D, 0x2E, 0x19, 0x5A, 0x07, 
+  0x21, 0xA5, 0xA2, 0xA0, 0x1E, 0x57, 0x20, 0x3C, 0xD0, 0xCD, 0x27, 0x96, 0x32, 0x6E, 0x22, 0x5B, 0x45, 0x07, 0xD2, 0x86, 
+  0x92, 0xDD, 0x00, 0x32, 0xF5, 0x54, 0xF6, 0x8D, 0x36, 0xA6, 0x9C, 0xC1, 0x96, 0x21, 0x44, 0x61, 0xFE, 0xC2, 0x6F, 0x10, 
+  0xB5, 0x25, 0xD2, 0x02, 0x31, 0x3B, 0xB1, 0x32, 0xCB, 0xB2, 0x85, 0x02, 0x43, 0x39, 0xB6, 0x7A, 0x78, 0xDB, 0xEE, 0xDD, 
+  0x57, 0xDC, 0x72, 0xF3, 0x83, 0x07, 0xF6, 0x5C, 0x45, 0x77, 0xE8, 0xE6, 0x5B, 0x1F, 0x64, 0xC4, 0x7D, 0xDB, 0x6D, 0x0F, 
+  0x1D, 0xDC, 0x7F, 0x0D, 0xAE, 0x40, 0xE1, 0xC6, 0xBF, 0x83, 0x8E, 0xDF, 0x54, 0xDF, 0x06, 0xED, 0x3C, 0x74, 0x41, 0x80, 
+  0xC6, 0x24, 0x99, 0x5B, 0x04, 0x45, 0x49, 0xD9, 0x0F, 0xF8, 0x18, 0xB9, 0x5B, 0x8A, 0x89, 0xAA, 0x41, 0x66, 0x56, 0xEE, 
+  0xAF, 0xB8, 0xEB, 0x63, 0xCD, 0xDC, 0x4B, 0x45, 0x72, 0xD5, 0x20, 0xF3, 0x58, 0xE5, 0xC3, 0x68, 0x32, 0x23, 0x86, 0x26, 
+  0x52, 0x76, 0xC6, 0xA1, 0x0E, 0x87, 0x85, 0x91, 0x10, 0xB3, 0x14, 0x1D, 0x1D, 0xAB, 0x86, 0x4C, 0x23, 0x48, 0x49, 0x4E, 
+  0xEE, 0x5C, 0xDB, 0xB9, 0xD0, 0xDA, 0x58, 0x27, 0x79, 0x02, 0x1A, 0x8C, 0xC2, 0xFD, 0x64, 0xA0, 0x4F, 0xDE, 0x82, 0x43, 
+  0x90, 0xB9, 0x83, 0xAD, 0x34, 0xEC, 0x20, 0x11, 0xD3, 0xF3, 0x1A, 0x7F, 0xC1, 0x85, 0x42, 0x22, 0x3E, 0xFD, 0xCC, 0x73, 
+  0xCE, 0x18, 0xC7, 0xD8, 0xE4, 0x81, 0x47, 0x9E, 0x7B, 0xFA, 0xA9, 0x57, 0xEF, 0xB9, 0xE7, 0xB1, 0xE3, 0x57, 0xDF, 0xC1, 
+  0x37, 0xE1, 0x1C, 0x3B, 0x76, 0x0B, 0xE3, 0x1D, 0x1C, 0x62, 0xE5, 0x92, 0x8D, 0xDD, 0x9D, 0x8B, 0xE5, 0x5B, 0x71, 0x8A, 
+  0x5B, 0x18, 0x78, 0x71, 0x1A, 0x34, 0x3D, 0x3E, 0x1A, 0x99, 0x12, 0xAE, 0x62, 0x4C, 0x7D, 0xCE, 0x58, 0x9F, 0x14, 0xD6, 
+  0xF0, 0x8B, 0xB9, 0x6B, 0xDE, 0x61, 0x12, 0x43, 0x2A, 0x06, 0xF4, 0xFC, 0x4A, 0x76, 0xB5, 0x24, 0xA4, 0x53, 0x67, 0xC0, 
+  0x88, 0x85, 0xB9, 0x5D, 0x92, 0x59, 0x49, 0x8B, 0x94, 0x6E, 0x39, 0x18, 0x78, 0xFB, 0x6D, 0x8F, 0xDC, 0x73, 0xD7, 0x13, 
+  0xF4, 0x24, 0xEE, 0xBC, 0xFB, 0xF1, 0x07, 0x1F, 0xFC, 0x3A, 0xD2, 0xBF, 0xFF, 0xFE, 0xA7, 0x09, 0x4E, 0xD7, 0x5C, 0x7D, 
+  0xC7, 0xD1, 0xCB, 0x6F, 0x5A, 0xB7, 0x76, 0x17, 0xBD, 0x13, 0x8A, 0x09, 0xF6, 0x17, 0x13, 0xC6, 0x66, 0x4E, 0x99, 0x2E, 
+  0x29, 0xBF, 0xF1, 0x39, 0x05, 0x1C, 0x47, 0xE2, 0x1E, 0x9A, 0x8F, 0xD7, 0x1B, 0xCC, 0x75, 0x18, 0x4B, 0xFC, 0xC0, 0x6B, 
+  0xF8, 0xA3, 0xC7, 0x8D, 0x42, 0x80, 0xC1, 0xBA, 0x91, 0x9A, 0xF2, 0x00, 0xB8, 0x90, 0x61, 0x8B, 0x09, 0xE8, 0x12, 0x52, 
+  0x82, 0x23, 0xF9, 0xD6, 0x25, 0x1E, 0x27, 0x23, 0xE4, 0xB5, 0x94, 0x6D, 0x29, 0xAA, 0x8A, 0x66, 0xD2, 0x6B, 0x36, 0xF5, 
+  0x45, 0xB2, 0xD1, 0xD5, 0x21, 0x16, 0x58, 0xB2, 0x85, 0x4B, 0x43, 0x12, 0x6A, 0x9E, 0x74, 0xE8, 0x4C, 0xC5, 0x48, 0x84, 
+  0x24, 0x84, 0x92, 0x2C, 0x6A, 0x77, 0x01, 0xB7, 0x10, 0x65, 0x40, 0x22, 0x9E, 0x38, 0xE9, 0xDC, 0xAF, 0xC9, 0x16, 0x87, 
+  0xAC, 0xA4, 0x7C, 0x6C, 0xF0, 0xBE, 0xFB, 0x9E, 0xBA, 0xEE, 0xF8, 0x9D, 0x00, 0xC2, 0xD1, 0x23, 0x37, 0x90, 0xA8, 0xD0, 
+  0x2D, 0xC0, 0x24, 0xA1, 0x96, 0x0E, 0x0F, 0xAD, 0x87, 0xB0, 0xC5, 0x6E, 0x03, 0xC8, 0x2F, 0x18, 0x66, 0x4E, 0xD2, 0xC8, 
+  0xD1, 0x35, 0x08, 0x1A, 0x05, 0xA8, 0x37, 0x90, 0xF0, 0x70, 0x8C, 0x1B, 0x8E, 0xC2, 0x86, 0x06, 0xC2, 0x38, 0x5C, 0x5B, 
+  0xD9, 0x4E, 0xC1, 0xB1, 0xFC, 0x4C, 0x26, 0x98, 0x9D, 0x65, 0x70, 0x5C, 0x47, 0x2D, 0xD1, 0x98, 0xD6, 0x2C, 0x95, 0x20, 
+  0x73, 0x6C, 0x58, 0x1D, 0x77, 0xDC, 0xFE, 0x28, 0x89, 0xD9, 0x93, 0x4F, 0xBE, 0x74, 0xC7, 0x6D, 0x0F, 0x73, 0x77, 0xD7, 
+  0xF6, 0x23, 0x03, 0x1D, 0xC3, 0x7D, 0xDD, 0xCB, 0xF8, 0xA7, 0xD0, 0xF1, 0xD6, 0xAF, 0xDF, 0xD5, 0x54, 0xDF, 0x45, 0x53, 
+  0x8B, 0x39, 0x2B, 0xEE, 0x45, 0x8A, 0xA1, 0x88, 0xA4, 0x0A, 0xF0, 0x62, 0x8E, 0x48, 0xDC, 0x98, 0xBF, 0x75, 0x05, 0xEB, 
+  0x1F, 0x8E, 0x1F, 0x78, 0xE3, 0xA7, 0x35, 0x5E, 0xC5, 0x10, 0x37, 0x8F, 0x14, 0x1E, 0x0A, 0xB5, 0x0F, 0xFF, 0x43, 0x67, 
+  0xF1, 0xDC, 0x15, 0x69, 0x86, 0x40, 0x71, 0x4D, 0x60, 0x8C, 0x07, 0x0F, 0xDE, 0xD0, 0x17, 0xA5, 0x01, 0xA7, 0x0C, 0x17, 
+  0xEB, 0x19, 0x5E, 0x36, 0xC7, 0x18, 0x2A, 0x98, 0x36, 0x4A, 0x35, 0x35, 0xD4, 0xEC, 0x85, 0x7E, 0x0B, 0xD0, 0xA4, 0xAD, 
+  0x2E, 0x5A, 0x9E, 0xB3, 0xA6, 0x4D, 0xA5, 0xE1, 0x7B, 0x9A, 0xCF, 0x59, 0x4C, 0xE1, 0xAF, 0xBD, 0xE6, 0xCE, 0x07, 0x1E, 
+  0x7A, 0xF6, 0xA1, 0x87, 0x9E, 0xBD, 0xFD, 0xF6, 0x07, 0xB1, 0x50, 0xBA, 0x05, 0x57, 0x1F, 0xBB, 0xF5, 0xC8, 0xA1, 0xEB, 
+  0x48, 0x64, 0xE9, 0xA6, 0x6D, 0x5C, 0xBD, 0x83, 0x4C, 0x09, 0xAE, 0x35, 0x6C, 0xC6, 0x46, 0x73, 0x42, 0x7A, 0x41, 0xAA, 
+  0x1C, 0x67, 0xC0, 0x4C, 0x38, 0x33, 0x39, 0x1D, 0xE6, 0x84, 0x94, 0x99, 0x09, 0x69, 0x24, 0x5D, 0xC2, 0x52, 0x30, 0xDF, 
+  0x85, 0x00, 0xF9, 0x1E, 0x8E, 0x17, 0x4C, 0xE1, 0xF4, 0x98, 0x1C, 0x78, 0x44, 0x9C, 0xD1, 0xC4, 0xA0, 0xA6, 0x91, 0xAF, 
+  0x67, 0xE2, 0x4B, 0xFB, 0x5A, 0x06, 0xF7, 0xEC, 0xBA, 0x02, 0x87, 0xBB, 0xFF, 0xBE, 0x67, 0x30, 0xFF, 0x9B, 0x6E, 0xB8, 
+  0x97, 0x6D, 0x77, 0xB8, 0xC8, 0xC2, 0x39, 0xC1, 0x6C, 0x4D, 0xC4, 0x2C, 0xE8, 0x11, 0x01, 0xA4, 0x2D, 0x75, 0x1D, 0xA4, 
+  0x49, 0x0D, 0x35, 0x8B, 0xF0, 0x06, 0x88, 0x81, 0xBC, 0x79, 0x96, 0xA6, 0x43, 0xC4, 0x67, 0x09, 0x06, 0xA1, 0xCC, 0x4D, 
+  0x1D, 0xF4, 0xF7, 0x3A, 0x81, 0x92, 0x0D, 0x25, 0x66, 0x10, 0x0F, 0x6C, 0x36, 0x39, 0x86, 0x99, 0xA2, 0x44, 0x25, 0x91, 
+  0x66, 0xB8, 0xD0, 0x89, 0xF9, 0x1B, 0x14, 0x90, 0x99, 0x9C, 0x8A, 0x8F, 0x4B, 0x81, 0x47, 0x1C, 0x0B, 0x8D, 0xC4, 0x7E, 
+  0x4D, 0x7B, 0xD6, 0xB7, 0xBA, 0xA2, 0x9E, 0x7F, 0x49, 0xB2, 0x61, 0xC8, 0xDF, 0x86, 0x63, 0x23, 0xA8, 0x25, 0x3D, 0x51, 
+  0x75, 0x20, 0x13, 0x3C, 0x5C, 0x75, 0x1A, 0x4A, 0x8B, 0x8E, 0x91, 0x59, 0x26, 0x6F, 0x71, 0xF8, 0xA9, 0x5A, 0xE2, 0x6A, 
+  0xC5, 0x44, 0x91, 0x45, 0xCB, 0x81, 0x61, 0x13, 0xDD, 0x18, 0x7A, 0x93, 0xF4, 0x27, 0x6E, 0xBD, 0xF9, 0x81, 0xDB, 0xEE, 
+  0x78, 0xE4, 0xE1, 0x87, 0xBE, 0xF1, 0xC8, 0x43, 0x12, 0x12, 0xEE, 0xBA, 0xF3, 0x71, 0x1E, 0x41, 0x07, 0xBB, 0x76, 0x5E, 
+  0xB1, 0x6E, 0xCD, 0x8E, 0x15, 0x4B, 0x37, 0x61, 0x9B, 0x3D, 0x9D, 0x7C, 0x6D, 0xE0, 0x80, 0xE8, 0x80, 0x6D, 0x20, 0x85, 
+  0xF5, 0x25, 0x99, 0xE5, 0x6C, 0x1B, 0x2D, 0xCD, 0xAA, 0x80, 0xA2, 0x90, 0x9B, 0x98, 0x2F, 0x47, 0x21, 0x16, 0xD7, 0x65, 
+  0xC4, 0xE6, 0xE6, 0x25, 0x71, 0xC0, 0x33, 0x67, 0xC0, 0x96, 0xC0, 0x40, 0xA5, 0xCE, 0x82, 0x3F, 0x09, 0xCB, 0x91, 0x56, 
+  0x39, 0xDC, 0x19, 0xE1, 0xA4, 0x36, 0xF4, 0xF2, 0x6A, 0xFB, 0xF7, 0x5F, 0xCD, 0x78, 0x80, 0x20, 0x74, 0xCD, 0x55, 0xB7, 
+  0xAD, 0x5A, 0xBE, 0x25, 0x3C, 0x30, 0xF6, 0x74, 0x9F, 0xB3, 0x6C, 0xDA, 0xA6, 0x17, 0x9C, 0x6D, 0x0B, 0x07, 0x60, 0xE9, 
+  0xE2, 0xB5, 0x75, 0xD5, 0x2D, 0xCA, 0x82, 0xA1, 0x1D, 0x22, 0xB5, 0x5E, 0x90, 0xF0, 0x2A, 0x94, 0x8F, 0x8D, 0x0E, 0xC2, 
+  0x43, 0x25, 0x0B, 0x38, 0x09, 0x88, 0xC8, 0x4D, 0x05, 0xB2, 0x44, 0x07, 0x63, 0xA5, 0x3F, 0x42, 0x48, 0x32, 0x24, 0x2D, 
+  0xB0, 0x3B, 0x24, 0x1C, 0xA0, 0x80, 0xB6, 0x46, 0xDA, 0x3E, 0x6B, 0x86, 0x2F, 0x0D, 0x2F, 0x18, 0x03, 0xD8, 0x29, 0x03, 
+  0x10, 0x7C, 0x85, 0xDD, 0x58, 0x58, 0x01, 0x00, 0xA2, 0xFC, 0x6F, 0x65, 0xD2, 0xA1, 0x03, 0x95, 0xBE, 0xF5, 0x24, 0x0D, 
+  0xE6, 0xFA, 0x82, 0x2E, 0xC9, 0x0E, 0xC6, 0x47, 0xB8, 0x43, 0xAA, 0x30, 0xD5, 0x8D, 0xCE, 0x34, 0xB4, 0xBF, 0x48, 0x12, 
+  0xC9, 0x77, 0x3B, 0xA1, 0x8C, 0xA9, 0x97, 0x48, 0xE7, 0x9D, 0xF1, 0x21, 0x72, 0xBF, 0xF7, 0xDE, 0x27, 0x1F, 0x78, 0xE8, 
+  0xB9, 0xFB, 0x1E, 0xF8, 0x3A, 0xA0, 0xF4, 0xC0, 0x03, 0xCF, 0x3C, 0xF2, 0xC8, 0x37, 0x58, 0x24, 0x8E, 0x97, 0x6D, 0x3B, 
+  0xC4, 0x13, 0x56, 0x0F, 0x6F, 0xE5, 0xC8, 0x6B, 0x86, 0xCF, 0x10, 0x00, 0xE8, 0x36, 0x37, 0x55, 0x89, 0x45, 0xB7, 0xD4, 
+  0x75, 0xB3, 0x69, 0x92, 0x38, 0xC1, 0xD7, 0x8A, 0x72, 0xC8, 0x3F, 0x5A, 0x61, 0x31, 0x91, 0xAF, 0xCA, 0xAF, 0xA7, 0xB6, 
+  0x90, 0x60, 0x9E, 0x51, 0x01, 0xF2, 0xB4, 0x35, 0x0D, 0xA0, 0x03, 0xF9, 0xE2, 0xE8, 0xB6, 0xC5, 0xE8, 0x92, 0xD1, 0xD8, 
+  0x75, 0xC7, 0xEF, 0x42, 0x01, 0xB7, 0xDE, 0xF9, 0x08, 0x0E, 0x91, 0x18, 0x99, 0x26, 0x89, 0x9A, 0x49, 0x11, 0x18, 0x74, 
+  0x43, 0xE5, 0x27, 0x8B, 0x33, 0xE9, 0x82, 0xA4, 0x0D, 0x64, 0x53, 0x83, 0x7D, 0x2B, 0xE8, 0x68, 0xD5, 0x54, 0xB6, 0x20, 
+  0x22, 0xD4, 0x20, 0x19, 0xAA, 0x22, 0x92, 0x64, 0x47, 0x92, 0x1A, 0x99, 0x40, 0xED, 0x44, 0x08, 0x55, 0x86, 0x4D, 0x52, 
+  0x7D, 0xDC, 0xD4, 0xC5, 0x61, 0xEF, 0x3A, 0x00, 0x12, 0x65, 0x98, 0x71, 0x0E, 0x23, 0x31, 0x8E, 0x6A, 0x13, 0xB0, 0xA2, 
+  0x9A, 0x15, 0xE2, 0x85, 0x7C, 0x43, 0x52, 0x1E, 0xE7, 0x4E, 0x32, 0x2F, 0x65, 0x76, 0xCA, 0xA8, 0x8F, 0xD4, 0x18, 0x46, 
+  0xBB, 0x28, 0x3F, 0x50, 0x38, 0x97, 0x8A, 0x36, 0x4A, 0x63, 0xD2, 0x30, 0xEE, 0xA2, 0x93, 0x13, 0xCC, 0x5D, 0x1D, 0x08, 
+  0x25, 0x4B, 0x88, 0x37, 0x86, 0xA7, 0xA5, 0xF1, 0x79, 0x34, 0x5B, 0x5B, 0x7C, 0x02, 0x50, 0xA2, 0x6E, 0x68, 0x6A, 0xEC, 
+  0x04, 0xF7, 0x89, 0xC3, 0xE4, 0x45, 0xF7, 0x3F, 0xF8, 0xEC, 0x8B, 0x2F, 0xBF, 0xF5, 0xF2, 0xCB, 0xDF, 0x7F, 0xF9, 0xD5, 
+  0xB7, 0x5F, 0xF9, 0xD6, 0x0F, 0x1F, 0x7E, 0xF4, 0x79, 0xF4, 0xF1, 0xD0, 0x83, 0xCF, 0x91, 0x3B, 0x6E, 0xD9, 0x78, 0x90, 
+  0x9A, 0x16, 0x13, 0xA6, 0x92, 0xA2, 0x90, 0xE6, 0x62, 0xED, 0xCA, 0xCB, 0xA0, 0x4A, 0x0A, 0x19, 0x82, 0x01, 0x40, 0x43, 
+  0x0F, 0x23, 0x20, 0xBE, 0x34, 0x5D, 0xBE, 0x9B, 0xB2, 0xB9, 0x8F, 0xC7, 0xE9, 0x43, 0x34, 0xD5, 0x75, 0x93, 0xF8, 0x12, 
+  0x7E, 0x07, 0x16, 0x0D, 0x2F, 0x5D, 0xBC, 0x7E, 0xCD, 0xAA, 0xED, 0x5B, 0x37, 0xEF, 0x27, 0xD2, 0xE0, 0x5E, 0x84, 0x5F, 
+  0xE2, 0xF0, 0x3D, 0x77, 0x3F, 0x49, 0xCC, 0xBF, 0xE0, 0x9C, 0x8B, 0x10, 0xF7, 0x19, 0x67, 0x9C, 0xC5, 0x84, 0x15, 0x14, 
+  0x1A, 0x7F, 0xF1, 0x85, 0x13, 0x2E, 0x18, 0xCF, 0xD6, 0x23, 0xB6, 0xE3, 0x69, 0x4A, 0x4D, 0x83, 0x84, 0xAD, 0xFA, 0xCD, 
+  0x1C, 0x5A, 0x5F, 0xDB, 0xA5, 0xDF, 0x04, 0x63, 0x0A, 0x05, 0x47, 0xD0, 0x24, 0xAF, 0x4E, 0xAD, 0xE0, 0xC9, 0x50, 0x47, 
+  0xE9, 0x40, 0x13, 0x47, 0xDB, 0x4A, 0x73, 0x87, 0x8B, 0x71, 0x89, 0x61, 0xB0, 0x77, 0x25, 0x72, 0xD2, 0x5D, 0x01, 0x3A, 
+  0xB0, 0x2F, 0x86, 0xA2, 0x9C, 0x6F, 0x06, 0x2F, 0x1C, 0xE9, 0xE3, 0x16, 0x81, 0x01, 0x41, 0x54, 0x58, 0xD8, 0xA9, 0xA1, 
+  0x96, 0x48, 0x2E, 0x2C, 0x34, 0x26, 0x08, 0x3C, 0x11, 0x51, 0xF1, 0x91, 0xB2, 0x4B, 0x54, 0x5E, 0xD6, 0xD5, 0x81, 0xF2, 
+  0x1B, 0x8D, 0x1F, 0xC8, 0x73, 0x48, 0x37, 0x75, 0x94, 0x2F, 0x89, 0x79, 0x28, 0x39, 0x92, 0x99, 0xA0, 0x05, 0x88, 0x1A, 
+  0x1C, 0xC6, 0xFC, 0x82, 0x60, 0xB0, 0x88, 0x93, 0x63, 0xE1, 0xF8, 0xAF, 0x5B, 0xB5, 0x63, 0xC3, 0xBA, 0x5D, 0x07, 0xF6, 
+  0x1D, 0x23, 0x17, 0x7A, 0xEA, 0xA9, 0x97, 0x9F, 0xFF, 0xE6, 0xF7, 0xBE, 0xFE, 0xDC, 0xEB, 0xAF, 0xBD, 0xF6, 0xF6, 0xB3, 
+  0xCF, 0xBE, 0xFA, 0xCD, 0x6F, 0xBE, 0xF1, 0xDC, 0x73, 0xAF, 0x3F, 0xF2, 0xD8, 0x0B, 0xE8, 0x86, 0xF4, 0x11, 0xDA, 0x36, 
+  0xB1, 0x81, 0xA6, 0xC2, 0xEA, 0x65, 0x9B, 0xF9, 0xDA, 0x2E, 0x88, 0xAA, 0x74, 0x17, 0x54, 0xCA, 0x24, 0xFB, 0xCB, 0x06, 
+  0xD6, 0x12, 0x33, 0xC8, 0x29, 0x71, 0x17, 0x1E, 0xA1, 0xF3, 0xC1, 0x33, 0x65, 0x28, 0x7F, 0xE0, 0x38, 0x64, 0x6F, 0xCA, 
+  0x0E, 0xDA, 0x0F, 0x87, 0x0F, 0x5E, 0x7B, 0xFC, 0xEA, 0x5B, 0xAF, 0xB9, 0xE6, 0x76, 0xDC, 0x8E, 0x71, 0x31, 0xBF, 0x82, 
+  0x78, 0x2A, 0x93, 0xB2, 0x33, 0x65, 0x50, 0x33, 0x75, 0xE2, 0x25, 0xEC, 0x56, 0x67, 0x31, 0x11, 0x63, 0x34, 0xC6, 0x67, 
+  0xE7, 0x98, 0x67, 0x65, 0x43, 0x11, 0xD5, 0x70, 0x23, 0x16, 0x69, 0x12, 0xF8, 0x2C, 0x35, 0xA0, 0xA9, 0x99, 0x25, 0x4D, 
+  0x72, 0x32, 0x51, 0x97, 0x76, 0x0E, 0x04, 0x49, 0xC0, 0x90, 0x14, 0x56, 0xB0, 0xC8, 0x2A, 0xC0, 0x9B, 0xBF, 0x8B, 0x09, 
+  0x43, 0xA5, 0x0F, 0x33, 0xB1, 0x37, 0x28, 0x0A, 0x59, 0x43, 0x4F, 0x67, 0x70, 0x48, 0x0A, 0x81, 0xF8, 0xC8, 0xE8, 0x49, 
+  0xE4, 0x81, 0xC2, 0x89, 0x17, 0x4E, 0x20, 0xA1, 0xD4, 0xC6, 0x00, 0x9D, 0x4B, 0x07, 0x8B, 0x22, 0xA3, 0x84, 0x41, 0x46, 
+  0x05, 0xE0, 0x38, 0x84, 0xBB, 0x37, 0xC8, 0xC4, 0x6A, 0x8B, 0x45, 0xC2, 0xD0, 0x0E, 0x17, 0x92, 0x1D, 0xB4, 0x7D, 0xD8, 
+  0x67, 0x1A, 0x9D, 0x30, 0x1C, 0xA9, 0xF5, 0x03, 0x44, 0x0D, 0x0C, 0x9E, 0xF8, 0x24, 0xC4, 0x52, 0x52, 0x8E, 0x86, 0xDA, 
+  0x0E, 0xEA, 0x03, 0x86, 0x88, 0x9B, 0xD6, 0xEF, 0x04, 0x19, 0x38, 0xB5, 0x02, 0x08, 0x7A, 0xEA, 0xA9, 0x17, 0x7F, 0xF4, 
+  0xA3, 0xF7, 0x7F, 0xF0, 0x83, 0x9F, 0x3F, 0xF3, 0xCC, 0xCB, 0xDF, 0x7E, 0xE3, 0xC7, 0xAF, 0xBD, 0xF6, 0x43, 0x4D, 0x1C, 
+  0xC1, 0x71, 0x34, 0xB1, 0x7F, 0xC7, 0x95, 0xDB, 0x36, 0xED, 0x67, 0xE3, 0x34, 0x0E, 0x84, 0x32, 0x56, 0x0E, 0x6F, 0xA2, 
+  0xF5, 0x8F, 0x99, 0x93, 0xED, 0xE0, 0x4F, 0x58, 0x3A, 0x7D, 0xA7, 0xDD, 0x97, 0x5D, 0x4E, 0x2B, 0xD0, 0x04, 0xF6, 0xEB, 
+  0xA9, 0xBC, 0x30, 0x79, 0x62, 0xCC, 0x7D, 0xF7, 0x3E, 0x8D, 0xA6, 0xAF, 0x3E, 0x76, 0x33, 0xA1, 0xF8, 0xAA, 0x2B, 0x6F, 
+  0xD9, 0xBC, 0x79, 0x5F, 0x62, 0x64, 0x06, 0x22, 0x86, 0x0B, 0x4B, 0x05, 0x43, 0x70, 0x62, 0x33, 0x8B, 0xB3, 0xA6, 0x4E, 
+  0xF7, 0x9D, 0x3C, 0x95, 0x4C, 0x1A, 0x65, 0xB0, 0x13, 0x04, 0x80, 0x02, 0x9F, 0x39, 0xEB, 0x8A, 0x83, 0xCE, 0x81, 0x6B, 
+  0xBA, 0x81, 0xD2, 0xBD, 0xA0, 0x49, 0x47, 0x54, 0x30, 0x0E, 0x61, 0xF0, 0x47, 0x3E, 0xA6, 0xB9, 0x8D, 0x8A, 0x0C, 0x8C, 
+  0x51, 0x98, 0x1A, 0xD1, 0x81, 0x42, 0x87, 0x75, 0x02, 0x01, 0x22, 0x73, 0x6A, 0x87, 0x39, 0x58, 0x2B, 0x64, 0x8E, 0xEF, 
+  0x6C, 0x4C, 0x9E, 0xC1, 0xF4, 0x39, 0xE7, 0x9C, 0x8D, 0x0F, 0xA2, 0x7F, 0xA2, 0xB1, 0x34, 0xEB, 0x69, 0xB9, 0xF8, 0x07, 
+  0x21, 0x38, 0x09, 0xF4, 0x80, 0x7B, 0xB0, 0x70, 0xB6, 0x14, 0x6D, 0x0C, 0xE8, 0xCB, 0xFE, 0x2C, 0xD4, 0x36, 0xE2, 0x0D, 
+  0x91, 0x44, 0x0B, 0x93, 0xC2, 0x86, 0x4B, 0x89, 0x60, 0xA8, 0xF0, 0xF8, 0x81, 0x79, 0x7F, 0x92, 0xD5, 0x85, 0x84, 0x2C, 
+  0x0C, 0x04, 0xFA, 0x18, 0xBF, 0x10, 0x81, 0xC8, 0xE8, 0x31, 0x25, 0x66, 0xF7, 0x18, 0x2C, 0x3B, 0x2C, 0xC9, 0xE2, 0x43, 
+  0x65, 0xEA, 0x1B, 0x91, 0x1E, 0x9F, 0xD3, 0xDD, 0x36, 0x48, 0xFB, 0xFE, 0xC1, 0x07, 0x9E, 0x7D, 0xF6, 0xD9, 0xD7, 0x5E, 
+  0xFE, 0xD6, 0xF7, 0x5F, 0x7C, 0xE5, 0x7B, 0xCF, 0x3D, 0xFF, 0x1D, 0x74, 0x40, 0x4F, 0x89, 0x98, 0xC1, 0xC5, 0xE5, 0x97, 
+  0xDF, 0xC0, 0x77, 0x8D, 0x23, 0x44, 0x0C, 0x99, 0x0E, 0x07, 0x2E, 0x62, 0x94, 0x77, 0xCB, 0x9D, 0x77, 0x3C, 0x76, 0xDD, 
+  0x75, 0x77, 0x91, 0x53, 0x91, 0x71, 0xDE, 0x7D, 0xEF, 0x93, 0x32, 0x97, 0xBF, 0xE5, 0x81, 0xFB, 0xEF, 0x7F, 0xF2, 0x9E, 
+  0x7B, 0x9E, 0xF8, 0xC6, 0x37, 0xBE, 0xFD, 0xCC, 0x33, 0xAF, 0x82, 0x3F, 0x38, 0x99, 0xD4, 0x83, 0x37, 0x3F, 0xC8, 0xD3, 
+  0x2E, 0xDB, 0x72, 0x28, 0x2E, 0x2C, 0x19, 0x1D, 0x40, 0x3B, 0x43, 0xF4, 0xF3, 0xA7, 0xCB, 0xE4, 0x47, 0x13, 0x68, 0xEC, 
+  0xCF, 0xB4, 0xC1, 0x67, 0x12, 0x00, 0x7C, 0xA7, 0x4F, 0x63, 0x97, 0xD1, 0x85, 0xE3, 0xCE, 0x23, 0x99, 0xF6, 0x9D, 0xCA, 
+  0x50, 0x73, 0x56, 0x70, 0x80, 0xEA, 0x20, 0x42, 0x5A, 0xB9, 0x76, 0x37, 0x86, 0xCD, 0x97, 0xDC, 0x4E, 0x06, 0x85, 0xBA, 
+  0x8F, 0x95, 0xBB, 0xBD, 0x50, 0xFB, 0x15, 0x0F, 0x40, 0x46, 0x2C, 0x34, 0x16, 0x20, 0xAD, 0x79, 0xC4, 0x6D, 0xDA, 0xBF, 
+  0x32, 0x29, 0xD5, 0x7E, 0x24, 0x78, 0xAD, 0x0A, 0xD0, 0xFE, 0x94, 0xD9, 0x6A, 0x20, 0xD8, 0xA2, 0x7F, 0x6E, 0xD4, 0x20, 
+  0x83, 0x62, 0x93, 0xB0, 0x3A, 0x65, 0x1D, 0x04, 0x1B, 0xE3, 0x01, 0xD2, 0x1B, 0x10, 0xE0, 0x32, 0x6A, 0x60, 0x47, 0x5B, 
+  0x70, 0x60, 0x08, 0x6D, 0x77, 0x94, 0x6A, 0x06, 0x2C, 0xB3, 0xE8, 0xB1, 0x10, 0xC3, 0xB1, 0x2F, 0xD4, 0xBF, 0x78, 0x70, 
+  0x2D, 0x03, 0x03, 0x3C, 0x4F, 0x53, 0x11, 0xAD, 0x9C, 0x27, 0x5C, 0x30, 0x91, 0xE9, 0x1B, 0xA5, 0x2C, 0x12, 0x7C, 0xEA, 
+  0x89, 0x6F, 0xBE, 0xF0, 0xC2, 0xB7, 0x9F, 0x7E, 0xFA, 0xA5, 0xC7, 0x1E, 0x7B, 0x01, 0x95, 0x90, 0xCB, 0xD3, 0x59, 0x7A, 
+  0xE2, 0x89, 0x17, 0xB9, 0x25, 0xA7, 0x24, 0xB4, 0xE2, 0x34, 0x8F, 0x3F, 0xF9, 0xF2, 0x53, 0x4F, 0xBC, 0x74, 0xEF, 0x83, 
+  0x5F, 0xBF, 0xFD, 0xCE, 0xC7, 0xB8, 0xFB, 0xD8, 0x63, 0xDF, 0x78, 0xFC, 0xB1, 0x17, 0x5F, 0x27, 0x9C, 0x3C, 0xFC, 0x1C, 
+  0xD2, 0x07, 0xDC, 0xF8, 0xAB, 0xEF, 0x7E, 0xFB, 0x47, 0xAF, 0xBE, 0xFA, 0xFD, 0xE7, 0x5E, 0x78, 0xFD, 0x89, 0xA7, 0x5E, 
+  0x46, 0x13, 0x94, 0x23, 0xC7, 0xAE, 0xBC, 0x95, 0xD3, 0x19, 0x60, 0xFB, 0x72, 0x78, 0x0F, 0x5F, 0x73, 0xA1, 0xF3, 0x67, 
+  0x19, 0xBA, 0xF9, 0x8A, 0x1C, 0xA4, 0x2B, 0x6E, 0x68, 0x03, 0x2C, 0x99, 0xD9, 0xCD, 0xF2, 0x65, 0xA1, 0x27, 0x54, 0xA2, 
+  0x4D, 0x59, 0x69, 0x52, 0x19, 0x92, 0x99, 0x69, 0xD5, 0x99, 0x34, 0x69, 0xA1, 0x2C, 0x15, 0x97, 0x2A, 0x46, 0x7A, 0x76, 
+  0x2A, 0x7A, 0x5B, 0xFA, 0x3A, 0xF9, 0xBB, 0xF0, 0xC8, 0xA3, 0x65, 0xB3, 0x67, 0xB8, 0x90, 0x41, 0xB5, 0x07, 0x6B, 0xC7, 
+  0x23, 0x9A, 0xB7, 0x68, 0x4B, 0xD2, 0x34, 0xCA, 0xE5, 0xB5, 0x00, 0x13, 0xD1, 0x41, 0xB0, 0x34, 0x82, 0x34, 0xF5, 0xB4, 
+  0xFB, 0x0C, 0x34, 0x5B, 0x55, 0x14, 0x92, 0x97, 0xA5, 0x69, 0x6A, 0xB4, 0x6B, 0x4A, 0x18, 0x43, 0xC6, 0xF2, 0x0B, 0x64, 
+  0x04, 0xC8, 0xC7, 0x63, 0x8C, 0x95, 0x9F, 0x53, 0xDC, 0xD5, 0xDA, 0x0D, 0xCD, 0xDD, 0x7C, 0x91, 0x47, 0x2C, 0x29, 0x0A, 
+  0x95, 0x81, 0xC6, 0x3D, 0x91, 0xFD, 0x69, 0x9A, 0x90, 0x38, 0xAD, 0xA4, 0xA9, 0x93, 0xA6, 0x81, 0xEF, 0x77, 0xDD, 0xF1, 
+  0xB0, 0xC0, 0xD1, 0xB7, 0x7F, 0xF8, 0xDE, 0xBB, 0x1F, 0xBC, 0xFB, 0xEE, 0x6F, 0x89, 0x10, 0x44, 0x6C, 0x94, 0x41, 0x90, 
+  0xE0, 0xE2, 0x95, 0x6F, 0xFD, 0xE0, 0xD5, 0x57, 0xDF, 0x7E, 0xFC, 0xF1, 0x6F, 0x3E, 0xFB, 0xF5, 0xD7, 0x09, 0xE0, 0x2F, 
+  0xBD, 0xF2, 0xD6, 0x4B, 0x2F, 0xBD, 0xF9, 0xC6, 0xDB, 0x3F, 0x79, 0xE5, 0xB5, 0xB7, 0xB0, 0x7A, 0xAA, 0x0D, 0xA6, 0xF3, 
+  0x34, 0x44, 0xF1, 0x2A, 0x3A, 0xE4, 0x8C, 0x65, 0x68, 0xCD, 0xDE, 0x76, 0xCB, 0x83, 0x37, 0xDD, 0x70, 0x9F, 0xF6, 0x85, 
+  0x40, 0x33, 0x36, 0xDB, 0x4C, 0x9A, 0x30, 0x11, 0xD7, 0x07, 0x6A, 0xE0, 0x61, 0x08, 0x01, 0x60, 0xCE, 0x02, 0x5D, 0x0B, 
+  0x67, 0xF3, 0xCD, 0x3B, 0x73, 0x64, 0x8A, 0x39, 0x7B, 0x81, 0x79, 0x7C, 0x9E, 0x9A, 0xA6, 0x88, 0xC8, 0x5F, 0x98, 0x7D, 
+  0x90, 0x9D, 0x64, 0xC0, 0x67, 0x10, 0xC9, 0xA8, 0x41, 0x96, 0x48, 0xCC, 0x3F, 0x3C, 0xCA, 0x3F, 0x82, 0x2F, 0xB7, 0xE5, 
+  0x56, 0x74, 0x60, 0x13, 0x18, 0x23, 0x29, 0x43, 0x87, 0x86, 0x36, 0x1B, 0x2A, 0xBD, 0x65, 0xF0, 0x5A, 0xC9, 0xA0, 0x2A, 
+  0x68, 0x28, 0xAB, 0xDA, 0x80, 0xD4, 0xD6, 0x23, 0xFD, 0x48, 0x1D, 0x82, 0x1B, 0x20, 0x92, 0x4A, 0x44, 0xB0, 0xC5, 0x98, 
+  0xB6, 0x83, 0x48, 0xC6, 0xEA, 0xA3, 0x23, 0x63, 0x90, 0xBB, 0xEC, 0x9F, 0x06, 0x9A, 0xA4, 0x4B, 0x01, 0xEB, 0x4C, 0x6A, 
+  0x48, 0x90, 0x87, 0x61, 0x8B, 0xA6, 0xB3, 0xF4, 0x59, 0x3B, 0x9A, 0x3B, 0x37, 0xAE, 0xDE, 0xBA, 0xA4, 0x7F, 0x19, 0x3D, 
+  0x73, 0x2C, 0x8E, 0x0E, 0x3E, 0x3B, 0xA2, 0x48, 0x7F, 0x91, 0x3D, 0x32, 0xA7, 0x7D, 0x04, 0x4B, 0x87, 0x1F, 0x02, 0xE0, 
+  0xD9, 0x67, 0x9E, 0x75, 0xFA, 0xE9, 0x6C, 0xBC, 0x35, 0x1D, 0xBD, 0xA9, 0xB3, 0xD9, 0x50, 0x86, 0x2D, 0x7F, 0xEB, 0x5B, 
+  0x6F, 0xBD, 0xF5, 0xFD, 0x9F, 0xFC, 0xE2, 0x17, 0xBF, 0x7F, 0xFE, 0xF9, 0xD7, 0x5F, 0x79, 0xE5, 0xCD, 0x37, 0xBE, 0xFF, 
+  0xD3, 0x5F, 0xFF, 0xF6, 0xCF, 0xEF, 0xBC, 0xFB, 0xAB, 0x9F, 0xFC, 0xE4, 0x97, 0xEF, 0xBF, 0xFF, 0x87, 0xA7, 0x9F, 0x66, 
+  0xAB, 0xF1, 0xDB, 0x84, 0x8D, 0x6F, 0xBD, 0xFE, 0x23, 0xA2, 0xFA, 0x4B, 0x2F, 0xBD, 0xF1, 0xF0, 0x83, 0x7C, 0xDD, 0xF8, 
+  0x8D, 0x40, 0x5C, 0x4A, 0x62, 0x16, 0x9C, 0xD4, 0xB9, 0x33, 0xE0, 0x1B, 0xD3, 0xBC, 0x0A, 0x82, 0x2D, 0x40, 0x3A, 0x4B, 
+  0x43, 0x10, 0xAE, 0x31, 0x34, 0x4B, 0x52, 0x2C, 0xEA, 0xE1, 0x85, 0xFE, 0x81, 0x97, 0x8C, 0xBF, 0x58, 0xAA, 0x96, 0x39, 
+  0x01, 0x41, 0x73, 0x11, 0x37, 0xE4, 0x14, 0x61, 0x63, 0xC8, 0xA4, 0x48, 0x59, 0x04, 0x3A, 0xBE, 0x37, 0xB3, 0x7B, 0x9D, 
+  0x9D, 0xC9, 0xBE, 0x47, 0xFF, 0x30, 0x64, 0x2D, 0xFD, 0x98, 0x20, 0x86, 0x4B, 0x22, 0x43, 0xED, 0x57, 0x5B, 0x0F, 0xD0, 
+  0x0B, 0x1F, 0xA1, 0xBB, 0x3A, 0x74, 0x78, 0xDD, 0x48, 0x23, 0x20, 0xAE, 0xCD, 0x7D, 0xED, 0x26, 0x3A, 0x95, 0x94, 0x06, 
+  0x4C, 0x67, 0xC9, 0xEB, 0xAA, 0xF4, 0xD5, 0x03, 0xB4, 0xEC, 0xD6, 0x67, 0xCA, 0xF6, 0x1B, 0x04, 0x6D, 0xA4, 0x8F, 0x21, 
+  0xB3, 0xCC, 0xB4, 0x20, 0x2E, 0x36, 0x32, 0x8A, 0x6B, 0x43, 0x76, 0x97, 0xC3, 0x1B, 0xA9, 0xE9, 0x40, 0x36, 0x92, 0x5D, 
+  0x8C, 0x40, 0xBE, 0xC3, 0xC9, 0x7C, 0x95, 0x1F, 0x1F, 0x00, 0x2C, 0xA2, 0x87, 0xC3, 0x1E, 0x7F, 0x22, 0xDB, 0xC5, 0x17, 
+  0x4F, 0x90, 0x3A, 0xE8, 0x9C, 0x73, 0x49, 0x07, 0x85, 0x38, 0x35, 0x7E, 0xA2, 0x72, 0xA7, 0xB8, 0x86, 0xCC, 0xE3, 0x38, 
+  0x84, 0xD9, 0xA9, 0xA0, 0xED, 0x65, 0x1A, 0x3B, 0x8A, 0x2D, 0x4F, 0x3C, 0xF1, 0xC2, 0xD3, 0x4F, 0xBF, 0xF2, 0xE2, 0x2B, 
+  0xDF, 0x45, 0xEE, 0x6F, 0xBE, 0xF9, 0xD3, 0x37, 0xDF, 0x7C, 0xEF, 0xAD, 0xB7, 0xDE, 0x7B, 0xE3, 0xAD, 0x77, 0x5F, 0x7A, 
+  0xE9, 0x3B, 0x8F, 0x3E, 0xF1, 0xFC, 0x95, 0x57, 0xDD, 0xCA, 0x44, 0x88, 0x3D, 0x81, 0x28, 0x18, 0xA5, 0x8E, 0x29, 0xBB, 
+  0x24, 0xFC, 0x9E, 0x77, 0x21, 0xC2, 0xAA, 0x2E, 0xAB, 0x1D, 0xEC, 0x5F, 0x43, 0x75, 0x46, 0x30, 0xCF, 0xC9, 0x2C, 0x18, 
+  0x7F, 0xC1, 0xF9, 0xC2, 0xDA, 0x33, 0xC3, 0x1F, 0x23, 0x6B, 0xC7, 0xDE, 0xED, 0xEC, 0xDE, 0xD9, 0xF4, 0xE8, 0x0E, 0x32, 
+  0xC5, 0x4C, 0x0D, 0xC3, 0x55, 0x45, 0x8F, 0x0E, 0x54, 0x1F, 0xEA, 0x13, 0xD2, 0xAF, 0x35, 0xD0, 0x64, 0x74, 0x80, 0x02, 
+  0xDC, 0x2D, 0xB5, 0xE2, 0x07, 0xB2, 0xD3, 0xDC, 0x70, 0xC4, 0x9D, 0x2D, 0x63, 0x0E, 0x77, 0xDE, 0x5B, 0x56, 0x58, 0x4D, 
+  0xDA, 0xAE, 0x88, 0x94, 0xBB, 0x41, 0xB2, 0xEF, 0x4C, 0xFD, 0x40, 0x82, 0x41, 0x88, 0x58, 0xB7, 0xBE, 0x8E, 0xB8, 0x54, 
+  0x48, 0x3C, 0xB3, 0x72, 0xCD, 0x44, 0xB5, 0x4B, 0x8C, 0x1D, 0x01, 0x71, 0xD4, 0xF7, 0xC2, 0xCD, 0x9A, 0x2F, 0x9E, 0x4B, 
+  0x8F, 0x13, 0xFE, 0x2C, 0xA2, 0xE9, 0x6C, 0xEE, 0x09, 0x5A, 0x18, 0x8C, 0xF9, 0xD3, 0xB0, 0xC3, 0xFA, 0xF8, 0xCA, 0x21, 
+  0x72, 0x41, 0x72, 0x12, 0xDA, 0x47, 0xB2, 0xC8, 0x43, 0x48, 0x0D, 0x27, 0x5D, 0x42, 0x8E, 0xA0, 0xAE, 0xC0, 0xAF, 0x18, 
+  0x1E, 0x90, 0xF2, 0xF7, 0x72, 0xF8, 0x5F, 0xF7, 0x32, 0x9A, 0x77, 0x64, 0xFA, 0xA4, 0xA4, 0xF4, 0x94, 0x40, 0x24, 0xA2, 
+  0x02, 0xD1, 0xE2, 0xF1, 0xC7, 0x9F, 0x7B, 0x0A, 0xE4, 0x79, 0xE0, 0xEB, 0x77, 0xDF, 0xFD, 0x28, 0xE7, 0xFD, 0x40, 0xDE, 
+  0xBA, 0xE8, 0x9C, 0x8B, 0x75, 0x4A, 0x61, 0xE0, 0x4D, 0x0A, 0x2E, 0xA9, 0xC0, 0xCC, 0xB5, 0x6A, 0x05, 0xCB, 0xE0, 0x1B, 
+  0x08, 0x97, 0x2D, 0x5E, 0x4B, 0x46, 0xC0, 0x46, 0x20, 0xFE, 0x23, 0xA0, 0xAF, 0x40, 0xAF, 0xB3, 0x7B, 0x61, 0x48, 0x2C, 
+  0x70, 0xB8, 0x2A, 0x0A, 0xCE, 0x6C, 0xC5, 0x61, 0xA2, 0xE9, 0x0E, 0x90, 0x9D, 0xB1, 0x9A, 0x00, 0x86, 0x44, 0x66, 0x59, 
+  0xAA, 0x03, 0xEF, 0x22, 0xD6, 0xA2, 0x03, 0x27, 0x77, 0xD4, 0x4C, 0x86, 0x7C, 0x14, 0xC4, 0xD0, 0xAD, 0x64, 0x36, 0x66, 
+  0xBA, 0xBD, 0x27, 0x69, 0xCC, 0x8D, 0x2E, 0xB8, 0xE5, 0xAE, 0x45, 0x21, 0x92, 0x28, 0xFE, 0x04, 0x89, 0xC7, 0x87, 0x02, 
+  0x65, 0xB2, 0xA4, 0x9B, 0x24, 0x9B, 0x20, 0xA4, 0x0E, 0x10, 0xAD, 0x04, 0xB3, 0x71, 0xD3, 0x99, 0x6F, 0x00, 0xF7, 0x3C, 
+  0xD8, 0xD7, 0xBE, 0x98, 0x96, 0x0B, 0x4D, 0x1E, 0x44, 0x4F, 0xFD, 0x41, 0xC5, 0x87, 0x7F, 0xA8, 0x6D, 0x32, 0xC0, 0x21, 
+  0x26, 0xCF, 0x9C, 0x32, 0x95, 0xB6, 0x30, 0xEC, 0x1D, 0xDF, 0x99, 0x1C, 0x04, 0xA0, 0xCC, 0xB5, 0xE9, 0xDC, 0x45, 0xEE, 
+  0x08, 0x65, 0xDC, 0xD9, 0x92, 0x98, 0x63, 0xA1, 0xE4, 0x08, 0xE0, 0x03, 0x1A, 0xA2, 0xD5, 0x3A, 0xFE, 0xBC, 0x0B, 0x2E, 
+  0x38, 0xE7, 0xC2, 0x49, 0x17, 0x4D, 0x86, 0x1F, 0x5F, 0x5B, 0xD9, 0xBE, 0x62, 0xF9, 0x46, 0x9A, 0x0D, 0xD4, 0x5C, 0xB7, 
+  0xDE, 0xFE, 0x08, 0xD9, 0xED, 0x50, 0xFF, 0x30, 0x81, 0x4A, 0x63, 0x3B, 0x12, 0x17, 0x35, 0x9C, 0x7E, 0x3A, 0x28, 0x77, 
+  0xCE, 0xD9, 0x5F, 0xE3, 0xFF, 0x92, 0x5F, 0x8E, 0x28, 0xC3, 0xE7, 0x34, 0xEC, 0x17, 0xA5, 0xF6, 0xF7, 0x0E, 0x2F, 0x5F, 
+  0xB2, 0x8E, 0x58, 0xC5, 0x3F, 0x95, 0x01, 0x1C, 0xA2, 0x9F, 0x2F, 0x94, 0x61, 0x97, 0x30, 0xE1, 0x0C, 0xEE, 0x2D, 0x65, 
+  0xC8, 0x12, 0x87, 0x74, 0xB4, 0xA9, 0x88, 0x8D, 0x02, 0x34, 0x30, 0x9C, 0xBC, 0x7C, 0xA4, 0xA5, 0x63, 0x3A, 0x42, 0xDE, 
+  0x10, 0x4A, 0x19, 0x25, 0xC0, 0x6D, 0x3A, 0xCC, 0x8A, 0x30, 0x2A, 0x68, 0xDB, 0xEA, 0x93, 0x71, 0x9D, 0x48, 0xDF, 0x86, 
+  0x01, 0xC8, 0xC9, 0xE6, 0x69, 0x61, 0x62, 0xFE, 0x04, 0x73, 0x8D, 0xBA, 0x72, 0x0B, 0xDC, 0x9B, 0x0B, 0xEA, 0x00, 0x09, 
+  0x2D, 0xF4, 0x0E, 0x83, 0xA4, 0xD1, 0x04, 0x97, 0x62, 0xCA, 0xF8, 0x4B, 0xA0, 0xF6, 0x73, 0xAE, 0x2E, 0x07, 0x01, 0x67, 
+  0x24, 0xA5, 0x61, 0x65, 0x00, 0x3D, 0x86, 0x4D, 0x06, 0x8C, 0x7C, 0xB1, 0xF7, 0x59, 0x97, 0x0A, 0x15, 0x85, 0x48, 0xC8, 
+  0xAF, 0xF8, 0x86, 0x15, 0x19, 0xC7, 0xCB, 0x44, 0x5E, 0x58, 0x11, 0x74, 0x55, 0xF1, 0x06, 0x60, 0x0A, 0xAB, 0x95, 0xA3, 
+  0x00, 0xCE, 0x95, 0xFD, 0x84, 0xA7, 0xFC, 0x39, 0x7F, 0xDC, 0x05, 0xA4, 0xEA, 0x42, 0x54, 0xAD, 0x6C, 0xE0, 0x84, 0x1E, 
+  0xF2, 0x16, 0x95, 0x3B, 0x2A, 0xE0, 0x96, 0xBA, 0x97, 0x89, 0x05, 0xE0, 0x36, 0x79, 0xC2, 0x45, 0x32, 0xBD, 0x18, 0x3F, 
+  0x41, 0x0E, 0xDE, 0x38, 0xEB, 0x6C, 0xED, 0x43, 0x9C, 0x77, 0xDE, 0x79, 0x6C, 0x1A, 0x1C, 0xEC, 0x5F, 0xD9, 0xB3, 0x68, 
+  0x39, 0xA7, 0x30, 0xC0, 0xC0, 0xA4, 0xCD, 0x4E, 0x6C, 0x20, 0x81, 0x36, 0x5C, 0x15, 0x93, 0xF9, 0xC8, 0x4E, 0x6C, 0xB9, 
+  0xB0, 0x3A, 0xB0, 0x33, 0x64, 0x51, 0x80, 0x0A, 0x5D, 0x5C, 0xE1, 0x14, 0xD2, 0xC7, 0x09, 0x78, 0xDC, 0x47, 0x73, 0x79, 
+  0x3A, 0x88, 0xEA, 0x07, 0xCE, 0x52, 0xE9, 0x87, 0x4B, 0x20, 0xB5, 0x6A, 0x70, 0x35, 0x21, 0xC5, 0xB0, 0xED, 0xCA, 0xAA, 
+  0xE8, 0xD5, 0x63, 0xC4, 0x0F, 0x8C, 0xB8, 0x61, 0x8E, 0xB2, 0xDC, 0x6B, 0x7D, 0xC4, 0xFC, 0xD6, 0x74, 0xE8, 0x94, 0xF0, 
+  0x0D, 0x03, 0x87, 0x4C, 0xE3, 0xDC, 0xAF, 0x8D, 0xBB, 0xF8, 0xC2, 0xF1, 0xE7, 0x8C, 0x3B, 0x57, 0x51, 0x05, 0x99, 0x02, 
+  0xF7, 0xD8, 0x3E, 0x29, 0x36, 0x26, 0x2F, 0x0C, 0x38, 0x93, 0x7E, 0x28, 0x25, 0x42, 0x77, 0xFD, 0x4B, 0x16, 0x38, 0x73, 
+  0x0E, 0xC4, 0x45, 0xCA, 0x25, 0x8C, 0x97, 0xAD, 0xFF, 0x98, 0xA7, 0xD3, 0xCB, 0x51, 0xC9, 0x49, 0x53, 0x41, 0x66, 0xA2, 
+  0x62, 0xE8, 0xA7, 0x09, 0x11, 0x5A, 0x20, 0xFE, 0xDC, 0x71, 0x08, 0x9A, 0xE9, 0x90, 0xB6, 0x7A, 0x78, 0x3E, 0x17, 0xC2, 
+  0x10, 0x9D, 0x74, 0x09, 0xCD, 0x28, 0x07, 0xEB, 0x64, 0x6E, 0x31, 0x99, 0x37, 0x30, 0x79, 0xC2, 0x78, 0x94, 0xAA, 0x6F, 
+  0x89, 0xDA, 0x93, 0xB3, 0x2E, 0x6A, 0xAB, 0xDB, 0x20, 0x81, 0x4B, 0x2B, 0x77, 0xC6, 0x6C, 0x9A, 0x02, 0xE1, 0xFE, 0x81, 
+  0xDA, 0xEB, 0xB5, 0xE9, 0x89, 0x93, 0xAA, 0x90, 0x89, 0xDA, 0x9C, 0x45, 0xE2, 0xA5, 0x2C, 0x76, 0xA3, 0x9C, 0x52, 0x01, 
+  0xF6, 0x41, 0x1F, 0x4D, 0xE1, 0x4D, 0x4F, 0x5F, 0x6C, 0x5F, 0xEA, 0x5B, 0x13, 0x48, 0xD5, 0x0F, 0x9C, 0x0B, 0x37, 0xD5, 
+  0x71, 0xA4, 0x6F, 0x9A, 0xAE, 0x32, 0x08, 0xD4, 0x00, 0x60, 0x54, 0xA2, 0x82, 0xD6, 0xA5, 0xD2, 0xD7, 0x4C, 0x54, 0x55, 
+  0xA8, 0x11, 0x1B, 0xBF, 0x31, 0xCC, 0xEA, 0x08, 0x8A, 0x17, 0x99, 0xB9, 0xFB, 0xCE, 0x45, 0xDC, 0x60, 0x0E, 0x8B, 0x8A, 
+  0x9F, 0xCF, 0x6F, 0xA4, 0x0F, 0xE0, 0xCC, 0x16, 0xEE, 0x9B, 0x61, 0x8E, 0xBA, 0x34, 0x08, 0xAE, 0xE7, 0x91, 0x08, 0x4A, 
+  0x5B, 0x7B, 0xAE, 0x34, 0x53, 0x65, 0xAF, 0xCE, 0x84, 0x89, 0xF4, 0xA9, 0x20, 0x64, 0xE8, 0xA6, 0x1D, 0xB5, 0x6B, 0xF0, 
+  0x84, 0x3D, 0xB6, 0x08, 0x17, 0x71, 0x13, 0x4E, 0x08, 0x2A, 0x36, 0x97, 0x55, 0x99, 0x9A, 0xBE, 0x9B, 0x3C, 0x93, 0x70, 
+  0xA2, 0x91, 0x06, 0x5D, 0xCE, 0x98, 0x36, 0x1D, 0x9E, 0x3A, 0x6B, 0xE6, 0xD4, 0x4B, 0xA7, 0x5D, 0x3A, 0x55, 0xE3, 0x8D, 
+  0x6C, 0x99, 0xF6, 0xF1, 0xC1, 0x59, 0x7B, 0xDA, 0x07, 0xEA, 0x6A, 0x5B, 0xD9, 0x9A, 0xC9, 0xBC, 0x81, 0x5E, 0x85, 0x04, 
+  0x30, 0x93, 0x97, 0x6B, 0xBB, 0xD7, 0x7B, 0x2B, 0xDE, 0xE0, 0xCF, 0xC4, 0x14, 0x08, 0x12, 0x03, 0x57, 0x33, 0xFF, 0x32, 
+  0x08, 0x72, 0x92, 0x1A, 0xFF, 0x30, 0x74, 0x60, 0x6C, 0x5F, 0x91, 0xC7, 0xA4, 0x43, 0x12, 0x51, 0x75, 0xAB, 0x94, 0xEC, 
+  0xF0, 0x72, 0xA4, 0x29, 0x76, 0xED, 0x9A, 0xFC, 0x48, 0x1A, 0x1A, 0xE6, 0x40, 0x90, 0x91, 0xB8, 0x81, 0xAF, 0x91, 0xE7, 
+  0xBB, 0x58, 0xE4, 0x28, 0x49, 0x58, 0x05, 0x5A, 0xAC, 0x03, 0xB2, 0xDA, 0x14, 0x22, 0xAC, 0x99, 0x02, 0x47, 0x38, 0x58, 
+  0x4A, 0xC5, 0xA5, 0xFE, 0x74, 0x68, 0x3F, 0x73, 0xE0, 0xC6, 0x8A, 0x02, 0xBC, 0x69, 0x9F, 0xB9, 0xAB, 0x89, 0xF9, 0x3C, 
+  0xE6, 0x0A, 0x60, 0x88, 0x7C, 0xE3, 0x42, 0x69, 0xCD, 0x84, 0x8B, 0x27, 0x22, 0x5D, 0x92, 0x57, 0xDA, 0x09, 0xF4, 0x97, 
+  0x94, 0x7A, 0x8E, 0x86, 0x68, 0xEF, 0xD0, 0xE8, 0x57, 0xB9, 0x5B, 0xE9, 0x6B, 0xEF, 0x53, 0x3C, 0x60, 0xE2, 0x94, 0xE9, 
+  0x97, 0x4C, 0x85, 0x11, 0x0D, 0xAC, 0xCD, 0x21, 0xD8, 0x50, 0x1B, 0x4E, 0x95, 0xF2, 0x4A, 0xD8, 0xC1, 0x53, 0x67, 0x12, 
+  0x5A, 0xA6, 0x5E, 0x32, 0xE1, 0xDC, 0x73, 0xCF, 0xE5, 0x0F, 0x39, 0x5E, 0x9A, 0x96, 0x1F, 0x0E, 0xC1, 0x76, 0x04, 0x66, 
+  0x4D, 0xD2, 0x9E, 0xB1, 0xB5, 0x91, 0x76, 0x84, 0xC4, 0xDE, 0x05, 0xFA, 0xA3, 0xFC, 0xB8, 0x36, 0x81, 0xD7, 0x4D, 0xDC, 
+  0x4D, 0x26, 0x39, 0x92, 0x0E, 0x69, 0x52, 0x64, 0x9F, 0x6F, 0x92, 0x57, 0x74, 0x60, 0x48, 0xE7, 0xD2, 0x47, 0x93, 0xAA, 
+  0xCA, 0xDD, 0xDB, 0xED, 0x11, 0xA5, 0xB5, 0x6E, 0xB1, 0x6B, 0x4D, 0x3D, 0xDD, 0x20, 0x71, 0xCA, 0x5F, 0xF1, 0xA0, 0xC4, 
+  0x61, 0x8F, 0x43, 0x8C, 0x84, 0x13, 0x69, 0x0A, 0x69, 0x6F, 0x4E, 0x48, 0x38, 0x14, 0xC6, 0x86, 0xF9, 0x23, 0x20, 0xA3, 
+  0x92, 0x35, 0x35, 0x8E, 0x44, 0x57, 0x60, 0x57, 0x93, 0x3F, 0x87, 0x2D, 0x6B, 0xE6, 0x0A, 0xCE, 0x69, 0x24, 0xEC, 0x2D, 
+  0x98, 0x3D, 0x7F, 0xF2, 0xC5, 0x93, 0x38, 0xED, 0x44, 0xE8, 0x30, 0x45, 0x95, 0x08, 0x1A, 0x60, 0xE1, 0x70, 0x6C, 0x36, 
+  0x56, 0xA8, 0x69, 0xB3, 0xA4, 0xE3, 0x3D, 0xE9, 0x12, 0xD4, 0x00, 0xB8, 0x5B, 0x2F, 0x51, 0x8C, 0xE2, 0xF9, 0xB4, 0xBF, 
+  0x78, 0x0E, 0x7B, 0x28, 0x67, 0x4F, 0x15, 0xE6, 0x1D, 0x1D, 0x08, 0x86, 0xF2, 0x08, 0x57, 0x6A, 0xDD, 0x99, 0xF3, 0x84, 
+  0x23, 0x6C, 0xCE, 0x9D, 0xE1, 0x45, 0x50, 0x98, 0xFF, 0x82, 0x40, 0x36, 0xFE, 0x51, 0x36, 0xE1, 0x82, 0xC4, 0x15, 0x22, 
+  0x0A, 0xAE, 0x20, 0x52, 0x0E, 0x16, 0x3E, 0x92, 0x65, 0xCF, 0x69, 0xE0, 0x15, 0xF9, 0xBA, 0x7C, 0xBA, 0x91, 0x60, 0xA0, 
+  0x2C, 0x23, 0x17, 0xA9, 0x22, 0x8D, 0xE8, 0xB5, 0x7A, 0x70, 0x74, 0xE0, 0xF6, 0x76, 0x4C, 0xF2, 0xEE, 0x81, 0x14, 0x95, 
+  0xB5, 0x57, 0xD0, 0x5E, 0x33, 0x1F, 0xF3, 0x4C, 0xEF, 0x5D, 0x22, 0xB3, 0xA2, 0xBF, 0xB3, 0xF4, 0xE8, 0x04, 0x43, 0x6D, 
+  0x97, 0x4E, 0xBA, 0x61, 0x7F, 0x08, 0x19, 0xC4, 0xD0, 0x31, 0x75, 0x6E, 0xA3, 0x24, 0x59, 0x14, 0xE0, 0xE4, 0xDD, 0x9A, 
+  0xEA, 0x99, 0xDF, 0x2A, 0x7B, 0x50, 0x2F, 0x48, 0x0A, 0x79, 0xCE, 0x8C, 0x89, 0x93, 0xE9, 0x30, 0x92, 0x8F, 0x42, 0x44, 
+  0x64, 0xCB, 0x22, 0x62, 0x25, 0x96, 0x22, 0xAF, 0xA9, 0x97, 0x4E, 0x9E, 0x3E, 0x79, 0x86, 0xA0, 0x0A, 0x11, 0xDB, 0x85, 
+  0x14, 0x30, 0x07, 0xF4, 0x17, 0x44, 0x3A, 0x43, 0xE2, 0x30, 0xEE, 0x42, 0x7F, 0x6D, 0xDA, 0xE4, 0x4B, 0x44, 0x01, 0xE2, 
+  0x79, 0xC2, 0x81, 0xC4, 0x17, 0x1D, 0xBA, 0xBC, 0xE9, 0x3A, 0x68, 0x47, 0x88, 0xDF, 0x4E, 0x9F, 0x3A, 0x8D, 0x36, 0xF5, 
+  0xD9, 0xE7, 0x7C, 0xAD, 0xA3, 0xB9, 0x8B, 0x29, 0x1B, 0x69, 0x02, 0xA2, 0x04, 0x06, 0x70, 0x5C, 0xCA, 0x55, 0xCB, 0x95, 
+  0x73, 0xA7, 0x66, 0xA1, 0xDA, 0xFA, 0x75, 0x62, 0xB2, 0xAB, 0x09, 0xAB, 0x12, 0xC4, 0x8D, 0xA3, 0xA8, 0xE8, 0x23, 0xA9, 
+  0x90, 0xD9, 0xF9, 0xC3, 0x19, 0x1E, 0x01, 0x21, 0x3E, 0x0E, 0xCF, 0xC0, 0x40, 0xD0, 0xC9, 0x62, 0x1D, 0x91, 0xA3, 0x8B, 
+  0xFB, 0xDE, 0x20, 0xEC, 0x7D, 0xBE, 0xA1, 0x4A, 0x8C, 0xC2, 0x9F, 0x91, 0x58, 0x6D, 0x14, 0xA0, 0x69, 0x95, 0x33, 0x6E, 
+  0x65, 0x76, 0x16, 0x14, 0xE6, 0xE4, 0x76, 0xC6, 0x21, 0x2C, 0x59, 0x53, 0xE4, 0x6E, 0x96, 0x00, 0xAE, 0xE6, 0xDA, 0x7E, 
+  0x41, 0x28, 0xCC, 0xE5, 0x92, 0x06, 0x20, 0x5F, 0x71, 0xFF, 0x90, 0x28, 0x7A, 0x35, 0x6D, 0x75, 0x8B, 0x7C, 0x67, 0xCC, 
+  0x3B, 0xFF, 0x9C, 0xAF, 0xCD, 0x98, 0x3C, 0x0D, 0xB3, 0x25, 0x79, 0xD5, 0x8E, 0xA6, 0x30, 0xAB, 0x09, 0xDA, 0x53, 0x50, 
+  0xCA, 0x14, 0x70, 0x89, 0xE4, 0x47, 0x63, 0x80, 0x86, 0x01, 0x8D, 0x01, 0x73, 0xA6, 0xE9, 0xAE, 0x10, 0x89, 0x3D, 0x0A, 
+  0x80, 0x1A, 0xF3, 0x69, 0x07, 0xE1, 0x8E, 0xB4, 0x83, 0x78, 0xDC, 0xE0, 0xD2, 0x74, 0x9A, 0x45, 0xB1, 0x31, 0x89, 0x9C, 
+  0xE0, 0x49, 0x37, 0x05, 0xF9, 0xF2, 0xB9, 0x64, 0xAF, 0xD5, 0x5C, 0x3F, 0x15, 0xAE, 0x70, 0x8A, 0xE8, 0x42, 0x2B, 0x75, 
+  0x8E, 0xCF, 0x65, 0x13, 0x21, 0x25, 0x37, 0x62, 0xFE, 0x41, 0xC1, 0xAE, 0xD5, 0x87, 0x21, 0x7A, 0xBD, 0xD6, 0xC7, 0x95, 
+  0x95, 0x64, 0x74, 0x70, 0x92, 0xED, 0xDB, 0xA2, 0xD7, 0x03, 0xFD, 0x1E, 0xBB, 0x76, 0x0C, 0xDC, 0x09, 0x06, 0x4E, 0x19, 
+  0x61, 0x32, 0x1F, 0x96, 0xA4, 0x40, 0xBA, 0x1F, 0xDA, 0x85, 0x2C, 0x6F, 0x6A, 0xEB, 0x90, 0x70, 0x4C, 0xD3, 0x4A, 0xB9, 
+  0x69, 0x9A, 0xD2, 0x39, 0xF4, 0x58, 0x76, 0x4F, 0xBA, 0xD2, 0x47, 0x01, 0x26, 0xEE, 0x29, 0x41, 0x5C, 0x46, 0x6C, 0x14, 
+  0x44, 0xD8, 0x26, 0xD7, 0x98, 0x1B, 0x92, 0x85, 0xD1, 0xC5, 0x60, 0x12, 0x60, 0x31, 0x59, 0xEC, 0x34, 0xD3, 0xD1, 0x14, 
+  0x30, 0xD1, 0x76, 0x26, 0x08, 0x83, 0x26, 0x78, 0xDC, 0x54, 0x12, 0x13, 0xC9, 0x38, 0x49, 0x75, 0x8C, 0x07, 0x4C, 0x21, 
+  0xE5, 0xB5, 0x3B, 0x0F, 0x04, 0x06, 0x09, 0x33, 0x6C, 0x87, 0x22, 0x02, 0x99, 0x9E, 0x8F, 0x1B, 0x75, 0x44, 0x2B, 0xF8, 
+  0x07, 0x81, 0x8A, 0x66, 0xD1, 0xF8, 0x8B, 0x26, 0xB0, 0x9B, 0x2C, 0x92, 0x24, 0x3E, 0x34, 0x8A, 0xEF, 0xDA, 0x06, 0x55, 
+  0x98, 0x1B, 0xB3, 0x97, 0x4D, 0x5A, 0x6F, 0x48, 0x9F, 0xB2, 0x5F, 0x67, 0xC8, 0x66, 0x76, 0xE6, 0x74, 0xE0, 0x49, 0xDF, 
+  0xCD, 0x49, 0x42, 0x22, 0x74, 0x0A, 0x66, 0x28, 0xD6, 0x01, 0xC1, 0x62, 0xF8, 0xDC, 0x85, 0xF0, 0x6B, 0x58, 0xEF, 0x8E, 
+  0x0E, 0x6C, 0x20, 0xD5, 0x4C, 0xC6, 0x26, 0xA3, 0x5E, 0x09, 0x8E, 0xF1, 0x86, 0xFF, 0xF5, 0xAE, 0x4D, 0x8D, 0x3C, 0x19, 
+  0x91, 0x53, 0x5E, 0x38, 0x9C, 0x0C, 0x13, 0xA9, 0xC4, 0x25, 0xDD, 0x61, 0x32, 0xAE, 0xAD, 0x6A, 0x40, 0xF4, 0x32, 0xD4, 
+  0x84, 0x39, 0xCB, 0x46, 0x46, 0x37, 0xCF, 0xD3, 0x44, 0x50, 0x82, 0x21, 0xC7, 0x27, 0x9A, 0xF2, 0x02, 0xF9, 0x72, 0xC6, 
+  0x3C, 0xA9, 0x3A, 0x94, 0x5B, 0xB3, 0xD5, 0x09, 0x1E, 0xF5, 0x6C, 0x0E, 0x1E, 0x91, 0xED, 0x66, 0xB2, 0xE1, 0x69, 0x16, 
+  0xF5, 0x84, 0xD0, 0xF7, 0xA6, 0x39, 0x59, 0x2C, 0x7A, 0x02, 0x7C, 0x58, 0xD8, 0xF5, 0xFC, 0xE9, 0x8E, 0xED, 0x6B, 0xDE, 
+  0xE5, 0x6C, 0x1B, 0x61, 0x88, 0xAD, 0xCB, 0x34, 0x7F, 0x84, 0x7C, 0x6F, 0x1C, 0x82, 0x97, 0x42, 0x0D, 0x24, 0xC1, 0x7C, 
+  0x77, 0x6F, 0x73, 0x5D, 0x2B, 0x0E, 0xC7, 0xD9, 0x84, 0x6B, 0x86, 0xD7, 0xF1, 0x7E, 0x50, 0x1E, 0x34, 0x53, 0xA6, 0xF6, 
+  0xB6, 0x78, 0x62, 0x5C, 0x33, 0x12, 0x1E, 0xDC, 0x70, 0x2D, 0x9F, 0xD4, 0x60, 0x8E, 0x90, 0xFB, 0x02, 0x8D, 0x4F, 0xAB, 
+  0xF4, 0xF5, 0x6E, 0x40, 0xB0, 0x8F, 0x05, 0xFD, 0xFF, 0x55, 0xB2, 0x63, 0x9F, 0x60, 0x8A, 0x2F, 0x6F, 0xAD, 0x20, 0x68, 
+  0x63, 0x96, 0x4D, 0x58, 0xB5, 0x33, 0x6A, 0xDF, 0xA2, 0x62, 0x91, 0xD3, 0xC8, 0xC5, 0x0F, 0x4C, 0x3A, 0xA1, 0xB9, 0x9D, 
+  0x96, 0x33, 0x7A, 0xA1, 0xDB, 0x48, 0x25, 0xB8, 0x29, 0x79, 0xD6, 0x58, 0x10, 0x92, 0x05, 0xAF, 0x98, 0xEB, 0x71, 0x8E, 
+  0x0E, 0x81, 0x9A, 0x13, 0x10, 0xEA, 0x6B, 0x5A, 0x31, 0x6D, 0x8C, 0x1A, 0x04, 0x77, 0x13, 0x59, 0x8C, 0x3A, 0x00, 0x30, 
+  0x71, 0x1A, 0xCB, 0xBA, 0x1D, 0xCA, 0x6C, 0x93, 0x47, 0x8E, 0xF3, 0xA6, 0x89, 0x73, 0x98, 0xD4, 0x8B, 0xED, 0x4A, 0x22, 
+  0x62, 0x9B, 0x74, 0xC9, 0x8E, 0x01, 0x67, 0x88, 0xED, 0xEC, 0x21, 0x20, 0x29, 0xD0, 0xFE, 0xA8, 0x32, 0xB7, 0x27, 0x8C, 
+  0xBF, 0x68, 0xE6, 0xF4, 0x59, 0x9C, 0x27, 0x05, 0x48, 0xD2, 0xDA, 0x7A, 0xF9, 0x1B, 0xDF, 0x3E, 0xB2, 0xEB, 0x30, 0xED, 
+  0x23, 0x82, 0x13, 0x72, 0xE4, 0x73, 0xC9, 0x18, 0xCA, 0x24, 0x7E, 0x4E, 0x39, 0x16, 0x28, 0xF8, 0xC3, 0x3E, 0x03, 0xC5, 
+  0x2B, 0xB5, 0x77, 0xC7, 0xEF, 0x9D, 0x8E, 0xA7, 0xB1, 0x36, 0x3E, 0xA0, 0x3F, 0x3A, 0x30, 0x3D, 0x89, 0xFF, 0xE7, 0xE5, 
+  0x84, 0x59, 0x39, 0x34, 0xCA, 0x36, 0xEC, 0xBC, 0x74, 0x1A, 0x2D, 0x1D, 0xEC, 0x23, 0x9E, 0x0E, 0x07, 0x56, 0x63, 0x66, 
+  0xDC, 0x32, 0x43, 0x96, 0x63, 0x2A, 0x24, 0xB5, 0x30, 0x18, 0xCA, 0x3B, 0xA6, 0x93, 0xAA, 0x59, 0x93, 0xB5, 0x26, 0xAD, 
+  0x3F, 0x75, 0x17, 0x23, 0x45, 0xC9, 0x70, 0xDF, 0x72, 0xBE, 0x10, 0x65, 0xEA, 0xA4, 0x4B, 0x39, 0xD8, 0x17, 0x40, 0xB8, 
+  0xE8, 0xC2, 0xF3, 0x01, 0x74, 0xDD, 0x62, 0xA7, 0xB9, 0xEC, 0x08, 0xAD, 0x5A, 0x76, 0x82, 0x38, 0x1D, 0x66, 0xCB, 0x80, 
+  0x17, 0xDC, 0x37, 0xD6, 0xAD, 0xE6, 0x6F, 0xB7, 0x28, 0x39, 0xBB, 0x94, 0x4C, 0xE2, 0xAF, 0x14, 0x1B, 0x93, 0x20, 0x38, 
+  0x0D, 0x51, 0xFE, 0x5C, 0x5C, 0xE1, 0x9C, 0xB3, 0x21, 0x4F, 0x34, 0xD7, 0xB6, 0x93, 0xD1, 0x72, 0xA8, 0xD8, 0x5F, 0x7E, 
+  0xFB, 0x4F, 0xCE, 0xD6, 0x36, 0x53, 0x2C, 0x3F, 0x09, 0x12, 0xC1, 0xA2, 0x00, 0xC5, 0x22, 0x69, 0x65, 0x8A, 0x85, 0x89, 
+  0x19, 0xF1, 0x2B, 0x46, 0x23, 0x6E, 0x39, 0xED, 0x6C, 0x40, 0x53, 0x50, 0xB2, 0x08, 0xEC, 0xC3, 0x8E, 0x54, 0x8B, 0x18, 
+  0x5F, 0xA1, 0x89, 0x31, 0x11, 0x42, 0xC7, 0x35, 0x1A, 0x69, 0xED, 0xC2, 0x16, 0x46, 0x5A, 0x1A, 0x9E, 0x5F, 0x9D, 0xCC, 
+  0xE9, 0x90, 0x5E, 0xB7, 0x91, 0xBE, 0xEA, 0xC0, 0x82, 0xA9, 0x06, 0xB7, 0x91, 0x24, 0xCF, 0x98, 0x09, 0x82, 0x43, 0x28, 
+  0x04, 0xE1, 0xAD, 0x6B, 0x2F, 0x5B, 0x3B, 0xB4, 0x76, 0xC6, 0xE4, 0xC9, 0x64, 0x44, 0x44, 0x63, 0x6A, 0x28, 0x42, 0xAB, 
+  0xEE, 0xE8, 0xB3, 0x02, 0x95, 0x64, 0xD7, 0x74, 0xF0, 0x0D, 0xF1, 0xDD, 0xD9, 0x14, 0x66, 0x68, 0x32, 0xEC, 0x38, 0x93, 
+  0x7D, 0xB2, 0xDA, 0x6A, 0x96, 0xDE, 0x27, 0x7B, 0x31, 0x3D, 0x1B, 0x95, 0x40, 0x15, 0xA7, 0xEF, 0xE6, 0xA6, 0x6A, 0xF6, 
+  0x45, 0xF8, 0x5B, 0x06, 0xAB, 0x13, 0x2E, 0xBC, 0x00, 0x9E, 0xC7, 0xBA, 0xE5, 0x5B, 0xF9, 0x38, 0xA8, 0xEA, 0x91, 0xFB, 
+  0x9E, 0x42, 0x0D, 0x9C, 0xAE, 0x46, 0x2C, 0x09, 0x99, 0x1B, 0xE0, 0x04, 0x86, 0xE0, 0x60, 0x97, 0x00, 0x27, 0x70, 0x6A, 
+  0x44, 0x4F, 0x2D, 0xED, 0x0C, 0x5A, 0xB8, 0x1B, 0x21, 0x35, 0xB6, 0x1B, 0xFF, 0xDC, 0x58, 0x88, 0x0E, 0xBE, 0xDC, 0x09, 
+  0xE8, 0x77, 0x9A, 0xF3, 0x85, 0xC6, 0x00, 0x8E, 0x07, 0x61, 0x14, 0x67, 0x1C, 0xB4, 0xF1, 0xE8, 0x43, 0x2A, 0x32, 0x75, 
+  0x91, 0x53, 0x29, 0x40, 0x06, 0x9F, 0xDA, 0xBE, 0x66, 0xB9, 0x07, 0xAF, 0xC9, 0x70, 0x43, 0xCA, 0x1C, 0x13, 0x2A, 0x24, 
+  0xC3, 0x33, 0xFB, 0x29, 0x40, 0x15, 0x42, 0x31, 0x65, 0x1D, 0x27, 0xCD, 0xEE, 0xBB, 0x6C, 0x3F, 0x39, 0xD2, 0x7C, 0xDF, 
+  0x05, 0x1C, 0x30, 0x07, 0x5E, 0x11, 0x66, 0x49, 0x8D, 0x4C, 0x2B, 0x9F, 0x8C, 0xD6, 0xD9, 0x6E, 0xE7, 0xCC, 0x4F, 0xDC, 
+  0x7A, 0x42, 0xB3, 0x5E, 0x50, 0xDE, 0xB9, 0x35, 0x6D, 0x67, 0x31, 0x73, 0x77, 0xCF, 0x8C, 0xED, 0xBB, 0xE9, 0xE6, 0x19, 
+  0xBB, 0x9C, 0xED, 0x0B, 0xF2, 0x64, 0xF1, 0x2D, 0xFE, 0x11, 0xF9, 0x18, 0xF1, 0xBF, 0x83, 0x6F, 0x75, 0x6E, 0x19, 0x00, 
+  0x00, 0x71, 0xC7, 0xB7, 0xBF, 0xFD, 0xCE, 0x2F, 0x7E, 0xFC, 0x6B, 0xBE, 0x28, 0x42, 0x66, 0x50, 0xF3, 0x16, 0x90, 0xE9, 
+  0xE9, 0x10, 0x5F, 0x58, 0x6B, 0xEE, 0x5E, 0x33, 0x4D, 0x61, 0xBD, 0xDD, 0x24, 0x6F, 0x0E, 0xA2, 0x8F, 0x8F, 0xD5, 0xC1, 
+  0x28, 0x7B, 0x37, 0xAC, 0xD8, 0x51, 0x08, 0x33, 0x62, 0xF5, 0x66, 0x7A, 0xAC, 0xD2, 0xD7, 0xD4, 0xD3, 0x1A, 0x3E, 0x9D, 
+  0x8C, 0x93, 0x45, 0xEF, 0x65, 0x38, 0xC9, 0xC9, 0x1E, 0x86, 0x58, 0x20, 0x24, 0x1C, 0x65, 0xDD, 0x38, 0xBD, 0x2D, 0x13, 
+  0x15, 0xA4, 0x8A, 0xD6, 0xC0, 0x80, 0xA9, 0xFA, 0xCD, 0x9D, 0x43, 0x71, 0x94, 0x95, 0x92, 0xB1, 0x61, 0xD5, 0x36, 0x36, 
+  0x7A, 0x80, 0x03, 0xD0, 0x49, 0x61, 0x34, 0xC1, 0x28, 0x20, 0x71, 0x64, 0xB7, 0x29, 0x1F, 0xDE, 0x14, 0x74, 0xCE, 0x1E, 
+  0xBC, 0x11, 0x5B, 0xF6, 0x96, 0x17, 0x5A, 0x5B, 0x8C, 0xDE, 0x9E, 0x67, 0xC5, 0xED, 0x08, 0x45, 0xB7, 0x81, 0xF8, 0x33, 
+  0x9D, 0x95, 0xA5, 0xB9, 0xB2, 0x2A, 0x4C, 0x51, 0x8E, 0xA8, 0x43, 0xF8, 0x01, 0x58, 0xD6, 0xAF, 0xD9, 0x0E, 0xD5, 0x9E, 
+  0x8C, 0x8B, 0x23, 0x41, 0x7E, 0xF6, 0xD6, 0xAF, 0x9E, 0x7C, 0xF0, 0x19, 0xBE, 0xA2, 0x59, 0xBE, 0x60, 0x6F, 0x8E, 0x9F, 
+  0x26, 0xA3, 0xB6, 0x7B, 0xE1, 0x74, 0xF1, 0x0C, 0x6F, 0xCA, 0xCD, 0xAD, 0x47, 0x36, 0x65, 0xDA, 0x07, 0x1D, 0x1D, 0x9C, 
+  0x52, 0xD0, 0x63, 0x9A, 0x13, 0x5F, 0xA2, 0x8C, 0x11, 0x2C, 0xD2, 0x90, 0x7B, 0xB2, 0xF9, 0x5B, 0x92, 0xE5, 0x28, 0x6E, 
+  0x13, 0x1E, 0x80, 0xC9, 0x07, 0x38, 0x5D, 0x3C, 0x33, 0xE5, 0x90, 0x90, 0x60, 0xEA, 0x78, 0xD9, 0x31, 0x00, 0x62, 0x82, 
+  0xC2, 0xB2, 0xD7, 0x2C, 0x38, 0x9C, 0x93, 0x05, 0x39, 0xCD, 0x95, 0xAC, 0x86, 0xFD, 0x26, 0xCB, 0xFA, 0xD7, 0xCD, 0x9B, 
+  0xE3, 0x37, 0xFE, 0x82, 0x71, 0xD2, 0xD1, 0x23, 0x41, 0x74, 0x2B, 0x6A, 0x95, 0x9A, 0x57, 0xB2, 0xA7, 0xBC, 0xD6, 0xDC, 
+  0xD7, 0x9A, 0xBF, 0xDE, 0x75, 0xCC, 0xD6, 0x95, 0x94, 0xAD, 0x0D, 0x9D, 0xE2, 0x9C, 0x33, 0x17, 0xD0, 0x01, 0xB5, 0xC7, 
+  0x25, 0x53, 0x20, 0x14, 0xB5, 0x34, 0x77, 0x2E, 0x1D, 0x5A, 0xA3, 0xFB, 0x0F, 0x39, 0x93, 0xE5, 0xAD, 0x37, 0x7E, 0xC6, 
+  0xE1, 0x93, 0x58, 0x12, 0x9E, 0x84, 0xB6, 0x8C, 0x1A, 0xC0, 0x7D, 0xC9, 0x7F, 0xD4, 0xCC, 0xED, 0xBF, 0xF0, 0x7A, 0x80, 
+  0xF7, 0xAD, 0xFA, 0x7C, 0xA9, 0x64, 0x47, 0x63, 0xFD, 0xD8, 0xA7, 0xB9, 0x21, 0xD7, 0x43, 0xE1, 0x93, 0x04, 0xD9, 0x91, 
+  0xB2, 0x7B, 0x81, 0xA3, 0x68, 0xEC, 0xB5, 0x9E, 0xA1, 0x6C, 0x0E, 0x61, 0x76, 0xD8, 0xCD, 0x40, 0xCC, 0x57, 0xD9, 0x94, 
+  0xB2, 0x90, 0xBA, 0x51, 0x9A, 0x5C, 0xA6, 0xCF, 0x45, 0xAB, 0x3D, 0x94, 0x0C, 0x52, 0x1A, 0xB7, 0x1C, 0x97, 0x19, 0x93, 
+  0xC2, 0x79, 0x65, 0xDC, 0x25, 0x1F, 0xE7, 0x2C, 0x4B, 0x1A, 0x44, 0xE3, 0xCE, 0x3E, 0x8B, 0xC6, 0x8E, 0x89, 0x04, 0xEC, 
+  0x9F, 0x95, 0x6D, 0x1D, 0x76, 0xC4, 0x3D, 0x22, 0x5C, 0x4F, 0xD9, 0x61, 0x3F, 0xFC, 0x08, 0x16, 0x5B, 0xB9, 0xBB, 0xE9, 
+  0xAF, 0x3A, 0x9F, 0xD5, 0xD0, 0x68, 0x3F, 0x30, 0xC7, 0xE7, 0xCE, 0x9E, 0x3F, 0x7B, 0x96, 0x2F, 0x93, 0x54, 0xFA, 0xA6, 
+  0xEB, 0x56, 0x6C, 0x21, 0x33, 0x06, 0xA0, 0xC0, 0x52, 0xCE, 0xA2, 0x7C, 0xEE, 0xF1, 0x17, 0xF9, 0x86, 0x1C, 0xB3, 0xB7, 
+  0x4E, 0xF6, 0xF3, 0x3A, 0xD5, 0x8C, 0x47, 0xA3, 0x56, 0xEB, 0x5E, 0xB8, 0xB3, 0xD7, 0x5F, 0xAE, 0x83, 0x53, 0x01, 0xBD, 
+  0x88, 0x52, 0xD1, 0xC9, 0x00, 0xCE, 0xC9, 0xBB, 0x1B, 0xC6, 0xA0, 0x90, 0x23, 0xF1, 0x11, 0xDD, 0x40, 0x0A, 0x17, 0xE9, 
+  0xC3, 0x3B, 0x1B, 0xA1, 0x7B, 0x98, 0x93, 0x0E, 0x8C, 0xF4, 0x0D, 0x81, 0xC3, 0x0C, 0xC1, 0x09, 0x9B, 0x7C, 0x66, 0xCE, 
+  0x98, 0xE1, 0x96, 0x66, 0xA2, 0x20, 0xF2, 0x8C, 0x39, 0x74, 0x2E, 0x39, 0x06, 0x96, 0x5C, 0xF3, 0xE2, 0xF3, 0xCF, 0xD3, 
+  0xB6, 0x76, 0xF0, 0x3C, 0xC1, 0x22, 0xA5, 0x77, 0x78, 0xAD, 0x5E, 0x2B, 0x20, 0x5B, 0x5E, 0x38, 0x96, 0x38, 0x5A, 0xDC, 
+  0x6E, 0xB7, 0x59, 0x23, 0xA7, 0x2C, 0xDD, 0xB2, 0xCA, 0x2C, 0xCC, 0xB6, 0x49, 0x6C, 0x93, 0x4A, 0x7A, 0x85, 0xC6, 0x15, 
+  0xE8, 0x41, 0xD1, 0x8E, 0x65, 0xCC, 0x89, 0x1A, 0x0A, 0xF2, 0x4B, 0x69, 0xF6, 0x31, 0x9B, 0x62, 0x0C, 0x7E, 0x68, 0xD7, 
+  0x15, 0x30, 0xD8, 0x99, 0xCB, 0x92, 0xFB, 0x4A, 0x91, 0x4F, 0xF7, 0xD4, 0x6C, 0x86, 0x35, 0xFF, 0x9A, 0x0B, 0x61, 0x00, 
+  0x7D, 0xD9, 0xFA, 0x4A, 0x3F, 0x30, 0x28, 0x7F, 0x4A, 0xB2, 0xAA, 0x91, 0xB5, 0x8C, 0x71, 0xC4, 0xF6, 0x45, 0x2B, 0xCE, 
+  0x66, 0xAB, 0x11, 0x1D, 0x18, 0xCE, 0x96, 0x2C, 0xDD, 0x88, 0x42, 0x88, 0x36, 0x94, 0x02, 0x48, 0x02, 0x6E, 0x89, 0xE0, 
+  0x8E, 0xB6, 0x9D, 0xEE, 0xAE, 0x0E, 0xAB, 0xB5, 0xFF, 0x1E, 0x04, 0xDA, 0xA2, 0x00, 0x7A, 0x7F, 0x94, 0x48, 0xA4, 0x92, 
+  0x7C, 0x78, 0x40, 0x09, 0x4E, 0x27, 0xDF, 0x92, 0x7A, 0xCE, 0x99, 0x67, 0x91, 0x0E, 0xA1, 0x03, 0xD3, 0xDA, 0x73, 0xC8, 
+  0xA9, 0xD6, 0xFC, 0x15, 0x55, 0x74, 0xD9, 0x60, 0xE8, 0xA4, 0x86, 0xAE, 0x62, 0xB4, 0x4C, 0xB5, 0x0F, 0xEA, 0x05, 0x82, 
+  0xD3, 0x84, 0x7D, 0xA4, 0x37, 0x65, 0xE2, 0x87, 0x09, 0x09, 0x7E, 0xCC, 0xF1, 0x25, 0x3B, 0x9A, 0xC5, 0x7E, 0xFF, 0x19, 
+  0xB4, 0xC7, 0x09, 0x45, 0x9C, 0x47, 0xC4, 0x56, 0x35, 0x4E, 0x2F, 0xA1, 0x42, 0xA4, 0x24, 0xEA, 0x6E, 0xED, 0xAE, 0xAF, 
+  0xA8, 0x97, 0x49, 0x70, 0x64, 0x02, 0xCD, 0x12, 0x23, 0x7D, 0x67, 0xB8, 0x6F, 0x33, 0xAE, 0x93, 0xBD, 0x41, 0xBD, 0x6D, 
+  0x94, 0x0E, 0xD4, 0xCC, 0x9D, 0xA5, 0x71, 0x55, 0xEF, 0x9E, 0x2A, 0xBD, 0xF1, 0xCE, 0x35, 0xA3, 0x43, 0xA5, 0x93, 0x65, 
+  0x3D, 0xC3, 0x4D, 0xFF, 0x9D, 0x2E, 0x8A, 0x66, 0xA2, 0xD1, 0x81, 0xA2, 0x15, 0xC9, 0x85, 0x5C, 0x9A, 0x8D, 0x42, 0xD0, 
+  0x48, 0x7D, 0x10, 0x00, 0xFF, 0x40, 0x86, 0xE0, 0xE4, 0x42, 0x34, 0x64, 0x98, 0xE5, 0x2E, 0x98, 0x2E, 0x65, 0x2A, 0xAE, 
+  0xC0, 0x07, 0x6B, 0x6E, 0xE8, 0xA4, 0x44, 0x9A, 0xE3, 0x3B, 0x97, 0x69, 0x0C, 0x6D, 0x09, 0xD9, 0xD6, 0x0A, 0x51, 0x7E, 
+  0xC1, 0x88, 0x0E, 0x2C, 0xA6, 0x5B, 0xF9, 0x9E, 0xF2, 0x42, 0xAA, 0x10, 0x53, 0xB2, 0x7A, 0x73, 0x76, 0xF5, 0x1B, 0x1B, 
+  0x24, 0xA5, 0x43, 0x65, 0x06, 0xC5, 0xAA, 0x03, 0x4D, 0xBD, 0x24, 0xBB, 0x9D, 0x35, 0x4F, 0x5B, 0x17, 0x74, 0x9F, 0x52, 
+  0xE2, 0x12, 0x38, 0x77, 0xB8, 0xB7, 0x7B, 0x19, 0x7B, 0x1A, 0x68, 0xE1, 0x91, 0x68, 0xD1, 0xC7, 0x25, 0x18, 0x40, 0x45, 
+  0x0C, 0x09, 0x08, 0xE3, 0x11, 0x0D, 0x2A, 0x8E, 0x4B, 0x2D, 0x90, 0x7D, 0x89, 0x5F, 0xB6, 0x7C, 0x94, 0x64, 0x38, 0x86, 
+  0x12, 0xFC, 0x25, 0x42, 0x3F, 0x45, 0xA2, 0xE9, 0x6C, 0x78, 0x73, 0x50, 0x5E, 0x37, 0xBC, 0x99, 0x17, 0x74, 0x77, 0x80, 
+  0x4A, 0x0E, 0x3A, 0xC2, 0xE6, 0x70, 0x48, 0x06, 0xEC, 0x01, 0xD6, 0x83, 0x86, 0xDC, 0x21, 0x9F, 0x04, 0x80, 0xC8, 0x85, 
+  0xA6, 0x35, 0x14, 0x10, 0x48, 0x5F, 0x81, 0x84, 0x8F, 0x31, 0xA7, 0x9C, 0xE3, 0xE1, 0x17, 0xC2, 0xC9, 0x05, 0x70, 0xBC, 
+  0x96, 0x0C, 0xAE, 0x66, 0x5A, 0x00, 0xAD, 0x85, 0x36, 0x1C, 0x4D, 0x21, 0x9C, 0xC3, 0x9B, 0xE3, 0x7B, 0x43, 0xAB, 0x7A, 
+  0x80, 0x54, 0x49, 0xA3, 0x1D, 0x42, 0x4B, 0x6E, 0x5D, 0xF6, 0x57, 0x5A, 0x2B, 0x8D, 0xB8, 0x85, 0xD9, 0xC4, 0xC9, 0x3F, 
+  0x55, 0xE9, 0x43, 0x02, 0x97, 0xF3, 0x17, 0xE6, 0x91, 0x7A, 0x4A, 0x0D, 0x48, 0x04, 0x9A, 0x33, 0x63, 0xAA, 0x1E, 0xB7, 
+  0x47, 0x75, 0xC2, 0x97, 0x57, 0x32, 0xF1, 0x87, 0xBA, 0x8A, 0xDC, 0xB5, 0xE5, 0x27, 0x66, 0x31, 0x67, 0x01, 0x24, 0x78, 
+  0x5C, 0x41, 0x62, 0x83, 0x47, 0xEE, 0x36, 0x69, 0xB6, 0x9A, 0xB0, 0x31, 0xCC, 0xC7, 0x15, 0x77, 0x18, 0x15, 0x96, 0x0D, 
+  0xAA, 0x56, 0x07, 0x58, 0xB7, 0x3E, 0x08, 0xDB, 0xCE, 0x71, 0x0B, 0x8F, 0xAF, 0x08, 0x97, 0x42, 0xAC, 0x5B, 0x46, 0x02, 
+  0x9C, 0x9E, 0x61, 0x44, 0xAF, 0xB9, 0xBF, 0xEC, 0xB2, 0x53, 0xE9, 0x9B, 0x23, 0xCE, 0xA4, 0xA9, 0x6B, 0x9E, 0x13, 0xC5, 
+  0xC1, 0xE2, 0x12, 0xA2, 0x17, 0xBA, 0xFB, 0xB9, 0x8D, 0xA4, 0x14, 0x82, 0x90, 0x05, 0xE7, 0x7E, 0x18, 0xE4, 0x99, 0x03, 
+  0x49, 0x82, 0x9D, 0xE2, 0x6C, 0x1E, 0xE1, 0xA0, 0x45, 0x1C, 0x42, 0xBE, 0x4A, 0xA2, 0x67, 0x98, 0x34, 0x9F, 0x0F, 0x8F, 
+  0xEF, 0x83, 0x09, 0x4A, 0xEC, 0x39, 0x19, 0x8B, 0xA4, 0x31, 0xE0, 0x91, 0xA9, 0x0A, 0x17, 0x41, 0x47, 0xFA, 0x3B, 0xD2, 
+  0x37, 0x7D, 0x7C, 0x93, 0xB0, 0x9F, 0x14, 0x1E, 0xBC, 0x09, 0x12, 0x4A, 0xF5, 0x92, 0x56, 0x4C, 0x07, 0x49, 0x0A, 0x6F, 
+  0xDE, 0x1B, 0x13, 0x1E, 0x3A, 0x86, 0x34, 0xCC, 0xD9, 0xFC, 0xC4, 0x57, 0xF4, 0xC9, 0xD9, 0x5D, 0x1D, 0x43, 0x20, 0x27, 
+  0x61, 0x0C, 0x25, 0x81, 0xA2, 0x69, 0x09, 0xF2, 0x65, 0xB8, 0x58, 0x92, 0x57, 0xEE, 0xE8, 0x43, 0x96, 0x7B, 0x72, 0x88, 
+  0x05, 0x28, 0xC1, 0xA2, 0xFF, 0xD5, 0xE4, 0x2D, 0x45, 0x1B, 0x3C, 0xB1, 0xD7, 0x5E, 0x4B, 0x77, 0xDB, 0xB6, 0xA2, 0x24, 
+  0xE7, 0xDA, 0x94, 0xEC, 0x23, 0x51, 0xD7, 0x90, 0xF1, 0x0D, 0xCD, 0xCF, 0xB4, 0x28, 0xCC, 0x84, 0x4F, 0x27, 0x79, 0x52, 
+  0xD6, 0x63, 0x98, 0xA6, 0x1C, 0x53, 0xB7, 0xA5, 0xFC, 0xA1, 0x3D, 0xC9, 0xAE, 0xA6, 0xF2, 0xA2, 0x0A, 0x3E, 0x61, 0x5B, 
+  0x43, 0x37, 0xFE, 0xCE, 0x4E, 0x79, 0xE6, 0xFE, 0xD2, 0xF8, 0x9C, 0x78, 0x11, 0x79, 0xBA, 0x6C, 0x7D, 0xE0, 0x6C, 0x14, 
+  0x90, 0xDA, 0xCF, 0x1F, 0x3B, 0xD5, 0x3F, 0x74, 0xDA, 0x2F, 0x27, 0xE9, 0x40, 0x48, 0x9F, 0xEE, 0xD0, 0x51, 0x2F, 0x88, 
+  0xBA, 0xB6, 0x7F, 0x60, 0x11, 0xC9, 0xE6, 0x4E, 0xF2, 0x04, 0xB7, 0xB6, 0xB0, 0xCD, 0x0C, 0xAB, 0x03, 0xD3, 0xB7, 0xF0, 
+  0x45, 0xBE, 0xE7, 0x9D, 0x2B, 0x93, 0x4E, 0x42, 0x05, 0x5F, 0xEE, 0xCB, 0xEE, 0xE5, 0xBE, 0x9E, 0x15, 0x75, 0x15, 0x2D, 
+  0x14, 0xF0, 0xD8, 0x1C, 0x86, 0xCB, 0xB1, 0xB4, 0xB8, 0x82, 0x7A, 0x06, 0xEF, 0xD3, 0x51, 0x27, 0xBE, 0x35, 0x52, 0xC7, 
+  0x18, 0x8E, 0x8C, 0xB9, 0xEB, 0xEA, 0xC0, 0x86, 0x50, 0x97, 0x15, 0xAC, 0x7B, 0x16, 0x14, 0x58, 0xC2, 0x42, 0xCC, 0x16, 
+  0x06, 0x17, 0x5E, 0x04, 0xDF, 0x21, 0x8E, 0xB9, 0xF4, 0x55, 0xEF, 0xB5, 0xE9, 0xD6, 0x2A, 0x29, 0x4F, 0x68, 0x74, 0x66, 
+  0xD1, 0xEB, 0x97, 0xB2, 0x4B, 0x1E, 0x34, 0x5D, 0x14, 0x9D, 0x74, 0xB3, 0x4C, 0x73, 0x74, 0xA4, 0x97, 0x22, 0xEF, 0xC9, 
+  0x2F, 0xF0, 0xD2, 0x09, 0x93, 0x92, 0x12, 0x52, 0xD9, 0x70, 0xCA, 0xA6, 0x81, 0xBE, 0xCE, 0x25, 0x1C, 0xBE, 0xCE, 0x4E, 
+  0xF1, 0xB6, 0xBA, 0x4E, 0xDE, 0x3D, 0xE3, 0x17, 0xE6, 0xBD, 0xC4, 0x67, 0x9A, 0xCC, 0x4E, 0x69, 0xE6, 0x29, 0x77, 0x6D, 
+  0x10, 0x36, 0xB0, 0x26, 0xB0, 0x63, 0x8D, 0xDD, 0x1A, 0xB8, 0xC5, 0x1C, 0xD4, 0xA0, 0xBF, 0xB5, 0x0D, 0x35, 0xAB, 0x03, 
+  0x5B, 0x30, 0xDB, 0xB2, 0x4E, 0x7B, 0x47, 0x96, 0x5D, 0x20, 0x85, 0xC2, 0xD4, 0x69, 0x4C, 0x4C, 0xD9, 0x0C, 0xC2, 0x90, 
+  0x8E, 0x3F, 0xE4, 0x6B, 0x8C, 0xD9, 0xE3, 0x0E, 0xCF, 0x9E, 0x6F, 0x5C, 0xE0, 0x5B, 0xD2, 0x38, 0xDA, 0x87, 0x33, 0xCA, 
+  0xF9, 0xBC, 0x7C, 0xD9, 0x83, 0xF4, 0x51, 0x4C, 0xDC, 0xD2, 0x13, 0x74, 0x3C, 0xE4, 0xB0, 0x11, 0x8A, 0x98, 0x8F, 0x2B, 
+  0x6B, 0x91, 0x78, 0x8C, 0xC3, 0x8B, 0x37, 0x47, 0xB3, 0x1B, 0x29, 0x3B, 0xE8, 0x14, 0x38, 0xB2, 0xDF, 0x5C, 0xC6, 0x14, 
+  0xA1, 0xCE, 0x28, 0x46, 0x03, 0xAC, 0xA4, 0xF6, 0x86, 0xCA, 0x6A, 0xC6, 0x78, 0x96, 0x55, 0x29, 0xE0, 0xA3, 0x8D, 0x75, 
+  0x3B, 0x53, 0x95, 0x51, 0x9F, 0x9F, 0x3B, 0xE5, 0xF0, 0x13, 0x14, 0x72, 0x86, 0x33, 0x9C, 0xE5, 0xE8, 0x27, 0x4D, 0x05, 
+  0xDE, 0x22, 0xD3, 0x47, 0x76, 0x3E, 0xCB, 0x96, 0x8D, 0x8E, 0xC5, 0x8B, 0x3A, 0x06, 0x98, 0x56, 0xF2, 0x7D, 0x9C, 0x6C, 
+  0xEA, 0xC3, 0x09, 0x68, 0x4E, 0x10, 0x12, 0x01, 0x22, 0x6D, 0xF4, 0x5B, 0x20, 0xD2, 0xD0, 0x67, 0x21, 0x88, 0xC0, 0x8E, 
+  0x0E, 0xA2, 0xFC, 0x46, 0x02, 0x2F, 0x56, 0xEF, 0x55, 0xB6, 0xD7, 0xE4, 0xBD, 0x75, 0x93, 0xBD, 0x1E, 0xDB, 0xB1, 0x30, 
+  0x0D, 0x28, 0xC1, 0xA2, 0xD9, 0xFE, 0x42, 0xEF, 0x9D, 0xE9, 0x2B, 0x04, 0xA7, 0xC9, 0xD3, 0x74, 0xE8, 0x4F, 0x5B, 0x5B, 
+  0x09, 0x83, 0x6C, 0x8A, 0xE9, 0x6A, 0xEA, 0xE9, 0x69, 0x1F, 0xE2, 0xC4, 0x07, 0xF6, 0x67, 0x00, 0x4D, 0xD3, 0xC6, 0x4F, 
+  0x32, 0xFD, 0x41, 0x39, 0xD1, 0x08, 0x8F, 0xD1, 0x45, 0x35, 0x43, 0x80, 0xD1, 0x60, 0xA6, 0x1F, 0xC1, 0xC7, 0x63, 0xD4, 
+  0x4E, 0x7B, 0xC7, 0xA9, 0x9E, 0x3C, 0xE3, 0x21, 0x45, 0x1E, 0xE1, 0x14, 0x29, 0xBD, 0x57, 0xC9, 0xC3, 0x2E, 0x83, 0xD5, 
+  0xBD, 0x70, 0xE8, 0xC4, 0x1A, 0x0F, 0xC5, 0x21, 0xA4, 0x7F, 0x62, 0x0A, 0x2E, 0xB7, 0x00, 0x96, 0x81, 0x81, 0x6C, 0xA2, 
+  0x37, 0xF3, 0x23, 0x33, 0x52, 0xD6, 0x8F, 0x2D, 0x2E, 0x29, 0x2D, 0x17, 0xD9, 0x80, 0xC6, 0xB4, 0x9D, 0xFE, 0x33, 0x9C, 
+  0x5F, 0xD2, 0x50, 0xCE, 0xD5, 0x85, 0xCA, 0x40, 0xDE, 0x4D, 0x2E, 0xC8, 0x16, 0x7E, 0xA6, 0x95, 0x7A, 0xD4, 0x8D, 0x1E, 
+  0x3B, 0xA1, 0x7E, 0x6D, 0xCB, 0x63, 0xAF, 0x64, 0x2D, 0xC2, 0x8C, 0x98, 0xB9, 0xF9, 0x5F, 0x72, 0xAC, 0x87, 0x69, 0x99, 
+  0xA9, 0x97, 0x8C, 0x29, 0xD9, 0x6C, 0x5E, 0x64, 0xB1, 0xC8, 0xB6, 0x2B, 0xB4, 0x1D, 0x6B, 0x4E, 0x08, 0x93, 0xD1, 0x1B, 
+  0xA6, 0x00, 0x19, 0x00, 0xDA, 0x80, 0x50, 0x37, 0x7C, 0x7C, 0xA0, 0x45, 0x31, 0x1A, 0xE2, 0xCF, 0xD9, 0x7B, 0xCB, 0xE1, 
+  0x19, 0x55, 0xC5, 0x55, 0xA4, 0x0F, 0x0C, 0xF2, 0x78, 0x82, 0x39, 0xCD, 0xCB, 0x99, 0x93, 0x8F, 0x16, 0xBD, 0xC7, 0x0F, 
+  0x64, 0x8B, 0x88, 0x96, 0xAC, 0x9C, 0xF4, 0x69, 0xB6, 0x2A, 0x58, 0x5E, 0xAA, 0x5E, 0x48, 0x47, 0x41, 0x4F, 0x56, 0x30, 
+  0xA2, 0xB7, 0x4B, 0xE3, 0xAD, 0x76, 0x3D, 0x47, 0x96, 0x6C, 0x92, 0x36, 0xDA, 0xC2, 0x75, 0x9C, 0xA2, 0x57, 0x76, 0x15, 
+  0x68, 0xFE, 0x23, 0x2A, 0x31, 0x07, 0x68, 0xE8, 0xB2, 0x75, 0xBC, 0x8A, 0x52, 0x0A, 0x31, 0xDF, 0x79, 0x1C, 0x87, 0x88, 
+  0x9B, 0x6B, 0xA6, 0x2B, 0xC7, 0xA3, 0x91, 0x9A, 0xCF, 0xF2, 0xE5, 0x43, 0xE2, 0x07, 0x7C, 0x6C, 0x93, 0x11, 0x8D, 0x38, 
+  0x81, 0x0D, 0x71, 0x5E, 0x73, 0xF6, 0x26, 0xFE, 0x9A, 0xF6, 0x48, 0x00, 0x70, 0xB9, 0x40, 0x7A, 0xD7, 0xA9, 0xC5, 0xDC, 
+  0x0B, 0xEF, 0x9F, 0x7B, 0x2B, 0x29, 0x7D, 0x7D, 0xB7, 0x89, 0x2D, 0x63, 0x09, 0xBF, 0xD9, 0xB3, 0x51, 0xC3, 0xEC, 0x59, 
+  0x12, 0x99, 0xB1, 0x09, 0x26, 0xA3, 0xCA, 0x9D, 0xE1, 0x07, 0x72, 0xD4, 0xE4, 0xF1, 0x72, 0x5C, 0x1D, 0xAF, 0x80, 0x81, 
+  0xF3, 0xC5, 0x33, 0x1C, 0x65, 0x2A, 0xE9, 0x83, 0xAF, 0x58, 0x8C, 0xEE, 0x16, 0x70, 0x6F, 0x1D, 0x82, 0xB0, 0xA2, 0x93, 
+  0x0F, 0xC2, 0x22, 0x54, 0x3A, 0x0B, 0x36, 0xB6, 0x5C, 0xEB, 0x6D, 0xB4, 0x0A, 0xDD, 0x09, 0xAD, 0x1E, 0xBE, 0xFC, 0x29, 
+  0x44, 0xEF, 0x12, 0xEA, 0xB5, 0xE1, 0xA3, 0x1B, 0x1F, 0x74, 0x49, 0x12, 0x82, 0x67, 0x08, 0xEB, 0x46, 0xA4, 0x4F, 0x37, 
+  0x54, 0xA5, 0x6F, 0x9D, 0x40, 0xDE, 0xB1, 0x41, 0x21, 0x4D, 0xC0, 0x99, 0xCE, 0x63, 0x5C, 0x7C, 0x3C, 0xD8, 0x25, 0x4A, 
+  0x8C, 0xC0, 0xD9, 0xF9, 0x9C, 0x66, 0x6F, 0xC5, 0x74, 0x02, 0xB2, 0xE8, 0xC0, 0xD3, 0xFA, 0x57, 0x3F, 0xD0, 0x57, 0x73, 
+  0x9A, 0xF2, 0xE6, 0x5A, 0x01, 0x4A, 0x27, 0xD2, 0xD2, 0x31, 0x5E, 0x10, 0x44, 0x6A, 0x24, 0x77, 0xDD, 0x69, 0x9D, 0x37, 
+  0x0B, 0xB2, 0xD7, 0xB6, 0x53, 0x34, 0xA6, 0x65, 0xA4, 0x31, 0xD9, 0x0C, 0xD7, 0x84, 0x8C, 0x23, 0x47, 0x21, 0x4D, 0x57, 
+  0xFE, 0xCB, 0x64, 0x06, 0x79, 0x32, 0xA7, 0x3E, 0x13, 0x96, 0xA4, 0x28, 0x83, 0xE1, 0x33, 0xE6, 0x42, 0xE8, 0xE2, 0x6D, 
+  0x93, 0xC5, 0x3A, 0x07, 0xAC, 0x29, 0x22, 0xCD, 0x95, 0xBA, 0xD2, 0x65, 0x68, 0x3B, 0xD0, 0x24, 0x3A, 0xD0, 0x2A, 0x49, 
+  0x8D, 0x5A, 0xF3, 0x16, 0x79, 0xC4, 0xC4, 0x52, 0xBB, 0x1C, 0x47, 0x31, 0xB3, 0x53, 0x39, 0x9A, 0xC4, 0xD1, 0x87, 0x1C, 
+  0xCD, 0x11, 0x11, 0x10, 0x24, 0xD3, 0x22, 0x13, 0x63, 0x95, 0xD9, 0x61, 0xCD, 0xDF, 0x99, 0xC3, 0x38, 0xF9, 0x0F, 0xD9, 
+  0x67, 0x90, 0x4E, 0x53, 0x9D, 0x96, 0x96, 0x6D, 0x09, 0x2C, 0x90, 0xDD, 0x25, 0x0A, 0x44, 0x7C, 0x36, 0x3E, 0x18, 0x3A, 
+  0xA0, 0x16, 0xA5, 0x51, 0x4C, 0xC4, 0x33, 0x6C, 0x14, 0x61, 0x24, 0x9A, 0x13, 0xFB, 0xA6, 0x31, 0xA1, 0x14, 0xFE, 0x8B, 
+  0x3B, 0x1B, 0xF0, 0xF6, 0xE9, 0x1C, 0x5B, 0xF6, 0x60, 0x0E, 0xA5, 0x16, 0xA2, 0x57, 0x4D, 0xA8, 0xCF, 0x49, 0xBC, 0x75, 
+  0xFD, 0xE0, 0x94, 0xD8, 0xE5, 0x3C, 0xC7, 0xD3, 0x73, 0x55, 0x53, 0x55, 0xF8, 0x56, 0xDE, 0xB5, 0xB3, 0xE3, 0x63, 0xE6, 
+  0x1C, 0xBA, 0xD9, 0x44, 0x05, 0x48, 0xB1, 0x4A, 0xDF, 0x3B, 0xE3, 0xAC, 0x33, 0xCF, 0xE4, 0x20, 0x4D, 0xC3, 0xE3, 0x13, 
+  0xF6, 0xC6, 0x84, 0x89, 0x62, 0x34, 0x72, 0xC4, 0xA0, 0x97, 0xAC, 0xA6, 0xA3, 0x0E, 0x3F, 0x07, 0x97, 0x24, 0x42, 0x04, 
+  0xF8, 0x58, 0x41, 0xE3, 0x10, 0xA6, 0x99, 0xEC, 0x88, 0x5E, 0x65, 0x6D, 0xEF, 0x6A, 0x5B, 0xDF, 0xBB, 0x5C, 0x71, 0x43, 
+  0xE9, 0x96, 0x52, 0x4B, 0x3D, 0x40, 0x27, 0x47, 0x0E, 0xE1, 0x40, 0x20, 0x88, 0x91, 0x9E, 0x0C, 0xB5, 0x19, 0xF8, 0xA9, 
+  0x0E, 0xBC, 0xB9, 0xA0, 0xB7, 0x2D, 0xA3, 0x89, 0x87, 0x30, 0x4A, 0xA6, 0xCD, 0x20, 0x24, 0x38, 0x1F, 0x89, 0x7D, 0x78, 
+  0x67, 0x9E, 0x41, 0xAB, 0x52, 0x28, 0x78, 0xC6, 0xA6, 0x24, 0x2B, 0xD5, 0x61, 0x99, 0x71, 0x05, 0x5B, 0xEF, 0x8C, 0xD4, 
+  0x68, 0x7E, 0xC2, 0xC3, 0x90, 0x42, 0xD7, 0x08, 0x5D, 0x8E, 0x88, 0x12, 0x11, 0xCC, 0x93, 0x67, 0xB2, 0x29, 0xE3, 0x54, 
+  0x4D, 0x9B, 0x93, 0x43, 0xB1, 0x3E, 0x4D, 0x11, 0x52, 0x27, 0x39, 0x6A, 0x25, 0xFA, 0xAF, 0x9D, 0x8D, 0x37, 0xBE, 0xB3, 
+  0x67, 0x31, 0xDE, 0x44, 0x0D, 0xB2, 0x3D, 0x70, 0x32, 0xEF, 0x19, 0xBB, 0x41, 0xF4, 0xEA, 0x01, 0xB8, 0x2F, 0xEA, 0x21, 
+  0x8C, 0xB9, 0x3A, 0x10, 0x3F, 0xD0, 0x1D, 0x22, 0x06, 0x8E, 0x9C, 0x53, 0x95, 0x54, 0xB5, 0xFF, 0x17, 0x16, 0x99, 0xD1, 
+  0x86, 0x7F, 0x90, 0x34, 0x08, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
+};
+
+NPT_UInt8 Platinum_48x48_jpg[3041] =
+{
+  0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 
+  0xFF, 0xDB, 0x00, 0x43, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xDB, 0x00, 0x43, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xC0, 
+  0x00, 0x11, 0x08, 0x00, 0x30, 0x00, 0x30, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, 0xC4, 0x00, 
+  0x1D, 0x00, 0x00, 0x01, 0x04, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 
+  0x07, 0x08, 0x09, 0x03, 0x04, 0x01, 0x02, 0x0A, 0xFF, 0xC4, 0x00, 0x31, 0x10, 0x00, 0x01, 0x04, 0x02, 0x01, 0x03, 0x02, 
+  0x05, 0x03, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x11, 0x08, 0x12, 0x21, 
+  0x00, 0x31, 0x09, 0x13, 0x14, 0x41, 0x71, 0x15, 0x51, 0x61, 0x16, 0x22, 0x17, 0x32, 0x81, 0x91, 0xA1, 0xC1, 0xF0, 0xFF, 
+  0xC4, 0x00, 0x1A, 0x01, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x02, 0x03, 0x00, 0x01, 0x04, 0x05, 0x06, 0xFF, 0xC4, 0x00, 0x30, 0x11, 0x01, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 
+  0x06, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x21, 0x00, 0x03, 0x31, 0x12, 0x41, 0x51, 0x61, 0x71, 
+  0x04, 0x13, 0x22, 0x91, 0x32, 0x42, 0x81, 0xA1, 0xD1, 0xF0, 0xB1, 0x14, 0x15, 0x23, 0xE1, 0xF1, 0xC1, 0xFF, 0xDA, 0x00, 
+  0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0xAF, 0x09, 0xB2, 0x4E, 0x79, 0xFE, 0xF5, 0xF6, 0xFD, 
+  0xFE, 0xC9, 0xE7, 0xF7, 0xF2, 0xBF, 0xBF, 0xB7, 0x1F, 0xB2, 0xF8, 0xF5, 0xEB, 0x19, 0xA3, 0xFF, 0x00, 0x55, 0xFB, 0x3F, 
+  0xCE, 0x47, 0xB6, 0xBB, 0x44, 0x26, 0xF8, 0x3C, 0x77, 0xB7, 0xD8, 0xE3, 0xFF, 0x00, 0xBE, 0x71, 0xA1, 0x13, 0xE4, 0x6B, 
+  0xC2, 0xA7, 0x7F, 0xF1, 0xC7, 0x3C, 0xFB, 0xAF, 0xF0, 0xA8, 0xAB, 0xED, 0xCF, 0xB7, 0xB2, 0x7F, 0x3E, 0x85, 0x92, 0x94, 
+  0xF9, 0xBF, 0x6E, 0x7F, 0x9F, 0xDB, 0x45, 0xF2, 0xB8, 0xB9, 0x57, 0xB6, 0x5F, 0xD6, 0xC7, 0xD3, 0xB3, 0xDF, 0xC6, 0xB0, 
+  0x63, 0x7B, 0x6E, 0xA7, 0x02, 0xCE, 0xF0, 0x5B, 0xEC, 0x90, 0x2A, 0xEB, 0x4C, 0x70, 0x4C, 0xCF, 0x17, 0x5B, 0xC0, 0x2E, 
+  0x7E, 0x72, 0xD2, 0x95, 0x59, 0x25, 0xD8, 0x51, 0x4C, 0x2D, 0xCB, 0x87, 0x7C, 0x73, 0xC7, 0x48, 0x5B, 0xE4, 0x88, 0x5B, 
+  0xA9, 0xA0, 0x7B, 0x25, 0x82, 0xA2, 0x73, 0x49, 0x8D, 0xDD, 0xD0, 0xF9, 0xCD, 0xBD, 0x3A, 0x08, 0xF5, 0x74, 0xF5, 0x34, 
+  0xCA, 0xEB, 0xA6, 0xFE, 0x92, 0xF0, 0xD1, 0x68, 0xAD, 0x60, 0xCD, 0x78, 0x93, 0x08, 0x46, 0x49, 0x77, 0xD3, 0x22, 0x2F, 
+  0x28, 0x87, 0x8E, 0xCD, 0x7E, 0x1A, 0x39, 0x0C, 0xE1, 0xD4, 0xA9, 0xF8, 0x8C, 0xF5, 0x17, 0xD3, 0x36, 0xD7, 0xEA, 0x02, 
+  0x3B, 0x2E, 0x98, 0xB0, 0xD8, 0xF5, 0xDE, 0x2E, 0x4E, 0x0D, 0x8C, 0x4D, 0x97, 0x61, 0x62, 0x86, 0x2D, 0x78, 0x98, 0xB6, 
+  0xC9, 0x81, 0x85, 0x09, 0x9A, 0x63, 0xE2, 0x08, 0x13, 0xBE, 0x82, 0x16, 0xD7, 0x12, 0xC0, 0x60, 0x99, 0x41, 0x64, 0x22, 
+  0x12, 0x4B, 0x26, 0xB0, 0x84, 0x61, 0xBE, 0xB5, 0xF1, 0x22, 0x36, 0x9D, 0xCD, 0x8B, 0xDB, 0xDD, 0x9F, 0x54, 0x8B, 0x32, 
+  0xAF, 0x48, 0x35, 0x9F, 0x5A, 0xFF, 0x00, 0x26, 0x68, 0xD0, 0x7C, 0x3F, 0xD1, 0xB7, 0x5B, 0x8F, 0x54, 0x99, 0x2C, 0x5B, 
+  0xB7, 0xA1, 0x31, 0x27, 0x9A, 0xBA, 0xE1, 0x57, 0x25, 0x95, 0x9D, 0x57, 0xB4, 0xFB, 0x50, 0x59, 0xAA, 0x23, 0xC4, 0x5B, 
+  0x89, 0x43, 0x1E, 0x41, 0x06, 0x52, 0x6D, 0xA9, 0x19, 0xBF, 0xEB, 0x56, 0xEE, 0x9E, 0x7C, 0x5A, 0x4C, 0x7C, 0x10, 0xC2, 
+  0xC5, 0xBF, 0xA6, 0xDC, 0x3B, 0x28, 0x20, 0x88, 0x7B, 0xD6, 0x17, 0x76, 0x99, 0x14, 0x46, 0x4F, 0x78, 0x64, 0xA4, 0xC9, 
+  0x4F, 0x30, 0xE3, 0x55, 0xD7, 0x45, 0x21, 0x57, 0xF3, 0xA5, 0xD6, 0xCB, 0x21, 0xC5, 0x21, 0x5E, 0x39, 0xF5, 0xEC, 0x1D, 
+  0xF2, 0xF9, 0xD1, 0xFC, 0xDC, 0xDB, 0x17, 0x25, 0x55, 0x1F, 0x8B, 0xA9, 0x3A, 0xBA, 0xB9, 0xC9, 0x8A, 0xA2, 0x3F, 0x7A, 
+  0xD0, 0x72, 0x2E, 0x5C, 0xE4, 0x54, 0xEF, 0xE3, 0xF0, 0xBF, 0x9F, 0x0B, 0xCF, 0x3C, 0xFB, 0xF0, 0xBF, 0xC7, 0x8F, 0xB7, 
+  0xA2, 0x77, 0x1F, 0x57, 0xC5, 0xBE, 0xBF, 0xC7, 0xDE, 0x83, 0xD7, 0x53, 0xE6, 0xCB, 0xC0, 0x79, 0xE7, 0x3C, 0xFA, 0xDF, 
+  0x7F, 0x2D, 0xE9, 0x4E, 0xEB, 0xBE, 0xEF, 0x1D, 0xEE, 0x55, 0x5F, 0x64, 0xF2, 0xBC, 0xFF, 0x00, 0x3E, 0xEA, 0xBF, 0x9E, 
+  0x3D, 0x39, 0xDD, 0x2B, 0xB6, 0x78, 0x6F, 0xFB, 0x79, 0xFF, 0x00, 0xBF, 0x3A, 0x63, 0x28, 0x1D, 0xFF, 0x00, 0x46, 0xBC, 
+  0xF1, 0x87, 0xD8, 0xF3, 0xCE, 0x81, 0xDE, 0x5F, 0x97, 0x52, 0x34, 0x85, 0x7D, 0x34, 0xB2, 0xAC, 0x6C, 0x49, 0x5B, 0x0A, 
+  0xB9, 0x62, 0x74, 0xCD, 0x45, 0x45, 0x56, 0x31, 0xF2, 0x27, 0x6B, 0x16, 0x46, 0xA2, 0xB5, 0x8F, 0x7A, 0x2B, 0x11, 0xEA, 
+  0xD5, 0x7A, 0xF6, 0xF7, 0x7A, 0x5C, 0xB7, 0x51, 0x29, 0xBF, 0xD8, 0xE3, 0xB6, 0x32, 0xE3, 0xD8, 0x78, 0xE3, 0x42, 0xEE, 
+  0x54, 0x8B, 0x8F, 0x39, 0xC9, 0x46, 0x2C, 0xA1, 0x30, 0xF7, 0x7B, 0xE0, 0xCE, 0xA5, 0x4C, 0xDD, 0x25, 0x33, 0xAA, 0xBD, 
+  0x39, 0x95, 0xEC, 0xBE, 0x92, 0x2D, 0xC8, 0xDC, 0x38, 0xBE, 0x3F, 0x57, 0x24, 0x5B, 0x23, 0x5C, 0x4E, 0xD1, 0x44, 0xDF, 
+  0x5A, 0x89, 0xF3, 0x8C, 0xD8, 0x6C, 0x63, 0xCE, 0x75, 0xF8, 0x8D, 0x8E, 0x7B, 0xEC, 0x74, 0x29, 0xE6, 0x54, 0x13, 0x63, 
+  0xE0, 0x23, 0xD9, 0x50, 0x10, 0x0C, 0x82, 0x1D, 0x7F, 0x51, 0x86, 0xCD, 0x2A, 0x0C, 0xEC, 0xB3, 0xDD, 0x37, 0x31, 0x3A, 
+  0x05, 0xA2, 0x47, 0xE1, 0x5A, 0xCC, 0x6D, 0xCC, 0x66, 0x19, 0xE9, 0x41, 0xBA, 0x4E, 0xA3, 0x3A, 0x09, 0x6E, 0x46, 0x69, 
+  0x19, 0xA6, 0xDC, 0xAE, 0x89, 0x52, 0xC2, 0x77, 0x76, 0x5F, 0xE5, 0x53, 0x20, 0xD2, 0xDD, 0x0C, 0xBB, 0x30, 0xFB, 0x33, 
+  0xA2, 0xFE, 0xA7, 0xF4, 0x4E, 0x33, 0xAD, 0xB7, 0xB6, 0xE8, 0xC1, 0x6D, 0x31, 0xAC, 0x77, 0x7C, 0x57, 0xD9, 0x9F, 0x40, 
+  0x4D, 0x8B, 0x25, 0x88, 0xC2, 0x2C, 0xF1, 0x70, 0x31, 0x7A, 0x3C, 0x88, 0xAB, 0x21, 0x64, 0x8A, 0x39, 0x42, 0x5B, 0xC3, 
+  0xE2, 0x75, 0xED, 0x63, 0xA7, 0x6B, 0x56, 0xC8, 0x12, 0x9C, 0x7C, 0x3D, 0xF0, 0x3D, 0x92, 0xBC, 0x46, 0xE5, 0x29, 0x75, 
+  0x12, 0x96, 0x19, 0x11, 0x15, 0x25, 0xD3, 0x1B, 0x6A, 0x8F, 0xC5, 0x48, 0xBC, 0xDB, 0xDA, 0xB4, 0xAD, 0xB8, 0x8F, 0x51, 
+  0x19, 0x12, 0x76, 0xC0, 0x91, 0x1B, 0x68, 0x55, 0x13, 0x17, 0x20, 0x39, 0x4E, 0x1E, 0xCF, 0x66, 0x78, 0x88, 0x08, 0x8D, 
+  0xA8, 0x43, 0xE0, 0x73, 0x7B, 0x93, 0xFC, 0xCA, 0x9E, 0x7C, 0xA2, 0x2A, 0x72, 0xBE, 0x15, 0xBC, 0xB5, 0x5A, 0xA8, 0x9E, 
+  0x55, 0x51, 0x5A, 0xEE, 0x38, 0x5E, 0x7D, 0x33, 0x06, 0x78, 0xFB, 0xFF, 0x00, 0xE2, 0xFE, 0xF5, 0xED, 0xA3, 0x62, 0xC2, 
+  0x87, 0x0B, 0xC6, 0x39, 0xE6, 0xDF, 0xB9, 0xC6, 0x39, 0xD2, 0x6C, 0x9B, 0x27, 0x35, 0x55, 0xBD, 0xDC, 0x2A, 0x73, 0xEF, 
+  0xCF, 0xDB, 0xF6, 0xE7, 0x85, 0x4F, 0x7F, 0x1F, 0xED, 0xC7, 0xAB, 0xD5, 0x6B, 0xAD, 0xCD, 0xF9, 0xC3, 0x04, 0x4C, 0x95, 
+  0xCA, 0xC5, 0x31, 0xB1, 0x48, 0xB0, 0x7C, 0xC7, 0x48, 0xD6, 0x2C, 0x88, 0xD5, 0x56, 0xA4, 0x8E, 0x85, 0x7E, 0x6B, 0x58, 
+  0xE5, 0x4E, 0xD7, 0xBE, 0x35, 0x49, 0x18, 0x8A, 0xAF, 0x8F, 0x87, 0xB5, 0x17, 0xD0, 0xCA, 0xE9, 0x4A, 0xB3, 0x25, 0x96, 
+  0x5F, 0xAF, 0x0D, 0x79, 0xA4, 0x6B, 0x87, 0x51, 0xF4, 0xE7, 0x15, 0x60, 0x9C, 0xF7, 0x1A, 0xBA, 0xF7, 0xFD, 0x1D, 0x3D, 
+  0x5B, 0x1B, 0xAC, 0x8D, 0x37, 0xB7, 0x75, 0x56, 0x3F, 0x8B, 0x1B, 0xD2, 0x81, 0x3A, 0x43, 0x75, 0x62, 0x21, 0x54, 0xD4, 
+  0xA6, 0x6F, 0xAD, 0x32, 0x28, 0xAD, 0xB5, 0x9E, 0xC9, 0xAF, 0x01, 0xB0, 0x86, 0x61, 0x59, 0xA6, 0x20, 0x7B, 0x88, 0x22, 
+  0x8F, 0x2F, 0x9C, 0x46, 0x3C, 0xD6, 0xE5, 0xD8, 0xBA, 0xE3, 0x01, 0x5B, 0xD8, 0x23, 0xD2, 0xFF, 0x00, 0x15, 0x26, 0x42, 
+  0x7E, 0xB4, 0x64, 0x9B, 0x8D, 0xB6, 0x4C, 0xEF, 0xD3, 0xF4, 0xCE, 0xB2, 0xFE, 0x19, 0xC7, 0xB7, 0x38, 0x94, 0x2B, 0xB1, 
+  0x2E, 0x35, 0x51, 0xDC, 0xDD, 0x16, 0x33, 0xFA, 0xE3, 0x27, 0x1D, 0x5D, 0x2F, 0x4B, 0xCD, 0xC5, 0xC3, 0x45, 0x62, 0x32, 
+  0x8B, 0xEE, 0x77, 0x79, 0xB4, 0x2E, 0x2D, 0x6B, 0xD3, 0x56, 0xB9, 0xA8, 0xEB, 0xFF, 0x00, 0x43, 0xF5, 0x8D, 0xAC, 0x31, 
+  0x5D, 0xA8, 0xFA, 0xC9, 0x29, 0x28, 0xF4, 0xFE, 0x30, 0xFD, 0x93, 0x26, 0xC3, 0xB2, 0xB0, 0x92, 0xF0, 0x31, 0xA6, 0x1E, 
+  0xD8, 0xB4, 0xC2, 0xC4, 0xD7, 0xB3, 0x4B, 0x8A, 0x0E, 0xD3, 0x4A, 0x2A, 0x07, 0x64, 0x97, 0x21, 0xA0, 0xD6, 0xA7, 0x63, 
+  0x76, 0xAD, 0x46, 0x59, 0x9D, 0x56, 0x43, 0x08, 0x12, 0x59, 0xFC, 0xBE, 0xA8, 0x4E, 0x0D, 0xCC, 0x4F, 0x97, 0x26, 0xCA, 
+  0xEE, 0xDC, 0xE2, 0x94, 0x0A, 0x22, 0xA3, 0x46, 0x35, 0x5F, 0xF1, 0x6E, 0x3D, 0x2C, 0x65, 0x2E, 0x98, 0xAC, 0xE4, 0xB0, 
+  0x20, 0xE1, 0xA2, 0xAD, 0x91, 0x72, 0xC0, 0xD0, 0x88, 0xA6, 0x07, 0x56, 0xEF, 0xAB, 0x3E, 0x30, 0xB8, 0x77, 0x53, 0x58, 
+  0x19, 0xDA, 0x8B, 0xE2, 0x2D, 0x84, 0xB3, 0x70, 0xE1, 0xF7, 0x67, 0x8F, 0x75, 0x53, 0x7D, 0x8B, 0x14, 0x15, 0x06, 0x71, 
+  0x83, 0xDF, 0x80, 0xC7, 0xC1, 0x0D, 0xBE, 0x3C, 0xF7, 0x04, 0x3D, 0x3A, 0x3C, 0x81, 0x66, 0x20, 0x63, 0x00, 0x6C, 0x91, 
+  0x02, 0x50, 0x72, 0xAC, 0x24, 0xC7, 0x3C, 0x5F, 0x30, 0x57, 0xB3, 0xFD, 0x2C, 0x64, 0x46, 0x5F, 0x0F, 0x38, 0xC2, 0x79, 
+  0x25, 0x07, 0xB8, 0xF6, 0xAB, 0x3A, 0xBC, 0x92, 0x1B, 0xCF, 0x9E, 0x33, 0x91, 0xF9, 0x72, 0xEB, 0xD9, 0x94, 0xB6, 0xD3, 
+  0x91, 0x6C, 0x4E, 0xF9, 0xC3, 0x5C, 0x73, 0xFF, 0x00, 0xAB, 0xAE, 0xA7, 0x77, 0xAF, 0xC1, 0x2F, 0x34, 0xD1, 0x74, 0x15, 
+  0x74, 0x7A, 0xAF, 0x69, 0xD5, 0xE5, 0x3A, 0xA6, 0x80, 0xAA, 0x7C, 0x2E, 0x8B, 0x0F, 0x3E, 0x83, 0x18, 0xB6, 0xD8, 0x12, 
+  0xD9, 0xD9, 0x4E, 0x73, 0x1B, 0xB2, 0x72, 0xF5, 0x0E, 0xFC, 0xF6, 0xC1, 0xFA, 0xC9, 0x24, 0x1C, 0x7E, 0x40, 0x1D, 0x6B, 
+  0xB2, 0x10, 0x6B, 0xC8, 0x26, 0xB6, 0x9E, 0x41, 0x43, 0xFA, 0x16, 0x57, 0xAD, 0xD8, 0xF8, 0x9D, 0xBB, 0x65, 0x28, 0x31, 
+  0x93, 0x52, 0x93, 0x9A, 0xED, 0xF4, 0x9C, 0x38, 0xF3, 0x8F, 0xBA, 0xAC, 0xDA, 0x97, 0xC5, 0x75, 0x49, 0x67, 0x19, 0x45, 
+  0xCC, 0x94, 0xEA, 0x0E, 0x98, 0xFE, 0x53, 0x05, 0xA6, 0x02, 0xF3, 0xCF, 0x7B, 0x7C, 0x9D, 0x49, 0x93, 0xA5, 0xF4, 0xC6, 
+  0x5C, 0xC5, 0x5E, 0x2D, 0x30, 0x76, 0x66, 0x16, 0x70, 0x94, 0xE0, 0x92, 0x59, 0x81, 0xD3, 0x8A, 0x54, 0xEF, 0x94, 0x7A, 
+  0x81, 0xCD, 0x3C, 0xA3, 0x4E, 0x2E, 0x3A, 0xB8, 0x55, 0xA1, 0x29, 0x47, 0x18, 0x51, 0x73, 0xC9, 0x0B, 0xE6, 0x26, 0x69, 
+  0x25, 0x7A, 0xAF, 0xA0, 0x27, 0x24, 0xC5, 0x17, 0x90, 0x2A, 0xCE, 0xE1, 0x58, 0x7B, 0x97, 0x8C, 0xFB, 0x5E, 0x9C, 0xA5, 
+  0xFB, 0xE4, 0x30, 0x7A, 0xF0, 0x70, 0xE7, 0x27, 0x6F, 0x05, 0x3A, 0xDF, 0x9A, 0xC9, 0x8A, 0x8B, 0xDE, 0xA9, 0xC7, 0x85, 
+  0xF2, 0xE4, 0x4F, 0x6F, 0xBF, 0x95, 0xE3, 0xD9, 0x7D, 0xBD, 0xFF, 0x00, 0xED, 0x9D, 0x63, 0x78, 0xEF, 0x59, 0xE2, 0x9F, 
+  0x2D, 0x63, 0xBF, 0x9F, 0xE2, 0x7F, 0x3E, 0x3D, 0xBF, 0xBE, 0x9A, 0x04, 0x69, 0x01, 0x24, 0x13, 0x4C, 0xAC, 0x47, 0x35, 
+  0x18, 0xF7, 0xAA, 0xB5, 0xA8, 0xE5, 0x54, 0x46, 0xAA, 0xAF, 0x6F, 0x6F, 0x2A, 0xE5, 0x5E, 0x17, 0xB5, 0x13, 0x9E, 0x57, 
+  0x8E, 0x3C, 0xAA, 0x7A, 0x5A, 0x99, 0x68, 0x3E, 0xFE, 0xB7, 0xFD, 0xF6, 0xAE, 0xFA, 0x9A, 0x79, 0x3A, 0x67, 0xD7, 0x16, 
+  0xDB, 0x83, 0x03, 0xDE, 0x78, 0x9E, 0xB1, 0xCB, 0x30, 0x3B, 0xAF, 0xD1, 0x4F, 0x03, 0x67, 0x65, 0x98, 0x4D, 0x4E, 0x55, 
+  0xF5, 0x19, 0x92, 0x94, 0x35, 0x6C, 0x18, 0x90, 0x79, 0x00, 0xD8, 0xC9, 0x02, 0x86, 0x32, 0x53, 0x8F, 0x09, 0x2D, 0x1A, 
+  0xFA, 0xE6, 0xB6, 0x63, 0x8B, 0x22, 0xC5, 0xF4, 0xE1, 0x5A, 0xA0, 0xA3, 0xC2, 0x0A, 0x4D, 0xA7, 0xE0, 0xF6, 0xCD, 0xDD, 
+  0xBD, 0xF8, 0x43, 0x72, 0x19, 0x94, 0x67, 0xD2, 0x3D, 0xC3, 0xA4, 0xBF, 0xCA, 0x47, 0x9B, 0x72, 0xAD, 0x0D, 0x70, 0xE4, 
+  0x9E, 0xE6, 0xDC, 0x77, 0x2F, 0x85, 0xFA, 0x57, 0xF2, 0xF3, 0xDE, 0xB3, 0x6F, 0x49, 0x58, 0x4C, 0x73, 0x8C, 0xC4, 0x2C, 
+  0x8E, 0x2D, 0x91, 0x41, 0x74, 0x55, 0x74, 0x43, 0x1E, 0x3A, 0x0A, 0x44, 0xA3, 0xAC, 0x4B, 0x14, 0xF1, 0x3B, 0xFB, 0x5E, 
+  0xE4, 0x72, 0x2C, 0x6A, 0x88, 0xA8, 0x8E, 0x56, 0xAB, 0xD7, 0x84, 0xED, 0x5E, 0x79, 0x6A, 0xFD, 0xBD, 0x64, 0xDC, 0x96, 
+  0xF4, 0x67, 0xD2, 0xC5, 0x2A, 0x54, 0xE1, 0x28, 0x2A, 0xF2, 0x7A, 0xE0, 0x5B, 0x3D, 0x79, 0xD6, 0x82, 0x05, 0x64, 0xA6, 
+  0xB9, 0xBB, 0xE7, 0xF6, 0xAE, 0x3F, 0xB9, 0xD5, 0x9E, 0x74, 0x5B, 0xAB, 0x6F, 0xB2, 0xEC, 0x67, 0x28, 0xD9, 0xF9, 0x76, 
+  0x33, 0x79, 0x7B, 0x47, 0x87, 0x53, 0x5B, 0x98, 0x88, 0x24, 0xB6, 0x55, 0x90, 0xAD, 0xF5, 0x5D, 0x5C, 0xE5, 0xD4, 0x46, 
+  0x5D, 0xBD, 0x57, 0x16, 0x75, 0x50, 0xBA, 0xCE, 0x30, 0x19, 0x3D, 0x98, 0x6E, 0x69, 0x61, 0x8D, 0x24, 0xE4, 0xB6, 0x56, 
+  0xA3, 0x58, 0xAD, 0xEA, 0x7C, 0x1E, 0xDA, 0xED, 0x4B, 0x72, 0x71, 0xBE, 0xA2, 0x44, 0x46, 0xB2, 0x87, 0x6E, 0x28, 0x5C, 
+  0x59, 0xE3, 0x35, 0xD9, 0x1B, 0xB3, 0x76, 0xD2, 0x31, 0x97, 0x4C, 0x97, 0x15, 0x4A, 0x1C, 0x2E, 0x4A, 0xB7, 0xD9, 0xC7, 
+  0x27, 0x7D, 0x57, 0x5D, 0xEE, 0xC8, 0xDA, 0x39, 0xF1, 0xB6, 0x97, 0xD9, 0xD4, 0xB8, 0x79, 0x39, 0x06, 0x42, 0x54, 0x76, 
+  0x57, 0x27, 0x55, 0xE1, 0x35, 0x54, 0xB6, 0x43, 0xD8, 0xB5, 0x5C, 0xB3, 0x0E, 0x3D, 0x88, 0x12, 0xC6, 0x5C, 0xEE, 0x8A, 
+  0x47, 0xBC, 0x62, 0xCC, 0xB7, 0x7D, 0x9D, 0x8D, 0xAC, 0x90, 0x34, 0xDB, 0x72, 0xCE, 0x3F, 0xB8, 0x87, 0x72, 0x19, 0xEE, 
+  0x4A, 0xFA, 0x88, 0x1D, 0x56, 0x9D, 0x31, 0x23, 0xD3, 0x9E, 0x05, 0x73, 0x5E, 0x5B, 0x6F, 0xBF, 0x1A, 0x74, 0x63, 0x22, 
+  0xBE, 0xBB, 0xA3, 0x21, 0x10, 0xF1, 0x8A, 0x0B, 0xE0, 0xA3, 0xC1, 0xC1, 0xE3, 0x9B, 0x29, 0xCE, 0x9B, 0x95, 0x12, 0x51, 
+  0x51, 0x5C, 0xC7, 0xC4, 0xF6, 0x96, 0x08, 0xD6, 0x11, 0xFC, 0xB7, 0x3A, 0x37, 0x7C, 0xC8, 0xA1, 0x2D, 0xAE, 0x8E, 0x22, 
+  0x58, 0xE8, 0xDB, 0xF2, 0x49, 0x46, 0xBD, 0x58, 0xD5, 0x95, 0x8E, 0x64, 0x8C, 0x91, 0xED, 0x59, 0x39, 0x82, 0x53, 0xDB, 
+  0x2B, 0x1B, 0x05, 0xA7, 0x16, 0x9E, 0x31, 0x2F, 0x5E, 0xE3, 0xA3, 0x4B, 0xC5, 0xA7, 0x0D, 0x9F, 0xAE, 0x3F, 0xBE, 0x9E, 
+  0xDA, 0xC1, 0x21, 0x6E, 0x08, 0x07, 0x7D, 0x43, 0xA5, 0x21, 0x58, 0xC5, 0x59, 0x15, 0x1A, 0x92, 0xCD, 0x22, 0xAB, 0xBB, 
+  0x9E, 0xFE, 0xC6, 0xF6, 0x77, 0xBD, 0x51, 0x5C, 0xF4, 0x89, 0x8B, 0x1A, 0x3B, 0x84, 0x8E, 0x3E, 0xDE, 0x5B, 0xC4, 0xEB, 
+  0x7A, 0x6B, 0x37, 0x76, 0xE1, 0x68, 0xEF, 0xC2, 0x16, 0x9C, 0x56, 0x6F, 0x06, 0x2B, 0x57, 0xA5, 0x6E, 0x8B, 0xEA, 0x8B, 
+  0x64, 0x74, 0xBD, 0xB3, 0x3F, 0xC4, 0x9D, 0x01, 0x85, 0xE1, 0xD9, 0x2E, 0x4F, 0x61, 0x5A, 0xCC, 0x4E, 0xCE, 0x4D, 0xBF, 
+  0x8C, 0x4A, 0x78, 0x19, 0x0D, 0x15, 0x85, 0x88, 0x85, 0xDA, 0xE2, 0x54, 0xD4, 0x61, 0xDB, 0x57, 0x17, 0x48, 0x06, 0x48, 
+  0x68, 0x55, 0x8C, 0x2E, 0xFA, 0xD0, 0xF5, 0xB8, 0x1A, 0x30, 0x45, 0x70, 0xC1, 0x88, 0xC6, 0x4F, 0x33, 0xCB, 0x6B, 0x7E, 
+  0x5B, 0x13, 0x65, 0xB3, 0x02, 0x6C, 0xAA, 0x0B, 0x31, 0x2E, 0x37, 0xF8, 0x63, 0x1B, 0xC5, 0xB5, 0xF5, 0x36, 0x88, 0x3E, 
+  0x75, 0x9B, 0x77, 0x6A, 0x5B, 0xC6, 0x40, 0xA5, 0x4E, 0x49, 0x49, 0x38, 0xE1, 0xC1, 0xE2, 0xD7, 0xD4, 0x4A, 0xD5, 0x83, 
+  0xE6, 0x9F, 0x13, 0x6F, 0x86, 0x36, 0x7D, 0x53, 0x7D, 0x97, 0xE4, 0x1D, 0x1C, 0xF5, 0x11, 0x5B, 0xB9, 0x0B, 0x80, 0x62, 
+  0x71, 0xDD, 0x7C, 0x16, 0x41, 0x85, 0xC3, 0xAF, 0x72, 0xAC, 0x8E, 0x46, 0x32, 0x1B, 0x31, 0x84, 0xCF, 0x60, 0x20, 0xDB, 
+  0xBC, 0x73, 0x1C, 0x0A, 0xC7, 0xE6, 0x94, 0xC9, 0xAC, 0xB1, 0xDB, 0x12, 0x66, 0xA4, 0x86, 0x19, 0x06, 0x85, 0x49, 0x9D, 
+  0x62, 0x66, 0xDF, 0xF7, 0x1D, 0x89, 0x17, 0x2D, 0xA9, 0x33, 0x0C, 0x0C, 0x62, 0xDB, 0x74, 0x7D, 0x77, 0x55, 0xEB, 0x47, 
+  0x16, 0x1A, 0xCB, 0x19, 0x7C, 0x44, 0x3A, 0x61, 0x1D, 0xC7, 0xA7, 0x88, 0xDC, 0x6E, 0x49, 0x79, 0xE9, 0xBC, 0x1D, 0xB3, 
+  0x8A, 0x32, 0x6A, 0x1C, 0xEF, 0x9E, 0xAD, 0x05, 0xEA, 0x73, 0x4F, 0x62, 0x98, 0x2E, 0x1F, 0xAD, 0xCF, 0xE9, 0x7C, 0x1D, 
+  0x69, 0xB0, 0x1D, 0x91, 0xDF, 0xE0, 0x78, 0x2E, 0xCC, 0xC8, 0xAE, 0x29, 0x33, 0xD7, 0x65, 0x54, 0x9F, 0xA7, 0xD0, 0xE6, 
+  0xF2, 0x5E, 0x20, 0xB8, 0xED, 0xD2, 0xD8, 0x62, 0x16, 0x94, 0x52, 0x56, 0x2D, 0x49, 0x9F, 0x34, 0x2A, 0xF9, 0x6F, 0x21, 
+  0xB1, 0xAF, 0x73, 0x54, 0x8E, 0xD8, 0xF3, 0xEF, 0xFC, 0x5B, 0xF1, 0x3B, 0x21, 0x12, 0x5B, 0x0C, 0x26, 0x5C, 0x09, 0x7E, 
+  0x28, 0xA7, 0xD1, 0x21, 0x08, 0xB5, 0x19, 0x46, 0x91, 0x2B, 0x23, 0x8D, 0x3B, 0x6F, 0x6A, 0x4E, 0xE4, 0x9D, 0xEB, 0x92, 
+  0xC7, 0x96, 0x5F, 0x94, 0xF1, 0x55, 0x8C, 0xB6, 0x01, 0x9A, 0x5E, 0x0D, 0x47, 0x15, 0xB0, 0xB6, 0x26, 0x47, 0x91, 0x6E, 
+  0x67, 0xD7, 0xD8, 0x4A, 0xD8, 0x5A, 0x51, 0xAF, 0x1E, 0x01, 0xA7, 0x3A, 0x68, 0x61, 0x64, 0x0E, 0x34, 0xD6, 0x8D, 0x1C, 
+  0x51, 0x4F, 0x64, 0x53, 0x63, 0x6C, 0xB6, 0x06, 0xA4, 0x51, 0x48, 0x79, 0x4B, 0x21, 0x73, 0x31, 0x48, 0x9A, 0x57, 0xBD, 
+  0x31, 0xA7, 0x33, 0x6E, 0x5C, 0xDD, 0x03, 0xC1, 0xF5, 0x21, 0x46, 0x79, 0x5B, 0xE6, 0xD4, 0xB5, 0xD6, 0xC8, 0xC6, 0x80, 
+  0xE6, 0xBD, 0x8A, 0x3F, 0x63, 0xF5, 0xA3, 0xDB, 0x44, 0x9C, 0x62, 0x7B, 0xAB, 0xBF, 0x3F, 0x7F, 0xC7, 0x9F, 0x0B, 0xC7, 
+  0xDB, 0xFE, 0x3F, 0x21, 0xD1, 0x2A, 0xE3, 0x3E, 0xE7, 0xF7, 0xFC, 0xFF, 0x00, 0x37, 0xAD, 0x49, 0xCC, 0x6A, 0xB5, 0x51, 
+  0xDC, 0xB9, 0x17, 0x9E, 0x3D, 0x95, 0x3F, 0xD5, 0x3F, 0xF2, 0xA7, 0x0B, 0xC2, 0xF3, 0xC7, 0xAB, 0x22, 0x0D, 0xAD, 0x01, 
+  0x63, 0x66, 0x7C, 0x51, 0xCF, 0xEC, 0xFD, 0x9B, 0x25, 0x27, 0x25, 0x77, 0xE2, 0xBD, 0xDD, 0x0E, 0x5C, 0x8B, 0x19, 0x0E, 
+  0x86, 0xC6, 0x20, 0xEF, 0xE9, 0x0E, 0xCC, 0x2E, 0xE7, 0x9F, 0x1E, 0x83, 0x1A, 0x88, 0x79, 0x88, 0xBE, 0xC6, 0xEB, 0xA1, 
+  0x9A, 0x02, 0x2C, 0xF2, 0x72, 0x64, 0x96, 0x14, 0x0A, 0xAC, 0x52, 0x81, 0x46, 0x89, 0x54, 0x44, 0x32, 0x4B, 0x61, 0x60, 
+  0x69, 0x90, 0x45, 0x0A, 0x8E, 0x10, 0x96, 0x48, 0x55, 0xB2, 0x8F, 0x4A, 0xC5, 0x3A, 0x97, 0xA6, 0x30, 0x3F, 0x14, 0x4E, 
+  0x65, 0x35, 0x68, 0xE2, 0xC0, 0x2D, 0x16, 0xFB, 0x36, 0xB6, 0x63, 0x2E, 0x83, 0x9B, 0xFA, 0xAD, 0xA4, 0x3C, 0xF9, 0xA7, 
+  0x01, 0xEF, 0xEB, 0xA0, 0x6C, 0xA8, 0xAC, 0xE2, 0x17, 0x38, 0x78, 0x3B, 0xE2, 0x62, 0x7C, 0xB4, 0x46, 0x35, 0x15, 0x8D, 
+  0x6B, 0x51, 0xAD, 0x6B, 0x79, 0x4E, 0x51, 0xA8, 0xDE, 0x1B, 0xE3, 0x9E, 0x53, 0xEF, 0xED, 0xCA, 0x80, 0x3B, 0x1F, 0x63, 
+  0x4C, 0xAA, 0xCF, 0xDB, 0xF5, 0x7D, 0x5F, 0x37, 0xFE, 0x03, 0x4A, 0x2C, 0x4F, 0x3D, 0x97, 0x54, 0x66, 0x74, 0x59, 0xD8, 
+  0xD5, 0x42, 0x5D, 0x09, 0x51, 0x34, 0xB0, 0x5E, 0x51, 0x1B, 0x58, 0x1D, 0xC8, 0x57, 0xB8, 0xDD, 0x84, 0x2E, 0x12, 0xF2, 
+  0xAC, 0xBA, 0x73, 0xF8, 0x0A, 0xDA, 0x29, 0xC3, 0x7A, 0xBD, 0x6B, 0x0B, 0x7C, 0x31, 0xD8, 0x36, 0x37, 0x80, 0xD2, 0x82, 
+  0x90, 0xB6, 0x9C, 0x31, 0x46, 0x7F, 0x2E, 0x44, 0x9F, 0xA8, 0xBA, 0x91, 0x43, 0x71, 0x79, 0x2B, 0x03, 0x5C, 0x82, 0x9E, 
+  0xF9, 0xD0, 0x4E, 0xEA, 0xCE, 0x63, 0x9A, 0xAB, 0xB3, 0x84, 0xAF, 0x6F, 0xF1, 0xA1, 0xF7, 0x59, 0x16, 0x25, 0x67, 0x72, 
+  0x7C, 0xF8, 0x55, 0xCD, 0x4D, 0xBE, 0x3C, 0x4C, 0xAE, 0x36, 0xB1, 0x29, 0xCA, 0xB5, 0x36, 0x2A, 0xB0, 0x8C, 0x98, 0x89, 
+  0x05, 0xA3, 0x2E, 0x5B, 0xC0, 0x81, 0xB8, 0x65, 0x85, 0x58, 0xCD, 0x8A, 0x12, 0x20, 0xB3, 0x89, 0xF6, 0x51, 0x44, 0xA3, 
+  0xA1, 0xE4, 0x94, 0x63, 0xA6, 0x26, 0x69, 0x36, 0x37, 0x51, 0x91, 0x28, 0xB9, 0x02, 0xEB, 0x3D, 0x9E, 0xA0, 0xC8, 0x72, 
+  0x52, 0xE4, 0xCE, 0xA4, 0x27, 0xD6, 0x08, 0xD9, 0xE8, 0xF1, 0x8E, 0x5B, 0x01, 0x6F, 0xD3, 0x1D, 0xEB, 0x8D, 0x7F, 0xFF, 
+  0xD9
+};
+
+NPT_UInt8 Platinum_48x48_png[4681] =
+{
+  0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x30, 
+  0x00, 0x00, 0x00, 0x30, 0x08, 0x02, 0x00, 0x00, 0x00, 0xD8, 0x60, 0x6E, 0xD0, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 
+  0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 
+  0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 
+  0xFA, 0x00, 0x00, 0x00, 0x80, 0xE8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xEA, 0x60, 0x00, 0x00, 0x3A, 0x98, 0x00, 0x00, 
+  0x17, 0x70, 0x9C, 0xBA, 0x51, 0x3C, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x12, 0x00, 0x00, 
+  0x0B, 0x12, 0x01, 0xD2, 0xDD, 0x7E, 0xFC, 0x00, 0x00, 0x11, 0xB2, 0x49, 0x44, 0x41, 0x54, 0x58, 0x47, 0x6D, 0x98, 0x09, 
+  0x90, 0x5C, 0xD5, 0x75, 0x86, 0x9F, 0x90, 0x10, 0x48, 0x02, 0x84, 0x00, 0xED, 0xB3, 0xAF, 0xBD, 0x4F, 0x77, 0xCF, 0xF4, 
+  0xEC, 0x7B, 0xEF, 0x33, 0xBD, 0xCE, 0xDA, 0x3D, 0x3D, 0xDD, 0xB3, 0xF6, 0xEC, 0xDA, 0x46, 0x1A, 0xA1, 0x0D, 0xA1, 0x65, 
+  0x8C, 0x30, 0x94, 0x04, 0x8C, 0x25, 0x90, 0xC0, 0x06, 0x51, 0x91, 0x64, 0x04, 0xA2, 0x2C, 0x88, 0x21, 0x18, 0x12, 0x0C, 
+  0x49, 0x2C, 0x82, 0x4C, 0xC0, 0x31, 0x06, 0x93, 0x18, 0x2A, 0x94, 0x43, 0x62, 0xA8, 0x72, 0x01, 0x55, 0x10, 0x6C, 0x19, 
+  0xA4, 0xC9, 0x77, 0xDF, 0x1D, 0x35, 0x63, 0xC7, 0x5D, 0xA7, 0x5E, 0xBD, 0x7E, 0xCB, 0x3D, 0xFF, 0xFD, 0xCF, 0x39, 0xFF, 
+  0x39, 0xDD, 0x0B, 0xC6, 0xFA, 0xB7, 0x28, 0xEA, 0x67, 0xC1, 0x95, 0xD9, 0x2B, 0x0B, 0xC4, 0xC9, 0xEC, 0x15, 0xBE, 0xCC, 
+  0xF2, 0x91, 0xD7, 0x95, 0xD9, 0x05, 0xB3, 0x0A, 0x97, 0xAE, 0x88, 0x4B, 0x7C, 0x16, 0x28, 0x0B, 0xAF, 0x28, 0xB3, 0xD7, 
+  0x88, 0x27, 0xB8, 0xB9, 0x70, 0xE1, 0xC2, 0xEB, 0xAE, 0xBB, 0x6E, 0xE1, 0x82, 0xD9, 0x25, 0x37, 0x2C, 0xF9, 0xFA, 0x4F, 
+  0xB3, 0x57, 0xAE, 0x5C, 0xF9, 0xD3, 0x1F, 0xFE, 0xF8, 0xD5, 0xA5, 0x3F, 0x7E, 0xF3, 0xCD, 0x37, 0xCA, 0x65, 0xF1, 0x8A, 
+  0x82, 0x2D, 0x10, 0x9F, 0x85, 0x8B, 0x16, 0x70, 0xF7, 0xEB, 0xCB, 0xB3, 0x0B, 0x2E, 0x5F, 0x11, 0x37, 0x38, 0xB0, 0xB6, 
+  0x58, 0xE4, 0x9A, 0x05, 0xCA, 0x37, 0x72, 0xB5, 0xCB, 0xF8, 0x1E, 0xE9, 0xDD, 0x24, 0x2D, 0xD9, 0xB3, 0x61, 0xB8, 0x67, 
+  0x23, 0x36, 0x94, 0xD8, 0x30, 0x14, 0xDF, 0x38, 0x98, 0x98, 0x48, 0xC6, 0xC7, 0x92, 0x71, 0x8E, 0x13, 0x03, 0x5D, 0xE3, 
+  0x83, 0xDD, 0xA3, 0x03, 0xB1, 0x91, 0xFE, 0xAE, 0x61, 0x69, 0x7D, 0xD1, 0xA1, 0xDE, 0xAE, 0x21, 0x4E, 0x46, 0x7B, 0xC6, 
+  0x26, 0x7A, 0x27, 0x4E, 0x3D, 0x76, 0xFA, 0xE3, 0x8F, 0x3F, 0x7E, 0xFD, 0xB5, 0x8B, 0x7B, 0x77, 0xEE, 0x9B, 0x1C, 0xD9, 
+  0x92, 0x8C, 0x0D, 0xF5, 0xB4, 0xF5, 0xC7, 0x5B, 0x7A, 0x63, 0xA1, 0x44, 0x77, 0x28, 0xC1, 0x49, 0x5F, 0x67, 0x6F, 0xC4, 
+  0x17, 0xE9, 0x0A, 0x74, 0xF5, 0xB4, 0xF6, 0x44, 0x03, 0x89, 0x88, 0x3F, 0xD6, 0xE1, 0xEB, 0xC4, 0xB8, 0xD8, 0xDE, 0xDC, 
+  0xD1, 0xD1, 0xD4, 0xD1, 0xD6, 0xD4, 0xDE, 0xEA, 0x6D, 0xC3, 0x14, 0xDC, 0x4B, 0x10, 0xB8, 0xC7, 0x2B, 0xEE, 0x39, 0x0E, 
+  0x76, 0x8F, 0x0F, 0xC4, 0xC6, 0x40, 0xC0, 0x51, 0x20, 0x88, 0x8E, 0xF5, 0xC5, 0x86, 0xB1, 0x44, 0x6C, 0xA8, 0x37, 0x92, 
+  0xEC, 0xE9, 0x1C, 0xEC, 0xEB, 0x18, 0xEC, 0x6D, 0x1F, 0xE0, 0x38, 0x10, 0xED, 0x4F, 0xC6, 0x06, 0x7F, 0xF5, 0xCB, 0x77, 
+  0x66, 0x67, 0x2F, 0xB3, 0xCB, 0xBF, 0x7B, 0xEE, 0x85, 0xF1, 0xBE, 0xB1, 0x91, 0xEE, 0x91, 0x78, 0xB8, 0x27, 0x16, 0x8C, 
+  0x47, 0x03, 0xDD, 0x9D, 0xC1, 0xEE, 0x78, 0x38, 0x1E, 0x68, 0xF4, 0xFD, 0xF8, 0x47, 0xCF, 0x3D, 0x74, 0xFF, 0x43, 0xCD, 
+  0x75, 0xDE, 0x58, 0x30, 0x06, 0x88, 0xCE, 0xE6, 0xCE, 0x8E, 0xA6, 0x36, 0x15, 0x4A, 0x2B, 0x38, 0x5A, 0x3C, 0xAD, 0x61, 
+  0x67, 0xB8, 0xC5, 0xD5, 0xA2, 0x0C, 0x26, 0x04, 0x0E, 0xE9, 0x7B, 0x20, 0x2E, 0x69, 0x18, 0xC5, 0xB7, 0xA4, 0x41, 0x30, 
+  0x11, 0x49, 0xF6, 0x46, 0x86, 0x53, 0x20, 0xC0, 0xD1, 0xDB, 0xD6, 0x9F, 0x68, 0xED, 0x63, 0xDF, 0xDD, 0xE1, 0x9E, 0x88, 
+  0xAF, 0xA3, 0xBF, 0x2B, 0x79, 0x6C, 0xE6, 0x04, 0x31, 0x02, 0x10, 0xC8, 0x46, 0xE3, 0xC3, 0xFD, 0x1D, 0xBD, 0x5D, 0x81, 
+  0xEE, 0xA8, 0xBF, 0x33, 0xEA, 0x8F, 0xE2, 0x9B, 0xDD, 0xBB, 0x2A, 0x1D, 0x67, 0x7F, 0x78, 0x6E, 0xCF, 0xD4, 0x1D, 0x8E, 
+  0xF2, 0x46, 0x10, 0x08, 0xF7, 0xDE, 0xB6, 0x90, 0x47, 0x9C, 0x60, 0x9C, 0x04, 0x3C, 0x2D, 0x41, 0x77, 0x4B, 0xC0, 0x1D, 
+  0x54, 0x54, 0xF7, 0x02, 0x41, 0x5F, 0x2C, 0x29, 0xDD, 0xAB, 0xC7, 0xE1, 0x44, 0xC7, 0x80, 0x04, 0x21, 0x8E, 0x80, 0x50, 
+  0x71, 0x10, 0x88, 0x44, 0x4B, 0xAF, 0x84, 0xD2, 0x05, 0x01, 0xC1, 0x48, 0x53, 0xAD, 0x07, 0x40, 0x5B, 0x37, 0x6E, 0x3B, 
+  0x7F, 0xF6, 0x3C, 0x80, 0xFE, 0xF9, 0x1F, 0x5F, 0x4B, 0xB4, 0xC5, 0xC1, 0xD1, 0xE1, 0x6B, 0x57, 0xAD, 0x13, 0xC7, 0x4D, 
+  0xF6, 0x66, 0x67, 0x95, 0xA3, 0x58, 0x6B, 0xAD, 0xB3, 0xD5, 0x72, 0xE2, 0x77, 0x05, 0x70, 0x8C, 0xFB, 0xA0, 0x27, 0xC4, 
+  0xD1, 0xEF, 0x09, 0xF2, 0x35, 0xE0, 0x0A, 0x07, 0xDC, 0x01, 0x6E, 0x29, 0xF8, 0x56, 0xA3, 0x30, 0x24, 0xDD, 0xCB, 0x58, 
+  0xCC, 0x59, 0x5B, 0xBF, 0x00, 0xD1, 0xDA, 0x07, 0x1F, 0x82, 0x92, 0x70, 0x0F, 0x68, 0x80, 0x12, 0x0B, 0x77, 0xC7, 0x02, 
+  0x3D, 0x9D, 0xFE, 0x48, 0x4B, 0x73, 0xAB, 0xBB, 0xDE, 0xD3, 0x50, 0x56, 0x7F, 0xE7, 0xEE, 0xEF, 0x8E, 0xF5, 0x6F, 0x38, 
+  0x77, 0xF6, 0xFC, 0xF7, 0x0E, 0x3F, 0x14, 0xB4, 0xFB, 0x83, 0x8D, 0xBE, 0x60, 0x53, 0x58, 0xEE, 0x1E, 0x67, 0x1E, 0xBB, 
+  0xB7, 0xDA, 0x56, 0x1D, 0xF6, 0xB5, 0x36, 0xD6, 0xD8, 0xEB, 0xCA, 0xEB, 0x9A, 0x1C, 0x81, 0x66, 0x97, 0x5F, 0x60, 0xF2, 
+  0x84, 0x38, 0x02, 0x42, 0x9A, 0xCF, 0xE9, 0xC7, 0x94, 0x94, 0x7B, 0x1C, 0x43, 0x80, 0x34, 0x89, 0x00, 0xF7, 0x12, 0x87, 
+  0xA4, 0x24, 0x1A, 0x4E, 0x90, 0xA4, 0x18, 0x99, 0x41, 0x56, 0x46, 0x9A, 0x3A, 0x59, 0x8E, 0x25, 0x0A, 0xB3, 0xF3, 0x87, 
+  0x06, 0x36, 0x6E, 0x1A, 0xBD, 0x7D, 0xB0, 0x2B, 0x99, 0x68, 0x49, 0xD4, 0x57, 0x34, 0x34, 0x56, 0x35, 0xCE, 0xD1, 0xE0, 
+  0x09, 0x71, 0xE2, 0x75, 0x34, 0x01, 0x08, 0xAB, 0xB0, 0x56, 0x38, 0xEB, 0xDD, 0x5E, 0x47, 0x33, 0x6F, 0xCD, 0x07, 0x21, 
+  0xA1, 0x34, 0x3B, 0x7C, 0x98, 0x92, 0x68, 0x1D, 0x50, 0x4D, 0xE5, 0x40, 0x0D, 0x87, 0x04, 0x01, 0x02, 0x41, 0x46, 0x28, 
+  0x41, 0x68, 0x24, 0x08, 0x4E, 0x44, 0x98, 0xFC, 0x31, 0x91, 0xAA, 0xFE, 0x08, 0x99, 0x11, 0x72, 0x05, 0x59, 0xC2, 0x6A, 
+  0x30, 0x97, 0x17, 0x57, 0xEC, 0xD8, 0x76, 0xB0, 0xB6, 0xA4, 0xAE, 0xCC, 0x5C, 0xD6, 0x50, 0xD9, 0x50, 0x53, 0x5A, 0xE3, 
+  0x6D, 0x6C, 0xC2, 0x87, 0x8C, 0x02, 0x21, 0xF3, 0xD4, 0xBA, 0x6B, 0xCB, 0xEA, 0xEC, 0x55, 0x2E, 0x18, 0x05, 0x1F, 0x6F, 
+  0xA5, 0x10, 0x48, 0x1C, 0x3C, 0x23, 0x4D, 0x89, 0xB7, 0xF4, 0x4B, 0xDF, 0x29, 0x04, 0x12, 0xC4, 0x7C, 0x03, 0xC1, 0x55, 
+  0x4B, 0x00, 0x48, 0xD0, 0xE3, 0x13, 0x80, 0x60, 0xC8, 0xDB, 0xE8, 0x6D, 0xAC, 0xA8, 0xCD, 0x5A, 0x9F, 0x39, 0x3A, 0xB4, 
+  0xC5, 0x59, 0xEF, 0x32, 0x14, 0x68, 0xEA, 0x2A, 0x1B, 0xC0, 0xE7, 0x69, 0xF0, 0x48, 0xAF, 0x00, 0x6A, 0x76, 0xF9, 0x78, 
+  0xCC, 0xD3, 0xE0, 0x15, 0x68, 0x1A, 0x05, 0x9A, 0xF9, 0x26, 0x71, 0x70, 0x5D, 0x9A, 0xF2, 0x17, 0xBE, 0x65, 0xAD, 0x0A, 
+  0x83, 0x09, 0xE1, 0xB8, 0xAB, 0xD3, 0xD7, 0x85, 0x7B, 0x28, 0xE1, 0x84, 0x2B, 0xE8, 0x0A, 0xCF, 0x48, 0xFD, 0x08, 0xBB, 
+  0x5B, 0xF0, 0xE4, 0xAC, 0x75, 0xE5, 0x65, 0xE4, 0x34, 0x7B, 0xC2, 0x6D, 0x81, 0x48, 0x7E, 0x66, 0x6E, 0x55, 0x69, 0x75, 
+  0xB9, 0xA5, 0x9C, 0x8B, 0xB8, 0x91, 0x98, 0x30, 0xD5, 0x6B, 0x93, 0x6A, 0x73, 0x4C, 0xCC, 0x07, 0x21, 0xA1, 0x48, 0xC4, 
+  0x0A, 0xF5, 0x89, 0x54, 0xA8, 0x69, 0x11, 0x17, 0x5B, 0x57, 0x8F, 0x94, 0x09, 0x06, 0x82, 0x36, 0x21, 0x5F, 0xED, 0x68, 
+  0x86, 0x94, 0x2F, 0x4E, 0xC2, 0xCE, 0x56, 0x6E, 0xF5, 0x53, 0xEC, 0xBE, 0x68, 0xC8, 0x1B, 0x66, 0xF7, 0xA4, 0x85, 0x45, 
+  0x5F, 0x64, 0x35, 0x16, 0x47, 0x5B, 0xE3, 0xB9, 0xE9, 0x99, 0xD0, 0x53, 0x66, 0x2D, 0x77, 0xD4, 0x38, 0xBD, 0x76, 0xB7, 
+  0x60, 0xC2, 0x35, 0x97, 0x1C, 0x02, 0x81, 0xE3, 0xAF, 0xA0, 0x91, 0x38, 0xA4, 0xB9, 0xEA, 0xDC, 0xCA, 0xB7, 0x1C, 0xA8, 
+  0x64, 0x48, 0x93, 0x32, 0x2A, 0x4D, 0x6A, 0x28, 0xD5, 0xEB, 0xB7, 0xFB, 0x20, 0xE6, 0xFC, 0x53, 0xCF, 0x4C, 0x8D, 0x6F, 
+  0x6B, 0xF3, 0xB4, 0x20, 0x89, 0x5D, 0x81, 0x08, 0x11, 0x71, 0x35, 0xB8, 0xAB, 0x4A, 0xAA, 0x35, 0xB9, 0x85, 0xED, 0x2D, 
+  0x51, 0x6D, 0x6E, 0x61, 0xA9, 0xA5, 0xAC, 0xA2, 0xB8, 0x0C, 0x40, 0x44, 0x4D, 0x50, 0xE2, 0x14, 0x01, 0xF2, 0x39, 0x45, 
+  0x96, 0xA4, 0xE2, 0xE2, 0xB1, 0x0B, 0x3E, 0x52, 0x50, 0xC0, 0x01, 0xA3, 0x18, 0x6F, 0x01, 0x28, 0xC2, 0xBE, 0x29, 0x19, 
+  0x7C, 0x0B, 0xF5, 0x54, 0x8F, 0xF0, 0x21, 0x05, 0xAD, 0xD5, 0xD3, 0x41, 0xE9, 0xAA, 0xF5, 0x19, 0xE0, 0x85, 0x86, 0xCA, 
+  0xC6, 0x03, 0xBB, 0x0F, 0xBC, 0xF3, 0xF6, 0xBB, 0x33, 0xF7, 0xCE, 0xB4, 0x37, 0xB7, 0x25, 0x5A, 0x84, 0x0A, 0x07, 0x9D, 
+  0x7E, 0x47, 0xA5, 0x5D, 0x9B, 0xA7, 0xC1, 0x77, 0x9D, 0xAD, 0xA6, 0xBE, 0xA2, 0xBE, 0xA2, 0xA4, 0xD2, 0x5D, 0xA3, 0xE6, 
+  0x6F, 0xE3, 0x9F, 0xC5, 0xC8, 0xD7, 0x08, 0x49, 0xDF, 0x46, 0x07, 0x1C, 0x29, 0x28, 0x12, 0x8D, 0x00, 0xD4, 0xD2, 0xD4, 
+  0x8E, 0xE3, 0x79, 0x26, 0x84, 0x9C, 0xAF, 0x5C, 0x0F, 0x7B, 0x3B, 0x38, 0x07, 0x0D, 0xDA, 0x05, 0x3D, 0xEE, 0xBA, 0xA6, 
+  0x32, 0x63, 0x69, 0xA9, 0xC1, 0x36, 0x31, 0xB8, 0xE9, 0xAD, 0x8B, 0x6F, 0xBE, 0xF9, 0xE6, 0x1B, 0xD3, 0xBB, 0x0E, 0xC4, 
+  0xC3, 0x31, 0x60, 0xD1, 0x04, 0x50, 0x23, 0xA0, 0xEF, 0xDF, 0x75, 0x60, 0xFF, 0xCE, 0x69, 0x7B, 0x99, 0x9D, 0xDC, 0x12, 
+  0x85, 0x26, 0x4C, 0x84, 0x49, 0x66, 0x31, 0xE7, 0x92, 0x18, 0x69, 0xF3, 0x89, 0x91, 0x68, 0xEC, 0xD5, 0x0E, 0x85, 0x55, 
+  0x64, 0x2B, 0x91, 0x12, 0x2E, 0x8E, 0xDE, 0x30, 0x27, 0x32, 0x4C, 0xE1, 0xA6, 0x16, 0x7F, 0x53, 0x18, 0x40, 0x42, 0x6D, 
+  0x55, 0x86, 0xCC, 0x85, 0x86, 0xC2, 0xAC, 0xC2, 0x48, 0x28, 0xF6, 0xDC, 0xF9, 0xE7, 0x2F, 0x5F, 0xBE, 0xFC, 0xDA, 0x6B, 
+  0xAF, 0x6F, 0x9F, 0x98, 0x1A, 0x49, 0x0C, 0x0F, 0xC7, 0x93, 0xDB, 0x36, 0x4C, 0x7D, 0xF0, 0xC1, 0x7F, 0xFE, 0xE2, 0xCD, 
+  0xB7, 0x81, 0xD8, 0xE6, 0x0D, 0x8B, 0x30, 0x39, 0xBD, 0xEC, 0x24, 0xE8, 0x0C, 0xB4, 0xBA, 0x85, 0x10, 0xAB, 0x57, 0xA8, 
+  0x38, 0xE2, 0x25, 0xD2, 0x25, 0xC5, 0x4A, 0x63, 0x95, 0x1D, 0x28, 0x18, 0x27, 0x4A, 0xD8, 0x1D, 0x82, 0x03, 0x10, 0xC8, 
+  0x56, 0x22, 0xE4, 0xBC, 0x29, 0x0C, 0x8E, 0x4E, 0x7F, 0x47, 0x2C, 0xDC, 0x45, 0x7F, 0xA6, 0xF5, 0x70, 0x9D, 0xE4, 0x65, 
+  0x09, 0x00, 0x21, 0xB5, 0x60, 0xCA, 0x5C, 0x9F, 0xC6, 0x2B, 0x27, 0x66, 0x1E, 0xFE, 0xEA, 0xAB, 0x2F, 0x3F, 0xFF, 0xFC, 
+  0xF3, 0xA7, 0x4E, 0x3D, 0x75, 0xF2, 0x91, 0xC7, 0xFF, 0xE3, 0xBD, 0xDF, 0xD0, 0x3D, 0x2E, 0x5D, 0xBA, 0x74, 0xE4, 0xD0, 
+  0x91, 0xDE, 0xB6, 0x44, 0xBB, 0xA7, 0x25, 0xE0, 0xF0, 0x87, 0x9D, 0xC1, 0xCE, 0xE6, 0xF6, 0x56, 0x57, 0x88, 0x10, 0xB3, 
+  0xB2, 0xCF, 0x4D, 0xC5, 0x11, 0x35, 0x91, 0xC8, 0x12, 0x90, 0xC4, 0x81, 0xB1, 0x38, 0xA6, 0xA4, 0xC4, 0x5B, 0x6A, 0x06, 
+  0xFB, 0x08, 0x78, 0x83, 0xF4, 0x04, 0xF6, 0xC4, 0x5A, 0xDD, 0xA1, 0xAE, 0xBE, 0xF6, 0x1E, 0x56, 0x64, 0x69, 0x77, 0xA3, 
+  0x97, 0xF7, 0xD1, 0x37, 0x34, 0xB7, 0x48, 0xAB, 0x5F, 0x75, 0xCB, 0xAD, 0x91, 0xD6, 0xAE, 0xC3, 0x77, 0xDF, 0xF7, 0xC9, 
+  0x27, 0x9F, 0xA8, 0xE3, 0x0D, 0x9F, 0x6F, 0xBE, 0xFE, 0xFA, 0x6B, 0xCE, 0xDF, 0xFD, 0xD5, 0xAF, 0xB7, 0x0C, 0x6F, 0x1E, 
+  0x89, 0x25, 0x7B, 0x5A, 0xBA, 0x07, 0x3A, 0xFB, 0x06, 0x23, 0xFD, 0x87, 0xEF, 0x3A, 0xBC, 0x71, 0x70, 0xA2, 0xA7, 0x35, 
+  0xCE, 0xF6, 0x20, 0x2C, 0xE8, 0x22, 0x76, 0x1E, 0x7B, 0xED, 0x1C, 0x2B, 0x12, 0x0A, 0x86, 0xCA, 0x2B, 0x52, 0x27, 0xE6, 
+  0x8B, 0x37, 0xB0, 0xDC, 0x55, 0xCE, 0x1D, 0x1B, 0x6F, 0x7F, 0xE9, 0xF9, 0x17, 0x0F, 0xEE, 0x99, 0xA6, 0x94, 0x08, 0x01, 
+  0x98, 0x44, 0x4A, 0xD6, 0xB8, 0xD9, 0x0A, 0x42, 0x5C, 0x55, 0x52, 0x65, 0x28, 0xD0, 0xDD, 0x76, 0xEB, 0x8A, 0x8D, 0x23, 
+  0x93, 0x7B, 0x6F, 0xDF, 0xFB, 0xC6, 0xC5, 0xB7, 0x7E, 0xF7, 0xBB, 0x4F, 0xDE, 0xFF, 0xCD, 0x87, 0xFF, 0xFE, 0xDE, 0x07, 
+  0xBF, 0xFF, 0xFD, 0xA7, 0x8C, 0x22, 0xAF, 0xBC, 0xFC, 0xEA, 0xD6, 0x89, 0x6D, 0xDB, 0x27, 0xB6, 0x4D, 0x8E, 0x4F, 0x7E, 
+  0x7F, 0xE6, 0x61, 0x50, 0x3E, 0xFB, 0xF4, 0xDF, 0x4E, 0xF4, 0x33, 0x3C, 0x8D, 0xC5, 0x82, 0x51, 0x9A, 0xBF, 0xB3, 0xC2, 
+  0xCE, 0xF6, 0x40, 0x20, 0x71, 0xD4, 0x95, 0xD7, 0x53, 0x0D, 0x1C, 0x95, 0x94, 0x68, 0x5E, 0xD5, 0x89, 0x26, 0x7B, 0xB5, 
+  0xDD, 0x53, 0xDF, 0x3C, 0x39, 0xBE, 0xF5, 0xDD, 0x77, 0xDF, 0x63, 0xA1, 0x7F, 0xB9, 0xF0, 0x3A, 0x29, 0xE2, 0xAB, 0xF3, 
+  0x86, 0x9C, 0x7E, 0x77, 0xBD, 0xDB, 0x5E, 0xE3, 0x6E, 0xA8, 0x70, 0x50, 0x4D, 0x50, 0x95, 0xB1, 0x66, 0x9D, 0xC7, 0xE9, 
+  0xDB, 0x3C, 0x32, 0x15, 0x6F, 0xED, 0x26, 0x97, 0xEF, 0xBF, 0x77, 0xE6, 0xF1, 0x47, 0x4F, 0xBF, 0xFA, 0xCA, 0x85, 0x2F, 
+  0xBF, 0xFC, 0x52, 0x8E, 0x22, 0x0C, 0x6E, 0x3F, 0x7E, 0xF6, 0xB9, 0x2F, 0xBE, 0xF8, 0x82, 0xAF, 0xFF, 0xFB, 0x87, 0xAF, 
+  0x9E, 0x7E, 0xE2, 0x47, 0xFB, 0x76, 0xEE, 0xDF, 0x3A, 0xB1, 0xF5, 0xFB, 0x0F, 0x3E, 0x7C, 0xF4, 0xF0, 0x31, 0x51, 0x8F, 
+  0xD6, 0x8A, 0xBA, 0xCA, 0x7A, 0x96, 0x22, 0x13, 0xB0, 0xDA, 0xB2, 0x5A, 0x45, 0xEC, 0x5B, 0x55, 0x49, 0x21, 0x12, 0x75, 
+  0x22, 0xD7, 0xAA, 0x2B, 0xEB, 0x4C, 0x46, 0x7D, 0x77, 0x47, 0xEF, 0x68, 0xDF, 0xC4, 0xF7, 0x8E, 0x1C, 0xFB, 0xB7, 0xB7, 
+  0x7E, 0xF9, 0xFE, 0xFB, 0xEF, 0x43, 0x03, 0xC3, 0x83, 0xC8, 0xC4, 0x7A, 0xEA, 0xD9, 0x0D, 0x85, 0xEC, 0xD2, 0x92, 0x5F, 
+  0xE4, 0xAD, 0xF5, 0x35, 0x37, 0xF8, 0x98, 0x72, 0xBA, 0x42, 0xB1, 0x81, 0xE8, 0xE0, 0xA6, 0xE1, 0xC9, 0xC3, 0x87, 0x1E, 
+  0xF8, 0xC9, 0xF3, 0xFF, 0xA0, 0x82, 0x60, 0x64, 0x53, 0xC7, 0xD8, 0xAB, 0x1F, 0x82, 0xFA, 0xD9, 0x67, 0x9F, 0x71, 0x7C, 
+  0xE3, 0xE2, 0xBF, 0x92, 0xA3, 0x26, 0x8D, 0x81, 0xE8, 0xB3, 0x37, 0x28, 0x07, 0x8A, 0x38, 0x96, 0x57, 0x2B, 0x12, 0x8D, 
+  0xD4, 0x28, 0xA1, 0x4E, 0x55, 0x0E, 0x78, 0x43, 0xDF, 0x6E, 0xBE, 0x69, 0xB9, 0x26, 0x2F, 0xBF, 0xA6, 0xBC, 0xCE, 0xE7, 
+  0x0A, 0x4D, 0x8E, 0x4D, 0xDD, 0x7D, 0xF0, 0x1E, 0x31, 0x3C, 0xD8, 0x6A, 0xA1, 0xD7, 0xDF, 0xD0, 0xCC, 0x08, 0x36, 0x92, 
+  0x18, 0xDA, 0x33, 0xB5, 0x67, 0xFA, 0x8E, 0x69, 0xC8, 0x2F, 0xB3, 0x42, 0x9A, 0xCB, 0x6B, 0x0F, 0xB6, 0xF9, 0x98, 0x29, 
+  0x27, 0xB6, 0x6F, 0xDC, 0xF9, 0xD0, 0xCC, 0x89, 0xD7, 0x7E, 0x76, 0xF1, 0xB7, 0x1F, 0xFE, 0xF7, 0x47, 0x1F, 0xFD, 0xCF, 
+  0x87, 0x1F, 0xFE, 0xF6, 0xA3, 0xFF, 0xFA, 0xF8, 0xD3, 0x4F, 0x3F, 0xBF, 0x74, 0xE9, 0x0F, 0x60, 0x7B, 0xF5, 0xEF, 0x5F, 
+  0x41, 0x54, 0x4D, 0xF9, 0x3A, 0x5B, 0x51, 0x71, 0x65, 0x71, 0x25, 0xD1, 0x07, 0x16, 0x68, 0x30, 0x4E, 0x14, 0x21, 0x5F, 
+  0x2A, 0x31, 0xB2, 0x0E, 0x49, 0x11, 0x18, 0x82, 0x49, 0x7D, 0x7E, 0x21, 0x69, 0x7B, 0xE3, 0xB2, 0x1B, 0x56, 0xDC, 0x7C, 
+  0x53, 0xDA, 0xBA, 0x74, 0xB3, 0xB1, 0x04, 0xB9, 0x2B, 0x31, 0x59, 0x2B, 0x8B, 0xAB, 0x18, 0xFC, 0xC8, 0x98, 0xAB, 0x23, 
+  0xE2, 0xAF, 0x19, 0x93, 0x59, 0xB4, 0xBE, 0xAA, 0x91, 0xAC, 0xEF, 0xEA, 0x48, 0x32, 0xEE, 0x0D, 0xC4, 0xC7, 0x37, 0x0D, 
+  0x6F, 0xDB, 0xBE, 0x79, 0xD7, 0xBE, 0x5D, 0xD3, 0x0F, 0xDC, 0x7B, 0xEC, 0xFE, 0x7B, 0x8E, 0x1E, 0x7D, 0xE0, 0xF8, 0x63, 
+  0xC7, 0x4F, 0x9E, 0x3D, 0xF3, 0xF4, 0x83, 0x0F, 0x1C, 0x1F, 0xEA, 0x4E, 0x46, 0xDB, 0x62, 0x05, 0x59, 0x79, 0x78, 0xA1, 
+  0xEB, 0x49, 0x40, 0xD5, 0xA5, 0x95, 0x72, 0x44, 0x51, 0xE6, 0xCB, 0x25, 0x59, 0x06, 0x20, 0x18, 0xE2, 0xA1, 0x32, 0x73, 
+  0xB9, 0xCD, 0x64, 0x2B, 0x36, 0x14, 0x43, 0x2C, 0x2F, 0xE7, 0x64, 0x64, 0x92, 0xC5, 0x00, 0xA2, 0x67, 0xF5, 0x44, 0x93, 
+  0xBB, 0xA7, 0xEE, 0x3C, 0x76, 0xFF, 0x83, 0x3F, 0x38, 0xFE, 0xE8, 0xD6, 0xE1, 0xAD, 0x84, 0x8C, 0xC4, 0x6C, 0xAC, 0x71, 
+  0xD0, 0xD4, 0x90, 0x99, 0xA0, 0xB7, 0x3D, 0xDC, 0x1C, 0x8D, 0xB6, 0xF6, 0xF5, 0x77, 0x8F, 0x0D, 0xF7, 0x6D, 0x60, 0x5A, 
+  0x1F, 0xE9, 0xDF, 0x48, 0x9E, 0x8D, 0x0D, 0x6E, 0x1E, 0x4F, 0x6E, 0xE9, 0x8D, 0x0C, 0x78, 0xAA, 0x5D, 0x3C, 0x66, 0xD0, 
+  0xE9, 0x6B, 0xAC, 0x95, 0x60, 0x62, 0x87, 0xF4, 0x63, 0x9A, 0x4F, 0xA5, 0xAD, 0x0A, 0xBF, 0x4A, 0x4A, 0x9D, 0x52, 0xD2, 
+  0x94, 0xAA, 0x23, 0xE0, 0x97, 0x16, 0x95, 0x42, 0x2C, 0x53, 0x4E, 0xA9, 0xA5, 0x9C, 0xAF, 0x58, 0x7E, 0x76, 0xCE, 0xBA, 
+  0x35, 0x6B, 0xE3, 0x9D, 0x03, 0xBB, 0x77, 0xDE, 0xC5, 0xC4, 0x12, 0x76, 0xB5, 0x09, 0x21, 0xA9, 0x71, 0xD4, 0x94, 0xD7, 
+  0x36, 0x54, 0xDB, 0xC1, 0x04, 0x4F, 0x58, 0xB3, 0x3D, 0xD0, 0xCA, 0x40, 0x1D, 0xEE, 0x69, 0x0B, 0x77, 0x73, 0x12, 0xF2, 
+  0x47, 0x82, 0x8E, 0xB6, 0x90, 0xB3, 0x35, 0xE4, 0x0A, 0x33, 0x1B, 0x39, 0x6A, 0x1C, 0x6C, 0xCF, 0x58, 0x60, 0xAC, 0xB2, 
+  0x55, 0xC0, 0x4A, 0x55, 0x69, 0x25, 0x68, 0x08, 0x5F, 0x85, 0xB5, 0x52, 0x49, 0x69, 0xB6, 0x04, 0x24, 0x8B, 0x90, 0xFC, 
+  0x27, 0xCB, 0xC4, 0xA3, 0x25, 0xE2, 0x39, 0x69, 0xEC, 0x06, 0x64, 0x90, 0x94, 0x95, 0x96, 0xCE, 0x6F, 0xA8, 0xF1, 0x91, 
+  0x2D, 0x07, 0xF6, 0x1D, 0xF1, 0x39, 0xC2, 0x0C, 0x40, 0xB4, 0x77, 0x10, 0xDB, 0xCC, 0x65, 0xD5, 0x65, 0xB5, 0x55, 0xA5, 
+  0x35, 0xE5, 0xA4, 0x6A, 0x65, 0x03, 0x41, 0xAC, 0xAD, 0xA8, 0x27, 0xB7, 0x40, 0x09, 0x62, 0x3A, 0x8F, 0xE8, 0xFC, 0xCE, 
+  0x20, 0x7B, 0xD8, 0xB9, 0x69, 0xD7, 0x03, 0x47, 0x8E, 0xF9, 0x5D, 0x7E, 0x8B, 0xC1, 0x4A, 0x10, 0xAC, 0x7A, 0x2B, 0xD1, 
+  0x60, 0xE7, 0xB8, 0x50, 0x52, 0xC4, 0xD0, 0x20, 0xA5, 0x5C, 0xD6, 0x97, 0xDB, 0xA5, 0x30, 0xCC, 0x65, 0xBE, 0x9A, 0xFF, 
+  0xA9, 0x19, 0x94, 0x37, 0x4B, 0x8C, 0x25, 0xA4, 0x57, 0xB1, 0xA5, 0x74, 0xCF, 0xAE, 0x43, 0x38, 0x80, 0x1B, 0x92, 0x1A, 
+  0x34, 0x56, 0x63, 0x09, 0x66, 0x31, 0x14, 0x9B, 0xF5, 0x16, 0xE1, 0xC9, 0x68, 0x29, 0x36, 0x95, 0x70, 0x4B, 0x88, 0x4D, 
+  0xB5, 0x88, 0xA9, 0xB7, 0x21, 0xD0, 0x19, 0xEE, 0xE9, 0x08, 0xC4, 0xFD, 0xCE, 0xD0, 0xD4, 0x86, 0x1D, 0xF7, 0x4C, 0x1F, 
+  0x21, 0x82, 0x2D, 0x9E, 0x70, 0x5F, 0xF7, 0x00, 0xBC, 0xB0, 0x2C, 0xBB, 0x55, 0xA4, 0x6C, 0x33, 0x05, 0x8B, 0x3C, 0x90, 
+  0x80, 0x04, 0x43, 0xC2, 0x54, 0x4C, 0x42, 0x1B, 0xE4, 0x11, 0x58, 0xF0, 0x24, 0x83, 0x98, 0xBD, 0x3E, 0xBD, 0xD9, 0x13, 
+  0x1C, 0xEC, 0xDD, 0x44, 0x98, 0xC4, 0x5A, 0x45, 0x36, 0x89, 0xC3, 0x90, 0x6F, 0xD0, 0xE5, 0xEA, 0xB4, 0x39, 0x5A, 0x4D, 
+  0xB6, 0x46, 0x93, 0xAB, 0xD5, 0xE5, 0xEB, 0x4D, 0x5A, 0x23, 0x77, 0xA1, 0xD0, 0x5E, 0xEB, 0x6C, 0x76, 0x86, 0x49, 0xF9, 
+  0xDD, 0x3B, 0x0F, 0x1D, 0xBE, 0xEF, 0x91, 0xCE, 0xF6, 0xDE, 0xF4, 0xF5, 0x59, 0x85, 0xF9, 0x05, 0x56, 0xB3, 0xAD, 0xAE, 
+  0xD6, 0xC1, 0x3A, 0x66, 0x93, 0x85, 0x4A, 0x52, 0x50, 0xB9, 0x94, 0x6C, 0x4B, 0xDD, 0x14, 0x6C, 0x7F, 0x8B, 0xE9, 0x5B, 
+  0xC9, 0x92, 0x02, 0x0D, 0xAB, 0x0C, 0xD1, 0x56, 0x83, 0x09, 0xFE, 0x2B, 0x6D, 0xD5, 0xF8, 0x70, 0x3B, 0xFC, 0xE5, 0xC5, 
+  0x95, 0x24, 0x3B, 0x68, 0x18, 0xF8, 0x99, 0x1E, 0x73, 0xD2, 0xB2, 0x72, 0xD2, 0x32, 0x18, 0xD6, 0x72, 0x33, 0xF2, 0xE8, 
+  0xC4, 0x45, 0x9A, 0xA2, 0xB2, 0x92, 0xAA, 0x86, 0x2A, 0x27, 0x99, 0xBE, 0x61, 0x7C, 0xC7, 0xC3, 0xC7, 0xCF, 0xEC, 0xDE, 
+  0x71, 0xF0, 0xDA, 0x6B, 0xAF, 0xBD, 0x65, 0xC5, 0xF2, 0xF4, 0xB5, 0xEB, 0xD2, 0xD6, 0xAC, 0x5D, 0xBF, 0x7A, 0x4D, 0xE6, 
+  0xBA, 0x8C, 0xFC, 0xAC, 0x3C, 0x0A, 0x48, 0x51, 0x99, 0xA8, 0xAB, 0xAB, 0xA8, 0x61, 0x7E, 0x80, 0x12, 0x19, 0x29, 0xA9, 
+  0x9B, 0x52, 0x3A, 0xE5, 0x51, 0x46, 0x0D, 0x86, 0x08, 0xB9, 0x51, 0x63, 0x22, 0x25, 0x71, 0x56, 0x63, 0x6B, 0xEC, 0x89, 
+  0x8D, 0xF9, 0x9B, 0xDA, 0x49, 0x17, 0x38, 0xD0, 0x17, 0x50, 0x8F, 0x39, 0x39, 0xE9, 0xD9, 0xD9, 0xEB, 0x33, 0xB3, 0xD6, 
+  0xA5, 0xC1, 0x22, 0xC8, 0xB8, 0x62, 0xD2, 0x16, 0x21, 0x19, 0xA8, 0x14, 0x75, 0xB7, 0x7D, 0xF2, 0xE0, 0x23, 0x27, 0x7E, 
+  0xE8, 0x71, 0x06, 0x56, 0xDC, 0x78, 0x13, 0x0D, 0x51, 0xA4, 0x76, 0xA1, 0xDE, 0x50, 0xA8, 0x07, 0x8A, 0x59, 0x67, 0x2A, 
+  0xD2, 0x1A, 0x15, 0xE9, 0xEF, 0xAA, 0x63, 0x71, 0xAE, 0xCA, 0x94, 0x40, 0x30, 0x67, 0x65, 0xE8, 0x84, 0x40, 0x03, 0x3D, 
+  0x24, 0x10, 0x0F, 0xD4, 0x57, 0x35, 0x50, 0x47, 0x1B, 0xC6, 0xA6, 0xF6, 0xEF, 0x3B, 0xB2, 0x63, 0xFB, 0x34, 0x51, 0xF0, 
+  0x39, 0x5A, 0xC9, 0xA4, 0x22, 0x9D, 0x59, 0x97, 0xAF, 0x45, 0x23, 0xF2, 0x33, 0xB3, 0x31, 0xA8, 0xE2, 0x1C, 0x8D, 0x25, 
+  0x6A, 0xAC, 0x80, 0x66, 0x26, 0xFB, 0x36, 0x4D, 0x6D, 0xDD, 0x77, 0xCF, 0xDD, 0x0F, 0x76, 0x47, 0xFB, 0x69, 0x3B, 0x16, 
+  0x9D, 0x85, 0xC1, 0x01, 0x10, 0x20, 0x63, 0x08, 0x06, 0x10, 0xA6, 0xCC, 0xC9, 0x76, 0xF9, 0x9C, 0x56, 0x0A, 0x40, 0x65, 
+  0xB8, 0x17, 0x68, 0xE6, 0x6A, 0x52, 0x15, 0x2E, 0x59, 0x68, 0xEC, 0x83, 0x42, 0x23, 0x9D, 0xF5, 0x5A, 0x93, 0xA3, 0xC1, 
+  0xF3, 0xC8, 0x89, 0x33, 0x67, 0xCF, 0x3E, 0x47, 0xAD, 0x25, 0xFB, 0x26, 0x49, 0x58, 0xD2, 0x8B, 0x75, 0x09, 0x90, 0x49, 
+  0xA3, 0x23, 0x1B, 0xF8, 0x05, 0x42, 0x10, 0xF9, 0x4A, 0x11, 0x51, 0x62, 0xC9, 0xBE, 0xCD, 0x77, 0xEC, 0xFE, 0xEE, 0xA1, 
+  0x83, 0x33, 0xB7, 0x4F, 0x1D, 0xE8, 0x8B, 0x8F, 0xC3, 0x0A, 0xEE, 0xB9, 0xA5, 0x26, 0x80, 0x59, 0x9C, 0xE8, 0xAD, 0x94, 
+  0x82, 0x22, 0x65, 0x9B, 0x63, 0x6D, 0x89, 0x50, 0x27, 0x59, 0xE7, 0xE8, 0x0D, 0x8E, 0x49, 0x17, 0xBE, 0x4A, 0x93, 0x17, 
+  0x29, 0x9C, 0x8C, 0x75, 0xEB, 0x6F, 0xBA, 0x71, 0xD9, 0x75, 0xD7, 0x2E, 0xA6, 0xF2, 0x35, 0xF9, 0x86, 0xB3, 0x4F, 0x3C, 
+  0x7F, 0xE2, 0xC4, 0xE9, 0x5D, 0x3B, 0xBE, 0xD3, 0x1B, 0x1D, 0x0D, 0x3A, 0x43, 0x24, 0x80, 0x14, 0x88, 0x8A, 0xA2, 0x72, 
+  0x55, 0xF4, 0x44, 0x67, 0xA0, 0x26, 0xC2, 0x4D, 0x5D, 0x07, 0xEF, 0x3C, 0x72, 0xF2, 0xB1, 0xA7, 0x9F, 0x7C, 0xF2, 0xF9, 
+  0x13, 0x0F, 0x9D, 0x82, 0x2A, 0x39, 0x2F, 0x14, 0x9B, 0x6C, 0x24, 0x9F, 0xA8, 0x47, 0xA3, 0xC5, 0x66, 0xB0, 0x94, 0x1A, 
+  0x05, 0xA0, 0xB9, 0x70, 0x08, 0x97, 0xD6, 0x52, 0x6E, 0x40, 0x03, 0xDB, 0x92, 0x05, 0x05, 0x08, 0xC4, 0x4A, 0x35, 0x55, 
+  0x84, 0x8C, 0x25, 0xC5, 0xBA, 0x22, 0xA2, 0xCE, 0x48, 0x8F, 0x76, 0x2F, 0xBF, 0xF1, 0xE6, 0xFB, 0x0E, 0x3F, 0x72, 0xFA, 
+  0xF4, 0x33, 0x33, 0xF7, 0xFF, 0x00, 0x4C, 0x23, 0xFD, 0x9B, 0x3B, 0x9A, 0xA3, 0x08, 0xF7, 0xD5, 0xCA, 0xB5, 0xBB, 0x6B, 
+  0x3C, 0x0C, 0x0E, 0x41, 0x77, 0x47, 0xBC, 0x33, 0x09, 0xEE, 0xC7, 0x1F, 0x7F, 0x1A, 0x85, 0x84, 0x5D, 0xAF, 0x27, 0x10, 
+  0x69, 0x4F, 0x58, 0x8D, 0x16, 0x96, 0xA2, 0x66, 0xD5, 0x06, 0x20, 0x30, 0x91, 0xA0, 0x8A, 0x24, 0x40, 0xB6, 0x15, 0x8B, 
+  0xDE, 0xC8, 0x0F, 0x6F, 0xE6, 0x26, 0x46, 0x02, 0x7C, 0x43, 0xA9, 0x0A, 0xA8, 0x42, 0x1A, 0x80, 0x78, 0x19, 0x7A, 0x81, 
+  0x4B, 0xE0, 0xF3, 0x32, 0xB2, 0x48, 0xD5, 0x93, 0x27, 0xCF, 0xBD, 0xFC, 0xCA, 0x5B, 0x2F, 0xBE, 0x78, 0xE1, 0xD1, 0x47, 
+  0x9F, 0xDC, 0xB5, 0xEB, 0xAE, 0xB1, 0xA1, 0x6D, 0xC0, 0x4A, 0x44, 0x86, 0x22, 0xA1, 0x78, 0xA7, 0xAF, 0xBB, 0xAB, 0xAD, 
+  0x7F, 0xA8, 0x77, 0xE3, 0x50, 0xFF, 0xE6, 0x1D, 0x3B, 0xA6, 0x9F, 0x38, 0xF7, 0x02, 0xBF, 0xDD, 0xF8, 0x7B, 0x6A, 0xD1, 
+  0x42, 0xF1, 0xBF, 0x18, 0xD1, 0xE9, 0x6E, 0xEB, 0x11, 0xA9, 0xA3, 0x35, 0x4B, 0x86, 0x30, 0xA2, 0x26, 0x00, 0x49, 0x34, 
+  0x34, 0xAF, 0xA2, 0x02, 0xBD, 0xD9, 0x54, 0x8C, 0x9A, 0x15, 0x64, 0xE7, 0x6B, 0x72, 0x0A, 0xC0, 0x5B, 0x66, 0xB1, 0x71, 
+  0x1D, 0x13, 0x0F, 0x88, 0xF3, 0x32, 0xF2, 0x9A, 0x6D, 0x91, 0xAA, 0xDA, 0xAC, 0xFC, 0xBE, 0xC4, 0xE8, 0xE8, 0xD0, 0xA6, 
+  0x1D, 0x53, 0xFB, 0x5E, 0x7C, 0xE1, 0x67, 0xAF, 0xBF, 0xF1, 0x0E, 0xE1, 0x80, 0xB0, 0x83, 0xFB, 0x8F, 0x1C, 0xFA, 0xCE, 
+  0xCC, 0xF4, 0x81, 0xFB, 0xEE, 0xBE, 0xFB, 0xE8, 0xD1, 0x99, 0xC7, 0x4E, 0x9D, 0x3A, 0xFF, 0xEC, 0xB3, 0x2F, 0x9F, 0x3B, 
+  0xF7, 0xC2, 0xC3, 0xC7, 0x4F, 0xE7, 0xE5, 0x14, 0xAE, 0x5A, 0xB1, 0x92, 0xBA, 0xCB, 0x5A, 0xB7, 0x8E, 0xB8, 0x1B, 0xF5, 
+  0x26, 0x40, 0x10, 0x38, 0xB2, 0x5B, 0xCD, 0x21, 0x21, 0xD9, 0x8A, 0x8A, 0x46, 0xEC, 0x9E, 0x00, 0x71, 0x9B, 0xA7, 0x73, 
+  0x33, 0x33, 0xC4, 0x43, 0xFA, 0x22, 0x98, 0xE4, 0x22, 0xB7, 0x30, 0xA2, 0x59, 0x66, 0xB1, 0x70, 0x51, 0xA7, 0xD1, 0x57, 
+  0xDA, 0x2A, 0x28, 0xB4, 0xBA, 0x9A, 0x46, 0x9D, 0xC6, 0x28, 0xFF, 0xF5, 0xD3, 0x16, 0x18, 0xCF, 0x9C, 0x7A, 0xE6, 0xED, 
+  0xB7, 0x3F, 0xB8, 0x78, 0xF1, 0xDD, 0x7F, 0xBA, 0xF0, 0xD6, 0xAB, 0xAF, 0xFE, 0xFC, 0x27, 0x2F, 0x31, 0xFE, 0xBF, 0xF3, 
+  0xEC, 0xF9, 0x97, 0xC0, 0x77, 0xD7, 0xF4, 0x7D, 0xC7, 0x1F, 0xFC, 0x9B, 0xA3, 0x33, 0x27, 0xAB, 0x2A, 0x6A, 0x33, 0x57, 
+  0xAD, 0xD5, 0xE5, 0x69, 0x0A, 0xB3, 0x73, 0x75, 0x79, 0x05, 0xD9, 0xE9, 0x19, 0x85, 0x39, 0x05, 0xF0, 0x6D, 0xD1, 0x59, 
+  0xC1, 0x84, 0x15, 0x6B, 0x2D, 0x0A, 0x9E, 0x48, 0xC0, 0x52, 0x53, 0x05, 0xBE, 0x41, 0x00, 0x2B, 0x25, 0xEA, 0x6D, 0xC0, 
+  0x95, 0x98, 0xCC, 0x12, 0x90, 0x3C, 0x12, 0x2C, 0xD0, 0xF3, 0x87, 0x41, 0xC0, 0x1B, 0x02, 0xCD, 0xFA, 0xB5, 0x69, 0x37, 
+  0x2C, 0x5D, 0xB6, 0x6E, 0xD5, 0xEA, 0xB5, 0x2B, 0x57, 0x81, 0xA9, 0xCC, 0x56, 0xB9, 0x7F, 0xEF, 0xA1, 0xBD, 0x7B, 0x0E, 
+  0x9D, 0x39, 0x73, 0xFE, 0xC2, 0x85, 0x5F, 0xFC, 0xF4, 0xA7, 0x3F, 0x9F, 0x9A, 0xBC, 0x63, 0xED, 0xEA, 0x34, 0x89, 0x78, 
+  0xE9, 0xD2, 0x1B, 0xBA, 0xA3, 0x83, 0xF1, 0xAE, 0x24, 0x35, 0x01, 0xC1, 0x18, 0xA2, 0x65, 0x2A, 0x34, 0x59, 0x34, 0x46, 
+  0x00, 0x89, 0x82, 0xD7, 0x5A, 0xA4, 0x29, 0x32, 0x58, 0x15, 0x45, 0xF4, 0x73, 0xD1, 0xDE, 0x00, 0x21, 0xC3, 0xC9, 0x09, 
+  0x5F, 0x4B, 0xCD, 0x25, 0xA0, 0x11, 0x47, 0x73, 0x09, 0xC9, 0xAE, 0xCF, 0xD7, 0xA2, 0xCE, 0x19, 0x69, 0x99, 0x8C, 0x6F, 
+  0x69, 0xAB, 0xD6, 0xA0, 0xCB, 0xE8, 0x0D, 0x8A, 0xBC, 0x62, 0xF9, 0xCD, 0xCB, 0x97, 0xDD, 0x20, 0x7D, 0x2F, 0x5E, 0x7C, 
+  0x3D, 0x71, 0xAF, 0x2C, 0xAF, 0x59, 0xB4, 0x68, 0x11, 0x7F, 0x89, 0xAE, 0x5C, 0x71, 0xCB, 0xAA, 0x95, 0xB7, 0x5E, 0x73, 
+  0x8D, 0xB2, 0x76, 0xF5, 0xBA, 0x64, 0xFF, 0x06, 0x7D, 0x01, 0x8A, 0xA0, 0x55, 0xB5, 0x47, 0xC8, 0x8F, 0x48, 0x47, 0x8D, 
+  0x99, 0x34, 0x82, 0x02, 0x64, 0x8C, 0x13, 0x45, 0x10, 0xA0, 0xFA, 0x2B, 0xB5, 0xAA, 0xEE, 0xCD, 0x56, 0x70, 0xCC, 0x41, 
+  0x31, 0x97, 0x90, 0x37, 0xEA, 0x15, 0x01, 0x91, 0x77, 0x48, 0x64, 0xDA, 0x2A, 0x4A, 0xAF, 0x72, 0xAE, 0x21, 0x93, 0x38, 
+  0xA2, 0xC8, 0x94, 0x24, 0xFE, 0x16, 0x2F, 0x5E, 0xB4, 0xEA, 0xB6, 0x95, 0xCB, 0x96, 0x2C, 0x95, 0xC8, 0xF8, 0x77, 0x36, 
+  0x7D, 0x4D, 0x5A, 0x56, 0xDA, 0x7A, 0x1E, 0xE0, 0x67, 0x13, 0x74, 0xD2, 0x89, 0xD9, 0xBF, 0x36, 0x37, 0x5F, 0xCA, 0xE0, 
+  0x55, 0x6E, 0x04, 0x0E, 0x91, 0xDA, 0x5A, 0x8B, 0xA5, 0xB0, 0x48, 0x49, 0x71, 0x30, 0x0F, 0x87, 0x15, 0x10, 0x5C, 0x97, 
+  0x65, 0x25, 0x4C, 0x9D, 0xD4, 0x84, 0xE8, 0xA9, 0x3B, 0x13, 0x62, 0x5F, 0xA0, 0x83, 0x30, 0x0C, 0x4C, 0xA4, 0xBF, 0xAB, 
+  0xDA, 0xB9, 0x7A, 0xE5, 0x2A, 0x1A, 0x53, 0x76, 0x5A, 0x16, 0xC7, 0xA5, 0x4B, 0x97, 0xC2, 0x13, 0xD1, 0xCC, 0x4D, 0x47, 
+  0xB2, 0x73, 0x31, 0xB8, 0x24, 0xB2, 0x06, 0x9D, 0x11, 0xCD, 0xA3, 0x1A, 0x8C, 0x1A, 0x1A, 0x90, 0xD8, 0xA1, 0x54, 0x67, 
+  0x0C, 0x28, 0x98, 0x50, 0x6A, 0xE1, 0x58, 0x0D, 0xD6, 0xFF, 0xB7, 0x12, 0x22, 0xA8, 0x5E, 0x17, 0xB9, 0xC5, 0xFB, 0x6A, 
+  0x89, 0xCE, 0xB1, 0x4D, 0x26, 0xEA, 0x8B, 0xF4, 0x79, 0xA2, 0x07, 0x91, 0x58, 0xB0, 0x9D, 0xBE, 0x7A, 0x6D, 0x61, 0xAE, 
+  0x68, 0x1A, 0xE8, 0x53, 0xE6, 0xDA, 0xF5, 0x74, 0x06, 0xE8, 0xA4, 0x75, 0x40, 0xA1, 0x21, 0x57, 0x70, 0x49, 0xB9, 0x00, 
+  0x97, 0x9E, 0x3F, 0x36, 0x30, 0x6E, 0x56, 0x19, 0x62, 0x4D, 0x21, 0xD6, 0x1A, 0x33, 0x50, 0xE4, 0xB2, 0x48, 0xBC, 0xF2, 
+  0x57, 0x70, 0x98, 0xAC, 0x20, 0x90, 0x38, 0xA4, 0x15, 0x1B, 0x8B, 0x64, 0x62, 0xC9, 0x5A, 0x10, 0xB0, 0x74, 0x66, 0x53, 
+  0x9E, 0x68, 0x87, 0x9D, 0xA1, 0x4E, 0x06, 0x1D, 0x1A, 0x2A, 0x1C, 0x68, 0x0B, 0x75, 0xB8, 0xC7, 0x90, 0x4D, 0x68, 0x03, 
+  0x04, 0x88, 0xE7, 0xDA, 0x67, 0x81, 0x8E, 0x36, 0x42, 0xE0, 0xD0, 0x94, 0x2D, 0xA3, 0xDB, 0x66, 0xEE, 0x39, 0x06, 0x6D, 
+  0x42, 0x78, 0xB4, 0xA2, 0xA1, 0xD2, 0xEC, 0x30, 0x15, 0x90, 0x41, 0x00, 0x4A, 0x39, 0x9E, 0x77, 0x42, 0x0E, 0xAB, 0x13, 
+  0xD6, 0x3C, 0x13, 0x7F, 0x02, 0x19, 0x08, 0xB6, 0x0A, 0x48, 0x53, 0x44, 0x6E, 0x32, 0x89, 0xF2, 0x1B, 0xC1, 0x66, 0x2E, 
+  0x81, 0x12, 0x19, 0x47, 0x59, 0x41, 0xF2, 0x3C, 0x15, 0x56, 0xF6, 0x6D, 0x2C, 0xD4, 0xF2, 0x3C, 0x84, 0xE5, 0x66, 0xE7, 
+  0x30, 0x43, 0xEE, 0xDD, 0xBE, 0x7F, 0xF3, 0xF8, 0x24, 0xDD, 0x97, 0x35, 0x65, 0xE8, 0xD5, 0xB7, 0xB4, 0x84, 0x52, 0xA1, 
+  0x9A, 0xE6, 0x70, 0xD0, 0x16, 0xE6, 0xB9, 0x4F, 0x69, 0xB9, 0xC5, 0x70, 0x15, 0x9C, 0xA1, 0x44, 0xA5, 0x47, 0x18, 0x12, 
+  0x0A, 0x38, 0x7C, 0xF0, 0x23, 0x89, 0x89, 0x16, 0x3E, 0x24, 0x9A, 0xD4, 0x46, 0xD9, 0xAE, 0x1C, 0x27, 0x52, 0x69, 0xC7, 
+  0xC3, 0x3C, 0xB0, 0xFA, 0xD6, 0xDB, 0x6A, 0xAA, 0xEA, 0xF9, 0xE7, 0x2A, 0xDA, 0xD2, 0x45, 0x03, 0xE5, 0x4F, 0x1C, 0x40, 
+  0x00, 0x85, 0xD7, 0x59, 0x93, 0xA3, 0x22, 0xA7, 0xAD, 0x39, 0x3E, 0x0C, 0xA2, 0xCF, 0xCD, 0xC5, 0x88, 0x51, 0x57, 0xF6, 
+  0xE1, 0xB9, 0x6E, 0x2C, 0x64, 0x54, 0x96, 0x03, 0xAF, 0xC9, 0x94, 0x0F, 0x37, 0xB7, 0xF3, 0x9B, 0x49, 0x64, 0xEB, 0x55, 
+  0x3E, 0xA4, 0x7B, 0x91, 0xA4, 0x1A, 0x71, 0x14, 0x6D, 0x51, 0x0D, 0x84, 0x10, 0x9E, 0x7C, 0x2D, 0xD1, 0x24, 0xC9, 0x96, 
+  0xDF, 0x78, 0x53, 0x7B, 0x30, 0xD6, 0x58, 0xE7, 0xA2, 0xE1, 0xCB, 0x28, 0xAB, 0xB2, 0x04, 0xA3, 0xFC, 0xBE, 0xD1, 0x29, 
+  0x73, 0x4D, 0xC4, 0x60, 0x16, 0xC3, 0xF6, 0x9F, 0x21, 0x50, 0xE7, 0x01, 0x3D, 0xC9, 0xAB, 0xFA, 0x10, 0x61, 0x12, 0x91, 
+  0xC2, 0x0D, 0xA3, 0x1D, 0xB4, 0x6F, 0x48, 0x4E, 0xC6, 0x3B, 0xFB, 0x56, 0xAE, 0xBC, 0x15, 0x1F, 0x0C, 0x1B, 0x2C, 0x9A, 
+  0x2A, 0x19, 0x89, 0x49, 0xB2, 0xF5, 0x17, 0x80, 0x74, 0xD9, 0x05, 0x6B, 0xF8, 0x4B, 0x60, 0xF9, 0xCD, 0xFC, 0xFF, 0xD7, 
+  0xD5, 0xD6, 0xEB, 0x73, 0x04, 0x0B, 0x33, 0x72, 0x99, 0xA2, 0x74, 0x05, 0x28, 0x48, 0x01, 0xA0, 0x95, 0xB9, 0x41, 0x64, 
+  0xAE, 0x9B, 0xCC, 0x49, 0xB8, 0x4C, 0xDE, 0x94, 0x89, 0x18, 0xA9, 0x68, 0x64, 0xBC, 0x11, 0x46, 0x4D, 0x81, 0xD6, 0xDD, 
+  0xE8, 0x41, 0x66, 0x56, 0xDF, 0xB2, 0x4A, 0x26, 0xB2, 0x88, 0x97, 0xC6, 0x20, 0x94, 0xF7, 0x2A, 0x0E, 0x09, 0x25, 0x65, 
+  0xEC, 0x5E, 0xD6, 0x5A, 0x6E, 0x66, 0x16, 0x9A, 0xB4, 0x78, 0xF1, 0x62, 0x66, 0x6D, 0x9B, 0xB9, 0x94, 0x11, 0x56, 0x74, 
+  0x46, 0x55, 0xD2, 0xA8, 0x47, 0x65, 0x9E, 0x57, 0x21, 0x97, 0xB2, 0x88, 0x30, 0xF2, 0x9F, 0x82, 0x44, 0xAC, 0x38, 0x49, 
+  0x65, 0x03, 0xF1, 0x66, 0x13, 0x50, 0xB2, 0x6C, 0xD9, 0x32, 0x54, 0xF8, 0xFA, 0xEB, 0xAF, 0x47, 0xA6, 0x19, 0xE6, 0x65, 
+  0x7E, 0x08, 0x62, 0x0A, 0x45, 0x74, 0xF8, 0x99, 0x2C, 0xC2, 0x34, 0x0F, 0x8D, 0x48, 0xEA, 0x02, 0x11, 0x1D, 0x4D, 0x4E, 
+  0x1E, 0x72, 0x40, 0x03, 0x59, 0xB2, 0x64, 0x89, 0x90, 0xF5, 0x45, 0xD7, 0x32, 0x4D, 0x23, 0xB3, 0x5C, 0x97, 0x0C, 0xFD, 
+  0x1F, 0x2E, 0xB6, 0xCD, 0xAB, 0xF2, 0x82, 0x27, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 
+  0x82
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltLeaks.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,98 @@
+/*****************************************************************
+|
+|   Platinum - Leaks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltLeaks.h"
+
+#if defined(WIN32)
+#include <crtdbg.h>
+#include <stdio.h>
+#include "string.h"
+
+/*----------------------------------------------------------------------
+|   PLT_Leak_AllocHook
++---------------------------------------------------------------------*/
+int PLT_Leak_AllocHook(int                  alloc_type, 
+                       void*                user_data, 
+                       size_t               size, 
+                       int                  block_type, 
+                       long                 request_number, 
+                       const unsigned char* filename, 
+                       int                  line_number)
+{
+    (void)alloc_type;
+    (void)user_data;
+    (void)size;
+    (void)block_type;
+    (void)request_number;
+    (void)line_number;
+    (void)filename;
+   /*
+    * if (request_number == 34556)
+    *   return 2;
+    *
+    */
+    return 1;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Leak_Enable
++---------------------------------------------------------------------*/
+void
+PLT_Leak_Enable(void) 
+{
+#if defined(_DEBUG)
+    /*
+    * If you want VC to dump file name and line number of leaking resource
+    * use #define _CRTDBG_MAP_ALLOC in suspected file (project)
+    * and #include "crtdbg.h" in suspected file
+    */
+_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF    |
+               _CRTDBG_CHECK_ALWAYS_DF |
+               _CRTDBG_LEAK_CHECK_DF);
+
+_CrtSetAllocHook(PLT_Leak_AllocHook );
+
+#endif
+}
+#else
+/*----------------------------------------------------------------------
+|   PLT_Leak_Enable
++---------------------------------------------------------------------*/
+void
+PLT_Leak_Enable(void) 
+{
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltLeaks.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,50 @@
+/*****************************************************************
+|
+|   Platinum - Leaks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_LEAKS_H_
+#define _PLT_LEAKS_H_ 
+
+/*----------------------------------------------------------------------
+|   functions
++---------------------------------------------------------------------*/
+#if defined(__cplusplus)
+extern "C" {
+#endif 
+
+void PLT_Leak_Enable(void);
+
+#if defined(__cplusplus)
+}
+#endif 
+
+#endif /* _PLT_LEAKS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltMetadataHandler.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,89 @@
+/*****************************************************************
+|
+|   Platinum - Metadata Handler
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltMetadataHandler.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.metadata.handler")
+
+/*----------------------------------------------------------------------
+|   PLT_MetadataHandler::Load
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MetadataHandler::LoadFile(const char* filename)
+{
+    NPT_File file(filename);
+    NPT_Result res = file.Open(NPT_FILE_OPEN_MODE_READ);
+    if (res != NPT_SUCCESS) {
+        NPT_LOG_SEVERE_2("error %d opening : %s\n", res, filename);
+    } else {
+        NPT_InputStreamReference stream;
+        res = file.GetInputStream(stream);
+        if (NPT_FAILED(res)) {
+            NPT_LOG_SEVERE_2("error %d getting input stream: %s\n", res, filename);
+        }
+        res = Load(*stream);
+        if (NPT_FAILED(res)) {
+            NPT_LOG_SEVERE_2("error %d reading header: %s\n", res, filename);
+        }
+    }
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MetadataHandler::Save
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MetadataHandler::SaveFile(const char* filename)
+{
+    NPT_File file(filename);
+    NPT_Result res = file.Open(NPT_FILE_OPEN_MODE_WRITE);
+    if (res != NPT_SUCCESS) {
+        NPT_LOG_SEVERE_2("error %d opening : %s\n", res, filename);
+    } else {
+        NPT_OutputStreamReference stream;
+        res = file.GetOutputStream(stream);
+        if (NPT_FAILED(res)) {
+            NPT_LOG_SEVERE_2("error %d getting output stream: %s\n", res, filename);
+        }
+        res = Save(*stream);
+        if (NPT_FAILED(res)) {
+            NPT_LOG_SEVERE_2("error %d writing header: %s\n", res, filename);
+        }
+    }
+
+    return res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltMetadataHandler.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,90 @@
+/*****************************************************************
+|
+|   Platinum - Metadata Handler
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_METADATA_HANDLER_H_
+#define _PLT_METADATA_HANDLER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   PLT_MetadataHandler class
++---------------------------------------------------------------------*/
+class PLT_MetadataHandler
+{
+public:
+    virtual ~PLT_MetadataHandler() {}
+
+    // metadata overridables
+    virtual bool HandleExtension(const char* extension) = 0;
+    virtual NPT_Result  Load(NPT_InputStream&  stream, 
+                             NPT_TimeInterval  sleeptime = NPT_TimeInterval(0, 10000), 
+                             NPT_TimeInterval  timeout = NPT_TimeInterval(30, 0)) = 0;
+    virtual NPT_Result  Save(NPT_OutputStream& stream,
+                             NPT_TimeInterval  sleeptime = NPT_TimeInterval(0, 10000), 
+                             NPT_TimeInterval  timeout = NPT_TimeInterval(30, 0)) = 0;
+
+    virtual const char* GetLicenseData(NPT_String& licenseData) = 0;
+    virtual NPT_Result  GetCoverArtData(char*& caData, int& len) = 0;
+    virtual const char* GetContentID(NPT_String& value) = 0;
+    virtual const char* GetTitle(NPT_String& value) = 0;
+    virtual const char* GetDescription(NPT_String& value) = 0;
+    virtual NPT_Result  GetDuration(NPT_UInt32& seconds) = 0;
+    virtual const char* GetProtection(NPT_String& protection) = 0;
+    virtual NPT_Result  GetYear(NPT_Size& year) = 0;
+    
+    // helper functions
+    virtual NPT_Result  LoadFile(const char* filename);
+    virtual NPT_Result  SaveFile(const char* filename);
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MetadataHandlerFinder
++---------------------------------------------------------------------*/
+class PLT_MetadataHandlerFinder
+{
+public:
+    // methods
+    PLT_MetadataHandlerFinder(const char* extension) : m_Extension(extension) {}
+    bool operator()(PLT_MetadataHandler* const & handler) const {
+        return handler->HandleExtension(m_Extension) ? true : false;
+    }
+
+private:
+    // members
+    NPT_String m_Extension;
+};
+
+#endif /* _PLT_METADATA_HANDLER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltRingBufferStream.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,213 @@
+/*****************************************************************
+|
+|   Platinum - Ring Buffer Stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltRingBufferStream.h"
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   defines
++---------------------------------------------------------------------*/
+#ifdef max
+#undef max
+#endif
+#define max(a,b)    (((a) > (b)) ? (a) : (b))
+
+#ifdef min
+#undef min
+#endif
+#define min(a,b)    (((a) < (b)) ? (a) : (b))
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::PLT_RingBufferStream(NPT_Size buffer_size,
+                                           bool     blocking /* = true */) : 
+    m_TotalBytesRead(0),
+    m_TotalBytesWritten(0),
+    m_Eos(false),
+    m_Blocking(blocking)
+{
+    m_RingBuffer = new NPT_RingBuffer(buffer_size);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::PLT_RingBufferStream(NPT_RingBufferReference& buffer,
+                                           bool blocking /* = true */) : 
+    m_RingBuffer(buffer),
+    m_TotalBytesRead(0),
+    m_TotalBytesWritten(0),
+    m_Eos(false),
+    m_Blocking(blocking)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::~PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::~PLT_RingBufferStream()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_RingBufferStream::Read(void*     buffer, 
+                           NPT_Size  max_bytes_to_read, 
+                           NPT_Size* bytes_read /*= NULL*/)
+{
+    NPT_Size bytes_avail, to_read;
+    NPT_Size last_read = 0;
+
+    // reset output param first
+    if (bytes_read) *bytes_read = 0;
+
+    // wait for data
+    do {
+        {
+            NPT_AutoLock autoLock(m_Lock);
+            if (m_RingBuffer->GetContiguousAvailable()) break;
+        }
+
+        if (m_Eos || m_RingBuffer->IsClosed()) {
+            return NPT_ERROR_EOS;
+        } else if (!m_Blocking) {
+            return NPT_ERROR_WOULD_BLOCK;
+        }
+
+        // sleep and try again
+        NPT_System::Sleep(NPT_TimeInterval(0, 10000));
+    } while (1);
+
+    {
+        NPT_AutoLock autoLock(m_Lock);
+
+        // try twice in case we looped
+        for (int i=0; i<2; i++) {
+            bytes_avail = m_RingBuffer->GetContiguousAvailable();
+            to_read = min(max_bytes_to_read - last_read, bytes_avail);
+
+            // break if nothing to read
+            if (to_read == 0) break;
+
+            // read into buffer and advance
+            NPT_CHECK(m_RingBuffer->Read((unsigned char*)buffer+last_read, to_read));
+
+            // keep track of the total bytes we have read so far
+            m_TotalBytesRead += to_read;
+            last_read += to_read;
+
+            if (bytes_read) *bytes_read += to_read;
+        }
+    }
+
+    // we have read some chars, so return success
+    // even if we have read less than asked
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::Write
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_RingBufferStream::Write(const void* buffer, 
+                            NPT_Size    bytes_to_write, 
+                            NPT_Size*   bytes_written /*= NULL*/)
+{
+    NPT_Size     space_avail, to_write;
+    NPT_Size     last_written = 0;
+
+    // reset output param first
+    if (bytes_written) *bytes_written = 0;
+
+    // wait for space
+    do {
+        {
+            NPT_AutoLock autoLock(m_Lock);
+            if (m_RingBuffer->GetContiguousSpace()) break;
+        }
+
+        if (m_Eos || m_RingBuffer->IsClosed()) {
+            return NPT_ERROR_EOS;
+        } else if (!m_Blocking) {
+            return NPT_ERROR_WOULD_BLOCK;
+        }
+
+        // sleep and try again
+        NPT_System::Sleep(NPT_TimeInterval(0, 10000));
+    } while (1);
+
+    {
+        NPT_AutoLock autoLock(m_Lock);
+
+        // try twice in case we looped
+        for (int i=0; i<2; i++) {
+            space_avail = m_RingBuffer->GetContiguousSpace();
+            to_write = min(bytes_to_write - last_written, space_avail);
+
+            // break if no space to write
+            if (to_write == 0) break;
+
+            // write into buffer
+            NPT_CHECK(m_RingBuffer->Write((unsigned char*)buffer+last_written, to_write));
+
+            m_TotalBytesWritten += to_write; 
+            last_written += to_write;
+
+            if (bytes_written) *bytes_written += to_write;
+        }
+    }
+
+    // we have written some chars, so return success
+    // even if we have written less than provided
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_RingBufferStream::Flush()
+{
+    NPT_AutoLock autoLock(m_Lock);
+
+    m_RingBuffer->Flush();
+    m_TotalBytesRead = 0;
+    m_TotalBytesWritten = 0;
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltRingBufferStream.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,113 @@
+/*****************************************************************
+|
+|   Platinum - Ring buffer stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_RING_BUFFER_STREAM_H_
+#define _PLT_RING_BUFFER_STREAM_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptStreams.h"
+#include "NptRingBuffer.h"
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream class
++---------------------------------------------------------------------*/
+class PLT_RingBufferStream : public NPT_DelegatingInputStream,   
+                             public NPT_DelegatingOutputStream
+{
+public:
+    PLT_RingBufferStream(NPT_Size buffer_size = 4096, bool blocking = true);
+    PLT_RingBufferStream(NPT_RingBufferReference& buffer, bool blocking = true);
+    virtual ~PLT_RingBufferStream();
+
+    void SetEos() {m_Eos = true;}
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read = NULL);
+    NPT_Result GetSize(NPT_LargeSize& size)  { 
+        NPT_AutoLock autoLock(m_Lock);
+        size = m_TotalBytesWritten;  
+        return NPT_SUCCESS;
+    }
+    NPT_Result GetAvailable(NPT_LargeSize& available) { 
+        NPT_AutoLock autoLock(m_Lock);
+        available = m_RingBuffer->GetAvailable();
+        return NPT_SUCCESS;
+    }
+
+    // NPT_OutputStream methods
+    NPT_Result Write(const void* buffer, 
+                     NPT_Size    bytes_to_write, 
+                     NPT_Size*   bytes_written = NULL);
+    NPT_Result Flush();
+    NPT_Result Close() { m_RingBuffer->Close(); return NPT_SUCCESS; }
+
+protected:
+    // NPT_DelegatingInputStream methods
+    NPT_Result InputSeek(NPT_Position offset) {
+        NPT_COMPILER_UNUSED(offset);
+        return NPT_FAILURE;
+    }
+    NPT_Result InputTell(NPT_Position& offset) { 
+        NPT_AutoLock autoLock(m_Lock);
+        offset = m_TotalBytesRead; 
+        return NPT_SUCCESS;
+    }
+
+    // NPT_DelegatingOutputStream methods
+    NPT_Result OutputSeek(NPT_Position offset) {
+        NPT_COMPILER_UNUSED(offset);
+        return NPT_FAILURE;
+    }
+    NPT_Result OutputTell(NPT_Position& offset) {
+        NPT_AutoLock autoLock(m_Lock);
+        offset = m_TotalBytesWritten; 
+        return NPT_SUCCESS;
+    }
+
+private:
+    NPT_RingBufferReference     m_RingBuffer;
+    NPT_Offset                  m_TotalBytesRead;
+    NPT_Offset                  m_TotalBytesWritten;
+    NPT_Mutex                   m_Lock;
+    bool                        m_Eos;
+    bool                        m_Blocking;
+};
+
+typedef NPT_Reference<PLT_RingBufferStream> PLT_RingBufferStreamReference;
+
+#endif // _PLT_RING_BUFFER_STREAM_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltService.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,795 @@
+/*****************************************************************
+|
+|   Platinum - Service
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltService.h"
+#include "PltSsdp.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltXmlHelper.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.service")
+
+/*----------------------------------------------------------------------
+|   PLT_Service::PLT_Service
++---------------------------------------------------------------------*/
+PLT_Service::PLT_Service(PLT_DeviceData* device,
+                         const char*     type, 
+                         const char*     id,
+                         const char*     last_change_namespace /* = NULL */) :  
+    m_Device(device),
+    m_ServiceType(type),
+    m_ServiceID(id),
+    m_EventTask(NULL),
+    m_EventingPaused(false),
+    m_LastChangeNamespace(last_change_namespace)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::~PLT_Service
++---------------------------------------------------------------------*/
+PLT_Service::~PLT_Service()
+{
+    Cleanup();
+}
+
+/*----------------------------------------------------------------------
+ |   PLT_Service::~PLT_Service
+ +---------------------------------------------------------------------*/
+ void
+ PLT_Service::Cleanup()
+ {
+     m_ActionDescs.Apply(NPT_ObjectDeleter<PLT_ActionDesc>());
+     m_StateVars.Apply(NPT_ObjectDeleter<PLT_StateVariable>());
+     m_Subscribers.Apply(NPT_ObjectDeleter<PLT_EventSubscriber>());
+
+     m_ActionDescs.Clear();
+     m_StateVars.Clear();
+     m_Subscribers.Clear();
+ }
+
+/*----------------------------------------------------------------------
+|   PLT_Service::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::GetSCPDXML(NPT_String& scpd)
+{
+    NPT_Result res;
+
+    // it is required to have at least 1 state variable
+    if (m_StateVars.GetItemCount() == 0) return NPT_FAILURE;
+
+    NPT_XmlElementNode* spec = NULL;
+    NPT_XmlElementNode* actionList = NULL;
+    NPT_XmlElementNode* top = new NPT_XmlElementNode("scpd");
+    NPT_XmlElementNode* serviceStateTable = NULL;
+    NPT_CHECK_LABEL_SEVERE(res = top->SetNamespaceUri("", "urn:schemas-upnp-org:service-1-0"), cleanup);
+
+    // add spec version
+    spec = new NPT_XmlElementNode("specVersion");
+    NPT_CHECK_LABEL_SEVERE(res = top->AddChild(spec), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "major", "1"), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "minor", "0"), cleanup);
+
+    // add actions
+    actionList = new NPT_XmlElementNode("actionList");
+    NPT_CHECK_LABEL_SEVERE(res = top->AddChild(actionList), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = m_ActionDescs.ApplyUntil(PLT_GetSCPDXMLIterator<PLT_ActionDesc>(actionList), 
+        NPT_UntilResultNotEquals(NPT_SUCCESS)), cleanup);
+
+    // add service state table
+    serviceStateTable = new NPT_XmlElementNode("serviceStateTable");
+    NPT_CHECK_LABEL_SEVERE(res = top->AddChild(serviceStateTable), cleanup);
+    NPT_CHECK_LABEL_SEVERE(res = m_StateVars.ApplyUntil(PLT_GetSCPDXMLIterator<PLT_StateVariable>(serviceStateTable), 
+        NPT_UntilResultNotEquals(NPT_SUCCESS)), cleanup);
+
+    // serialize node
+    NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*top, scpd), cleanup);
+    
+cleanup:
+    delete top;
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::ToXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** service_out /* = NULL */)
+{
+    NPT_XmlElementNode* service = new NPT_XmlElementNode("service");
+    if (service_out) {
+        *service_out = service;
+    }
+    NPT_CHECK_SEVERE(parent->AddChild(service));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "serviceType", m_ServiceType));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "serviceId", m_ServiceID));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "SCPDURL", GetSCPDURL()));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "controlURL", GetControlURL()));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "eventSubURL", GetEventSubURL()));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::InitURLs
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::InitURLs(const char* service_name, 
+                      const char* device_uuid)
+{
+    m_SCPDURL  = service_name;
+    m_SCPDURL += "/" + NPT_String(device_uuid) + NPT_String("/scpd.xml");
+    m_ControlURL  = service_name;
+    m_ControlURL += "/" + NPT_String(device_uuid) + NPT_String("/control.xml");
+    m_EventSubURL  = service_name;
+    m_EventSubURL += "/" + NPT_String(device_uuid) + NPT_String("/event.xml");
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::SetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetSCPDXML(const char* scpd)
+{
+    if (scpd == NULL) return NPT_FAILURE;
+
+    Cleanup();
+
+    NPT_XmlParser parser;
+    NPT_XmlNode*  tree = NULL;
+    NPT_Result    res;
+    NPT_Array<NPT_XmlElementNode*> stateVariables;
+    NPT_Array<NPT_XmlElementNode*> actions;
+    NPT_XmlElementNode* root;
+    NPT_XmlElementNode* actionList;
+    NPT_XmlElementNode* stateTable;
+
+    res = parser.Parse(scpd, tree);
+    NPT_CHECK_LABEL_FATAL(res, failure);
+
+    // make sure root tag is right
+    root = tree->AsElementNode();
+    if (!root || NPT_String::Compare(root->GetTag(), "scpd")) {
+        NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+    }
+
+    // make sure we have required children presents
+    stateTable = PLT_XmlHelper::GetChild(root, "serviceStateTable");
+    if (!stateTable || stateTable->GetChildren().GetItemCount() == 0) {
+        NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+    }
+
+    // stateVariable table
+    if (NPT_FAILED(PLT_XmlHelper::GetChildren(stateTable,
+                                              stateVariables, 
+                                              "stateVariable"))) {
+        NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+    }
+
+    for (int k = 0 ; k < (int)stateVariables.GetItemCount(); k++) {
+
+        NPT_String name, type, send;
+        PLT_XmlHelper::GetChildText(stateVariables[k], "name", name);
+        PLT_XmlHelper::GetChildText(stateVariables[k], "dataType", type);
+        PLT_XmlHelper::GetAttribute(stateVariables[k], "sendEvents", send);
+
+        if (name.GetLength() == 0 || type.GetLength() == 0) {
+            NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+        }
+
+        PLT_StateVariable* variable = new PLT_StateVariable(this);
+        m_StateVars.Add(variable);
+
+        variable->m_Name = name;
+        variable->m_DataType = type;
+        variable->m_IsSendingEvents = IsTrue(send); // could it be true/false ?
+        PLT_XmlHelper::GetChildText(stateVariables[k], "defaultValue", variable->m_DefaultValue);
+
+        NPT_XmlElementNode* allowedValueList = PLT_XmlHelper::GetChild(stateVariables[k], "allowedValueList");
+        if (allowedValueList) {
+            NPT_Array<NPT_XmlElementNode*> allowedValues;
+            PLT_XmlHelper::GetChildren(allowedValueList, allowedValues, "allowedValue");
+            for (int l = 0 ; l < (int)allowedValues.GetItemCount(); l++) {
+                const NPT_String* text = allowedValues[l]->GetText();
+                if (text) {
+                    variable->m_AllowedValues.Add(new NPT_String(*text));
+                }
+            }
+        } else {
+            NPT_XmlElementNode* allowedValueRange = PLT_XmlHelper::GetChild(stateVariables[k], "allowedValueRange");
+            if (allowedValueRange) {
+                NPT_String min, max, step;
+                PLT_XmlHelper::GetChildText(allowedValueRange, "minimum", min);
+                PLT_XmlHelper::GetChildText(allowedValueRange, "maximum", max);
+                PLT_XmlHelper::GetChildText(allowedValueRange, "step", step);
+
+                if (min.GetLength() == 0 || max.GetLength() == 0) {
+                    NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+                }
+
+                variable->m_AllowedValueRange = new NPT_AllowedValueRange;
+                NPT_ParseInteger32(min, variable->m_AllowedValueRange->min_value);
+                NPT_ParseInteger32(max, variable->m_AllowedValueRange->max_value);
+                variable->m_AllowedValueRange->step = -1;
+
+                if (step.GetLength() != 0) {
+                    NPT_ParseInteger(step, variable->m_AllowedValueRange->step);
+                }
+            }
+        }
+    }
+
+    // actions
+    actionList = PLT_XmlHelper::GetChild(root, "actionList");
+    if (actionList) {
+        if (NPT_FAILED(PLT_XmlHelper::GetChildren(actionList, actions, "action"))) {
+            NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+        }
+
+        for (int i = 0 ; i < (int)actions.GetItemCount(); i++) {
+            NPT_String action_name;
+            PLT_XmlHelper::GetChildText(actions[i],  "name", action_name);
+            if (action_name.GetLength() == 0) {
+                NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+            }
+
+            PLT_ActionDesc* action_desc = new PLT_ActionDesc(action_name, this);
+            m_ActionDescs.Add(action_desc);        
+            
+            // action arguments
+            NPT_XmlElementNode* argumentList = PLT_XmlHelper::GetChild(actions[i], "argumentList");
+            if (argumentList == NULL || !argumentList->GetChildren().GetItemCount())
+                continue; // no arguments is ok I guess
+
+            NPT_Array<NPT_XmlElementNode*> arguments;
+            NPT_CHECK_LABEL_SEVERE(PLT_XmlHelper::GetChildren(argumentList, arguments, "argument"), failure);
+
+            bool foundRetValue = false;
+            for (int j = 0 ; j < (int)arguments.GetItemCount(); j++) {
+                NPT_String name, direction, relatedStateVar;
+                PLT_XmlHelper::GetChildText(arguments[j], "name", name);
+                PLT_XmlHelper::GetChildText(arguments[j], "direction", direction);
+                PLT_XmlHelper::GetChildText(arguments[j], "relatedStateVariable", relatedStateVar);
+
+                if (name.GetLength() == 0 || direction.GetLength() == 0 || relatedStateVar.GetLength() == 0) {
+                    NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+                }
+
+                // make sure the related state variable exists
+                PLT_StateVariable* variable = FindStateVariable(relatedStateVar);
+                if (variable == NULL) {
+                    NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+                }
+
+                bool bReturnValue = false;
+                NPT_XmlElementNode* retval_node = PLT_XmlHelper::GetChild(arguments[j], "retVal");
+                if (retval_node) {
+                    // verify this is the only retVal we've had
+                    if (foundRetValue) {
+                        NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+                    } else {
+                        bReturnValue = true;
+                        foundRetValue = true;
+                    }
+                }
+                action_desc->GetArgumentDescs().Add(new PLT_ArgumentDesc(name, direction, variable, bReturnValue));
+            }
+        }
+    }
+
+    // delete the tree
+    delete tree;
+    return NPT_SUCCESS;
+
+failure:
+    NPT_LOG_FATAL_1("Failed to parse scpd: %s", scpd);
+    delete tree;
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::FindActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc*
+PLT_Service::FindActionDesc(const char* name)
+{
+    PLT_ActionDesc* action = NULL;
+    NPT_ContainerFind(m_ActionDescs, PLT_ActionDescNameFinder(this, name), action);
+    return action;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::FindStateVariable
++---------------------------------------------------------------------*/
+PLT_StateVariable*
+PLT_Service::FindStateVariable(const char* name)
+{
+    PLT_StateVariable* stateVariable = NULL;
+    NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+    return stateVariable;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::GetStateVariableValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::GetStateVariableValue(const char* name, NPT_String& value)
+{
+    PLT_StateVariable* stateVariable = FindStateVariable(name);
+    NPT_CHECK_POINTER_FATAL(stateVariable);
+    value = stateVariable->GetValue();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::IsSubscribable
++---------------------------------------------------------------------*/
+bool
+PLT_Service::IsSubscribable()
+{
+    NPT_List<PLT_StateVariable*>::Iterator var = m_StateVars.GetFirstItem();
+    while (var) {
+        if ((*var)->IsSendingEvents()) return true;
+        ++var;
+    }
+    return false;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::SetStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetStateVariable(const char* name, const char* value)
+{
+    PLT_StateVariable* stateVariable = NULL;
+    NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+    if (stateVariable == NULL)
+        return NPT_FAILURE;
+
+    return stateVariable->SetValue(value);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::SetStateVariableRate
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetStateVariableRate(const char* name, NPT_TimeInterval rate)
+{
+    PLT_StateVariable* stateVariable = NULL;
+    NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+    if (stateVariable == NULL)
+        return NPT_FAILURE;
+
+    return stateVariable->SetRate(rate);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::IncStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::IncStateVariable(const char* name)
+{
+    PLT_StateVariable* stateVariable = NULL;
+    NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+    if (stateVariable == NULL)
+        return NPT_FAILURE;
+
+    NPT_String value = stateVariable->GetValue();
+    NPT_Int32 num;
+    if (value.GetLength() == 0 || NPT_FAILED(value.ToInteger(num))) {
+        return NPT_FAILURE;
+    }
+
+    // convert value to int
+    return stateVariable->SetValue(NPT_String::FromInteger(num+1));
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::ProcessNewSubscription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ProcessNewSubscription(PLT_TaskManager*         task_manager,
+                                    const NPT_SocketAddress& addr, 
+                                    const NPT_String&        callback_urls, 
+                                    int                      timeout, 
+                                    NPT_HttpResponse&        response)
+{
+    NPT_LOG_FINE_1("New subscription for %s", m_EventSubURL.GetChars());
+
+//    // first look if we don't have a subscriber with same callbackURL
+//    PLT_EventSubscriber* subscriber = NULL;
+//    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers, PLT_EventSubscriberFinderByCallbackURL(strCallbackURL),
+//        subscriber))) {
+//        // update local interface and timeout
+//        subscriber->m_local_if.SetIpAddress((unsigned long) addr.GetIpAddress());
+//        subscriber->m_ExpirationTime = NPT_Time(NULL) + timeout;
+//
+//        PLT_UPnPMessageHelper::SetSID("uuid:" + subscriber->m_sid);
+//        PLT_UPnPMessageHelper::SetTimeOut(timeout);
+//        return NPT_SUCCESS;
+//    }
+//
+    // reject if we have too many subscribers already
+    if (m_Subscribers.GetItemCount() > 30) {
+        response.SetStatus(500, "Internal Server Error");
+        return NPT_FAILURE;
+    }
+
+    //TODO: prevent hacking by making sure callbackurl is not ourselves?
+
+    // generate a unique subscriber ID
+    NPT_String sid;
+    PLT_UPnPMessageHelper::GenerateUUID(19, sid);
+
+    PLT_EventSubscriber* subscriber = new PLT_EventSubscriber(task_manager, this, sid, timeout);
+    // parse the callback URLs
+    bool reachable = false;
+    if (callback_urls[0] == '<') {
+        char* szURLs = (char*)(const char*)callback_urls;
+        char* brackL = szURLs;
+        char* brackR = szURLs;
+        while (++brackR < szURLs + callback_urls.GetLength()) {
+            if (*brackR == '>') {
+                NPT_String strCallbackURL = NPT_String(brackL+1, (NPT_Size)(brackR-brackL-1));
+                NPT_HttpUrl url(strCallbackURL);
+
+                if (url.IsValid()) {
+                    subscriber->AddCallbackURL(strCallbackURL);
+                    reachable = true;
+                }
+                brackL = ++brackR;
+            }
+        }
+    }
+
+    if (reachable == false) {
+        NPT_CHECK_LABEL_FATAL(NPT_FAILURE, cleanup);
+    }
+
+    // keep track of which interface we receive the request, we will use this one
+    // when notifying
+    subscriber->SetLocalIf(addr);
+
+    PLT_UPnPMessageHelper::SetSID(response, subscriber->GetSID());
+    PLT_UPnPMessageHelper::SetTimeOut(response, timeout);
+
+    {
+        NPT_AutoLock lock(m_Lock);
+
+        // new subscriber should get all vars in the LastChange var
+        UpdateLastChange(m_StateVars);
+
+        // send all state vars to sub
+        NPT_Result res = subscriber->Notify(m_StateVars);
+
+        // reset LastChange var to what was really just changed
+        UpdateLastChange(m_StateVarsChanged);
+
+        NPT_CHECK_LABEL_FATAL(res, cleanup);
+
+        if (!m_EventTask) {
+            m_EventTask = new PLT_ServiceEventTask(this);
+            task_manager->StartTask(m_EventTask);
+        }
+
+        m_Subscribers.Add(subscriber);
+    }
+
+    return NPT_SUCCESS;
+
+cleanup:
+    response.SetStatus(412, "Precondition Failed");
+    delete subscriber;
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::ProcessRenewSubscription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ProcessRenewSubscription(const NPT_SocketAddress& addr, 
+                                      const NPT_String&        sid, 
+                                      int                      timeout, 
+                                      NPT_HttpResponse&        response)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    NPT_LOG_FINE_2("Renewing subscription for %s (sub=%s)", 
+        m_EventSubURL.GetChars(), 
+        sid.GetChars());
+
+    // first look if we don't have a subscriber with same callbackURL
+    PLT_EventSubscriber* subscriber = NULL;
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers, 
+                                        PLT_EventSubscriberFinderBySID(sid), 
+                                        subscriber))) {
+        // update local interface and timeout
+        subscriber->SetLocalIf(addr);
+        subscriber->SetTimeout(timeout);
+
+        PLT_UPnPMessageHelper::SetSID(response, subscriber->GetSID());
+        PLT_UPnPMessageHelper::SetTimeOut(response, timeout);
+        return NPT_SUCCESS;
+    }
+
+    NPT_LOG_WARNING_1("Renewing subscription for unknown %s!", sid.GetChars());
+
+    // didn't find a valid Subscriber in our list
+    response.SetStatus(412, "Precondition Failed");
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::ProcessCancelSubscription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ProcessCancelSubscription(const NPT_SocketAddress& /* addr */, 
+                                       const NPT_String&        sid, 
+                                       NPT_HttpResponse&        response)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    NPT_LOG_FINE_2("Cancelling subscription for %s (sub=%s)", 
+        m_EventSubURL.GetChars(),
+        sid.GetChars());
+
+    // first look if we don't have a subscriber with same callbackURL
+    PLT_EventSubscriber* sub = NULL;
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers, 
+                                        PLT_EventSubscriberFinderBySID(sid), 
+                                        sub))) {
+
+        // remove sub
+        m_Subscribers.Remove(sub);
+        delete sub;
+        return NPT_SUCCESS;
+    }
+
+    NPT_LOG_WARNING_1("Cancelling subscription for unknown %s!", sid.GetChars());
+
+    // didn't find a valid Subscriber in our list
+    response.SetStatus(412, "Precondition Failed");
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::AddChanged
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::AddChanged(PLT_StateVariable* var)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    // no event task means no subscribers yet, so don't bother
+    // Note: this will take care also when setting default state 
+    //       variables values during init and avoid being published
+    if (!m_EventTask) return NPT_SUCCESS;
+    
+    if (var->IsSendingEvents()) {
+        if (!m_StateVarsToPublish.Contains(var)) 
+            m_StateVarsToPublish.Add(var);
+    } else if (var->IsSendingEvents(true)) {
+        if (!m_StateVarsChanged.Contains(var)) 
+            m_StateVarsChanged.Add(var);
+        UpdateLastChange(m_StateVarsChanged);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::UpdateLastChange
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::UpdateLastChange(NPT_List<PLT_StateVariable*>& vars)
+{
+    PLT_StateVariable* var = FindStateVariable("LastChange");
+    if (var == NULL) return NPT_FAILURE;
+
+    NPT_ASSERT(m_LastChangeNamespace.GetLength() > 0);
+
+    if (vars.GetItemCount() == 0) {
+        // no vars to update, remove LastChange from vars to publish
+        m_StateVarsToPublish.Remove(var);
+        return NPT_SUCCESS;
+    }
+
+    NPT_XmlElementNode* top = new NPT_XmlElementNode("Event");
+    NPT_CHECK_SEVERE(top->SetNamespaceUri("", m_LastChangeNamespace));
+
+    NPT_XmlElementNode* instance = new NPT_XmlElementNode("InstanceID");
+    NPT_CHECK_SEVERE(top->AddChild(instance));
+    NPT_CHECK_SEVERE(instance->SetAttribute("val", "0"));
+
+    // build list of changes
+    NPT_CHECK_SEVERE(vars.Apply(PLT_LastChangeXMLIterator(instance)));
+
+    // serialize node
+    NPT_String value;
+    NPT_CHECK_SEVERE(PLT_XmlHelper::Serialize(*top, value));
+    delete top;
+
+    // set the state change direcly instead of calling SetValue
+    // to avoid recursive lock, instead add var to publish here directly
+    var->m_Value = value;
+    if (!m_StateVarsToPublish.Contains(var)) m_StateVarsToPublish.Add(var);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::PauseEventing
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::PauseEventing(bool paused)
+{
+    NPT_AutoLock lock(m_Lock);
+    m_EventingPaused = paused;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Service::NotifyChanged
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::NotifyChanged()
+{
+    NPT_AutoLock lock(m_Lock);
+
+    // no eventing for now
+    if (m_EventingPaused) return NPT_SUCCESS;
+
+    // pick the vars that are ready to be published
+    // based on their moderation rate and last publication
+    NPT_List<PLT_StateVariable*> vars_ready;
+    NPT_List<PLT_StateVariable*>::Iterator iter = m_StateVarsToPublish.GetFirstItem();
+    while (iter) {
+        PLT_StateVariable* var = *iter;
+        if (var->IsReadyToPublish()) {
+            vars_ready.Add(var);
+            m_StateVarsToPublish.Erase(iter++);
+
+            // clear last changed list if we're about to send LastChange var
+            if (!var->GetName().Compare("LastChange")) m_StateVarsChanged.Clear();
+            
+            continue;
+        }
+            
+        iter++;
+    }
+    
+    // if nothing to publish then bail out now
+    // we'll clean up expired subscribers when we have something to publish
+    if (vars_ready.GetItemCount() == 0) return NPT_SUCCESS;
+    
+    // send vars that are ready to go and remove old subscribers 
+    NPT_List<PLT_EventSubscriber*>::Iterator sub_iter = m_Subscribers.GetFirstItem();
+    while (sub_iter) {
+        PLT_EventSubscriber* sub = *sub_iter;
+
+        NPT_TimeStamp now, expiration;
+        NPT_System::GetCurrentTimeStamp(now);
+        expiration = sub->GetExpirationTime();
+
+        // forget sub if it didn't renew in time or if notification failed
+        if (expiration == NPT_TimeStamp() || expiration > now ) {
+            NPT_Result res = vars_ready.GetItemCount()?sub->Notify(vars_ready):NPT_SUCCESS;
+            if (NPT_SUCCEEDED(res)) {
+                sub_iter++;
+                continue;
+            }
+        }
+            
+        m_Subscribers.Erase(sub_iter++);
+        delete sub;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ServiceSCPDURLFinder::operator()
++---------------------------------------------------------------------*/
+bool 
+PLT_ServiceSCPDURLFinder::operator()(PLT_Service* const & service) const 
+{
+    NPT_String url = service->GetSCPDURL();
+    if (!url.StartsWith("/")) {
+        url = service->GetDevice()->GetURLBase().GetPath() + url;
+    }
+    return m_URL.Compare(url, true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ServiceControlURLFinder::operator()
++---------------------------------------------------------------------*/
+bool 
+PLT_ServiceControlURLFinder::operator()(PLT_Service* const & service) const 
+{
+    NPT_String url = service->GetControlURL();
+    if (!url.StartsWith("/")) {
+        url = service->GetDevice()->GetURLBase().GetPath() + url;
+    }
+    return m_URL.Compare(url, true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ServiceEventSubURLFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceEventSubURLFinder::operator()(PLT_Service* const & service) const 
+{
+    NPT_String url = service->GetEventSubURL();
+    if (!url.StartsWith("/")) {
+        url = service->GetDevice()->GetURLBase().GetPath() + url;
+    }
+    return m_URL.Compare(url, true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ServiceIDFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceIDFinder::operator()(PLT_Service* const & service) const 
+{
+    return m_Id.Compare(service->GetServiceID(), true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ServiceTypeFinder::operator()
++---------------------------------------------------------------------*/
+bool 
+PLT_ServiceTypeFinder::operator()(PLT_Service* const & service) const 
+{
+    return m_Type.Compare(service->GetServiceType(), true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_GetLastChangeXMLIterator::operator()
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_LastChangeXMLIterator::operator()(PLT_StateVariable* const &var) const
+{   
+    // only add vars that are indirectly evented
+    if (!var->IsSendingEvents(true)) return NPT_SUCCESS;
+
+    NPT_XmlElementNode* variable = new NPT_XmlElementNode((const char*)var->GetName());
+    NPT_CHECK_SEVERE(m_Node->AddChild(variable));
+    NPT_CHECK_SEVERE(variable->SetAttribute("val", var->GetValue()));
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltService.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,268 @@
+/*****************************************************************
+|
+|   Platinum - Service
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_SERVICE_H_
+#define _PLT_SERVICE_H_
+
+/*----------------------------------------------------------------------
+|    includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltEvent.h"
+#include "PltArgument.h"
+#include "PltStateVariable.h"
+#include "PltAction.h"
+
+/*----------------------------------------------------------------------
+|    forward declarations
++---------------------------------------------------------------------*/
+class PLT_DeviceData;
+
+/*----------------------------------------------------------------------
+|    PLT_Service class
++---------------------------------------------------------------------*/
+class PLT_Service
+{
+public:
+    // methods
+    PLT_Service(PLT_DeviceData* device,
+                const char*     type = NULL, 
+                const char*     id = NULL,
+                const char*     last_change_namespace = NULL);
+    ~PLT_Service();
+    
+    // class methods
+    NPT_Result  InitURLs(const char* service_name, const char* device_uuid);
+    bool        IsInitted() {
+        return (m_ActionDescs.GetItemCount() > 0);
+    }
+    NPT_Result  PauseEventing(bool paused = true);
+
+    // static methods
+    static bool IsTrue(NPT_String& value) {
+        if (value.Compare("1", true)    && 
+            value.Compare("true", true) && 
+            value.Compare("yes", true)) {
+            return false;
+        }
+        return true;
+    }
+
+    // accessor methods
+    const NPT_String&   GetSCPDURL()      const   { return m_SCPDURL;     }
+    const NPT_String&   GetControlURL()   const   { return m_ControlURL;  }
+    const NPT_String&   GetEventSubURL()  const   { return m_EventSubURL; }
+    const NPT_String&   GetServiceID()    const   { return m_ServiceID;   }
+    const NPT_String&   GetServiceType()  const   { return m_ServiceType; }    
+    PLT_DeviceData*     GetDevice()               { return m_Device; }
+
+    // XML
+    NPT_Result          GetSCPDXML(NPT_String& xml);
+    NPT_Result          SetSCPDXML(const char* xml);
+    NPT_Result          GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** service = NULL);
+
+    // State Variables
+    NPT_Result          SetStateVariable(const char* name, const char* value);
+    NPT_Result          SetStateVariableRate(const char* name, NPT_TimeInterval rate);
+    NPT_Result          IncStateVariable(const char* name);
+    PLT_StateVariable*  FindStateVariable(const char* name);
+    NPT_Result          GetStateVariableValue(const char* name, NPT_String& value);
+    bool                IsSubscribable();
+
+    // Actions
+    PLT_ActionDesc*     FindActionDesc(const char* name);
+
+private:    
+    void                Cleanup();
+    NPT_Result          AddChanged(PLT_StateVariable* var);
+    NPT_Result          UpdateLastChange(NPT_List<PLT_StateVariable*>& vars);
+    NPT_Result          NotifyChanged();
+
+
+    /*----------------------------------------------------------------------
+    |    PLT_ServiceEventTask
+    +---------------------------------------------------------------------*/
+    class PLT_ServiceEventTask : public PLT_ThreadTask
+    {
+    public:
+        PLT_ServiceEventTask(PLT_Service* service) : m_Service(service) {}
+
+        void DoRun() { 
+            while (!IsAborting(100)) m_Service->NotifyChanged();
+        }
+
+    private:
+        PLT_Service* m_Service;
+    };
+
+    // Events
+    NPT_Result ProcessNewSubscription(
+        PLT_TaskManager*         task_manager,
+        const NPT_SocketAddress& addr, 
+        const NPT_String&        callback_urls, 
+        int                      timeout, 
+        NPT_HttpResponse&        response);
+
+    NPT_Result ProcessRenewSubscription(
+        const NPT_SocketAddress& addr, 
+        const NPT_String&        sid, 
+        int                      timeout,
+        NPT_HttpResponse&        response);
+    
+    NPT_Result ProcessCancelSubscription(
+        const NPT_SocketAddress& addr, 
+        const NPT_String&        sid, 
+        NPT_HttpResponse&        response);
+
+
+protected:
+    friend class PLT_StateVariable; // so that we can call AddChanged from StateVariable
+    friend class PLT_DeviceHost;
+    friend class PLT_DeviceData;
+    
+    //members
+    PLT_DeviceData* m_Device;
+    NPT_String      m_ServiceType;
+    NPT_String      m_ServiceID;
+    NPT_String      m_SCPDURL;
+    NPT_String      m_ControlURL;
+    NPT_String      m_EventSubURL;
+
+    PLT_ServiceEventTask*           m_EventTask;
+    NPT_Array<PLT_ActionDesc*>      m_ActionDescs;
+    NPT_List<PLT_StateVariable*>    m_StateVars;
+    NPT_Mutex                       m_Lock;
+    NPT_List<PLT_StateVariable*>    m_StateVarsChanged;
+    NPT_List<PLT_StateVariable*>    m_StateVarsToPublish;
+    NPT_List<PLT_EventSubscriber*>  m_Subscribers;
+    bool                            m_EventingPaused;
+    NPT_String                      m_LastChangeNamespace;
+};
+
+/*----------------------------------------------------------------------
+|    PLT_ServiceDescriptionURLFinder
++---------------------------------------------------------------------*/
+class PLT_ServiceSCPDURLFinder
+{
+public:
+    // methods
+    PLT_ServiceSCPDURLFinder(const char* url) : m_URL(url) {}
+    virtual ~PLT_ServiceSCPDURLFinder() {}
+    bool operator()(PLT_Service* const & service) const;
+
+private:
+    // members
+    NPT_String m_URL;
+};
+
+/*----------------------------------------------------------------------
+|    PLT_ServiceControlURLFinder
++---------------------------------------------------------------------*/
+class PLT_ServiceControlURLFinder
+{
+public:
+    // methods
+    PLT_ServiceControlURLFinder(const char* url) : m_URL(url) {}
+    virtual ~PLT_ServiceControlURLFinder() {}
+    bool operator()(PLT_Service* const & service) const;
+
+private:
+    // members
+    NPT_String m_URL;
+};
+
+/*----------------------------------------------------------------------
+|    PLT_ServiceEventSubURLFinder
++---------------------------------------------------------------------*/
+class PLT_ServiceEventSubURLFinder
+{
+public:
+    // methods
+    PLT_ServiceEventSubURLFinder(const char* url) : m_URL(url) {}
+    virtual ~PLT_ServiceEventSubURLFinder() {}
+    bool operator()(PLT_Service* const & service) const;
+
+private:
+    // members
+    NPT_String m_URL;
+};
+
+/*----------------------------------------------------------------------
+|    PLT_ServiceIDFinder
++---------------------------------------------------------------------*/
+class PLT_ServiceIDFinder
+{
+public:
+    // methods
+    PLT_ServiceIDFinder(const char* id) : m_Id(id) {}
+    virtual ~PLT_ServiceIDFinder() {}
+    bool operator()(PLT_Service* const & service) const;
+
+private:
+    // members
+    NPT_String m_Id;
+};
+
+/*----------------------------------------------------------------------
+|    PLT_ServiceTypeFinder
++---------------------------------------------------------------------*/
+class PLT_ServiceTypeFinder
+{
+public:
+    // methods
+    PLT_ServiceTypeFinder(const char* type) : m_Type(type) {}
+    virtual ~PLT_ServiceTypeFinder() {}
+    bool operator()(PLT_Service* const & service) const;
+
+private:
+    // members
+    NPT_String m_Type;
+};
+
+/*----------------------------------------------------------------------
+|    PLT_LastChangeXMLIterator
++---------------------------------------------------------------------*/
+class PLT_LastChangeXMLIterator
+{
+public:
+    // methods
+    PLT_LastChangeXMLIterator(NPT_XmlElementNode* node) : m_Node(node) {}
+    virtual ~PLT_LastChangeXMLIterator() {}
+
+    NPT_Result operator()(PLT_StateVariable* const & var) const;
+
+private:
+    NPT_XmlElementNode* m_Node;
+};
+
+#endif /* _PLT_SERVICE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltSsdp.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,512 @@
+/*****************************************************************
+|
+|   Platinum - SSDP
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltSsdp.h"
+#include "PltDatagramStream.h"
+#include "PltDeviceHost.h"
+#include "PltUPnP.h"
+#include "PltHttp.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.ssdp")
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_SSDP_MAX_LINE_SIZE  = 2048;
+const int NPT_SSDP_MAX_DGRAM_SIZE = 4096;
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSender::SendSsdp
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSender::SendSsdp(NPT_HttpRequest&   request,
+                         const char*        usn,
+                         const char*        target,
+                         NPT_UdpSocket&     socket,
+                         bool               notify,
+                         const NPT_SocketAddress* addr /* = NULL */)
+{
+    NPT_CHECK_SEVERE(FormatPacket(request, usn, target, socket, notify));
+
+    // logging
+    NPT_LOG_FINE_2("Sending SSDP %s for %s",
+        (const char*)request.GetMethod(), 
+        usn);
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+    // use a memory stream to write all the data
+    NPT_MemoryStream stream;
+    NPT_Result res = request.Emit(stream);
+    if (NPT_FAILED(res)) return res;
+
+    // copy stream into a data packet and send it
+    NPT_LargeSize size;
+    stream.GetSize(size);
+    if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE;
+
+    NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size);
+    return socket.Send(packet, addr);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSender::SendSsdp
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSender::SendSsdp(NPT_HttpResponse&  response,
+                         const char*        usn,
+                         const char*        target,
+                         NPT_UdpSocket&     socket,
+                         bool               notify, 
+                         const NPT_SocketAddress* addr /* = NULL */)
+{
+    NPT_CHECK_SEVERE(FormatPacket(response, usn, target, socket, notify));
+
+    // logging
+    NPT_LOG_FINE("Sending SSDP:");
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &response);
+
+    // use a memory stream to write all the data
+    NPT_MemoryStream stream;
+    NPT_Result res = response.Emit(stream);
+    if (NPT_FAILED(res)) return res;
+
+    // copy stream into a data packet and send it
+    NPT_LargeSize size;
+    stream.GetSize(size);
+    if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE;
+
+    NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size);
+    return socket.Send(packet, addr);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSender::FormatPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSender::FormatPacket(NPT_HttpMessage& message, 
+                             const char*      usn,
+                             const char*      target,
+                             NPT_UdpSocket&   socket,
+                             bool             notify)
+{
+    NPT_COMPILER_UNUSED(socket);
+
+    PLT_UPnPMessageHelper::SetUSN(message, usn);
+    if (notify) {
+        PLT_UPnPMessageHelper::SetNT(message, target);
+    } else {
+        PLT_UPnPMessageHelper::SetST(message, target);
+    }
+    PLT_HttpHelper::SetContentLength(message, 0);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpDeviceSearchResponseInterfaceIterator class
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpDeviceSearchResponseInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const 
+{
+    NPT_Result res;
+    const NPT_SocketAddress* remote_addr = &m_RemoteAddr;
+
+    NPT_List<NPT_NetworkInterfaceAddress>::Iterator netaddr = net_if->GetAddresses().GetFirstItem();
+    if (!netaddr) {
+        return NPT_SUCCESS;
+    }
+
+    // don't respond on loopback
+    // windows media player on vista sends it's M-SEARCH to loopback interface if it's a local clients sometimes
+    //if (net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
+    //    return NPT_SUCCESS;
+    //}
+
+    NPT_SocketAddress local_addr((*netaddr).GetPrimaryAddress(), 0); // 1900?
+    NPT_UdpSocket     socket;
+    //if (NPT_FAILED(res = socket.Bind(local_addr))) {
+    //    return res;
+    //}
+
+    // get the output socket stream
+    NPT_OutputStreamReference stream;
+    if (NPT_FAILED(res = socket.GetOutputStream(stream))) {
+        return res;
+    }
+
+    NPT_HttpResponse response(200, "OK", NPT_HTTP_PROTOCOL_1_1);
+
+    // get location URL based on ip address of interface
+    // by connecting, the kernel chooses which interface to use to route to the remote
+    // this is the IP we should use in our Location
+    if (NPT_FAILED(res = socket.Connect(m_RemoteAddr, 5000))) {
+        return res;
+    }
+    NPT_SocketInfo info;
+    socket.GetInfo(info);
+
+    // did we successfully connect and found out which interface is used?
+    if (info.local_address.GetIpAddress().AsLong()) {
+        // check that the interface the kernel chose matches the interface
+        // we wanted to send on
+        // FIXME: Should we fail instead and stop sending a response once we get NPT_SUCCESS?
+        if (local_addr.GetIpAddress().AsLong() != info.local_address.GetIpAddress().AsLong()) {
+            return NPT_SUCCESS;
+        }
+
+        // already connected, so we don't need to specify where to go
+        remote_addr = NULL;
+    }
+
+    PLT_UPnPMessageHelper::SetLocation(response, m_Device->GetDescriptionUrl(local_addr.GetIpAddress().ToString()));
+    PLT_UPnPMessageHelper::SetLeaseTime(response, (NPT_Timeout)((float)m_Device->GetLeaseTime()));
+    PLT_UPnPMessageHelper::SetServer(response, NPT_HttpServer::m_ServerHeader, false);
+    response.GetHeaders().SetHeader("EXT", "");
+
+    // process search response twice to be NMPR compliant
+    NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr));
+    NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpDeviceSearchResponseTask::DoRun()
++---------------------------------------------------------------------*/
+void
+PLT_SsdpDeviceSearchResponseTask::DoRun() 
+{
+    NPT_List<NPT_NetworkInterface*> if_list;
+    NPT_CHECK_LABEL_WARNING(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list), 
+                            done);
+
+    if_list.Apply(PLT_SsdpDeviceSearchResponseInterfaceIterator(
+        m_Device, 
+        m_RemoteAddr, 
+        m_ST));
+    if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+
+done:
+    return;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpAnnounceInterfaceIterator class
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpAnnounceInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const 
+{
+    // don't use this interface address if it's not broadcast capable
+    if (m_Broadcast && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST)) {
+        return NPT_FAILURE;
+    }
+
+    NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = 
+        net_if->GetAddresses().GetFirstItem();
+    if (!niaddr) return NPT_FAILURE;
+
+    // Remove disconnected interfaces
+    NPT_IpAddress addr =  (*niaddr).GetPrimaryAddress();
+    if (!addr.ToString().Compare("0.0.0.0")) return NPT_FAILURE;
+
+    NPT_HttpUrl            url;
+    NPT_UdpMulticastSocket multicast_socket;
+    NPT_UdpSocket          broadcast_socket;
+    NPT_UdpSocket*         socket;
+
+    if (m_Broadcast) {
+        //url = NPT_HttpUrl("255.255.255.255", 1900, "*");
+        url = NPT_HttpUrl((*niaddr).GetBroadcastAddress().ToString(), 1900, "*");
+        socket = &broadcast_socket;
+    } else {
+        url = NPT_HttpUrl("239.255.255.250", 1900, "*");
+        socket = &multicast_socket;
+        NPT_CHECK_SEVERE(((NPT_UdpMulticastSocket*)socket)->SetInterface(addr));
+    }
+
+    NPT_HttpRequest req(url, "NOTIFY", NPT_HTTP_PROTOCOL_1_1);
+    PLT_HttpHelper::SetHost(req, "239.255.255.250:1900");
+    
+    // put a location only if alive message
+    if (m_IsByeBye == false) {
+        PLT_UPnPMessageHelper::SetLocation(req, m_Device->GetDescriptionUrl(addr.ToString()));
+    }
+
+    NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_IsByeBye));
+    NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_IsByeBye));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpDeviceAnnounceUnicastTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_SsdpDeviceAnnounceTask::DoRun()
+{
+    NPT_Result res = NPT_SUCCESS;
+    NPT_List<NPT_NetworkInterface*> if_list;
+
+    while (1) {
+        NPT_CHECK_LABEL_FATAL(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list),
+                              cleanup);
+
+        // if we're announcing our arrival, sends a byebye first (NMPR compliance)
+        if (m_IsByeByeFirst == true) {
+            m_IsByeByeFirst = false;
+            res = if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(m_Device, true, m_IsBroadcast));
+            if (NPT_FAILED(res)) goto cleanup;
+
+            // schedule to announce alive in 300 ms
+            if (NPT_FAILED(res) || IsAborting((NPT_Timeout)300)) break;
+        }
+            
+        res = if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(m_Device, false, m_IsBroadcast));
+        
+cleanup:
+        if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+        if_list.Clear();
+
+        if (NPT_FAILED(res) || IsAborting(m_Repeat.m_Seconds*1000)) break;
+    };
+}
+
+/*----------------------------------------------------------------------
+|    PLT_SsdpListenTask::DoInit
++---------------------------------------------------------------------*/
+void
+PLT_SsdpListenTask::DoInit() 
+{
+    if (m_IsMulticast) {
+        NPT_List<NPT_NetworkInterface*> if_list;
+        NPT_CHECK_LABEL_FATAL(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list), 
+                              done);
+
+        /* Join multicast group for every interface we found */
+        if_list.ApplyUntil(
+            PLT_SsdpInitMulticastIterator((NPT_UdpMulticastSocket*)m_Socket), 
+            NPT_UntilResultNotEquals(NPT_SUCCESS));
+
+        if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+    }
+
+done: 
+    return;
+}
+
+/*----------------------------------------------------------------------
+|    PLT_SsdpListenTask::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_SsdpListenTask::GetInputStream(NPT_InputStreamReference& stream) 
+{
+    if (!m_Datagram.IsNull()) {
+        stream = m_Datagram;
+        return NPT_SUCCESS;
+    } else {
+        NPT_InputStreamReference input_stream;
+        NPT_Result res = m_Socket->GetInputStream(input_stream);
+        if (NPT_FAILED(res)) {
+            return res;
+        }
+        // for datagrams, we can't simply write to the socket directly
+        // we need to write into a datagramstream (buffer) that redirects to the real stream when flushed
+        m_Datagram = new PLT_InputDatagramStream((NPT_UdpSocket*)m_Socket);
+        stream = m_Datagram;
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|    PLT_SsdpListenTask::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_SsdpListenTask::GetInfo(NPT_SocketInfo& info) 
+{
+    if (m_Datagram.IsNull()) return NPT_FAILURE;
+    return m_Datagram->GetInfo(info);
+}
+
+/*----------------------------------------------------------------------
+|    PLT_SsdpListenTask::ProcessRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_SsdpListenTask::ProcessRequest(NPT_HttpRequest&              request, 
+                                   const NPT_HttpRequestContext& context,
+                                   NPT_HttpResponse*&            response,
+                                   bool&                         headers_only) 
+{
+    NPT_COMPILER_UNUSED(headers_only);
+
+    NPT_AutoLock lock(m_Mutex);
+    m_Listeners.Apply(PLT_SsdpPacketListenerIterator(request, context));
+
+    // set response to NULL since we don't have anything to respond
+    // as we use a separate task to respond with ssdp
+    response = NULL;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|    PLT_SsdpSearchTask::PLT_SsdpSearchTask
++---------------------------------------------------------------------*/
+PLT_SsdpSearchTask::PLT_SsdpSearchTask(NPT_UdpSocket*                  socket,
+                                       PLT_SsdpSearchResponseListener* listener, 
+                                       NPT_HttpRequest*                request,
+                                       NPT_Timeout                     timeout,
+                                       bool                            repeat     /* = true */) : 
+    m_Listener(listener), 
+    m_Request(request),
+    m_Timeout(timeout),
+    m_Repeat(repeat),
+    m_Socket(socket)
+{
+    m_Socket->SetReadTimeout(timeout);
+    m_Socket->SetWriteTimeout(10000);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSearchTask::~PLT_SsdpSearchTask
++---------------------------------------------------------------------*/
+PLT_SsdpSearchTask::~PLT_SsdpSearchTask()
+{
+    delete m_Socket;
+    delete m_Request;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::DoAbort
++---------------------------------------------------------------------*/
+void
+PLT_SsdpSearchTask::DoAbort()
+{
+     m_Socket->Disconnect();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpServerSocketTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_SsdpSearchTask::DoRun()
+{
+    NPT_HttpResponse*      response = NULL;
+    PLT_HttpClient         client;
+    NPT_Timeout            timeout = 30;
+    NPT_HttpRequestContext context;
+
+    do {
+        // get the address of the server
+        NPT_IpAddress server_address;
+        NPT_CHECK_LABEL_SEVERE(server_address.ResolveName(
+                                   m_Request->GetUrl().GetHost(), 
+                                   timeout), 
+                               done);
+        NPT_SocketAddress address(server_address, 
+                                  m_Request->GetUrl().GetPort());
+
+        // send 2 requests in a row
+        NPT_OutputStreamReference output_stream(
+            new PLT_OutputDatagramStream(m_Socket, 
+                                         4096, 
+                                         &address));
+        NPT_CHECK_LABEL_SEVERE(client.SendRequest(
+                                   output_stream, 
+                                   *m_Request), 
+                               done);
+        NPT_CHECK_LABEL_SEVERE(client.SendRequest(
+                                   output_stream, 
+                                   *m_Request), 
+                               done);
+        output_stream = NULL;
+
+        // keep track of when we sent the request
+        NPT_TimeStamp last_send;
+        NPT_System::GetCurrentTimeStamp(last_send);
+
+        while (!IsAborting(0)) {
+            // read response
+            PLT_InputDatagramStreamReference input_stream(
+                new PLT_InputDatagramStream(m_Socket));
+
+            NPT_InputStreamReference stream = input_stream;
+            NPT_Result res = client.WaitForResponse(stream, 
+                                                    *m_Request, 
+                                                    context, 
+                                                    response);
+            // callback to process response
+            if (NPT_SUCCEEDED(res)) {
+                // get source info    
+                NPT_SocketInfo info;
+                input_stream->GetInfo(info);
+
+                context.SetLocalAddress(info.local_address);
+                context.SetRemoteAddress(info.remote_address);
+
+                // process response
+                ProcessResponse(NPT_SUCCESS, m_Request, context, response);
+                delete response;
+                response = NULL;
+            } else if (res != NPT_ERROR_TIMEOUT) {
+                NPT_LOG_WARNING_1("PLT_SsdpSearchTask got an error (%d) waiting for response", res);
+            }
+
+            input_stream = NULL;
+
+            // check if it's time to resend request
+            NPT_TimeStamp now;
+            NPT_System::GetCurrentTimeStamp(now);
+            if (now >= last_send + (long)m_Timeout/1000)
+                break;
+        }
+    } while (!IsAborting(0) && m_Repeat);
+
+done:
+    return;
+}
+
+/*----------------------------------------------------------------------
+|    PLT_CtrlPointGetDescriptionTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_SsdpSearchTask::ProcessResponse(NPT_Result                    res, 
+                                    NPT_HttpRequest*              request,  
+                                    const NPT_HttpRequestContext& context,
+                                    NPT_HttpResponse*             response)
+{
+    NPT_COMPILER_UNUSED(request);
+    return m_Listener->ProcessSsdpSearchResponse(res, context, response);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltSsdp.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,310 @@
+/*****************************************************************
+|
+|   Platinum - SSDP
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_SSDP_H_
+#define _PLT_SSDP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltSsdpListener.h"
+#include "PltThreadTask.h"
+#include "PltHttpServerTask.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_DeviceHost;
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSender class
++---------------------------------------------------------------------*/
+class PLT_SsdpSender
+{
+public:
+    static NPT_Result SendSsdp(NPT_HttpRequest&   request, 
+                               const char*        usn,
+                               const char*        nt,
+                               NPT_UdpSocket&     socket,
+                               bool               notify,
+                               const NPT_SocketAddress* addr = NULL);
+     
+    static NPT_Result SendSsdp(NPT_HttpResponse&  response,
+                               const char*        usn,
+                               const char*        nt,
+                               NPT_UdpSocket&     socket,
+                               bool               notify, 
+                               const NPT_SocketAddress* addr = NULL);
+
+private:
+    static NPT_Result FormatPacket(NPT_HttpMessage&   message,
+                                   const char*        usn,
+                                   const char*        nt,
+                                   NPT_UdpSocket&     socket,
+                                   bool               notify);
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpDeviceSearchResponseInterfaceIterator class
++---------------------------------------------------------------------*/
+class PLT_SsdpDeviceSearchResponseInterfaceIterator
+{
+public:
+    PLT_SsdpDeviceSearchResponseInterfaceIterator(PLT_DeviceHost*   device, 
+                                                  NPT_SocketAddress remote_addr,
+                                                  const char*       st) :
+        m_Device(device), m_RemoteAddr(remote_addr), m_ST(st)  {}
+    virtual ~PLT_SsdpDeviceSearchResponseInterfaceIterator() {}
+      
+    NPT_Result operator()(NPT_NetworkInterface*& if_addr) const;
+
+private:
+    PLT_DeviceHost*   m_Device;
+    NPT_SocketAddress m_RemoteAddr;
+    NPT_String        m_ST;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpDeviceSearchResponseTask class
++---------------------------------------------------------------------*/
+class PLT_SsdpDeviceSearchResponseTask : public PLT_ThreadTask
+{
+public:
+    PLT_SsdpDeviceSearchResponseTask(PLT_DeviceHost*   device, 
+                                     NPT_SocketAddress remote_addr,
+                                     const char*       st) : 
+        m_Device(device), m_RemoteAddr(remote_addr), m_ST(st) {}
+
+protected:
+    virtual ~PLT_SsdpDeviceSearchResponseTask() {}
+
+    // PLT_ThreadTask methods
+    virtual void DoRun();
+    
+protected:
+    PLT_DeviceHost*     m_Device;
+    NPT_SocketAddress   m_RemoteAddr;
+    NPT_String          m_ST;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpAnnounceInterfaceIterator class
++---------------------------------------------------------------------*/
+class PLT_SsdpAnnounceInterfaceIterator
+{
+public:
+    PLT_SsdpAnnounceInterfaceIterator(PLT_DeviceHost* device, bool is_byebye = false, bool broadcast = false) :
+        m_Device(device), m_IsByeBye(is_byebye), m_Broadcast(broadcast) {}
+      
+    NPT_Result operator()(NPT_NetworkInterface*& if_addr) const;
+    
+private:
+    PLT_DeviceHost* m_Device;
+    bool            m_IsByeBye;
+    bool            m_Broadcast;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpInitMulticastIterator class
++---------------------------------------------------------------------*/
+class PLT_SsdpInitMulticastIterator
+{
+public:
+    PLT_SsdpInitMulticastIterator(NPT_UdpMulticastSocket* socket) :
+        m_Socket(socket) {}
+
+    NPT_Result operator()(NPT_NetworkInterface*& if_addr) const {
+        NPT_COMPILER_UNUSED(if_addr);
+
+        NPT_IpAddress addr;
+        addr.ResolveName("239.255.255.250");
+
+#if 0
+        NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = if_addr->GetAddresses().GetFirstItem();
+        if (!niaddr) return NPT_FAILURE;
+
+        //FIXME: Should we iterate through all addresses or at least check for disconnected ones ("0.0.0.0")?
+
+        return m_Socket->JoinGroup(addr, (*niaddr).GetPrimaryAddress());
+#else
+        return m_Socket->JoinGroup(addr, NPT_IpAddress::Any);
+#endif
+    }
+
+private:
+    NPT_UdpMulticastSocket* m_Socket;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpDeviceAnnounceTask class
++---------------------------------------------------------------------*/
+class PLT_SsdpDeviceAnnounceTask : public PLT_ThreadTask
+{
+public:
+    PLT_SsdpDeviceAnnounceTask(PLT_DeviceHost*  device, 
+                               NPT_TimeInterval repeat,
+                               bool             is_byebye_first = false,
+                               bool             broadcast = false) : 
+        m_Device(device), 
+        m_Repeat(repeat), m_IsByeByeFirst(is_byebye_first), 
+        m_IsBroadcast(broadcast) {}
+
+protected:
+    virtual ~PLT_SsdpDeviceAnnounceTask() {}
+
+    // PLT_ThreadTask methods
+    virtual void DoRun();
+
+protected:
+    PLT_DeviceHost*             m_Device;
+    NPT_TimeInterval            m_Repeat;
+    bool                        m_IsByeByeFirst;
+    bool                        m_IsBroadcast;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_NetworkInterfaceAddressSearchIterator class
++---------------------------------------------------------------------*/
+class PLT_NetworkInterfaceAddressSearchIterator
+{
+public:
+    PLT_NetworkInterfaceAddressSearchIterator(NPT_String ip) : m_Ip(ip)  {}
+    virtual ~PLT_NetworkInterfaceAddressSearchIterator() {}
+
+    NPT_Result operator()(NPT_NetworkInterface*& addr) const {
+        NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = addr->GetAddresses().GetFirstItem();
+        if (!niaddr) return NPT_FAILURE;
+
+        return (m_Ip.Compare((*niaddr).GetPrimaryAddress().ToString(), true) == 0) ? NPT_SUCCESS : NPT_FAILURE;
+    }
+
+private:
+    NPT_String m_Ip;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpPacketListenerIterator class
++---------------------------------------------------------------------*/
+class PLT_SsdpPacketListenerIterator
+{
+public:
+    PLT_SsdpPacketListenerIterator(NPT_HttpRequest&              request, 
+                                   const NPT_HttpRequestContext& context) :
+      m_Request(request), m_Context(context) {}
+
+    NPT_Result operator()(PLT_SsdpPacketListener*& listener) const {
+        return listener->OnSsdpPacket(m_Request, m_Context);
+    }
+
+private:
+    NPT_HttpRequest&              m_Request;
+    const NPT_HttpRequestContext& m_Context;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpListenTask class
++---------------------------------------------------------------------*/
+class PLT_SsdpListenTask : public PLT_HttpServerSocketTask
+{
+public:
+    PLT_SsdpListenTask(NPT_Socket* socket, bool multicast = true) : 
+        PLT_HttpServerSocketTask(socket, true), 
+        m_IsMulticast(multicast) {}
+
+    NPT_Result AddListener(PLT_SsdpPacketListener* listener) {
+        NPT_AutoLock lock(m_Mutex);
+        m_Listeners.Add(listener);
+        return NPT_SUCCESS;
+    }
+
+    NPT_Result RemoveListener(PLT_SsdpPacketListener* listener) {
+        NPT_AutoLock lock(m_Mutex);
+        m_Listeners.Remove(listener);
+        return NPT_SUCCESS;
+    }
+
+protected:
+    virtual ~PLT_SsdpListenTask() {}
+
+    // PLT_ThreadTask methods
+    virtual void DoInit();
+
+    // PLT_HttpServerSocketTask methods
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetInfo(NPT_SocketInfo& info);
+    NPT_Result ProcessRequest(NPT_HttpRequest&              request, 
+                              const NPT_HttpRequestContext& context,
+                              NPT_HttpResponse*&            response,
+                              bool&                         headers_only);
+
+protected:
+    PLT_InputDatagramStreamReference  m_Datagram;
+    bool                              m_IsMulticast;
+    NPT_List<PLT_SsdpPacketListener*> m_Listeners;
+    NPT_Mutex                         m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSearchTask class
++---------------------------------------------------------------------*/
+class PLT_SsdpSearchTask : public PLT_ThreadTask
+{
+public:
+    PLT_SsdpSearchTask(NPT_UdpSocket*                  socket,
+                       PLT_SsdpSearchResponseListener* listener, 
+                       NPT_HttpRequest*                request,
+                       NPT_Timeout                     timeout,
+                       bool                            repeat = true);
+
+protected:
+    virtual ~PLT_SsdpSearchTask();
+
+    // PLT_ThreadTask methods
+    virtual void DoAbort();
+    virtual void DoRun();
+
+    virtual NPT_Result ProcessResponse(NPT_Result                    res, 
+                                       NPT_HttpRequest*              request,  
+                                       const NPT_HttpRequestContext& context,
+                                       NPT_HttpResponse*             response);
+
+private:
+    PLT_SsdpSearchResponseListener* m_Listener;
+    NPT_HttpRequest*                m_Request;
+    NPT_Timeout                     m_Timeout;
+    bool                            m_Repeat;
+    NPT_UdpSocket*                  m_Socket;
+};
+
+#endif /* _PLT_SSDP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltSsdpListener.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,65 @@
+/*****************************************************************
+|
+|   Platinum - SSDP Listener
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_SSDP_LISTENER_H_
+#define _PLT_SSDP_LISTENER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpPacketListener class
++---------------------------------------------------------------------*/
+class PLT_SsdpPacketListener
+{
+public:
+    virtual ~PLT_SsdpPacketListener() {}
+    virtual NPT_Result OnSsdpPacket(NPT_HttpRequest&              request, 
+                                    const NPT_HttpRequestContext& context) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SsdpSearchResponseListener class
++---------------------------------------------------------------------*/
+class PLT_SsdpSearchResponseListener
+{
+public:
+    virtual ~PLT_SsdpSearchResponseListener() {}
+    virtual NPT_Result ProcessSsdpSearchResponse(NPT_Result                    res,  
+                                                 const NPT_HttpRequestContext& context,
+                                                 NPT_HttpResponse*             response) = 0;
+};
+
+#endif /* _PLT_SSDP_LISTENER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltStateVariable.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,211 @@
+/*****************************************************************
+|
+|   Platinum - Service State Variable
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltStateVariable.h"
+#include "PltService.h"
+#include "PltXmlHelper.h"
+#include "PltUPnP.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.statevariable")
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::PLT_StateVariable
++---------------------------------------------------------------------*/
+PLT_StateVariable::PLT_StateVariable(PLT_Service* service) : 
+    m_Service(service), 
+    m_AllowedValueRange(NULL),
+    m_IsSendingEventsIndirectly(true)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::~PLT_StateVariable
++---------------------------------------------------------------------*/
+PLT_StateVariable::~PLT_StateVariable() 
+{
+    m_AllowedValues.Apply(NPT_ObjectDeleter<NPT_String>());
+    if (m_AllowedValueRange) delete m_AllowedValueRange;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::GetSCPDXML(NPT_XmlElementNode* node)
+{
+    NPT_XmlElementNode* variable = new NPT_XmlElementNode("stateVariable");
+    NPT_CHECK_SEVERE(node->AddChild(variable));
+
+    NPT_CHECK_SEVERE(variable->SetAttribute("sendEvents", m_IsSendingEvents?"yes":"no"));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(variable, "name", m_Name));
+    NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(variable, "dataType", m_DataType));
+    if (m_DefaultValue.GetLength()) {
+        NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(variable, "defaultValue", m_DefaultValue));
+    }
+
+    if (m_AllowedValues.GetItemCount()) {
+        NPT_XmlElementNode* allowedValueList = new NPT_XmlElementNode("allowedValueList");
+        NPT_CHECK_SEVERE(variable->AddChild(allowedValueList));
+	    for( int l = 0 ; l < (int)m_AllowedValues.GetItemCount(); l++) {
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(allowedValueList, "allowedValue", (*m_AllowedValues[l])));
+        }
+    } else if (m_AllowedValueRange) {
+        NPT_XmlElementNode* range = new NPT_XmlElementNode("allowedValueRange");
+        NPT_CHECK_SEVERE(variable->AddChild(range));
+        NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(range, "minimum", NPT_String::FromInteger(m_AllowedValueRange->min_value)));
+        NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(range, "maximum", NPT_String::FromInteger(m_AllowedValueRange->max_value)));
+        if (m_AllowedValueRange->step != -1) {
+            NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(range, "step",    NPT_String::FromInteger(m_AllowedValueRange->step)));
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::GetService
++---------------------------------------------------------------------*/
+PLT_Service* 
+PLT_StateVariable::GetService() 
+{
+    return m_Service;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::IsSendingEvents
++---------------------------------------------------------------------*/
+bool 
+PLT_StateVariable::IsSendingEvents(bool indirectly /* = false */) 
+{
+    if (indirectly) {
+        return (!m_IsSendingEvents && 
+                !m_Name.StartsWith("A_ARG_TYPE_") && 
+                m_IsSendingEventsIndirectly);
+    }
+
+    return m_IsSendingEvents;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::DisableIndirectEventing
++---------------------------------------------------------------------*/
+void
+PLT_StateVariable::DisableIndirectEventing()
+{
+    m_IsSendingEventsIndirectly = false;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::SetRate
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::SetRate(NPT_TimeInterval rate)
+{
+    if (!IsSendingEvents()) return NPT_FAILURE;
+
+    m_Rate = rate;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::SetValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::SetValue(const char* value)
+{
+    if (value == NULL) {
+        return NPT_FAILURE;
+    }
+
+    // update only if it's different
+    if (m_Value != value) {
+        NPT_Result res = ValidateValue(value);
+        if (NPT_FAILED(res)) {
+            return res;
+        }
+
+        m_Value = value;
+        m_Service->AddChanged(this); 
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::IsReadyToPublish
++---------------------------------------------------------------------*/
+bool
+PLT_StateVariable::IsReadyToPublish()
+{
+    NPT_TimeStamp now;
+    NPT_System::GetCurrentTimeStamp(now);
+
+    if (m_Rate == NPT_TimeStamp() || m_LastEvent + m_Rate <= now ) {
+        m_LastEvent = now;
+        return true;
+    }
+
+    return false;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::ValidateValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::ValidateValue(const char* value)
+{
+    if (m_DataType.Compare("string", true) == 0) {
+        // if we have a value allowed restriction, make sure the value is in our list
+        if (m_AllowedValues.GetItemCount()) {
+            return m_AllowedValues.Find(NPT_StringFinder(value))?NPT_SUCCESS:NPT_FAILURE;
+        }
+    }
+
+    // TODO: there are more to it than allowed values, we need to test for range, etc..
+    return NPT_SUCCESS;    
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable::Find
++---------------------------------------------------------------------*/
+PLT_StateVariable*
+PLT_StateVariable::Find(NPT_List<PLT_StateVariable*>& vars, const char* name)
+{
+    PLT_StateVariable* stateVariable = NULL;
+    NPT_ContainerFind(vars, PLT_StateVariableNameFinder(name), stateVariable);
+    return stateVariable;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltStateVariable.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,139 @@
+/*****************************************************************
+|
+|   Platinum - Service State Variable
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_STATE_VARIABLE_H_
+#define _PLT_STATE_VARIABLE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_Argument;
+class PLT_Service;
+
+/*----------------------------------------------------------------------
+|   NPT_AllowedValueRange class
++---------------------------------------------------------------------*/
+typedef struct {
+    NPT_Int32 min_value;
+    NPT_Int32 max_value;
+    NPT_Int32 step;
+} NPT_AllowedValueRange;
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariable class
++---------------------------------------------------------------------*/
+class PLT_StateVariable
+{
+public:
+    PLT_StateVariable(PLT_Service* service);
+    ~PLT_StateVariable();
+
+    NPT_Result   GetSCPDXML(NPT_XmlElementNode* node);
+    PLT_Service* GetService();
+    bool         IsSendingEvents(bool indirectly = false);
+    void         DisableIndirectEventing();
+    NPT_Result   SetRate(NPT_TimeInterval rate);
+    NPT_Result   SetValue(const char* value);
+    NPT_Result   ValidateValue(const char* value);
+
+    const NPT_String& GetName()     const { return m_Name;     }
+    const NPT_String& GetValue()    const { return m_Value;    }
+    const NPT_String& GetDataType() const { return m_DataType; }
+
+    static PLT_StateVariable* Find(NPT_List<PLT_StateVariable*>& vars, 
+                                   const char*                   name);
+
+protected:
+    bool         IsReadyToPublish();
+
+protected:
+    friend class PLT_Service;
+
+    //members
+    PLT_Service*            m_Service;
+    NPT_AllowedValueRange*  m_AllowedValueRange;
+    NPT_String              m_Name;
+    NPT_String              m_DataType;
+    NPT_String              m_DefaultValue;
+    bool                    m_IsSendingEvents;
+    bool                    m_IsSendingEventsIndirectly;
+    NPT_TimeInterval        m_Rate;
+    NPT_TimeStamp           m_LastEvent;
+    NPT_Array<NPT_String*>  m_AllowedValues;
+    NPT_String              m_Value;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_StateVariableNameFinder
++---------------------------------------------------------------------*/
+class PLT_StateVariableNameFinder 
+{
+public:
+    // methods
+    PLT_StateVariableNameFinder(const char* name) : m_Name(name) {}
+    virtual ~PLT_StateVariableNameFinder() {}
+
+    bool operator()(const PLT_StateVariable* const & state_variable) const {
+        return state_variable->GetName().Compare(m_Name, true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String   m_Name;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_ListStateVariableNameFinder
++---------------------------------------------------------------------*/
+class PLT_ListStateVariableNameFinder
+{
+public:
+    // methods
+    PLT_ListStateVariableNameFinder(const char* name) : m_Name(name) {}
+    virtual ~PLT_ListStateVariableNameFinder() {}
+
+    bool operator()(const PLT_StateVariable* const & state_variable) const {
+        return state_variable->GetName().Compare(m_Name, true) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String   m_Name;
+};
+
+#endif /* _PLT_STATE_VARIABLE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltStreamPump.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,226 @@
+/*****************************************************************
+|
+|   Platinum - Stream Pump
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltStreamPump.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   PLT_StreamPump::PLT_StreamPump
++---------------------------------------------------------------------*/
+PLT_StreamPump::PLT_StreamPump(NPT_Size size) :
+    m_TotalBytesRead(0),
+    m_TotalBytesWritten(0)
+{
+    m_RingBuffer = new NPT_RingBuffer(size);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StreamPump::~PLT_StreamPump
++---------------------------------------------------------------------*/
+PLT_StreamPump::~PLT_StreamPump()
+{
+    delete m_RingBuffer;
+}
+/*----------------------------------------------------------------------+
+|    PLT_StreamPump::PushData
++----------------------------------------------------------------------*/
+NPT_Result
+PLT_StreamPump::PushData(NPT_OutputStream& output, 
+                         NPT_Size&         bytes_written)
+{
+    NPT_Result res = NPT_ERROR_WOULD_BLOCK;
+    NPT_Size   count = 0;
+    NPT_Size   bytes_available = m_RingBuffer->GetContiguousAvailable();
+
+    bytes_written = 0;
+
+    if (bytes_available) {
+        res = output.Write(m_RingBuffer->GetReadPointer(), bytes_available, &count);
+        m_RingBuffer->MoveOut(count);
+        bytes_written += count;
+
+        // check if we wrapped around
+        bytes_available = m_RingBuffer->GetContiguousAvailable();
+        if (NPT_SUCCEEDED(res) && bytes_available) {
+            res = output.Write(m_RingBuffer->GetReadPointer(), bytes_available, &count);
+            m_RingBuffer->MoveOut(count);
+            bytes_written += count;
+        }
+    }
+
+    m_TotalBytesWritten += bytes_written;
+
+    return res;
+}
+
+/*----------------------------------------------------------------------+
+|    PLT_StreamPump::PullData
++----------------------------------------------------------------------*/
+NPT_Result
+PLT_StreamPump::PullData(NPT_InputStream& input, 
+                         NPT_Size         max_bytes_to_read)
+{
+    NPT_Result res = NPT_ERROR_WOULD_BLOCK;
+    NPT_Size   byte_space = m_RingBuffer->GetContiguousSpace();
+
+    // check that there is space left
+    // make sure we don't read more than our contiguous space
+    NPT_Size nb_to_read = (max_bytes_to_read<byte_space)?max_bytes_to_read:byte_space;
+    if (nb_to_read > 0) {
+        NPT_Size count;
+        res = input.Read(m_RingBuffer->GetWritePointer(), nb_to_read, &count);
+        m_RingBuffer->MoveIn(count);
+        max_bytes_to_read -= count;
+        m_TotalBytesRead += count;
+
+        byte_space = m_RingBuffer->GetContiguousSpace();
+        nb_to_read = (max_bytes_to_read<byte_space)?max_bytes_to_read:byte_space;
+        // if we filled our contiguous space, and we wrapped, check if there is more to read 
+        if (NPT_SUCCEEDED(res) && (nb_to_read > 0)) {
+            res = input.Read(m_RingBuffer->GetWritePointer(), nb_to_read, &count);
+            m_RingBuffer->MoveIn(count);
+            m_TotalBytesRead += count;
+        }
+    }
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump::PLT_PipeInputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeInputStreamPump::PLT_PipeInputStreamPump(NPT_OutputStreamReference& output,
+                                                 NPT_Size                   size) : 
+    PLT_StreamPump(size),
+    m_Output(output),
+    m_LastRes(NPT_SUCCESS)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump::~PLT_PipeInputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeInputStreamPump::~PLT_PipeInputStreamPump()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump::Receive
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_PipeInputStreamPump::Receive(NPT_InputStream& input, 
+                                 NPT_Size         max_bytes_to_read, 
+                                 NPT_Size*        bytes_read)
+{
+    NPT_Size count;
+    NPT_Result res;
+
+    if ((m_LastRes == NPT_SUCCESS) || (m_LastRes == NPT_ERROR_WOULD_BLOCK)) {
+        // look at what we have buffered already from out input
+        // and if have less than what was asked, read more
+        NPT_Size available = m_RingBuffer->GetAvailable();
+        if (available < max_bytes_to_read) {
+            m_LastRes = PullData(input, max_bytes_to_read-available);
+        }    
+    } else if (!m_RingBuffer->GetAvailable()) {
+        // if the buffer is now empty, return the input last error
+        return m_LastRes;
+    }
+    
+    // write as much as we can on the output stream
+    res = PushData(*m_Output, count);
+
+    if (bytes_read) *bytes_read = count;
+    return res;
+}
+
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStreamPump::PLT_PipeOutputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeOutputStreamPump::PLT_PipeOutputStreamPump(NPT_InputStreamReference& input,
+                                                   NPT_Size                  size /* 65535 */,
+                                                   NPT_Size                  max_bytes_to_read /* = 0 */) : 
+    PLT_StreamPump(size),
+    m_Input(input),
+    m_MaxBytesToRead(max_bytes_to_read),
+    m_LastRes(NPT_SUCCESS)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStreamPump::~PLT_PipeOutputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeOutputStreamPump::~PLT_PipeOutputStreamPump()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStreamPump::Transmit
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_PipeOutputStreamPump::Transmit(NPT_OutputStream& output)
+{
+    NPT_Size count;
+    NPT_Result res;
+
+    if ((m_LastRes == NPT_SUCCESS) || (m_LastRes == NPT_ERROR_WOULD_BLOCK)) {
+        // fill the entire space by default
+        NPT_Size max_space   = m_RingBuffer->GetSpace();
+        if (max_space) {
+            NPT_Size max_to_read = max_space;
+            if (m_MaxBytesToRead != 0) {
+                // if a total maximum amount was set, make sure we don't read more
+                max_to_read = ((m_MaxBytesToRead - m_TotalBytesRead) < max_space) ? (m_MaxBytesToRead - m_TotalBytesRead) : max_space;
+            }
+
+            // any data to read
+            if (max_to_read) {
+                m_LastRes = PullData(*m_Input, max_to_read);   
+            } else {
+                m_LastRes = NPT_ERROR_EOS;
+            }
+        }    
+    } else if (!m_RingBuffer->GetAvailable()) {
+        // if the buffer is now empty, return the input last error
+        return m_LastRes;
+    }
+
+    // write as much as we can on the output stream
+    res = PushData(output, count);
+    return res;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltStreamPump.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,131 @@
+/*****************************************************************
+|
+|   Platinum - Stream Pump
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_STREAM_PUMP_H_
+#define _PLT_STREAM_PUMP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptStreams.h"
+#include "NptRingBuffer.h"
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStream
++---------------------------------------------------------------------*/
+class PLT_PipeInputStream
+{
+public:
+    // constructor and destructor
+    virtual ~PLT_PipeInputStream() {};
+
+    // methods
+    virtual NPT_Result Receive(NPT_InputStream& stream, NPT_Size max_bytes_to_read, NPT_Size* bytes_read = 0) = 0;
+};
+
+typedef NPT_Reference<PLT_PipeInputStream> PLT_PipeInputStreamReference;
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStream
++---------------------------------------------------------------------*/
+class PLT_PipeOutputStream
+{
+public:
+    // constructor and destructor
+    virtual ~PLT_PipeOutputStream() {};
+
+    // methods
+    virtual NPT_Result Transmit(NPT_OutputStream& stream) = 0;
+};
+
+typedef NPT_Reference<PLT_PipeOutputStream> PLT_PipeOutputStreamReference;
+
+/*----------------------------------------------------------------------
+|   PLT_StreamPump class
++---------------------------------------------------------------------*/
+class PLT_StreamPump
+{
+public:
+    virtual ~PLT_StreamPump();
+
+protected:
+    // methods
+    PLT_StreamPump(NPT_Size size = 65535);
+    NPT_Result PullData(NPT_InputStream& input, NPT_Size max_bytes_to_read);
+    NPT_Result PushData(NPT_OutputStream& output, NPT_Size& bytes_written);
+
+    // members
+    NPT_RingBuffer*     m_RingBuffer;
+    NPT_Offset          m_TotalBytesRead;
+    NPT_Offset          m_TotalBytesWritten;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump class
++---------------------------------------------------------------------*/
+class PLT_PipeInputStreamPump : public PLT_StreamPump,
+                                public PLT_PipeInputStream
+{
+public:
+    PLT_PipeInputStreamPump(NPT_OutputStreamReference& output, NPT_Size size = 65535);
+    virtual ~PLT_PipeInputStreamPump();
+
+    NPT_Result Receive(NPT_InputStream& input, NPT_Size max_bytes_to_read, NPT_Size* bytes_read);
+
+protected:
+    NPT_OutputStreamReference   m_Output;
+    NPT_Result                  m_LastRes;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump class
++---------------------------------------------------------------------*/
+class PLT_PipeOutputStreamPump : public PLT_StreamPump,
+                                 public PLT_PipeOutputStream
+{
+public:
+    PLT_PipeOutputStreamPump(NPT_InputStreamReference& input, 
+                             NPT_Size                  size = 65535,
+                             NPT_Size                  max_bytes_to_read = 0);
+    virtual ~PLT_PipeOutputStreamPump();
+
+    NPT_Result Transmit(NPT_OutputStream& output);
+
+protected:
+    NPT_InputStreamReference    m_Input;
+    NPT_Size                    m_MaxBytesToRead;
+    NPT_Result                  m_LastRes;
+};
+
+
+#endif // _PLT_STREAM_PUMP_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltTaskManager.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,147 @@
+/*****************************************************************
+|
+|   Platinum - Task Manager
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltThreadTask.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.taskmanager")
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager::PLT_TaskManager
++---------------------------------------------------------------------*/
+PLT_TaskManager::PLT_TaskManager(NPT_Cardinal max_items /* = 0 */) :
+    m_Queue(max_items?new NPT_Queue<int>(max_items):NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager::~PLT_TaskManager
++---------------------------------------------------------------------*/
+PLT_TaskManager::~PLT_TaskManager()
+{    
+    StopAllTasks();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager::StartTask
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_TaskManager::StartTask(PLT_ThreadTask*   task, 
+                           NPT_TimeInterval* delay /* = NULL*/,
+                           bool              auto_destroy /* = true */)
+{
+    return task->Start(this, delay, auto_destroy);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager::StopAllTasks
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_TaskManager::StopAllTasks()
+{
+    // unblock the queue if any
+    if (m_Queue) {
+        NPT_Queue<int>* queue = m_Queue;
+        m_Queue = NULL;
+        delete queue;
+    }  
+
+    // stop all tasks first but don't block
+    // otherwise when RemoveTask is called by PLT_ThreadTask::Run
+    // it will deadlock with m_TasksLock
+    {      
+        NPT_AutoLock lock(m_TasksLock);
+        NPT_List<PLT_ThreadTask*>::Iterator task = m_Tasks.GetFirstItem();
+        while (task) {
+            (*task)->Stop(false);
+            ++task;
+        }
+    }
+
+    // then wait for list to become empty
+    // as tasks remove themselves from the list
+    while (1) {
+        {
+            NPT_AutoLock lock(m_TasksLock);
+            if (m_Tasks.GetItemCount() == 0)
+                return NPT_SUCCESS;
+        }
+
+        NPT_System::Sleep(NPT_TimeInterval(0, 10000));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager::AddTask
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_TaskManager::AddTask(PLT_ThreadTask* task) 
+{
+    if (m_Queue) {
+        NPT_CHECK_SEVERE(m_Queue->Push(new int));
+    }
+
+    {
+        NPT_AutoLock lock(m_TasksLock);
+        return m_Tasks.Add(task);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager::RemoveTask
++---------------------------------------------------------------------*/
+// called by a PLT_ThreadTask::Run when done
+NPT_Result
+PLT_TaskManager::RemoveTask(PLT_ThreadTask* task)
+{
+    if (m_Queue) {
+        int* val = NULL;
+        if (NPT_SUCCEEDED(m_Queue->Pop(val)))
+            delete val;
+    }
+
+    {
+        NPT_AutoLock lock(m_TasksLock);
+        m_Tasks.Remove(task);
+    }
+    
+    // cleanup task only if auto-destroy flag was set
+    if (task->m_AutoDestroy) delete task;
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltTaskManager.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,82 @@
+/*****************************************************************
+|
+|   Platinum - Task Manager
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_TASKMANAGER_H_
+#define _PLT_TASKMANAGER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_ThreadTask;
+
+/*----------------------------------------------------------------------
+|   PLT_TaskManager class
++---------------------------------------------------------------------*/
+class PLT_TaskManager
+{
+    friend class PLT_ThreadTask;
+    friend class PLT_ThreadTaskCallback;
+
+public:
+	PLT_TaskManager(NPT_Cardinal max_items = 0);
+	virtual ~PLT_TaskManager();
+
+    // tasks related methods
+    virtual NPT_Result StartTask(PLT_ThreadTask*   task, 
+                                 NPT_TimeInterval* delay = NULL,
+                                 bool              auto_destroy = true);
+
+    // methods
+    NPT_Result StopAllTasks();
+
+private:
+    // called by PLT_ThreadTaskCallback
+    NPT_Mutex& GetCallbackLock() { return m_CallbackLock; }
+
+    // called by PLT_ThreadTask
+    NPT_Result AddTask(PLT_ThreadTask* task);
+    NPT_Result RemoveTask(PLT_ThreadTask* task);
+
+private:
+    NPT_List<PLT_ThreadTask*>  m_Tasks;
+    NPT_Mutex                  m_TasksLock;
+    NPT_Mutex                  m_CallbackLock;
+    NPT_Queue<int>*            m_Queue;
+};
+
+#endif /* _PLT_TASKMANAGER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltThreadTask.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,157 @@
+/*****************************************************************
+|
+|   Platinum - Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltThreadTask.h"
+#include "PltTaskManager.h" 
+
+NPT_SET_LOCAL_LOGGER("platinum.core.threadtask")
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask::PLT_ThreadTask
++---------------------------------------------------------------------*/
+PLT_ThreadTask::PLT_ThreadTask() :
+    m_TaskManager(NULL),
+    m_Thread(NULL),
+    m_AutoDestroy(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask::~PLT_ThreadTask
++---------------------------------------------------------------------*/
+PLT_ThreadTask::~PLT_ThreadTask()
+{
+    if (!m_AutoDestroy) delete m_Thread;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::Start(PLT_TaskManager*  task_manager /* = NULL */, 
+                      NPT_TimeInterval* delay /* = NULL */,
+                      bool              auto_destroy /* = true */)
+{
+    m_Abort.SetValue(0);
+    m_AutoDestroy = auto_destroy;
+
+    if (delay) m_Delay = *delay;
+
+    if (task_manager) {
+        m_TaskManager = task_manager;
+        NPT_CHECK_SEVERE(m_TaskManager->AddTask(this));
+    }
+
+    m_Thread = new NPT_Thread((NPT_Runnable&)*this, m_AutoDestroy);
+    return m_Thread->Start();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::Stop(bool blocking /* = true */)
+{
+    m_Abort.SetValue(1);
+
+    // tell thread we want to die
+    DoAbort();
+
+    // if auto-destroy, the thread may be dead, so we can't wait
+    // regardless on the m_Thread...only TaskManager knows
+    if (m_AutoDestroy == true && blocking) return NPT_FAILURE;
+
+    // wait for thread to be dead
+    return (blocking && m_Thread)?m_Thread->Wait():NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask::Kill
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::Kill()
+{
+    // A task can only be destroyed manually
+    // when the m_AutoDestroy is false
+    // otherwise the task manager takes
+    // care of deleting it
+
+    NPT_ASSERT(m_AutoDestroy == false);
+
+    Stop();
+
+    // cleanup
+    delete this;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask::Run
++---------------------------------------------------------------------*/
+void
+PLT_ThreadTask::Run() 
+{
+    if (m_Delay) {
+        NPT_TimeStamp start, now;
+        NPT_System::GetCurrentTimeStamp(start);
+        do {
+            NPT_System::GetCurrentTimeStamp(now);
+            if (now >= start + m_Delay) break;
+        } while(!IsAborting(100));
+    }
+
+    if (!IsAborting(0))  {
+        DoInit();
+        DoRun();
+    }
+
+    if (m_TaskManager) {
+        m_TaskManager->RemoveTask(this);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTaskCallback::Callback
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTaskCallback::Callback()
+{
+    // acquire global lock
+    NPT_AutoLock lock(m_Lock);
+
+    // invoke callback
+    return DoCallback();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltThreadTask.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,108 @@
+/*****************************************************************
+|
+|   Platinum - Thread Tasks
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_THREADTASK_H_
+#define _PLT_THREADTASK_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltTaskManager.h"
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTask class
++---------------------------------------------------------------------*/
+class PLT_ThreadTask : public NPT_Runnable
+{
+public:
+    friend class PLT_TaskManager;
+
+    PLT_ThreadTask();
+
+    NPT_Result Kill();
+
+    virtual bool IsAborting(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+        return NPT_SUCCEEDED(m_Abort.WaitUntilEquals(1, timeout));
+    }
+
+protected:
+    NPT_Result Start(PLT_TaskManager*  task_manager = NULL, 
+                     NPT_TimeInterval* delay = NULL,
+                     bool              auto_destroy = true);
+    NPT_Result Stop(bool blocking = true);
+
+    // overridable
+    virtual void DoAbort()   {}
+    virtual void DoRun()     {}
+    virtual void DoInit()    {}
+
+    // the task manager will destroy the task when finished
+    // if m_AutoDestroy is set otherwise use Kill 
+    virtual ~PLT_ThreadTask();
+    
+private:
+    // NPT_Thread methods
+    void Run();
+
+protected:
+    // members
+    PLT_TaskManager*    m_TaskManager;
+
+private:
+    // members
+    NPT_SharedVariable  m_Abort;
+    NPT_Thread*         m_Thread;
+    bool                m_AutoDestroy;
+    NPT_TimeInterval    m_Delay;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_ThreadTaskCallback class
++---------------------------------------------------------------------*/
+class PLT_ThreadTaskCallback
+{
+public:
+    PLT_ThreadTaskCallback(NPT_Mutex& lock) : m_Lock(lock) {}
+    virtual ~PLT_ThreadTaskCallback() {};
+
+    NPT_Result Callback();
+
+protected:
+    virtual NPT_Result DoCallback() = 0;
+
+protected:
+    NPT_Mutex& m_Lock;
+};
+
+#endif /* _PLT_THREADTASK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltUPnP.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,259 @@
+/*****************************************************************
+|
+|   Platinum - UPnP Engine
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltVersion.h"
+#include "PltUPnP.h"
+#include "PltDeviceHost.h"
+#include "PltCtrlPoint.h"
+#include "PltSsdp.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.upnp")
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP_CtrlPointStartIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_CtrlPointStartIterator
+{
+public:
+    PLT_UPnP_CtrlPointStartIterator(PLT_SsdpListenTask* listen_task) :
+        m_ListenTask(listen_task)  {}
+    virtual ~PLT_UPnP_CtrlPointStartIterator() {}
+
+    NPT_Result operator()(PLT_CtrlPointReference& ctrl_point) const {
+        NPT_CHECK_SEVERE(ctrl_point->Start(m_ListenTask));
+        return NPT_SUCCESS;
+    }
+
+private:
+    PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP_CtrlPointStopIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_CtrlPointStopIterator
+{
+public:
+    PLT_UPnP_CtrlPointStopIterator(PLT_SsdpListenTask* listen_task) :
+        m_ListenTask(listen_task)  {}
+    virtual ~PLT_UPnP_CtrlPointStopIterator() {}
+
+    NPT_Result operator()(PLT_CtrlPointReference& ctrl_point) const {
+        return ctrl_point->Stop(m_ListenTask);
+    }
+
+
+private:
+    PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP_DeviceStartIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_DeviceStartIterator
+{
+public:
+    PLT_UPnP_DeviceStartIterator(PLT_SsdpListenTask* listen_task) :
+        m_ListenTask(listen_task)  {}
+    virtual ~PLT_UPnP_DeviceStartIterator() {}
+
+    NPT_Result operator()(PLT_DeviceHostReference& device_host) const {
+        NPT_CHECK_SEVERE(device_host->Start(m_ListenTask));
+        return NPT_SUCCESS;
+    }
+
+private:
+    PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP_DeviceStopIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_DeviceStopIterator
+{
+public:
+    PLT_UPnP_DeviceStopIterator(PLT_SsdpListenTask* listen_task) :
+        m_ListenTask(listen_task)  {}
+    virtual ~PLT_UPnP_DeviceStopIterator() {}
+
+    NPT_Result operator()(PLT_DeviceHostReference& device_host) const {
+        return device_host->Stop(m_ListenTask);
+    }
+
+
+private:
+    PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::PLT_UPnP
++---------------------------------------------------------------------*/
+PLT_UPnP::PLT_UPnP(NPT_UInt32 port, bool multicast /* = true */) :
+    m_Started(false),
+    m_Port(port),
+    m_Multicast(multicast),
+    m_SsdpListenTask(NULL)
+{
+    NPT_HttpClient::m_UserAgentHeader = "Platinum/" PLT_PLATINUM_VERSION_STRING;
+    NPT_HttpServer::m_ServerHeader    = "UPnP/1.0, Platinum/" PLT_PLATINUM_VERSION_STRING;
+}
+    
+/*----------------------------------------------------------------------
+|   PLT_UPnP::~PLT_UPnP
++---------------------------------------------------------------------*/
+PLT_UPnP::~PLT_UPnP()
+{
+    Stop();
+
+    m_CtrlPoints.Clear();
+    m_Devices.Clear();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::Start()
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::Start()
+{
+    NPT_LOG_INFO("Starting UPnP...");
+
+    NPT_AutoLock lock(m_Lock);
+
+    if (m_Started == true) return NPT_FAILURE;
+
+    NPT_Socket* socket = m_Multicast?new NPT_UdpMulticastSocket(): new NPT_UdpSocket();
+    NPT_CHECK_SEVERE(socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, m_Port)));
+
+    /* create the ssdp listener */
+    m_SsdpListenTask = new PLT_SsdpListenTask(socket, m_Multicast);
+    NPT_CHECK_SEVERE(m_TaskManager.StartTask(m_SsdpListenTask));
+
+    /* start devices & ctrlpoints */
+    m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask));
+    m_Devices.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask));
+
+    m_Started = true;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::Stop()
+{
+    NPT_AutoLock lock(m_Lock);
+
+    if (m_Started == false) return NPT_FAILURE;
+
+    NPT_LOG_INFO("Stopping UPnP...");
+
+    // Stop ctrlpoints and devices first
+    m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStopIterator(m_SsdpListenTask));
+    m_Devices.Apply(PLT_UPnP_DeviceStopIterator(m_SsdpListenTask));
+
+    m_TaskManager.StopAllTasks();
+    m_SsdpListenTask = NULL;
+
+    m_Started = false;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::AddDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::AddDevice(PLT_DeviceHostReference& device)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    if (m_Started) {
+        NPT_LOG_INFO("Starting Device...");
+        NPT_CHECK_SEVERE(device->Start(m_SsdpListenTask));
+    }
+
+    m_Devices.Add(device);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::RemoveDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::RemoveDevice(PLT_DeviceHostReference& device)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    if (m_Started) {
+        device->Stop(m_SsdpListenTask);
+    }
+
+    return m_Devices.Remove(device);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::AddCtrlPoint
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::AddCtrlPoint(PLT_CtrlPointReference& ctrl_point)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    if (m_Started) {
+        NPT_LOG_INFO("Starting Ctrlpoint...");
+        NPT_CHECK_SEVERE(ctrl_point->Start(m_SsdpListenTask));
+    }
+
+    m_CtrlPoints.Add(ctrl_point);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP::RemoveCtrlPoint
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::RemoveCtrlPoint(PLT_CtrlPointReference& ctrl_point)
+{
+    NPT_AutoLock lock(m_Lock);
+
+    if (m_Started) {
+        ctrl_point->Stop(m_SsdpListenTask);
+    }
+
+    return m_CtrlPoints.Remove(ctrl_point);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltUPnP.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,84 @@
+/*****************************************************************
+|
+|   Platinum - UPnP Engine
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_UPNP_H_
+#define _PLT_UPNP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltCtrlPoint.h"
+#include "PltDeviceHost.h"
+#include "PltUPnPHelper.h"
+
+/*----------------------------------------------------------------------
+|   forward definitions
++---------------------------------------------------------------------*/
+class PLT_SsdpListenTask;
+
+/*----------------------------------------------------------------------
+|   PLT_UPnP class
++---------------------------------------------------------------------*/
+class PLT_UPnP
+{
+public:
+    PLT_UPnP(NPT_UInt32 ssdp_port = 1900, bool multicast = true);
+    ~PLT_UPnP();
+
+    NPT_Result AddDevice(PLT_DeviceHostReference& device);
+    NPT_Result AddCtrlPoint(PLT_CtrlPointReference& ctrlpoint);
+
+    NPT_Result RemoveDevice(PLT_DeviceHostReference& device);
+    NPT_Result RemoveCtrlPoint(PLT_CtrlPointReference& ctrlpoint);
+
+    NPT_Result Start();
+    NPT_Result Stop();
+
+private:
+    // members
+    NPT_Mutex                           m_Lock;
+    NPT_List<PLT_DeviceHostReference>   m_Devices;
+    NPT_List<PLT_CtrlPointReference>    m_CtrlPoints;
+    PLT_TaskManager                     m_TaskManager;
+
+    // since we can only have one socket listening on port 1900, 
+    // we create it in here and we will attach every control points
+    // and devices to it when they're added
+    bool                                m_Started;
+    NPT_UInt32                          m_Port;
+    bool                                m_Multicast;
+    PLT_SsdpListenTask*                 m_SsdpListenTask; 
+};
+
+#endif /* _PLT_UPNP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltUPnPHelper.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,306 @@
+/*****************************************************************
+|
+|   Platinum - UPnP Helper
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_UPNP_HELPER_H_
+#define _PLT_UPNP_HELPER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   NPT_StringFinder
++---------------------------------------------------------------------*/
+class NPT_StringFinder
+{
+public:
+    // methods
+    NPT_StringFinder(const char* value) : m_Value(value) {}
+    virtual ~NPT_StringFinder() {}
+    bool operator()(const NPT_String* const & value) const {
+        return value->Compare(m_Value) ? false : true;
+    }
+    bool operator()(const NPT_String& value) const {
+        return value.Compare(m_Value) ? false : true;
+    }
+
+private:
+    // members
+    NPT_String   m_Value;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_UPnPMessageHelper class
++---------------------------------------------------------------------*/
+class PLT_UPnPMessageHelper
+{
+public:
+    // methods
+    static const NPT_String* GetST(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("ST"); 
+    }
+    static NPT_Result SetST(NPT_HttpMessage& message, 
+                            const char*      st) { 
+        return message.GetHeaders().SetHeader("ST", st); 
+    }
+    static const NPT_String* GetNT(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("NT"); 
+    }
+    static NPT_Result SetNT(NPT_HttpMessage& message, 
+                            const char*      nt) { 
+        return message.GetHeaders().SetHeader("NT", nt); 
+    }
+    static const NPT_String* GetNTS(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("NTS"); 
+    }
+    static NPT_Result SetNTS(NPT_HttpMessage& message, 
+                             const char*      nts) { 
+        return message.GetHeaders().SetHeader("NTS", nts); 
+    }
+    static const NPT_String* GetMAN(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("MAN"); 
+    }
+    static NPT_Result SetMAN(NPT_HttpMessage& message, 
+                             const char*      man) { 
+        return message.GetHeaders().SetHeader("MAN", man); 
+    }
+    static const NPT_String* GetLocation(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("LOCATION"); 
+    }
+    static NPT_Result SetLocation(NPT_HttpMessage& message, 
+                                  const char*      location) { 
+        return message.GetHeaders().SetHeader("LOCATION", location); 
+    }
+    static const NPT_String* GetServer(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER); 
+    }
+    static NPT_Result SetServer(NPT_HttpMessage& message, 
+                                const char*      server, 
+                                bool             replace = true) { 
+        return message.GetHeaders().SetHeader(
+            NPT_HTTP_HEADER_SERVER, 
+            server, 
+            replace); 
+    }
+    static const NPT_String* GetUSN(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("USN"); 
+    }
+    static NPT_Result SetUSN(NPT_HttpMessage& message, 
+                             const char*      usn) { 
+        return message.GetHeaders().SetHeader("USN", usn); 
+    }
+    static const NPT_String* GetCallbacks(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("CALLBACK"); 
+    }
+    static NPT_Result SetCallbacks(NPT_HttpMessage& message, 
+                                   const char*      callbacks) { 
+        return message.GetHeaders().SetHeader("CALLBACK", callbacks); 
+    }
+    static const NPT_String* GetSID(NPT_HttpMessage& message) { 
+        return message.GetHeaders().GetHeaderValue("SID"); 
+    }
+    static NPT_Result SetSID(NPT_HttpMessage& message, 
+                             const char*      sid) { 
+        return message.GetHeaders().SetHeader("SID", sid); 
+    }
+    static NPT_Result GetLeaseTime(NPT_HttpMessage& message, 
+                                   NPT_Timeout&     value) { 
+        value = 0;
+        const NPT_String* cc = 
+            message.GetHeaders().GetHeaderValue("CACHE-CONTROL");
+        NPT_CHECK_POINTER(cc);
+        return ExtractLeaseTime(*cc, value); 
+    }
+    static NPT_Result SetLeaseTime(NPT_HttpMessage&  message, 
+                                   const NPT_Timeout lease) { 
+        return message.GetHeaders().SetHeader(
+            "CACHE-CONTROL", 
+            "max-age="+NPT_String::FromInteger(lease)); 
+    }
+    static NPT_Result GetTimeOut(NPT_HttpMessage& message, 
+                                 NPT_Int32&       value) { 
+        value = 0;
+        const NPT_String* timeout = 
+            message.GetHeaders().GetHeaderValue("TIMEOUT"); 
+        NPT_CHECK_POINTER(timeout);
+        return ExtractTimeOut(*timeout, value); 
+    }
+    static NPT_Result SetTimeOut(NPT_HttpMessage& message, 
+                                 const NPT_Int32  timeout) { 
+        if (timeout >= 0) {
+            return message.GetHeaders().SetHeader(
+                "TIMEOUT", 
+                "Second-"+NPT_String::FromInteger(timeout)); 
+        } else {
+            return message.GetHeaders().SetHeader(
+                "TIMEOUT", "Second-infinite"); 
+        }
+    }
+    static NPT_Result GetMX(NPT_HttpMessage& message, 
+                            NPT_UInt32&      value) { 
+        value = 0;
+        const NPT_String* mx = 
+            message.GetHeaders().GetHeaderValue("MX");
+        NPT_CHECK_POINTER(mx);
+        return NPT_ParseInteger32U(*mx, value);
+    }
+    static NPT_Result SetMX(NPT_HttpMessage& message, 
+                            const NPT_UInt32 mx) {
+        return message.GetHeaders().SetHeader(
+            "MX", 
+            NPT_String::FromInteger(mx)); 
+    }
+    static NPT_Result GetSeq(NPT_HttpMessage& message,  
+                             NPT_UInt32&      value) { 
+        value = 0;
+        const NPT_String* seq = 
+            message.GetHeaders().GetHeaderValue("SEQ");
+        NPT_CHECK_POINTER(seq);
+        return NPT_ParseInteger32U(*seq, value);
+    }
+    static NPT_Result SetSeq(NPT_HttpMessage& message, 
+                             const NPT_UInt32 seq) {
+        return message.GetHeaders().SetHeader(
+            "SEQ", 
+            NPT_String::FromInteger(seq)); 
+    }
+    static const char* GenerateUUID(int         count, 
+                                    NPT_String& uuid) {   
+        uuid = "";
+        for (int i=0;i<(count<100?count:100);i++) {
+            int random = NPT_System::GetRandomInteger();
+            uuid += (char)((random % 25) + 66);
+        }
+        return uuid;
+    }
+    static const char* GenerateGUID(NPT_String& guid) {   
+        guid = "";
+        for (int i=0;i<32;i++) {
+            char nibble = (char)(NPT_System::GetRandomInteger() % 16);
+            guid += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
+            if (i == 7 || i == 11 || i == 15 || i == 19) {
+                guid += '-';
+            }
+        }
+        return guid;
+    }
+    static NPT_Result ExtractLeaseTime(const char*  cache_control, 
+                                       NPT_Timeout& lease) {
+        int value;
+        if (cache_control && 
+            sscanf(cache_control, "max-age=%d", &value) == 1) {
+            lease = value;
+            return NPT_SUCCESS;
+        }
+        return NPT_FAILURE;
+    }
+    static NPT_Result ExtractTimeOut(const char* timeout, 
+                                     NPT_Int32&  len) {
+        NPT_String temp = timeout;
+        if (temp.CompareN("Second-", 7, true)) {
+            return NPT_ERROR_INVALID_FORMAT;
+        }
+
+        if (temp.Compare("Second-infinite", true) == 0) {
+            len = NPT_TIMEOUT_INFINITE;
+            return NPT_SUCCESS;
+        }
+        return temp.SubString(7).ToInteger(len);
+    }
+    static NPT_Result GetIPAddresses(NPT_List<NPT_String>& ips) {
+        NPT_List<NPT_NetworkInterface*> if_list;
+        NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(if_list));
+
+        NPT_List<NPT_NetworkInterface*>::Iterator iface = 
+            if_list.GetFirstItem();
+        while (iface) {
+            NPT_String ip = 
+                (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress().ToString();
+            if (ip.Compare("0.0.0.0") && ip.Compare("127.0.0.1")) {
+                ips.Add(ip);
+            }
+            ++iface;
+        }
+
+        if (ips.GetItemCount() == 0) {
+            ips.Add("127.0.0.1");
+        }
+
+        if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+        return NPT_SUCCESS;
+    }
+
+    static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list, 
+                                           bool with_localhost = false) {
+        NPT_CHECK(_GetNetworkInterfaces(if_list, false));
+
+        // if no valid interfaces or if requested, add localhost capable interface
+        if (if_list.GetItemCount() == 0 || with_localhost) {
+            NPT_CHECK(_GetNetworkInterfaces(if_list, true));
+        }
+        return NPT_SUCCESS;
+    }
+
+private:
+
+    static NPT_Result _GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list, 
+                                            bool only_localhost = false) {
+        NPT_List<NPT_NetworkInterface*> _if_list;
+        NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(_if_list));
+
+        NPT_NetworkInterface* iface;
+        while (NPT_SUCCEEDED(_if_list.PopHead(iface))) {
+            NPT_String ip = 
+                iface->GetAddresses().GetFirstItem()->GetPrimaryAddress().ToString();
+            if (ip.Compare("0.0.0.0") && 
+                ((!only_localhost && ip.Compare("127.0.0.1")) || 
+                 (only_localhost && !ip.Compare("127.0.0.1")))) {
+                if_list.Add(iface);
+
+                // add localhost only once
+                if (only_localhost) break;
+            } else {
+                delete iface;
+            }
+        }
+
+        // cleanup any remaining items in list if we breaked early
+        _if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+        return NPT_SUCCESS;
+    }
+    
+    NPT_String HttpServerHeader;
+};
+
+#endif /* _PLT_UPNP_HELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltVersion.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,42 @@
+/*****************************************************************
+|
+|   Platinum - Version Info
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_VERSION_H_
+#define _PLT_VERSION_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#define PLT_PLATINUM_VERSION_STRING "0.4.9"
+
+#endif // _PLT_VERSION_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltXmlHelper.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,267 @@
+/*****************************************************************
+|
+|   Platinum - Xml Helper
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_XML_HELPER_H_
+#define _PLT_XML_HELPER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+/*----------------------------------------------------------------------
+|   PLT_XmlAttributeFinder
++---------------------------------------------------------------------*/
+class PLT_XmlAttributeFinder
+{
+public:
+    // if 'namespc' is NULL, we're looking for ANY namespace
+    // if 'namespc' is '\0', we're looking for NO namespace
+    // if 'namespc' is non-empty, look for that SPECIFIC namespace
+    PLT_XmlAttributeFinder(const NPT_XmlElementNode& element, 
+                           const char*               name, 
+                           const char*               namespc) : 
+      m_Element(element), m_Name(name), m_Namespace(namespc) {}
+
+    bool operator()(const NPT_XmlAttribute* const & attribute) const {
+        if (attribute->GetName() == m_Name) {
+            if (m_Namespace) {
+                const NPT_String& prefix = attribute->GetPrefix();
+                if (m_Namespace[0] == '\0') {
+                    // match if the attribute has NO namespace
+                    return prefix.IsEmpty();
+                } else {
+                    // match if the attribute has the SPECIFIC namespace
+                    // we're looking for
+                    const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
+                    return namespc && *namespc == m_Namespace;
+                }
+            } else {
+                // ANY namespace will match
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+private:
+    const NPT_XmlElementNode& m_Element;
+    const char*               m_Name;
+    const char*               m_Namespace;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_XmlHelper
++---------------------------------------------------------------------*/
+class PLT_XmlHelper
+{
+public:
+
+    // static methods
+    static NPT_Result GetChildText(NPT_XmlElementNode* node, 
+                                   const char*         tag, 
+                                   NPT_String&         value,
+                                   const char*         namespc = "") {
+        value = "";
+
+        if (!node) return NPT_FAILURE;
+
+        // special case "" means we look for the same namespace as the parent
+        if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+
+        NPT_XmlElementNode* child = node->GetChild(tag, namespc);
+        if (!child) return NPT_FAILURE;
+
+        const NPT_String* text = child->GetText();
+        value = text?*text:"";
+        return NPT_SUCCESS;
+    }
+
+                                   
+    static NPT_Result GetAttribute(NPT_XmlElementNode* node, 
+                                   const char*         name,
+                                   NPT_XmlAttribute*&  attr,
+                                   const char*         namespc = "") {
+        attr = NULL;
+
+        if (!node) return NPT_FAILURE;
+
+        // special case "" means we look for the same namespace as the parent
+        if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+
+        NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+        attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
+        if (!attribute) return NPT_FAILURE;
+
+        attr = (*attribute);
+        return NPT_SUCCESS;
+    }
+
+
+    static NPT_Result GetAttribute(NPT_XmlElementNode* node, 
+                                   const char*         name,
+                                   NPT_String&         value,
+                                   const char*         namespc = "") {
+        value = "";
+        
+        NPT_XmlAttribute* attribute = NULL;
+        NPT_CHECK(GetAttribute(node, name, attribute, namespc));
+        if (!attribute) return NPT_FAILURE;
+
+        value = attribute->GetValue();
+        return NPT_SUCCESS;
+    }
+
+    static NPT_Result AddChildText(NPT_XmlElementNode* node,
+                                   const char*         tag,
+                                   const char*         text,
+                                   const char*         prefix = NULL) {
+        if (!node) return NPT_FAILURE;
+        NPT_XmlElementNode* child = new NPT_XmlElementNode(prefix, tag);
+        child->AddText(text);
+        return node->AddChild(child);
+    }
+
+    static bool IsMatch(const NPT_XmlNode* const & node, const char* tag, const char* namespc_mapped) {
+        // if m_Namespace is NULL, we're looking for ANY namespace
+        // if m_Namespace is '\0', we're looking for NO namespace
+        // if m_Namespace is non-empty, look for that SPECIFIC namespace
+        
+        const NPT_XmlElementNode* element = node->AsElementNode();
+        // is tag the same (case sensitive)?
+        if (element && element->GetTag() == tag) {
+            if (namespc_mapped) {
+                // look for a SPECIFIC namespace or NO namespace
+                const NPT_String* namespc = element->GetNamespace();
+                if (namespc) {
+                    // the element has a namespace, match if it is equal to
+                    // what we're looking for
+                    return *namespc == namespc_mapped;
+                } else {
+                    // the element does not have a namespace, match if we're
+                    // looking for NO namespace
+                    return namespc_mapped[0] == '\0';
+                }
+            } else {
+                // ANY namespace will match
+                return true;
+            }
+        }
+        return false;
+    } 
+
+    static NPT_Result GetChildren(NPT_XmlElementNode*              node,
+                                  NPT_Array<NPT_XmlElementNode*>&  children,
+                                  const char*                      tag,
+                                  const char*                      namespc = "") {
+        if (!node) return NPT_FAILURE;
+
+        // special case "" means we look for the same namespace as the parent
+        if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+
+        const char* namespc_mapped = (namespc==NULL)?"":(namespc[0]=='*' && namespc[1]=='\0')?NULL:namespc;
+
+        // get all children first
+        NPT_List<NPT_XmlNode*>& allchildren = node->GetChildren();
+
+        // iterate through children and add only elements with matching tag
+        NPT_List<NPT_XmlNode*>::Iterator child = allchildren.GetFirstItem();
+        while  (child) {
+            if (IsMatch(*child, tag, namespc_mapped)) {
+                children.Add((*child)->AsElementNode());
+            }
+            ++child;
+        }
+        return NPT_SUCCESS;
+    }
+
+    static NPT_XmlElementNode* GetChild(NPT_XmlElementNode* node,
+                                        const char*         tag,
+                                        const char*         namespc = "") {
+        if (!node) return NULL;
+
+        // special case "" means we look for the same namespace as the parent
+        if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+
+        return node->GetChild(tag, namespc);
+    }
+
+    static NPT_Result GetChild(NPT_XmlElementNode*  parent,
+                               NPT_XmlElementNode*& child,
+                               NPT_Ordinal          n = 0) {
+        if (!parent) return NPT_FAILURE;
+
+        // reset child
+        child = NULL;
+
+        // get all children first
+        NPT_List<NPT_XmlNode*>::Iterator children = parent->GetChildren().GetFirstItem();
+        while  (children) {
+            if ((*children)->AsElementNode() && n-- == 0) {
+                child = (*children)->AsElementNode();
+                return NPT_SUCCESS;
+            }
+            children++;
+        }
+
+        return NPT_FAILURE;
+    }
+
+    static NPT_Result Serialize(NPT_XmlNode& node, NPT_String& xml) {
+        NPT_XmlWriter writer(2);
+        NPT_MemoryStreamReference stream(new NPT_MemoryStream());
+        NPT_CHECK(writer.Serialize(node, *stream));
+
+        NPT_LargeSize size;
+        stream->GetAvailable(size);
+        if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE;
+
+        xml.Reserve((NPT_Size)size);
+        stream->Read(xml.UseChars(), (NPT_Size)size);
+        xml.SetLength((NPT_Size)size);
+        return NPT_SUCCESS;
+    }
+private:
+    // members
+};
+
+#endif // _PLT_XML_HELPER_H_
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/FrameStreamer/PltFrameBuffer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,91 @@
+/*****************************************************************
+|
+|   Platinum - Frame Buffer
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltFrameBuffer.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.framebuffer")
+
+/*----------------------------------------------------------------------
+|   PLT_FrameBuffer::PLT_FrameBuffer
++---------------------------------------------------------------------*/
+PLT_FrameBuffer::PLT_FrameBuffer()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameBuffer::~PLT_FrameBuffer
++---------------------------------------------------------------------*/
+PLT_FrameBuffer::~PLT_FrameBuffer()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameBuffer::SetNextFrame
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameBuffer::SetNextFrame(const NPT_Byte* data, NPT_Size size)
+{
+    NPT_AutoLock lock(m_FrameLock);
+
+    m_Frame.SetData(data, size);
+    m_FrameIndex.SetValue(m_FrameIndex.GetValue()+1);
+
+    NPT_LOG_INFO_1("Set frame %d", m_FrameIndex.GetValue());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameBuffer::GetNextFrame
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameBuffer::GetNextFrame(NPT_UInt32&     last_fame_index, 
+                              NPT_DataBuffer& buffer, 
+                              NPT_Timeout     timeout)
+{
+    NPT_CHECK_WARNING(m_FrameIndex.WaitWhileEquals(last_fame_index, timeout));
+
+    {
+        NPT_AutoLock lock(m_FrameLock);
+        buffer.SetData(m_Frame.GetData(), m_Frame.GetDataSize());
+
+        // update current frame index
+        last_fame_index = m_FrameIndex.GetValue();
+        NPT_LOG_INFO_1("Retrieved frame %d", last_fame_index);
+    }
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/FrameStreamer/PltFrameBuffer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,65 @@
+/*****************************************************************
+|
+|   Platinum - Frame Buffer
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FRAME_BUFFER_H_
+#define _PLT_FRAME_BUFFER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   PLT_FrameBuffer
++---------------------------------------------------------------------*/
+class PLT_FrameBuffer 
+{
+ public:
+    // constructor & destructor
+    PLT_FrameBuffer();
+    virtual ~PLT_FrameBuffer();
+
+    // data buffer handling methods
+    virtual NPT_Result SetNextFrame(const NPT_Byte* buffer, NPT_Size bufferSize);
+    virtual NPT_Result GetNextFrame(NPT_UInt32&     last_fame_index, 
+                                    NPT_DataBuffer& buffer, 
+                                    NPT_Timeout     timeout = NPT_TIMEOUT_INFINITE);
+
+ protected:
+    // members
+    NPT_SharedVariable m_FrameIndex;
+    NPT_DataBuffer     m_Frame;
+    NPT_Mutex          m_FrameLock;
+};
+
+#endif // _PLT_FRAME_BUFFER_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/FrameStreamer/PltFrameServer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,412 @@
+/*****************************************************************
+|
+|   Platinum - Frame Server
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltMediaItem.h"
+#include "PltService.h"
+#include "PltDidl.h"
+#include "PltFrameStream.h"
+#include "PltFrameServer.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.frame")
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define BOUNDARY "BOUNDARYGOAWAY"
+
+/*----------------------------------------------------------------------
+|   PLT_SocketPolicyServer
++---------------------------------------------------------------------*/
+class PLT_SocketPolicyServer : public NPT_Thread
+{
+public:
+    PLT_SocketPolicyServer(const char* policy, NPT_UInt32 port = 0) :
+        m_Policy(policy),
+        m_Port(port),
+        m_Aborted(false) {}
+        
+    ~PLT_SocketPolicyServer() {
+        Stop();
+    }
+        
+    NPT_Result Start() {
+        NPT_Result result = NPT_FAILURE;
+        
+        // bind
+        // randomly try a port for our http server
+        int retries = 100;
+        do {    
+            int random = NPT_System::GetRandomInteger();
+            int port = (unsigned short)(50000 + (random % 15000));
+                        
+            result = m_Socket.Bind(
+                NPT_SocketAddress(NPT_IpAddress::Any, m_Port?m_Port:port), 
+                true);
+                
+            if (NPT_SUCCEEDED(result) || m_Port)
+                break;
+        } while (--retries > 0);
+
+        if (NPT_FAILED(result) || retries == 0) return NPT_FAILURE;
+
+        // remember that we're bound
+        NPT_SocketInfo info;
+        m_Socket.GetInfo(info);
+        m_Port = info.local_address.GetPort();
+        
+        return NPT_Thread::Start();
+    }
+    
+    NPT_Result Stop() {
+        m_Aborted = true;
+        m_Socket.Disconnect();
+        
+        return Wait();
+    }
+    
+    void Run() {
+        do {
+            // wait for a connection
+            NPT_Socket* client = NULL;
+            NPT_LOG_FINE_1("waiting for connection on port %d...", m_Port);
+            NPT_Result result = m_Socket.WaitForNewClient(client, NPT_TIMEOUT_INFINITE);
+            if (NPT_FAILED(result) || client == NULL) return;
+                    
+            NPT_SocketInfo client_info;
+            client->GetInfo(client_info);
+            NPT_LOG_FINE_2("client connected (%s)",
+                       client_info.local_address.ToString().GetChars(),
+                       client_info.remote_address.ToString().GetChars());
+
+            // get the output stream
+            NPT_OutputStreamReference output;
+            client->GetOutputStream(output);
+            
+            NPT_MemoryStream* policy = new NPT_MemoryStream();
+            policy->Write(m_Policy.GetChars(), m_Policy.GetLength());
+            NPT_InputStreamReference input(policy);
+            
+            NPT_StreamToStreamCopy(*input, *output);
+            
+            
+            delete client;
+        } while (!m_Aborted);
+    }
+    
+    NPT_TcpServerSocket m_Socket;
+    NPT_String          m_Policy;
+    NPT_UInt32          m_Port;
+    bool                m_Aborted;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::PLT_FrameServer
++---------------------------------------------------------------------*/
+PLT_FrameServer::PLT_FrameServer(PLT_FrameBuffer& frame_buffer, 
+                                 const char*      www_root,
+                                 const char*      friendly_name, 
+                                 bool             show_ip, 
+                                 const char*      uuid, 
+                                 NPT_UInt16       port) :	
+    PLT_FileMediaServer(www_root,
+                        friendly_name, 
+                        show_ip,
+                        uuid, 
+                        port),
+    m_FrameBuffer(frame_buffer),
+    m_PolicyServer(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::~PLT_FrameServer
++---------------------------------------------------------------------*/
+PLT_FrameServer::~PLT_FrameServer()
+{
+    delete m_PolicyServer;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::SetupDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameServer::SetupDevice()
+{
+    // FIXME: hack for now: find the first valid non local ip address
+    // to use in item resources. TODO: we should advertise all ips as
+    // multiple resources instead.
+    NPT_List<NPT_String> ips;
+    PLT_UPnPMessageHelper::GetIPAddresses(ips);
+    if (ips.GetItemCount() == 0) return NPT_ERROR_INTERNAL;
+
+    // set the base paths for content
+    m_StreamBaseUri = NPT_HttpUrl(*ips.GetFirstItem(), GetPort(), "/screensplitr");
+    
+    // start the xml socket policy server for flash
+    m_PolicyServer = new PLT_SocketPolicyServer(
+        "<cross-domain-policy><allow-access-from domain=\"192.168.1.101\" to-ports=\"5900\" /></cross-domain-policy>", 
+        8989);
+    NPT_CHECK_SEVERE(m_PolicyServer->Start());
+
+    return PLT_FileMediaServer::SetupDevice();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::ProcessHttpRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FrameServer::ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                    const NPT_HttpRequestContext& context,
+                                    NPT_HttpResponse&             response)
+{
+    if (request.GetUrl().GetPath().StartsWith(m_StreamBaseUri.GetPath())) {
+        return ProcessStreamRequest(request, context, response);
+    }
+
+    return PLT_FileMediaServer::ProcessHttpRequest(request, context, response);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::ProcessStreamRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FrameServer::ProcessStreamRequest(NPT_HttpRequest&              request, 
+                                      const NPT_HttpRequestContext& context,
+                                      NPT_HttpResponse&             response)
+{
+    NPT_COMPILER_UNUSED(context);
+    
+    NPT_LOG_FINE("Received Request:");
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+    if (request.GetMethod().Compare("GET")) {
+        response.SetStatus(500, "Internal Server Error");
+        return NPT_SUCCESS;
+    }
+
+    response.SetProtocol(NPT_HTTP_PROTOCOL_1_0);
+    response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "close");
+    response.GetHeaders().SetHeader("Cache-Control", "no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0");
+    response.GetHeaders().SetHeader("Pragma", "no-cache");
+    response.GetHeaders().SetHeader("Expires", "Tue, 4 Jan 2000 02:43:05 GMT");
+
+    NPT_HttpEntity* entity = new NPT_HttpEntity();
+    entity->SetContentType("multipart/x-mixed-replace;boundary=" BOUNDARY);
+
+    NPT_InputStreamReference body(new PLT_InputFrameStream(m_FrameBuffer, BOUNDARY));
+    entity->SetInputStream(body, false);
+
+    return response.SetEntity(entity);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::OnBrowseMetadata
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameServer::OnBrowseMetadata(PLT_ActionReference&          action, 
+                                  const char*                   object_id, 
+                                  const PLT_HttpRequestContext& context)
+{
+    NPT_String didl;
+    PLT_MediaObjectReference item;
+
+    item = BuildFromID(object_id, &context.GetLocalAddress());
+    if (item.IsNull())  {
+        /* error */
+        NPT_LOG_WARNING("PLT_FrameServer::OnBrowse - ObjectID not found.");
+        action->SetError(701, "No Such Object.");
+        return NPT_FAILURE;
+    }
+
+    NPT_String filter;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+
+    NPT_String tmp;    
+    NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp));
+
+    /* add didl header and footer */
+    didl = didl_header + tmp + didl_footer;
+
+    NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", "1"));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", "1"));
+
+    // update ID may be wrong here, it should be the one of the container?
+    // TODO: We need to keep track of the overall updateID of the CDS
+    NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1"));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::OnBrowseDirectChildren
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameServer::OnBrowseDirectChildren(PLT_ActionReference&          action, 
+                                        const char*                   object_id, 
+                                        const PLT_HttpRequestContext& context)
+{
+    /* Only root allowed */
+    if (!NPT_StringsEqual(object_id, "0")) {
+        /* error */
+        NPT_LOG_WARNING("PLT_FrameServer::OnBrowse - ObjectID not found.");
+        action->SetError(701, "No Such Object.");
+        return NPT_FAILURE;
+    }
+
+    NPT_String startingInd;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd));
+
+    NPT_UInt32 start_index;
+    if (NPT_FAILED(startingInd.ToInteger(start_index))) {        
+        action->SetError(412, "Precondition failed");
+        return NPT_FAILURE;
+    }
+
+    NPT_String filter;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+
+    NPT_String didl = didl_header;
+    PLT_MediaObjectReference item;
+
+    unsigned long num_returned = 0;
+    unsigned long total_matches = 0;
+    if (start_index == 0) {
+        item = BuildFromID("1", &context.GetLocalAddress());
+        if (!item.IsNull()) {
+            NPT_String tmp;
+            NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp));
+            didl += tmp;
+
+            num_returned++;
+            total_matches++;        
+        }
+    };
+
+    didl += didl_footer;
+
+    NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned)));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches)));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1"));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::BuildResourceUri
++---------------------------------------------------------------------*/
+NPT_String
+PLT_FrameServer::BuildResourceUri(const NPT_HttpUrl& base_uri, 
+                                  const char*        host, 
+                                  const char*        file_path)
+{
+    NPT_HttpUrl uri = base_uri;
+
+    if (host) uri.SetHost(host);
+
+    if (file_path) {
+        uri.SetPath(uri.GetPath() + file_path);
+    }
+    
+    return uri.ToStringWithDefaultPort(0);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer::BuildFromID
++---------------------------------------------------------------------*/
+PLT_MediaObject*
+PLT_FrameServer::BuildFromID(const char* id,
+                             const NPT_SocketAddress* req_local_address /* = NULL */)
+{
+    PLT_MediaItemResource resource;
+    PLT_MediaObject*      object = NULL;
+
+    if (NPT_StringsEqual(id, "1")) {
+        object = new PLT_MediaItem();
+        object->m_ObjectID = "1";
+        object->m_ParentID = "0";
+
+        /* Set the title using the filename for now */
+        object->m_Title = "ScreenSplitr";
+
+        /* Set the protocol Info from the extension */
+        resource.m_ProtocolInfo = "http-get:*:video/x-motion-jpg:DLNA.ORG_OP=01";
+
+        /* Set the resource file size */
+        //resource.m_Size = info.m_Size;
+
+        // get list of ip addresses
+        NPT_List<NPT_String> ips;
+        NPT_CHECK_LABEL_SEVERE(PLT_UPnPMessageHelper::GetIPAddresses(ips), failure);
+
+        // if we're passed an interface where we received the request from
+        // move the ip to the top
+        if (req_local_address && req_local_address->GetIpAddress().ToString() != "0.0.0.0") {
+            ips.Remove(req_local_address->GetIpAddress().ToString());
+            ips.Insert(ips.GetFirstItem(), req_local_address->GetIpAddress().ToString());
+        }
+
+        // iterate through list and build list of resources
+        NPT_List<NPT_String>::Iterator ip = ips.GetFirstItem();
+        while (ip) {
+            /* prepend the base URI and url encode it */ 
+            //resource.m_Uri = NPT_Uri::Encode(uri.ToString(), NPT_Uri::UnsafeCharsToEncode);
+            resource.m_Uri = BuildResourceUri(m_StreamBaseUri, *ip, NULL);
+
+            object->m_ObjectClass.type = "object.item.videoItem.movie";
+            object->m_Resources.Add(resource);
+
+            ++ip;
+        }
+    } else if (NPT_StringsEqual(id, "0")) {
+        object = new PLT_MediaContainer;
+
+        object->m_ObjectID = "0";
+        object->m_ParentID = "-1";
+        object->m_Title    = "Root";
+        ((PLT_MediaContainer*)object)->m_ChildrenCount = 1;
+
+        object->m_ObjectClass.type = "object.container";
+    }
+
+    return object;
+
+failure:
+    delete object;
+    return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/FrameStreamer/PltFrameServer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,97 @@
+/*****************************************************************
+|
+|   Platinum - Frame Server
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FRAME_SERVER_H_
+#define _PLT_FRAME_SERVER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltFileMediaServer.h"
+#include "PltFrameBuffer.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_SocketPolicyServer;
+
+/*----------------------------------------------------------------------
+|   PLT_FrameServer class
++---------------------------------------------------------------------*/
+class PLT_FrameServer : public PLT_FileMediaServer
+{
+public:
+    PLT_FrameServer(PLT_FrameBuffer& frame_buffer, 
+                    const char*      www_root,
+                    const char*      friendly_name,
+                    bool             show_ip = false,
+                    const char*      uuid = NULL,
+                    NPT_UInt16       port = 0);
+
+protected:
+    virtual ~PLT_FrameServer();
+
+    // overridable
+    virtual NPT_Result ProcessStreamRequest(NPT_HttpRequest&              request, 
+                                            const NPT_HttpRequestContext& context,
+                                            NPT_HttpResponse&             response);
+    // PLT_DeviceHost methods
+    virtual NPT_Result SetupDevice();
+    virtual NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse&             response);
+    
+    // PLT_FileMediaServer methods
+    virtual NPT_String BuildResourceUri(const NPT_HttpUrl& base_uri, const char* host, const char* file_path);
+
+    // PLT_MediaServer methods
+    virtual NPT_Result OnBrowseMetadata(PLT_ActionReference&          action, 
+                                        const char*                   object_id, 
+                                        const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference&          action, 
+                                              const char*                   object_id, 
+                                              const PLT_HttpRequestContext& context);
+
+    virtual PLT_MediaObject* BuildFromID(const char* id,
+                                         const NPT_SocketAddress* req_local_address /* = NULL */);
+
+protected:
+    friend class PLT_MediaItem;
+
+    PLT_FrameBuffer&        m_FrameBuffer;
+    NPT_HttpUrl             m_StreamBaseUri;
+    PLT_SocketPolicyServer* m_PolicyServer;
+};
+
+#endif /* _PLT_FRAME_SERVER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/FrameStreamer/PltFrameStream.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,125 @@
+/*****************************************************************
+|
+|   Platinum - Frame Stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltFrameStream.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.framestream")
+
+/*----------------------------------------------------------------------
+|   PLT_InputFrameStream::PLT_InputFrameStream
++---------------------------------------------------------------------*/
+PLT_InputFrameStream::PLT_InputFrameStream(PLT_FrameBuffer& frame_buffer,
+                                           const char*      boundary) : 
+    m_FrameBuffer(frame_buffer),
+    m_LastFrameIndex(0),
+    m_Boundary(boundary),
+    m_Eos(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_InputFrameStream::~PLT_InputFrameStream
++---------------------------------------------------------------------*/
+PLT_InputFrameStream::~PLT_InputFrameStream()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_InputFrameStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_InputFrameStream::GetAvailable(NPT_LargeSize& available) 
+{ 
+    NPT_CHECK_WARNING(m_Part.GetAvailable(available));
+
+    if (available == 0 && !m_Eos) {
+        NPT_CHECK_WARNING(FillBuffer());
+        NPT_CHECK_WARNING(m_Part.GetAvailable(available));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_InputFrameStream::FillBuffer
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_InputFrameStream::FillBuffer()
+{
+    // reset memorystream
+    m_Part.SetSize(0);
+    
+    // fetch next frame
+    NPT_DataBuffer frame;
+    NPT_CHECK_WARNING(m_FrameBuffer.GetNextFrame(m_LastFrameIndex, frame));
+
+    // empty frame means we're done
+    if (frame.GetDataSize() == 0) {
+        m_Part.WriteLine("--" + m_Boundary + "--");
+        m_Eos = true;
+        return NPT_SUCCESS;
+    }
+
+    m_Part.WriteLine("--" + m_Boundary);
+    m_Part.WriteLine("Content-Type: image/jpeg");
+    m_Part.WriteLine("Content-Length: "+NPT_String::FromInteger(frame.GetDataSize()));
+    m_Part.WriteLine("");
+    m_Part.Write(frame.GetData(), frame.GetDataSize());
+    m_Part.WriteLine("");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_InputFrameStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_InputFrameStream::Read(void*     buffer, 
+                           NPT_Size  bytes_to_read, 
+                           NPT_Size* bytes_read /*= 0*/)
+{
+
+    if (bytes_read) *bytes_read = 0;
+
+    if (bytes_to_read == 0) {
+        return NPT_SUCCESS;
+    }
+
+    // make sure we have data
+    NPT_LargeSize available;
+    NPT_CHECK_WARNING(GetAvailable(available));
+
+    return m_Part.Read(buffer, bytes_to_read, bytes_read);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/FrameStreamer/PltFrameStream.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,78 @@
+/*****************************************************************
+|
+|   Platinum - Frame Stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FRAMESTREAM_H_
+#define _PLT_FRAMESTREAM_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltFrameBuffer.h"
+
+/*----------------------------------------------------------------------
+|   PLT_InputFrameStream
++---------------------------------------------------------------------*/
+class PLT_InputFrameStream : public NPT_InputStream
+{
+public:
+    // methods
+    PLT_InputFrameStream(PLT_FrameBuffer& frame_buffer,
+                         const char*      boundary);
+    virtual ~PLT_InputFrameStream();
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read = 0);
+
+    NPT_Result Seek(NPT_Position offset) { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result Skip(NPT_Size offset) { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result Tell(NPT_Position& offset){ NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+    NPT_Result GetSize(NPT_LargeSize& size)   { NPT_COMPILER_UNUSED(size); return NPT_FAILURE; }
+    NPT_Result GetAvailable(NPT_LargeSize& available);
+        
+private:
+    NPT_Result FillBuffer();
+
+protected:
+    PLT_FrameBuffer& m_FrameBuffer;
+    NPT_MemoryStream m_Part;
+    NPT_UInt32       m_LastFrameIndex;
+    NPT_String       m_Boundary;
+    bool             m_Eos;
+};
+
+typedef NPT_Reference<PLT_InputFrameStream> PLT_InputFrameStreamReference;
+
+#endif /* _PLT_FRAMESTREAM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,310 @@
+/*****************************************************************
+|
+|      Platinum - AV Media Connect Device
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "Platinum.h"
+#include "PltMediaConnect.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.devices.mediaconnect")
+
+/*----------------------------------------------------------------------
+|       forward references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 X_MS_MediaReceiverRegistrarSCPD[];
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::PLT_MediaConnect
++---------------------------------------------------------------------*/
+PLT_MediaConnect::PLT_MediaConnect(const char*  path, 
+                                   const char*  friendly_name, 
+                                   bool         show_ip     /* = false */, 
+                                   const char*  uuid        /* = NULL */, 
+                                   NPT_UInt16   port        /* = 0 */,
+                                   bool         port_rebind /* = false */) :	
+    PLT_FileMediaServer(path, friendly_name, show_ip, uuid, port, port_rebind),
+    m_RegistrarService(NULL)
+{
+    m_ModelName        = "Windows Media Player Sharing"; // for Xbox3630 & Sonos to accept us
+    m_ModelNumber      = "3.0";                          // must be >= 3.0 for Sonos to accept us
+    m_ModelDescription = "Media Server";
+    m_Manufacturer     = "Plutinosoft";
+    m_ManufacturerURL  = "http://www.plutinosoft.com/";
+    m_ModelURL         = "http://www.plutinosoft.com";
+    m_DlnaDoc          = "DMS-1.00";
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::~PLT_MediaConnect
++---------------------------------------------------------------------*/
+PLT_MediaConnect::~PLT_MediaConnect()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaConnect::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::SetupServices(PLT_DeviceData& data)
+{
+    m_RegistrarService = new PLT_Service(
+        &data,
+        "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1", 
+        "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar");
+
+    NPT_CHECK_FATAL(m_RegistrarService->SetSCPDXML((const char*) X_MS_MediaReceiverRegistrarSCPD));
+    NPT_CHECK_FATAL(m_RegistrarService->InitURLs("X_MS_MediaReceiverRegistrar", data.GetUUID()));
+    NPT_CHECK_FATAL(data.AddService(m_RegistrarService));
+    
+    m_RegistrarService->SetStateVariable("AuthorizationGrantedUpdateID", "0");
+    m_RegistrarService->SetStateVariable("AuthorizationDeniedUpdateID", "0");
+    m_RegistrarService->SetStateVariable("ValidationSucceededUpdateID", "0");
+    m_RegistrarService->SetStateVariable("ValidationRevokedUpdateID", "0");
+
+    return PLT_FileMediaServer::SetupServices(data);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaConnect::ProcessGetDescription
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaConnect::ProcessGetDescription(NPT_HttpRequest&              request,
+                                        const NPT_HttpRequestContext& context,
+                                        NPT_HttpResponse&             response)
+{
+    NPT_String m_OldModelName   = m_ModelName;
+    NPT_String m_OldModelNumber = m_ModelNumber;
+    NPT_String m_OldDlnaDoc     = m_DlnaDoc;
+    NPT_String m_OldDlnaCap     = m_DlnaCap;
+
+    // change some things based on User-Agent header
+    NPT_HttpHeader* user_agent = request.GetHeaders().GetHeader(NPT_HTTP_HEADER_USER_AGENT);
+    if (user_agent && user_agent->GetValue().Find("Xbox", 0, true)>=0) {
+        // For the XBox 360 to discover us, ModelName must stay "Windows Media Player Sharing"
+        m_ModelName        = "Windows Media Player Sharing";
+        m_ModelNumber      = "3.0";
+    }
+
+    // PS3
+    NPT_HttpHeader* client_info = request.GetHeaders().GetHeader("X-AV-Client-Info");
+    if (client_info && client_info->GetValue().Find("PLAYSTATION 3", 0, true)>=0) {
+        m_DlnaDoc = "DMS-1.50";
+        m_DlnaCap = "av-upload,image-upload,audio-upload";
+    }
+
+    NPT_Result res = PLT_FileMediaServer::ProcessGetDescription(request, context, response);
+    
+    // reset to old values now
+    m_ModelName   = m_OldModelName;
+    m_ModelNumber = m_OldModelNumber;
+    m_DlnaDoc     = m_OldDlnaDoc;
+    m_DlnaCap     = m_OldDlnaCap;
+    
+    return res;
+}
+
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::Authorize
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::Authorize(PLT_MediaConnectInfo* info, bool state)
+{
+    info->m_Authorized = state;
+    if (state == true) {
+        return m_RegistrarService->IncStateVariable("AuthorizationGrantedUpdateID");
+    }
+
+    return m_RegistrarService->IncStateVariable("AuthorizationDeniedUpdateID");
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::Validate
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::Validate(PLT_MediaConnectInfo* info, bool state)
+{
+    info->m_Validated = state;
+    if (state == true) {
+        return m_RegistrarService->IncStateVariable("ValidationSucceededUpdateID");
+    }
+
+    return m_RegistrarService->IncStateVariable("ValidationRevokedUpdateID");
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnAction(PLT_ActionReference&          action, 
+                           const PLT_HttpRequestContext& context)
+{
+    PLT_MediaConnectInfo* mc_info = NULL;
+
+    /* parse the action name */
+    NPT_String name = action->GetActionDesc()->GetName();
+
+    /* handle X_MS_MediaReceiverRegistrar actions here */
+    if (name.Compare("IsAuthorized") == 0) {
+        return OnIsAuthorized(action, mc_info);
+    }
+    if (name.Compare("RegisterDevice") == 0) {
+        return OnRegisterDevice(action, mc_info);
+    }
+    if (name.Compare("IsValidated") == 0) {
+        return OnIsValidated(action, mc_info);
+    }  
+
+    return PLT_FileMediaServer::OnAction(action, context);
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::LookUpMediaConnectInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::LookUpMediaConnectInfo(NPT_String             deviceID, 
+                                         PLT_MediaConnectInfo*& mc_info)
+{
+    mc_info = NULL;
+
+    if (deviceID.GetLength()) {
+        /* lookup the MAC from the UDN */
+        NPT_String* MAC;
+        if (NPT_SUCCEEDED(m_MediaConnectUDNMap.Get(deviceID, MAC))) {
+            /* lookup the PLT_MediaConnectInfo from the MAC now */
+            return m_MediaConnectDeviceInfoMap.Get(*MAC, mc_info);
+        }
+    }
+
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::OnIsAuthorized
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnIsAuthorized(PLT_ActionReference&  action, 
+                                 PLT_MediaConnectInfo* mc_info)
+{
+    bool authorized = true;
+
+    NPT_String deviceID;
+    action->GetArgumentValue("DeviceID", deviceID);
+
+    /* is there a device ID passed ? */
+    if (deviceID.GetLength()) {
+        /* lookup the MediaConnectInfo from the UDN */
+        NPT_String MAC;
+        PLT_MediaConnectInfo* device_info;
+        if (NPT_FAILED(LookUpMediaConnectInfo(deviceID, device_info))) {
+            authorized = false;
+        } else {
+            authorized = device_info->m_Authorized;
+        }
+    } else {
+        authorized = mc_info?mc_info->m_Authorized:true;
+    }
+
+    action->SetArgumentValue("Result", authorized?"1":"0");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::OnRegisterDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnRegisterDevice(PLT_ActionReference&  action, 
+                                   PLT_MediaConnectInfo* mc_info)
+{
+    NPT_COMPILER_UNUSED(mc_info);
+
+    NPT_String reqMsgBase64;
+    action->GetArgumentValue("RegistrationReqMsg", reqMsgBase64);
+
+    NPT_String respMsgBase64;
+    action->SetArgumentValue("RegistrationRespMsg", respMsgBase64);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       PLT_MediaConnect::OnIsValidated
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnIsValidated(PLT_ActionReference&  action, 
+                                PLT_MediaConnectInfo* mc_info)
+{
+    bool validated = true;
+
+    NPT_String deviceID;
+    action->GetArgumentValue("DeviceID", deviceID);
+
+    /* is there a device ID passed ? */
+    if (deviceID.GetLength()) {
+        /* lookup the MediaConnectInfo from the UDN */
+        NPT_String MAC;
+        PLT_MediaConnectInfo* device_info;
+        if (NPT_FAILED(LookUpMediaConnectInfo(deviceID, device_info))) {
+            validated = false;
+        } else {
+            validated = device_info->m_Validated;
+        }
+    } else {
+        validated = mc_info?mc_info->m_Validated:true;
+    }
+
+    action->SetArgumentValue("Result", validated?"1":"0");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaConnect::GetFilePath
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::GetFilePath(const char* object_id, 
+                              NPT_String& filepath) 
+{
+    if (!object_id) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // Reroute XBox360 and WMP requests to our route
+    if (NPT_StringsEqual(object_id, "15")) {
+        return PLT_FileMediaServer::GetFilePath("", filepath); // Videos
+    } else if (NPT_StringsEqual(object_id, "16")) {
+        return PLT_FileMediaServer::GetFilePath("", filepath); // Photos
+    } else if (NPT_StringsEqual(object_id, "13")) {
+        return PLT_FileMediaServer::GetFilePath("", filepath); // Music
+    }
+
+    return PLT_FileMediaServer::GetFilePath(object_id, filepath);;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaConnect/PltMediaConnect.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,116 @@
+/*****************************************************************
+|
+|      Platinum - AV Media Connect Device
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_CONNECT_H_
+#define _PLT_MEDIA_CONNECT_H_
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltFileMediaServer.h"
+
+/*----------------------------------------------------------------------
+|   PLT_MediaConnectInfo
++---------------------------------------------------------------------*/
+class PLT_MediaConnectInfo
+{
+public:
+    PLT_MediaConnectInfo(bool authorized = false) : 
+        m_Authorized(authorized), m_Validated(false) {}
+
+    bool       m_Authorized;
+    bool       m_Validated;
+    NPT_String m_UDN;
+};
+
+/*----------------------------------------------------------------------
+|   defines
++---------------------------------------------------------------------*/
+typedef NPT_Map<NPT_String, PLT_MediaConnectInfo>        PLT_MediaConnectDeviceInfoMap;
+typedef NPT_Map<NPT_String, PLT_MediaConnectInfo>::Entry PLT_MediaConnectDeviceInfoMapEntry;
+typedef NPT_Map<NPT_String, NPT_String>                  PLT_UDNtoMACMap;
+typedef NPT_Map<NPT_String, NPT_String>::Entry           PLT_UDNtoMACMapEntry;
+
+/*----------------------------------------------------------------------
+|   PLT_MediaConnect
++---------------------------------------------------------------------*/
+class PLT_MediaConnect : public PLT_FileMediaServer
+{
+public:
+    PLT_MediaConnect(const char*  path, 
+                     const char*  friendly_name,
+                     bool         show_ip = false,
+                     const char*  udn = NULL,
+                     NPT_UInt16   port = 0,
+                     bool         port_rebind = false);
+
+    NPT_Result Authorize(PLT_MediaConnectInfo* info, bool state);
+    NPT_Result Validate(PLT_MediaConnectInfo* info, bool state);
+
+protected:
+    virtual ~PLT_MediaConnect();
+
+
+    // PLT_DeviceHost methods
+    virtual NPT_Result SetupServices(PLT_DeviceData& data);
+    virtual NPT_Result OnAction(PLT_ActionReference&          action, 
+                                const PLT_HttpRequestContext& context);
+    virtual NPT_Result ProcessGetDescription(NPT_HttpRequest&              request,
+                                             const NPT_HttpRequestContext& context,
+                                             NPT_HttpResponse&             response);
+
+    // PLT_FileMediaServer methods
+    virtual NPT_Result GetFilePath(const char* object_id, NPT_String& filepath);
+
+    // X_MS_MediaReceiverRegistrar
+    virtual NPT_Result OnIsAuthorized(PLT_ActionReference&  action, 
+                                      PLT_MediaConnectInfo* mediaConnectInfo);
+    virtual NPT_Result OnRegisterDevice(PLT_ActionReference&  action, 
+                                        PLT_MediaConnectInfo* mediaConnectInfo);
+    virtual NPT_Result OnIsValidated(PLT_ActionReference&  action, 
+                                     PLT_MediaConnectInfo* mediaConnectInfo);
+
+private:
+    NPT_Result LookUpMediaConnectInfo(NPT_String             deviceID, 
+                                      PLT_MediaConnectInfo*& mediaConnectInfo);
+
+protected:
+    PLT_MediaConnectDeviceInfoMap m_MediaConnectDeviceInfoMap;
+    PLT_UDNtoMACMap               m_MediaConnectUDNMap;
+
+private:
+    PLT_Service*                  m_RegistrarService;
+};
+
+#endif /* _PLT_MEDIA_CONNECT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaConnect/PltMediaConnectSCPDs.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,175 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Server Device SCPDs
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+NPT_UInt8 X_MS_MediaReceiverRegistrarSCPD[2589] =
+{
+    0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+    0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+    0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x27, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+    0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+    0x65, 0x2D, 0x31, 0x2D, 0x30, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 
+    0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 
+    0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 
+    0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 
+    0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 
+    0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x73, 
+    0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+    0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 
+    0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 
+    0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+    0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 
+    0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+    0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+    0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+    0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+    0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+    0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 
+    0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x67, 
+    0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 
+    0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 
+    0x71, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 
+    0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+    0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+    0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+    0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x71, 0x4D, 0x73, 
+    0x67, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 
+    0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+    0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+    0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 
+    0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+    0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 
+    0x6E, 0x52, 0x65, 0x73, 0x70, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+    0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 
+    0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+    0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+    0x61, 0x6D, 0x65, 0x3E, 0x49, 0x73, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+    0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+    0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x65, 0x76, 
+    0x69, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+    0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+    0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 
+    0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+    0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+    0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+    0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+    0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+    0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+    0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+    0x0A, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 
+    0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 
+    0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 
+    0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 
+    0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 
+    0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+    0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 
+    0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 
+    0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x6E, 0x74, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+    0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+    0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 
+    0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x71, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 0x69, 0x6E, 
+    0x2E, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 
+    0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+    0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 0x69, 0x73, 
+    0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 0x69, 0x6E, 0x2E, 
+    0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 
+    0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 
+    0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+    0x61, 0x6D, 0x65, 0x3E, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x47, 0x72, 0x61, 
+    0x6E, 0x74, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 
+    0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 
+    0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+    0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 
+    0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x75, 0x74, 0x68, 0x6F, 
+    0x72, 0x69, 0x7A, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65, 0x6E, 0x69, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 
+    0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 
+    0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 
+    0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x75, 0x63, 0x63, 0x65, 
+    0x65, 0x64, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 
+    0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 
+    0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+    0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 
+    0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56, 0x61, 0x6C, 0x69, 0x64, 
+    0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x76, 0x6F, 0x6B, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 
+    0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+    0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+    0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 
+    0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns='urn:schemas-upnp-org:service-1-0'>
+	<specVersion>
+		<major>1</major>
+		<minor>0</minor>
+	</specVersion>
+	<actionList>
+		<action>
+			<name>IsAuthorized</name>
+			<argumentList>
+				<argument>
+					<name>DeviceID</name>
+					<direction>in</direction>
+					<relatedStateVariable>A_ARG_TYPE_DeviceID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Result</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>RegisterDevice</name>
+			<argumentList>
+				<argument>
+					<name>RegistrationReqMsg</name>
+					<direction>in</direction>
+					<relatedStateVariable>A_ARG_TYPE_RegistrationReqMsg</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>RegistrationRespMsg</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_RegistrationRespMsg</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>IsValidated</name>
+			<argumentList>
+				<argument>
+					<name>DeviceID</name>
+					<direction>in</direction>
+					<relatedStateVariable>A_ARG_TYPE_DeviceID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Result</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+	</actionList>
+	<serviceStateTable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_DeviceID</name>
+			<dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Result</name>
+			<dataType>int</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_RegistrationReqMsg</name>
+			<dataType>bin.base64</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_RegistrationRespMsg</name>
+			<dataType>bin.base64</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>AuthorizationGrantedUpdateID</name>
+			<dataType>ui4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>AuthorizationDeniedUpdateID</name>
+			<dataType>ui4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>ValidationSucceededUpdateID</name>
+			<dataType>ui4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>ValidationRevokedUpdateID</name>
+			<dataType>ui4</dataType>
+		</stateVariable>
+	</serviceStateTable>
+</scpd>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+   <specVersion>
+      <major>1</major>
+      <minor>0</minor>
+   </specVersion>
+   <actionList>
+      <action>
+         <name>GetCurrentTransportActions</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Actions</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentTransportActions</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetDeviceCapabilities</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>PlayMedia</name>
+               <direction>out</direction>
+               <relatedStateVariable>PossiblePlaybackStorageMedia</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RecMedia</name>
+               <direction>out</direction>
+               <relatedStateVariable>PossibleRecordStorageMedia</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RecQualityModes</name>
+               <direction>out</direction>
+               <relatedStateVariable>PossibleRecordQualityModes</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetMediaInfo</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NrTracks</name>
+               <direction>out</direction>
+               <relatedStateVariable>NumberOfTracks</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>MediaDuration</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentMediaDuration</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentURI</name>
+               <direction>out</direction>
+               <relatedStateVariable>AVTransportURI</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentURIMetaData</name>
+               <direction>out</direction>
+               <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NextURI</name>
+               <direction>out</direction>
+               <relatedStateVariable>NextAVTransportURI</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NextURIMetaData</name>
+               <direction>out</direction>
+               <relatedStateVariable>NextAVTransportURIMetaData</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>PlayMedium</name>
+               <direction>out</direction>
+               <relatedStateVariable>PlaybackStorageMedium</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RecordMedium</name>
+               <direction>out</direction>
+               <relatedStateVariable>RecordStorageMedium</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>WriteStatus</name>
+               <direction>out</direction>
+               <relatedStateVariable>RecordMediumWriteStatus</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetPositionInfo</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Track</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentTrack</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TrackDuration</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentTrackDuration</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TrackMetaData</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentTrackMetaData</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TrackURI</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentTrackURI</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RelTime</name>
+               <direction>out</direction>
+               <relatedStateVariable>RelativeTimePosition</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>AbsTime</name>
+               <direction>out</direction>
+               <relatedStateVariable>AbsoluteTimePosition</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RelCount</name>
+               <direction>out</direction>
+               <relatedStateVariable>RelativeCounterPosition</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>AbsCount</name>
+               <direction>out</direction>
+               <relatedStateVariable>AbsoluteCounterPosition</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetTransportInfo</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentTransportState</name>
+               <direction>out</direction>
+               <relatedStateVariable>TransportState</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentTransportStatus</name>
+               <direction>out</direction>
+               <relatedStateVariable>TransportStatus</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentSpeed</name>
+               <direction>out</direction>
+               <relatedStateVariable>TransportPlaySpeed</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetTransportSettings</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>PlayMode</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentPlayMode</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RecQualityMode</name>
+               <direction>out</direction>
+               <relatedStateVariable>CurrentRecordQualityMode</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>Next</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>Pause</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>Play</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Speed</name>
+               <direction>in</direction>
+               <relatedStateVariable>TransportPlaySpeed</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>Previous</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>Seek</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Unit</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_SeekMode</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Target</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_SeekTarget</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetAVTransportURI</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentURI</name>
+               <direction>in</direction>
+               <relatedStateVariable>AVTransportURI</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentURIMetaData</name>
+               <direction>in</direction>
+               <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetPlayMode</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NewPlayMode</name>
+               <direction>in</direction>
+               <relatedStateVariable>CurrentPlayMode</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>Stop</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+   </actionList>
+   <serviceStateTable>
+      <stateVariable sendEvents="no">
+         <name>CurrentPlayMode</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>NORMAL</allowedValue>
+            <allowedValue>REPEAT_ALL</allowedValue>
+            <allowedValue>INTRO</allowedValue>
+         </allowedValueList>
+         <defaultValue>NORMAL</defaultValue>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>RecordStorageMedium</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>UNKNOWN</allowedValue>
+            <allowedValue>DV</allowedValue>
+            <allowedValue>MINI-DV</allowedValue>
+            <allowedValue>VHS</allowedValue>
+            <allowedValue>W-VHS</allowedValue>
+            <allowedValue>S-VHS</allowedValue>
+            <allowedValue>D-VHS</allowedValue>
+            <allowedValue>VHSC</allowedValue>
+            <allowedValue>VIDEO8</allowedValue>
+            <allowedValue>HI8</allowedValue>
+            <allowedValue>CD-ROM</allowedValue>
+            <allowedValue>CD-DA</allowedValue>
+            <allowedValue>CD-R</allowedValue>
+            <allowedValue>CD-RW</allowedValue>
+            <allowedValue>VIDEO-CD</allowedValue>
+            <allowedValue>SACD</allowedValue>
+            <allowedValue>MD-AUDIO</allowedValue>
+            <allowedValue>MD-PICTURE</allowedValue>
+            <allowedValue>DVD-ROM</allowedValue>
+            <allowedValue>DVD-VIDEO</allowedValue>
+            <allowedValue>DVD-R</allowedValue>
+            <allowedValue>DVD+RW</allowedValue>
+            <allowedValue>DVD-RW</allowedValue>
+            <allowedValue>DVD-RAM</allowedValue>
+            <allowedValue>DVD-AUDIO</allowedValue>
+            <allowedValue>DAT</allowedValue>
+            <allowedValue>LD</allowedValue>
+            <allowedValue>HDD</allowedValue>
+            <allowedValue>MICRO-MV</allowedValue>
+            <allowedValue>NETWORK</allowedValue>
+            <allowedValue>NONE</allowedValue>
+            <allowedValue>NOT_IMPLEMENTED</allowedValue>
+            <allowedValue> vendor-defined </allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="yes">
+         <name>LastChange</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>RelativeTimePosition</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentTrackURI</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentTrackDuration</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentRecordQualityMode</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>0:EP</allowedValue>
+            <allowedValue>1:LP</allowedValue>
+            <allowedValue>2:SP</allowedValue>
+            <allowedValue>0:BASIC</allowedValue>
+            <allowedValue>1:MEDIUM</allowedValue>
+            <allowedValue>2:HIGH</allowedValue>
+            <allowedValue>NOT_IMPLEMENTED</allowedValue>
+            <allowedValue> vendor-defined </allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentMediaDuration</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>AbsoluteCounterPosition</name>
+         <dataType>i4</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>RelativeCounterPosition</name>
+         <dataType>i4</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_InstanceID</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>AVTransportURI</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>TransportState</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>STOPPED</allowedValue>
+            <allowedValue>PAUSED_PLAYBACK</allowedValue>
+            <allowedValue>PAUSED_RECORDING</allowedValue>
+            <allowedValue>PLAYING</allowedValue>
+            <allowedValue>RECORDING</allowedValue>
+            <allowedValue>TRANSITIONING</allowedValue>
+            <allowedValue>NO_MEDIA_PRESENT</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentTrackMetaData</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>NextAVTransportURI</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>PossibleRecordQualityModes</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentTrack</name>
+         <dataType>ui4</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>4294967295</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>AbsoluteTimePosition</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>NextAVTransportURIMetaData</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>PlaybackStorageMedium</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>UNKNOWN</allowedValue>
+            <allowedValue>DV</allowedValue>
+            <allowedValue>MINI-DV</allowedValue>
+            <allowedValue>VHS</allowedValue>
+            <allowedValue>W-VHS</allowedValue>
+            <allowedValue>S-VHS</allowedValue>
+            <allowedValue>D-VHS</allowedValue>
+            <allowedValue>VHSC</allowedValue>
+            <allowedValue>VIDEO8</allowedValue>
+            <allowedValue>HI8</allowedValue>
+            <allowedValue>CD-ROM</allowedValue>
+            <allowedValue>CD-DA</allowedValue>
+            <allowedValue>CD-R</allowedValue>
+            <allowedValue>CD-RW</allowedValue>
+            <allowedValue>VIDEO-CD</allowedValue>
+            <allowedValue>SACD</allowedValue>
+            <allowedValue>MD-AUDIO</allowedValue>
+            <allowedValue>MD-PICTURE</allowedValue>
+            <allowedValue>DVD-ROM</allowedValue>
+            <allowedValue>DVD-VIDEO</allowedValue>
+            <allowedValue>DVD-R</allowedValue>
+            <allowedValue>DVD+RW</allowedValue>
+            <allowedValue>DVD-RW</allowedValue>
+            <allowedValue>DVD-RAM</allowedValue>
+            <allowedValue>DVD-AUDIO</allowedValue>
+            <allowedValue>DAT</allowedValue>
+            <allowedValue>LD</allowedValue>
+            <allowedValue>HDD</allowedValue>
+            <allowedValue>MICRO-MV</allowedValue>
+            <allowedValue>NETWORK</allowedValue>
+            <allowedValue>NONE</allowedValue>
+            <allowedValue>NOT_IMPLEMENTED</allowedValue>
+            <allowedValue> vendor-defined </allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>CurrentTransportActions</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>RecordMediumWriteStatus</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>WRITABLE</allowedValue>
+            <allowedValue>PROTECTED</allowedValue>
+            <allowedValue>NOT_WRITABLE</allowedValue>
+            <allowedValue>UNKNOWN</allowedValue>
+            <allowedValue>NOT_IMPLEMENTED</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>PossiblePlaybackStorageMedia</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>AVTransportURIMetaData</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>NumberOfTracks</name>
+         <dataType>ui4</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>4294967295</maximum>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_SeekMode</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>ABS_TIME</allowedValue>
+            <allowedValue>REL_TIME</allowedValue>
+            <allowedValue>ABS_COUNT</allowedValue>
+            <allowedValue>REL_COUNT</allowedValue>
+            <allowedValue>TRACK_NR</allowedValue>
+            <allowedValue>CHANNEL_FREQ</allowedValue>
+            <allowedValue>TAPE-INDEX</allowedValue>
+            <allowedValue>FRAME</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_SeekTarget</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>PossibleRecordStorageMedia</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>TransportStatus</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>OK</allowedValue>
+            <allowedValue>ERROR_OCCURRED</allowedValue>
+            <allowedValue> vendor-defined </allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>TransportPlaySpeed</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>1</allowedValue>
+            <allowedValue> vendor-defined </allowedValue>
+         </allowedValueList>
+      </stateVariable>
+   </serviceStateTable>
+</scpd>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/ConnectionManagerSCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns='urn:schemas-upnp-org:service-1-0'>
+	<specVersion>
+		<major>1</major>
+		<minor>0</minor>
+	</specVersion>
+	<actionList>
+		<action>
+			<name>GetCurrentConnectionInfo</name>
+			<argumentList>
+				<argument>
+					<name>ConnectionID</name>
+					<direction>in</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>RcsID</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>AVTransportID</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>ProtocolInfo</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>PeerConnectionManager</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>PeerConnectionID</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Direction</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Status</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetProtocolInfo</name>
+			<argumentList>
+				<argument>
+					<name>Source</name>
+					<direction>out</direction>
+					<relatedStateVariable>SourceProtocolInfo</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Sink</name>
+					<direction>out</direction>
+					<relatedStateVariable>SinkProtocolInfo</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetCurrentConnectionIDs</name>
+			<argumentList>
+				<argument>
+					<name>ConnectionIDs</name>
+					<direction>out</direction>
+					<relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+	</actionList>
+	<serviceStateTable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ProtocolInfo</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ConnectionStatus</name>
+		    <dataType>string</dataType>
+		    <allowedValueList>
+		        <allowedValue>OK</allowedValue>
+		        <allowedValue>ContentFormatMismatch</allowedValue>
+		        <allowedValue>InsufficientBandwidth</allowedValue>
+		        <allowedValue>UnreliableChannel</allowedValue>
+		        <allowedValue>Unknown</allowedValue>
+		    </allowedValueList>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_AVTransportID</name>
+		    <dataType>i4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_RcsID</name>
+		    <dataType>i4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ConnectionID</name>
+		    <dataType>i4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ConnectionManager</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='yes'>
+		    <name>SourceProtocolInfo</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='yes'>
+		    <name>SinkProtocolInfo</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_Direction</name>
+		    <dataType>string</dataType>
+		    <allowedValueList>
+		        <allowedValue>Input</allowedValue>
+		        <allowedValue>Output</allowedValue>
+		    </allowedValueList>
+		</stateVariable>
+		<stateVariable sendEvents='yes'>
+		    <name>CurrentConnectionIDs</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+	</serviceStateTable>
+</scpd>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1035 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Controller (Media Renderer Control Point)
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaController.h"
+#include "PltDidl.h"
+#include "PltDeviceData.h"
+#include "PltXmlHelper.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.renderer.controller")
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::PLT_MediaController
++---------------------------------------------------------------------*/
+PLT_MediaController::PLT_MediaController(PLT_CtrlPointReference&      ctrl_point, 
+                                         PLT_MediaControllerDelegate* delegate /* = NULL */) :
+    m_CtrlPoint(ctrl_point),
+    m_Delegate(delegate)
+{
+    m_CtrlPoint->AddListener(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::~PLT_MediaController
++---------------------------------------------------------------------*/
+PLT_MediaController::~PLT_MediaController()
+{
+    m_CtrlPoint->RemoveListener(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnDeviceAdded
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnDeviceAdded(PLT_DeviceDataReference& device)
+{
+    PLT_DeviceDataReference data;
+    NPT_String uuid = device->GetUUID();
+    // is it a new device?
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) {
+        NPT_LOG_FINE_1("Device (%s) is already in our list!", (const char*)uuid);
+        return NPT_FAILURE;
+    }
+
+    NPT_LOG_FINE("Device Found:");
+    device->ToLog(NPT_LOG_LEVEL_FINE);
+
+    // verify the device implements the function we need
+    PLT_Service* serviceAVT;
+    PLT_Service* serviceCMR;
+    NPT_String type;
+    
+    type = "urn:schemas-upnp-org:service:AVTransport:1";
+    if (NPT_FAILED(device->FindServiceByType(type, serviceAVT))) {
+        NPT_LOG_FINE_1("Service %s not found", (const char*)type);
+        return NPT_FAILURE;
+    }
+    
+    type = "urn:schemas-upnp-org:service:ConnectionManager:1";
+    if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) {
+        NPT_LOG_FINE_1("Service %s not found", (const char*)type);
+        return NPT_FAILURE;
+    }
+
+    m_MediaRenderers.Add(device);
+    
+    if (m_Delegate && m_Delegate->OnMRAdded(device)) {
+        // subscribe to AVT eventing if delegate wants it
+        m_CtrlPoint->Subscribe(serviceAVT);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::OnDeviceRemoved(PLT_DeviceDataReference& device)
+{
+    // only release if we have kept it around
+    PLT_DeviceDataReference data;
+    NPT_String uuid = device->GetUUID();
+    // is it a new device?
+    if (NPT_FAILED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) {
+        NPT_LOG_FINE_1("Device (%s) not found in our list!", (const char*)uuid);
+        return NPT_FAILURE;
+    }
+
+    NPT_LOG_FINE("Device Removed:");
+    device->ToLog(NPT_LOG_LEVEL_FINE);
+
+    if (m_Delegate) {
+        m_Delegate->OnMRRemoved(device);
+    }
+    
+    m_MediaRenderers.Remove(device);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::FindActionDesc
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::FindActionDesc(PLT_DeviceDataReference& device, 
+                                    const char*              service_type,
+                                    const char*              action_name,
+                                    PLT_ActionDesc*&         action_desc)
+{
+    // look for the service
+    PLT_Service* service;
+    if (NPT_FAILED(device->FindServiceByType(service_type, service))) {
+        NPT_LOG_FINE_1("Service %s not found", (const char*)service_type);
+        return NPT_FAILURE;
+    }
+
+    action_desc = service->FindActionDesc(action_name);
+    if (action_desc == NULL) {
+        NPT_LOG_FINE_1("Action %s not found in service", action_name);
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::CreateAction
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::CreateAction(PLT_DeviceDataReference& device, 
+                                  const char*              service_type,
+                                  const char*              action_name,
+                                  PLT_ActionReference&     action)
+{
+    PLT_ActionDesc* action_desc;
+    NPT_CHECK_SEVERE(FindActionDesc(device, service_type, action_name, action_desc));
+    action = new PLT_Action(action_desc);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::CallAVTransportAction
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::CallAVTransportAction(PLT_ActionReference& action,
+                                           NPT_UInt32           instance_id,
+                                           void*                userdata)
+{
+    // Set the object id
+    NPT_CHECK_SEVERE(action->SetArgumentValue("InstanceID", 
+        NPT_String::FromInteger(instance_id)));
+
+    // set the arguments on the action, this will check the argument values
+    return m_CtrlPoint->InvokeAction(action, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetCurrentTransportActions
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetCurrentTransportActions(PLT_DeviceDataReference& device, 
+                                                NPT_UInt32               instance_id,
+                                                void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetCurrentTransportActions", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetDeviceCapabilities
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetDeviceCapabilities(PLT_DeviceDataReference& device, 
+                                           NPT_UInt32               instance_id,
+                                           void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetDeviceCapabilities", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetMediaInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetMediaInfo(PLT_DeviceDataReference& device, 
+                                  NPT_UInt32               instance_id,
+                                  void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetMediaInfo", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetPositionInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetPositionInfo(PLT_DeviceDataReference& device, 
+                                     NPT_UInt32               instance_id,
+                                     void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetPositionInfo", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetTransportInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetTransportInfo(PLT_DeviceDataReference& device, 
+                                      NPT_UInt32               instance_id,
+                                      void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetTransportInfo", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetTransportSettings
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetTransportSettings(PLT_DeviceDataReference&  device, 
+                                          NPT_UInt32                instance_id,
+                                          void*                     userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetTransportSettings", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Next
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Next(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Next", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Pause
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Pause(PLT_DeviceDataReference& device, 
+                           NPT_UInt32               instance_id,
+                           void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Pause", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Play
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Play(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          NPT_String               speed,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Play", 
+        action));
+
+    // Set the speed
+    if (NPT_FAILED(action->SetArgumentValue("Speed", speed))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Previous
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Previous(PLT_DeviceDataReference& device, 
+                              NPT_UInt32               instance_id,
+                              void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Previous", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Seek
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Seek(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          NPT_String               unit,
+                          NPT_String               target,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Seek", 
+        action));
+
+    // Set the unit
+    if (NPT_FAILED(action->SetArgumentValue("Unit", unit))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // Set the target
+    if (NPT_FAILED(action->SetArgumentValue("Target", target))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::SetAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::SetAVTransportURI(PLT_DeviceDataReference& device, 
+                                       NPT_UInt32               instance_id, 
+                                       const char*              uri,
+                                       const char*              metadata,
+                                       void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "SetAVTransportURI", 
+        action));
+
+    // set the uri
+    if (NPT_FAILED(action->SetArgumentValue("CurrentURI", uri))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the uri metadata
+    if (NPT_FAILED(action->SetArgumentValue("CurrentURIMetaData", metadata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::SetPlayMode
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::SetPlayMode(PLT_DeviceDataReference& device, 
+                                 NPT_UInt32               instance_id,
+                                 NPT_String               new_play_mode,
+                                 void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "SetPlayMode", 
+        action));
+
+    // set the New PlayMode
+    if (NPT_FAILED(action->SetArgumentValue("NewPlayMode", new_play_mode))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Stop
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Stop(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Stop", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetCurrentConnectionIDs
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetCurrentConnectionIDs(PLT_DeviceDataReference& device, 
+                                             void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:ConnectionManager:1", 
+        "GetCurrentConnectionIDs", 
+        action));
+
+    // set the arguments on the action, this will check the argument values
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetCurrentConnectionInfo(PLT_DeviceDataReference& device, 
+                                              NPT_UInt32               connection_id,
+                                              void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:ConnectionManager:1", 
+        "GetCurrentConnectionInfo", 
+        action));
+
+    // set the New PlayMode
+    if (NPT_FAILED(action->SetArgumentValue("ConnectionID", NPT_String::FromInteger(connection_id)))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the arguments on the action, this will check the argument values
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetProtocolInfo(PLT_DeviceDataReference& device, 
+                                     void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:ConnectionManager:1", 
+        "GetProtocolInfo", 
+        action));
+
+    // set the arguments on the action, this will check the argument values
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata)
+{
+    if (m_Delegate == NULL) return NPT_SUCCESS;
+
+    /* make sure device is a renderer we've previously found */
+    PLT_DeviceDataReference device;
+    NPT_String uuid = action->GetActionDesc()->GetService()->GetDevice()->GetUUID();
+    if (NPT_FAILED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), device))) {
+        NPT_LOG_FINE_1("Device (%s) not found in our list of renderers", (const char*)uuid);
+        res = NPT_FAILURE;
+    }
+       
+    /* extract action name */
+    NPT_String actionName = action->GetActionDesc()->GetName();
+
+    /* AVTransport response ? */
+    if (actionName.Compare("GetCurrentTransportActions", true) == 0) {
+        return OnGetCurrentTransportActionsResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetDeviceCapabilities", true) == 0) {
+        return OnGetDeviceCapabilitiesResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetMediaInfo", true) == 0) {
+        return OnGetMediaInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetPositionInfo", true) == 0) {
+        return OnGetPositionInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetTransportInfo", true) == 0) {
+        return OnGetTransportInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetTransportSettings", true) == 0) {
+        return OnGetTransportSettingsResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("Next", true) == 0) {
+        m_Delegate->OnNextResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Pause", true) == 0) {
+        m_Delegate->OnPauseResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Play", true) == 0) {
+        m_Delegate->OnPlayResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Previous", true) == 0) {
+        m_Delegate->OnPreviousResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Seek", true) == 0) {
+        m_Delegate->OnSeekResult(res, device, userdata);
+    }
+    else if (actionName.Compare("SetAVTransportURI", true) == 0) {
+        m_Delegate->OnSetAVTransportURIResult(res, device, userdata);
+    }
+    else if (actionName.Compare("SetPlayMode", true) == 0) {
+        m_Delegate->OnSetPlayModeResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Stop", true) == 0) {
+        m_Delegate->OnStopResult(res, device, userdata);
+    }
+    else if (actionName.Compare("GetCurrentConnectionIDs", true) == 0) {
+        return OnGetCurrentConnectionIDsResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetCurrentConnectionInfo", true) == 0) {
+        return OnGetCurrentConnectionInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetProtocolInfo", true) == 0) {
+        return OnGetProtocolInfoResponse(res, device, action, userdata);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetCurrentTransportActionsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentTransportActionsResponse(NPT_Result res, 
+                                                          PLT_DeviceDataReference& device, 
+                                                          PLT_ActionReference& action, 
+                                                          void* userdata)
+{
+    NPT_String actions;
+    PLT_StringList values;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("Actions", actions))) {
+        goto bad_action;
+    }
+
+    // parse the list of actions and return a list to listener
+    ParseCSV(actions, values);
+
+    m_Delegate->OnGetCurrentTransportActionsResult(NPT_SUCCESS, device, &values, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetCurrentTransportActionsResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetDeviceCapabilitiesResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetDeviceCapabilitiesResponse(NPT_Result res, 
+                                                     PLT_DeviceDataReference& device, 
+                                                     PLT_ActionReference& action, 
+                                                     void* userdata)
+{
+    NPT_String value;
+    PLT_DeviceCapabilities capabilities;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("PlayMedia", value))) {
+        goto bad_action;
+    }
+    // parse the list of medias and return a list to listener
+    ParseCSV(value, capabilities.play_media);
+
+    if (NPT_FAILED(action->GetArgumentValue("RecMedia", value))) {
+        goto bad_action;
+    }
+    // parse the list of rec and return a list to listener
+    ParseCSV(value, capabilities.rec_media);
+
+    if (NPT_FAILED(action->GetArgumentValue("RecQualityModes", value))) {
+        goto bad_action;
+    }
+    // parse the list of modes and return a list to listener
+    ParseCSV(value, capabilities.rec_quality_modes);
+
+    m_Delegate->OnGetDeviceCapabilitiesResult(NPT_SUCCESS, device, &capabilities, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetDeviceCapabilitiesResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetMediaInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetMediaInfoResponse(NPT_Result res, 
+                                            PLT_DeviceDataReference& device, 
+                                            PLT_ActionReference& action, 
+                                            void* userdata)
+{
+    NPT_String      value;
+    PLT_MediaInfo   info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("NrTracks", info.num_tracks))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("MediaDuration", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.media_duration))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("CurrentURI", info.cur_uri))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("CurrentURIMetaData", info.cur_metadata))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("NextURI", info.next_uri))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("NextURIMetaData",  info.next_metadata))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("PlayMedium", info.play_medium))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("RecordMedium", info.rec_medium))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("WriteStatus", info.write_status))) {
+        goto bad_action;
+    }
+
+    m_Delegate->OnGetMediaInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetMediaInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetPositionInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetPositionInfoResponse(NPT_Result res, 
+                                               PLT_DeviceDataReference& device, 
+                                               PLT_ActionReference& action, 
+                                               void* userdata)
+{
+    NPT_String       value;
+    PLT_PositionInfo info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("Track", info.track))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("TrackDuration", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.track_duration))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("TrackMetaData", info.track_metadata))) {
+        goto bad_action;
+    }    
+    
+    if (NPT_FAILED(action->GetArgumentValue("TrackURI", info.track_uri))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("RelTime", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.rel_time))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("AbsTime", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.abs_time))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("RelCount", info.rel_count))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("AbsCount", info.abs_count))) {
+        goto bad_action;
+    }
+
+    m_Delegate->OnGetPositionInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetPositionInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetTransportInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetTransportInfoResponse(NPT_Result res, 
+                                                PLT_DeviceDataReference& device, 
+                                                PLT_ActionReference& action, 
+                                                void* userdata)
+{
+    PLT_TransportInfo info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("CurrentTransportState", info.cur_transport_state))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("CurrentTransportStatus", info.cur_transport_status))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("CurrentSpeed", info.cur_speed))) {
+        goto bad_action;
+    }    
+
+    m_Delegate->OnGetTransportInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetTransportInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetTransportSettingsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetTransportSettingsResponse(NPT_Result res, 
+                                                    PLT_DeviceDataReference& device, 
+                                                    PLT_ActionReference& action, 
+                                                    void* userdata)
+{
+    PLT_TransportSettings settings;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("PlayMode", settings.play_mode))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("RecQualityMode", settings.rec_quality_mode))) {
+        goto bad_action;
+    }    
+
+    m_Delegate->OnGetTransportSettingsResult(NPT_SUCCESS, device, &settings, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetTransportSettingsResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetCurrentConnectionIDsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentConnectionIDsResponse(NPT_Result res, 
+                                                       PLT_DeviceDataReference& device, 
+                                                       PLT_ActionReference& action, 
+                                                       void* userdata)
+{
+    NPT_String value;
+    PLT_StringList IDs;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("ConnectionIDs", value))) {
+        goto bad_action;
+    }
+    // parse the list of medias and return a list to listener
+    ParseCSV(value, IDs);
+
+    m_Delegate->OnGetCurrentConnectionIDsResult(NPT_SUCCESS, device, &IDs, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetCurrentConnectionIDsResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetCurrentConnectionInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentConnectionInfoResponse(NPT_Result res, 
+                                                        PLT_DeviceDataReference& device, 
+                                                        PLT_ActionReference& action, 
+                                                        void* userdata)
+{
+    NPT_String value;
+    PLT_ConnectionInfo info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("RcsID", info.rcs_id))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("AVTransportID", info.avtransport_id))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("ProtocolInfo", info.protocol_info))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("PeerConnectionManager", info.peer_connection_mgr))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("PeerConnectionID", info.peer_connection_id))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("Direction", info.direction))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("Status", info.status))) {
+        goto bad_action;
+    }
+    m_Delegate->OnGetCurrentConnectionInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetCurrentConnectionInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetProtocolInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetProtocolInfoResponse(NPT_Result res, 
+                                               PLT_DeviceDataReference& device, 
+                                               PLT_ActionReference& action, 
+                                               void* userdata)
+{
+    NPT_String     source_info, sink_info;
+    PLT_StringList sources, sinks;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("Source", source_info))) {
+        goto bad_action;
+    }
+    ParseCSV(source_info, sources);
+
+    if (NPT_FAILED(action->GetArgumentValue("Sink", sink_info))) {
+        goto bad_action;
+    }
+    ParseCSV(sink_info, sinks);
+
+    m_Delegate->OnGetProtocolInfoResult(NPT_SUCCESS, device, &sources, &sinks, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetProtocolInfoResult(NPT_FAILURE, device, NULL, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnEventNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
+{
+    if (!m_Delegate) return NPT_SUCCESS;
+    
+    // parse LastChange var into smaller vars
+    PLT_StateVariable* lastChangeVar = NULL;
+    if (NPT_SUCCEEDED(NPT_ContainerFind(*vars, PLT_ListStateVariableNameFinder("LastChange"), lastChangeVar))) {
+        vars->Remove(lastChangeVar);
+        PLT_Service* var_service = lastChangeVar->GetService();
+        NPT_String text = lastChangeVar->GetValue();
+        
+        NPT_XmlNode* xml = NULL;
+        NPT_XmlParser parser;
+        if (NPT_FAILED(parser.Parse(text, xml)) || !xml || !xml->AsElementNode()) {
+            delete xml;
+            return NPT_FAILURE;
+        }
+
+        NPT_XmlElementNode* node = xml->AsElementNode();
+        if (!node->GetTag().Compare("Event", true)) {
+            // look for the instance with attribute id = 0
+            NPT_XmlElementNode* instance = NULL;
+            for (NPT_Cardinal i=0; i<node->GetChildren().GetItemCount(); i++) {
+                NPT_XmlElementNode* child;
+                if (NPT_FAILED(PLT_XmlHelper::GetChild(node, child, i)))
+                    continue;
+
+                if (!child->GetTag().Compare("InstanceID", true)) {
+                    // extract the "val" attribute value
+                    NPT_String value;
+                    if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(child, "val", value)) &&
+                        !value.Compare("0")) {
+                        instance = child;
+                        break;
+                    }
+                }
+            }
+
+            // did we find an instance with id = 0 ?
+            if (instance != NULL) {
+                // all the children of the Instance node are state variables
+                for (NPT_Cardinal j=0; j<instance->GetChildren().GetItemCount(); j++) {
+                    NPT_XmlElementNode* var_node;
+                    if (NPT_FAILED(PLT_XmlHelper::GetChild(instance, var_node, j)))
+                        continue;
+
+                    // look for the state variable in this service
+                    const NPT_String* value = var_node->GetAttribute("val");
+                    PLT_StateVariable* var = var_service->FindStateVariable(var_node->GetTag());
+                    if (value != NULL && var != NULL) {
+                        // get the value and set the state variable
+                        // if it succeeded, add it to the list of vars we'll event
+                        if (NPT_SUCCEEDED(var->SetValue(*value))) {
+                            vars->Add(var);
+                            NPT_LOG_FINE_2("PLT_MediaController received var change for (%s): %s", (const char*)var->GetName(), (const char*)var->GetValue());
+                        }
+                    }
+                }
+            }
+        }
+        delete xml;
+    }
+
+    if (vars->GetItemCount()) {
+        m_Delegate->OnMRStateVariablesChanged(service, vars);
+    }
+    
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/PltMediaController.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,305 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Controller (Media Renderer Control Point)
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_CONTROLLER_H_
+#define _PLT_MEDIA_CONTROLLER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltCtrlPoint.h"
+
+/*----------------------------------------------------------------------
+|   Defines
++---------------------------------------------------------------------*/
+typedef NPT_List<NPT_String> PLT_StringList;
+
+struct PLT_DeviceCapabilities {
+    PLT_StringList play_media;
+    PLT_StringList rec_media;
+    PLT_StringList rec_quality_modes;
+};
+
+struct PLT_MediaInfo {
+    NPT_UInt32    num_tracks;
+    NPT_TimeStamp media_duration;
+    NPT_String    cur_uri;
+    NPT_String    cur_metadata;
+    NPT_String    next_uri;
+    NPT_String    next_metadata;
+    NPT_String    play_medium;
+    NPT_String    rec_medium;
+    NPT_String    write_status;
+};
+
+struct PLT_PositionInfo {
+    NPT_UInt32    track;
+    NPT_TimeStamp track_duration;
+    NPT_String    track_metadata;
+    NPT_String    track_uri;
+    NPT_TimeStamp rel_time;
+    NPT_TimeStamp abs_time;
+    NPT_Int32     rel_count;
+    NPT_Int32     abs_count;
+};
+
+struct PLT_TransportInfo {
+    NPT_String cur_transport_state;
+    NPT_String cur_transport_status;
+    NPT_String cur_speed;
+};
+
+struct PLT_TransportSettings {
+    NPT_String play_mode;
+    NPT_String rec_quality_mode;
+};
+
+struct PLT_ConnectionInfo {
+    NPT_UInt32 rcs_id;
+    NPT_UInt32 avtransport_id;
+    NPT_String protocol_info;
+    NPT_String peer_connection_mgr;
+    NPT_UInt32 peer_connection_id;
+    NPT_String direction;
+    NPT_String status;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaControllerDelegate class
++---------------------------------------------------------------------*/
+class PLT_MediaControllerDelegate
+{
+public:
+    virtual ~PLT_MediaControllerDelegate() {}
+
+    virtual bool OnMRAdded(PLT_DeviceDataReference& /* device */) { return true; }
+    virtual void OnMRRemoved(PLT_DeviceDataReference& /* device */) {}
+    virtual void OnMRStateVariablesChanged(PLT_Service*                  /* service */, 
+                                           NPT_List<PLT_StateVariable*>* /* vars */) {}
+
+    // AVTransport
+    virtual void OnGetCurrentTransportActionsResult(
+        NPT_Result               /* res */, 
+        PLT_DeviceDataReference& /* device */,
+        PLT_StringList*          /* actions */, 
+        void*                    /* userdata */) {}
+
+    virtual void OnGetDeviceCapabilitiesResult(
+        NPT_Result               /* res */, 
+        PLT_DeviceDataReference& /* device */,
+        PLT_DeviceCapabilities*  /* capabilities */,
+        void*                    /* userdata */) {}
+
+    virtual void OnGetMediaInfoResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_MediaInfo*           /* info */,
+        void*                    /* userdata */) {}
+
+    virtual void OnGetPositionInfoResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_PositionInfo*        /* info */,
+        void*                    /* userdata */) {}
+
+    virtual void OnGetTransportInfoResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_TransportInfo*       /* info */,
+        void*                    /* userdata */) {}
+
+    virtual void OnGetTransportSettingsResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_TransportSettings*   /* settings */,
+        void*                    /* userdata */) {}
+
+    virtual void OnNextResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    virtual void OnPauseResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}  
+
+    virtual void OnPlayResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    virtual void OnPreviousResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    virtual void OnSeekResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    virtual void OnSetAVTransportURIResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    virtual void OnSetPlayModeResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    virtual void OnStopResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        void*                    /* userdata */) {}
+
+    // ConnectionManager
+    virtual void OnGetCurrentConnectionIDsResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_StringList*          /* ids */,
+        void*                    /* userdata */) {}
+
+    virtual void OnGetCurrentConnectionInfoResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_ConnectionInfo*      /* info */,
+        void*                    /* userdata */) {}
+
+    virtual void OnGetProtocolInfoResult(
+        NPT_Result               /* res */,
+        PLT_DeviceDataReference& /* device */,
+        PLT_StringList*          /* sources */,
+        PLT_StringList*          /* sinks */,
+        void*                    /* userdata */) {}
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController class
++---------------------------------------------------------------------*/
+class PLT_MediaController : public PLT_CtrlPointListener
+{
+public:
+    PLT_MediaController(PLT_CtrlPointReference&      ctrl_point, 
+                        PLT_MediaControllerDelegate* delegate = NULL);
+    virtual ~PLT_MediaController();
+
+    // public methods
+    virtual void SetDelegate(PLT_MediaControllerDelegate* delegate) {
+        m_Delegate = delegate;
+    }
+
+    // PLT_CtrlPointListener methods
+    virtual NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device);
+    virtual NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device);
+    virtual NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata);
+    virtual NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars);
+
+    // AVTransport
+    NPT_Result GetCurrentTransportActions(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result GetDeviceCapabilities(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result GetMediaInfo(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result GetPositionInfo(PLT_DeviceDataReference& device,  NPT_UInt32 instance_id, void* userdata);
+    NPT_Result GetTransportInfo(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result GetTransportSettings(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result Next(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result Pause(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result Play(PLT_DeviceDataReference&  device, NPT_UInt32 instance_id, NPT_String speed, void* userdata);
+    NPT_Result Previous(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+    NPT_Result Seek(PLT_DeviceDataReference&  device, NPT_UInt32 instance_id, NPT_String unit, NPT_String target, void* userdata);
+    NPT_Result SetAVTransportURI(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* uri, const char* metadata, void* userdata);
+    NPT_Result SetPlayMode(PLT_DeviceDataReference&  device, NPT_UInt32 instance_id, NPT_String new_play_mode, void* userdata);
+    NPT_Result Stop(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+
+    // ConnectionManager
+    NPT_Result GetCurrentConnectionIDs(PLT_DeviceDataReference& device, void* userdata);
+    NPT_Result GetCurrentConnectionInfo(PLT_DeviceDataReference& device, NPT_UInt32 connection_id, void* userdata);
+    NPT_Result GetProtocolInfo(PLT_DeviceDataReference& device, void* userdata);
+
+private:
+    NPT_Result FindActionDesc(PLT_DeviceDataReference& device, 
+        const char*              service_type,
+        const char*              action_name,
+        PLT_ActionDesc*&         action_desc);
+
+    NPT_Result CreateAction(PLT_DeviceDataReference& device, 
+        const char*              service_type,
+        const char*              action_name,
+        PLT_ActionReference&     action);
+
+    NPT_Result CallAVTransportAction(PLT_ActionReference& action,
+        NPT_UInt32               instance_id,
+        void*                    userdata = NULL);
+
+    NPT_Result OnGetCurrentTransportActionsResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetDeviceCapabilitiesResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetMediaInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetPositionInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetTransportInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetTransportSettingsResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+
+    NPT_Result OnGetCurrentConnectionIDsResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetCurrentConnectionInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+    NPT_Result OnGetProtocolInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+
+    static void ParseCSV(const char* csv, PLT_StringList& values) {
+        const char* start = csv;
+        const char* p = start;
+
+        // look for the , character
+        while (*p) {
+            if (*p == ',') {
+                NPT_String val(start, (int)(p-start));
+                val.Trim(' ');
+                values.Add(val);
+                start = p + 1;
+            }
+            p++;
+        }
+
+        // last one
+        NPT_String last(start, (int)(p-start));
+        last.Trim(' ');
+        if (last.GetLength()) {
+            values.Add(last);
+        }
+    }
+
+private:
+    PLT_CtrlPointReference            m_CtrlPoint;
+    PLT_MediaControllerDelegate*      m_Delegate;
+    NPT_List<PLT_DeviceDataReference> m_MediaRenderers;
+};
+
+#endif /* _PLT_MEDIA_CONTROLLER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,435 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Renderer Device
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaRenderer.h"
+#include "PltService.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.renderer")
+
+/*----------------------------------------------------------------------
+|   external references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 RDR_ConnectionManagerSCPD[];
+extern NPT_UInt8 RDR_AVTransportSCPD[];
+extern NPT_UInt8 RDR_RenderingControlSCPD[];
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::PLT_MediaRenderer
++---------------------------------------------------------------------*/
+PLT_MediaRenderer::PLT_MediaRenderer(const char*  friendly_name, 
+                                     bool         show_ip     /* = false */, 
+                                     const char*  uuid        /* = NULL */, 
+                                     unsigned int port        /* = 0 */,
+                                     bool         port_rebind /* = false */) :	
+    PLT_DeviceHost("/", uuid, "urn:schemas-upnp-org:device:MediaRenderer:1", friendly_name, show_ip, port, port_rebind)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::~PLT_MediaRenderer
++---------------------------------------------------------------------*/
+PLT_MediaRenderer::~PLT_MediaRenderer()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::SetupServices(PLT_DeviceData& data)
+{
+    PLT_Service* service;
+
+    {
+        /* AVTransport */
+        service = new PLT_Service(
+            &data,
+            "urn:schemas-upnp-org:service:AVTransport:1", 
+            "urn:upnp-org:serviceId:AVT_1-0",
+            "urn:schemas-upnp-org:metadata-1-0/AVT/");
+        NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_AVTransportSCPD));
+        NPT_CHECK_FATAL(service->InitURLs("AVTransport", data.GetUUID()));
+        NPT_CHECK_FATAL(data.AddService(service));
+
+        service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f));
+        service->SetStateVariable("A_ARG_TYPE_InstanceID", "0"); 
+
+        // GetCurrentTransportActions
+        service->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous");
+
+        // GetDeviceCapabilities
+        service->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK");
+        service->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED");
+        service->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED");
+
+        // GetMediaInfo
+        service->SetStateVariable("NumberOfTracks", "0");
+        service->SetStateVariable("CurrentMediaDuration", "00:00:00");;
+        service->SetStateVariable("AVTransportURI", "");
+        service->SetStateVariable("AVTransportURIMetadata", "");;
+        service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED");
+        service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED");
+        service->SetStateVariable("PlaybackStorageMedium", "NONE");
+        service->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED");
+        service->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED");
+
+        // GetPositionInfo
+        service->SetStateVariable("CurrentTrack", "0");
+        service->SetStateVariable("CurrentTrackDuration", "00:00:00");
+        service->SetStateVariable("CurrentTrackMetadata", "");
+        service->SetStateVariable("CurrentTrackURI", "");
+        service->SetStateVariable("RelativeTimePosition", "00:00:00"); 
+        service->SetStateVariable("AbsoluteTimePosition", "00:00:00");
+        service->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED
+        service->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED
+
+        // disable indirect eventing for certain state variables
+        PLT_StateVariable* var;
+        var = service->FindStateVariable("RelativeTimePosition");
+        if (var) var->DisableIndirectEventing();
+        var = service->FindStateVariable("AbsoluteTimePosition");
+        if (var) var->DisableIndirectEventing();
+        var = service->FindStateVariable("RelativeCounterPosition");
+        if (var) var->DisableIndirectEventing();
+        var = service->FindStateVariable("AbsoluteCounterPosition");
+        if (var) var->DisableIndirectEventing();
+
+        // GetTransportInfo
+        service->SetStateVariable("TransportState", "NO_MEDIA_PRESENT");
+        service->SetStateVariable("TransportStatus", "OK");
+        service->SetStateVariable("TransportPlaySpeed", "1");
+
+        // GetTransportSettings
+        service->SetStateVariable("CurrentPlayMode", "NORMAL");
+        service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED");
+    }
+
+    {
+        /* ConnectionManager */
+        service = new PLT_Service(
+            &data,
+            "urn:schemas-upnp-org:service:ConnectionManager:1", 
+            "urn:upnp-org:serviceId:CMGR_1-0");
+        NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD));
+        NPT_CHECK_FATAL(service->InitURLs("ConnectionManager", data.GetUUID()));
+        NPT_CHECK_FATAL(data.AddService(service));
+
+        service->SetStateVariable("CurrentConnectionIDs", "0");
+
+        // put all supported mime types here instead
+        service->SetStateVariable("SinkProtocolInfo", "http-get:*:*:*");
+        service->SetStateVariable("SourceProtocolInfo", "");
+    }
+
+    {
+        /* RenderingControl */
+        service = new PLT_Service(
+            &data,
+            "urn:schemas-upnp-org:service:RenderingControl:1", 
+            "urn:upnp-org:serviceId:RCS_1-0",
+            "urn:schemas-upnp-org:metadata-1-0/RCS/");
+        NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD));
+        NPT_CHECK_FATAL(service->InitURLs("RenderingControl", data.GetUUID()));
+        NPT_CHECK_FATAL(data.AddService(service));
+
+        service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f));
+
+        service->SetStateVariable("Mute", "0");
+        service->SetStateVariable("Volume", "100");
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnAction(PLT_ActionReference&          action, 
+                            const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    /* parse the action name */
+    NPT_String name = action->GetActionDesc()->GetName();
+
+    /* Is it a ConnectionManager Service Action ? */
+    if (name.Compare("GetCurrentConnectionIDs", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("GetProtocolInfo", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }    
+    if (name.Compare("GetCurrentConnectionInfo", true) == 0) {
+        return OnGetCurrentConnectionInfo(action);
+    }  
+
+    /* Is it a AVTransport Service Action ? */
+
+    // since all actions take an instance ID and we only support 1 instance
+    // verify that the Instance ID is 0 and return an error here now if not
+    NPT_String serviceType = action->GetActionDesc()->GetService()->GetServiceType();
+    if (serviceType.Compare("urn:schemas-upnp-org:service:AVTransport:1", true) == 0) {
+        if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {
+            action->SetError(802,"Not valid InstanceID.");
+            return NPT_FAILURE;
+        }
+    }
+
+    if (name.Compare("GetCurrentTransportActions", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("GetDeviceCapabilities", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("GetMediaInfo", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("GetPositionInfo", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("GetTransportInfo", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("GetTransportSettings", true) == 0) {
+        if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) {
+            return NPT_FAILURE;
+        }
+        return NPT_SUCCESS;
+    }
+    if (name.Compare("Next", true) == 0) {
+        return OnNext(action);
+    }
+    if (name.Compare("Pause", true) == 0) {
+        return OnPause(action);
+    }
+    if (name.Compare("Play", true) == 0) {
+        return OnPlay(action);
+    }
+    if (name.Compare("Previous", true) == 0) {
+        return OnPrevious(action);
+    }
+    if (name.Compare("Seek", true) == 0) {
+        return OnSeek(action);
+    }
+    if (name.Compare("Stop", true) == 0) {
+        return OnStop(action);
+    }
+    if (name.Compare("SetAVTransportURI", true) == 0) {
+        return OnSetAVTransportURI(action);
+    }
+    if (name.Compare("SetPlayMode", true) == 0) {
+        return OnSetPlayMode(action);
+    }
+
+    /* Is it a RendererControl Service Action ? */
+    if (serviceType.Compare("urn:schemas-upnp-org:service:RenderingControl:1", true) == 0) {
+        /* we only support master channel */
+        if (NPT_FAILED(action->VerifyArgumentValue("Channel", "Master"))) {
+            action->SetError(402,"Invalid Args.");
+            return NPT_FAILURE;
+        }
+    }
+
+    if (name.Compare("GetVolume", true) == 0) {
+        NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable());
+        return NPT_SUCCESS;
+    }
+
+    if (name.Compare("GetMute", true) == 0) {
+        NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable());
+        return NPT_SUCCESS;
+    }
+
+    if (name.Compare("SetVolume", true) == 0) {
+          return OnSetVolume(action);
+    }
+
+    if (name.Compare("SetMute", true) == 0) {
+          return OnSetMute(action);
+    }
+
+    action->SetError(401,"No Such Action.");
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnGetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnGetCurrentConnectionInfo(PLT_ActionReference& action)
+{
+    if (NPT_FAILED(action->VerifyArgumentValue("ConnectionID", "0"))) {
+        action->SetError(706,"No Such Connection.");
+        return NPT_FAILURE;
+    }
+
+    if (NPT_FAILED(action->SetArgumentValue("RcsID", "0"))){
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("AVTransportID", "0"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("ProtocolInfo", "http-get:*:*:*"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("PeerConnectionManager", "/"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("PeerConnectionID", "-1"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("Direction", "Input"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("Status", "Unknown"))) {
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnNext
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnNext(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnPause
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnPause(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnPlay
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnPlay(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnPrevious
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnPrevious(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnSeek
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSeek(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnStop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnStop(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnSetAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetAVTransportURI(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnSetPlayMode
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetPlayMode(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnSetVolume
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetVolume(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer::OnSetMute
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetMute(PLT_ActionReference& /* action */)
+{
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,108 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Renderer Device
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_RENDERER_H_
+#define _PLT_MEDIA_RENDERER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltDeviceHost.h"
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer class
++---------------------------------------------------------------------*/
+class PLT_MediaRendererInterface
+{
+public:
+    virtual ~PLT_MediaRendererInterface() {}
+
+    // ConnectionManager
+    virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action) = 0;
+
+    // AVTransport
+    virtual NPT_Result OnNext(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnPause(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnPlay(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnPrevious(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnSeek(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnStop(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action) = 0;
+
+    // RenderingControl
+    virtual NPT_Result OnSetVolume(PLT_ActionReference& action) = 0;
+    virtual NPT_Result OnSetMute(PLT_ActionReference& action) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaRenderer class
++---------------------------------------------------------------------*/
+class PLT_MediaRenderer : public PLT_DeviceHost,
+                          public PLT_MediaRendererInterface
+{
+public:
+    PLT_MediaRenderer(const char*  friendly_name,
+                      bool         show_ip = false,
+                      const char*  uuid = NULL,
+                      unsigned int port = 0,
+                      bool         port_rebind = false);
+
+    // PLT_DeviceHost methods
+    virtual NPT_Result SetupServices(PLT_DeviceData& data);
+    virtual NPT_Result OnAction(PLT_ActionReference&          action, 
+                                const PLT_HttpRequestContext& context);
+
+protected:
+    virtual ~PLT_MediaRenderer();
+
+    // PLT_MediaRendererInterface methods
+    // ConnectionManager
+    virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action);
+
+    // AVTransport
+    virtual NPT_Result OnNext(PLT_ActionReference& action);
+    virtual NPT_Result OnPause(PLT_ActionReference& action);
+    virtual NPT_Result OnPlay(PLT_ActionReference& action);
+    virtual NPT_Result OnPrevious(PLT_ActionReference& action);
+    virtual NPT_Result OnSeek(PLT_ActionReference& action);
+    virtual NPT_Result OnStop(PLT_ActionReference& action);
+    virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action);
+    virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action);
+
+    // RenderingControl
+    virtual NPT_Result OnSetVolume(PLT_ActionReference& action);
+    virtual NPT_Result OnSetMute(PLT_ActionReference& action);
+};
+
+#endif /* _PLT_MEDIA_RENDERER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/PltMediaRendererSCPDs.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,2791 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Renderer Device SCPDs
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+NPT_UInt8 RDR_AVTransportSCPD[22130] =
+{
+  0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+  0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+  0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+  0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+  0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 
+  0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 
+  0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 
+  0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 
+  0x74, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 
+  0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 
+  0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 
+  0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 
+  0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 
+  0x61, 0x79, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 
+  0x69, 0x62, 0x6C, 0x65, 0x50, 0x6C, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6B, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 
+  0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 
+  0x65, 0x63, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 
+  0x69, 0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 
+  0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 
+  0x51, 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 
+  0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x49, 
+  0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 
+  0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x72, 0x54, 0x72, 
+  0x61, 0x63, 0x6B, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 
+  0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x4F, 
+  0x66, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x44, 0x75, 0x72, 0x61, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 
+  0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x56, 
+  0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 
+  0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 
+  0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 
+  0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x4E, 0x65, 0x78, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 
+  0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6B, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 
+  0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x57, 0x72, 0x69, 0x74, 0x65, 
+  0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 
+  0x64, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x47, 0x65, 0x74, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 
+  0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+  0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x44, 0x75, 0x72, 0x61, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 
+  0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 
+  0x54, 0x72, 0x61, 0x63, 0x6B, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 
+  0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 
+  0x63, 0x6B, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x54, 0x69, 0x6D, 0x65, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x54, 0x69, 0x6D, 0x65, 
+  0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x54, 0x69, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 
+  0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x43, 0x6F, 0x75, 
+  0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 
+  0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 
+  0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x65, 
+  0x72, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6E, 
+  0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 
+  0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 
+  0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 
+  0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61, 
+  0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 
+  0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 
+  0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x53, 0x70, 0x65, 0x65, 
+  0x64, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x65, 0x74, 
+  0x74, 0x69, 0x6E, 0x67, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 
+  0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 
+  0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 
+  0x6E, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x51, 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x52, 0x65, 0x63, 0x6F, 0x72, 
+  0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 
+  0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 
+  0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x50, 0x61, 0x75, 0x73, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 
+  0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x54, 
+  0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6F, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 
+  0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x65, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 
+  0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x6E, 0x69, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x65, 0x65, 0x6B, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 
+  0x65, 0x65, 0x6B, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x41, 0x56, 0x54, 0x72, 
+  0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x55, 0x52, 0x49, 
+  0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 
+  0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x53, 0x65, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x77, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x6F, 0x70, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 
+  0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x3C, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 
+  0x6E, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 
+  0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x52, 0x4D, 0x41, 0x4C, 0x3C, 0x2F, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x5F, 0x41, 0x4C, 0x4C, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x49, 0x4E, 0x54, 0x52, 0x4F, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x65, 0x66, 0x61, 
+  0x75, 0x6C, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x52, 0x4D, 0x41, 0x4C, 0x3C, 0x2F, 0x64, 0x65, 0x66, 
+  0x61, 0x75, 0x6C, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 
+  0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 
+  0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 
+  0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x4E, 0x3C, 0x2F, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x44, 0x56, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x49, 0x4E, 0x49, 0x2D, 0x44, 0x56, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x48, 0x53, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x57, 0x2D, 0x56, 0x48, 0x53, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x2D, 0x56, 0x48, 0x53, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x2D, 
+  0x56, 0x48, 0x53, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x48, 0x53, 0x43, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x49, 0x44, 0x45, 0x4F, 0x38, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x48, 0x49, 0x38, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 
+  0x44, 0x41, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x52, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x52, 0x57, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x56, 0x49, 0x44, 0x45, 0x4F, 0x2D, 0x43, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x41, 0x43, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x44, 
+  0x2D, 0x41, 0x55, 0x44, 0x49, 0x4F, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x44, 0x2D, 0x50, 0x49, 0x43, 0x54, 0x55, 0x52, 0x45, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x56, 0x49, 0x44, 0x45, 
+  0x4F, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2B, 0x52, 0x57, 0x3C, 0x2F, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x57, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x41, 0x4D, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x44, 0x56, 0x44, 0x2D, 0x41, 0x55, 0x44, 0x49, 0x4F, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x41, 0x54, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4C, 0x44, 
+  0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x48, 0x44, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x49, 0x43, 0x52, 0x4F, 0x2D, 0x4D, 0x56, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x4E, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x54, 
+  0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x76, 0x65, 0x6E, 0x64, 
+  0x6F, 0x72, 0x2D, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4C, 0x61, 0x73, 
+  0x74, 0x43, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 
+  0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+  0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 
+  0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 
+  0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 
+  0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 
+  0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 
+  0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 
+  0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x30, 0x3A, 0x45, 0x50, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x31, 0x3A, 0x4C, 0x50, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x32, 0x3A, 0x53, 0x50, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x30, 0x3A, 0x42, 0x41, 0x53, 0x49, 0x43, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x31, 
+  0x3A, 0x4D, 0x45, 0x44, 0x49, 0x55, 0x4D, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x32, 0x3A, 0x48, 0x49, 0x47, 0x48, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 
+  0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x76, 0x65, 
+  0x6E, 0x64, 0x6F, 0x72, 0x2D, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 
+  0x72, 0x72, 0x65, 0x6E, 0x74, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+  0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 
+  0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x50, 0x6F, 
+  0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 
+  0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 
+  0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6F, 0x75, 0x6E, 0x74, 
+  0x65, 0x72, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 
+  0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 
+  0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 
+  0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 
+  0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 
+  0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 
+  0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 
+  0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 
+  0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x50, 
+  0x41, 0x55, 0x53, 0x45, 0x44, 0x5F, 0x50, 0x4C, 0x41, 0x59, 0x42, 0x41, 0x43, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x50, 0x41, 0x55, 
+  0x53, 0x45, 0x44, 0x5F, 0x52, 0x45, 0x43, 0x4F, 0x52, 0x44, 0x49, 0x4E, 0x47, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x50, 0x4C, 0x41, 0x59, 
+  0x49, 0x4E, 0x47, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x52, 0x45, 0x43, 0x4F, 0x52, 0x44, 0x49, 0x4E, 0x47, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x54, 0x52, 
+  0x41, 0x4E, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x49, 0x4E, 0x47, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x5F, 0x4D, 0x45, 0x44, 
+  0x49, 0x41, 0x5F, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4E, 0x54, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 
+  0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+  0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 
+  0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+  0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 
+  0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 
+  0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 
+  0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 
+  0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 
+  0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x34, 0x32, 0x39, 0x34, 0x39, 
+  0x36, 0x37, 0x32, 0x39, 0x35, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 
+  0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x6F, 0x6C, 0x75, 
+  0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 
+  0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 
+  0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 
+  0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 
+  0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 
+  0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6B, 0x53, 0x74, 
+  0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 
+  0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x4E, 
+  0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x44, 0x56, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x49, 0x4E, 0x49, 0x2D, 0x44, 0x56, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x48, 
+  0x53, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x57, 0x2D, 0x56, 0x48, 0x53, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x2D, 0x56, 0x48, 0x53, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x44, 0x2D, 0x56, 0x48, 0x53, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x48, 0x53, 0x43, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x49, 0x44, 0x45, 0x4F, 
+  0x38, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x48, 0x49, 0x38, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 
+  0x44, 0x2D, 0x44, 0x41, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x52, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x52, 0x57, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x56, 0x49, 0x44, 0x45, 0x4F, 0x2D, 0x43, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x41, 0x43, 0x44, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x4D, 0x44, 0x2D, 0x41, 0x55, 0x44, 0x49, 0x4F, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x44, 0x2D, 0x50, 0x49, 0x43, 0x54, 0x55, 0x52, 
+  0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x56, 0x49, 
+  0x44, 0x45, 0x4F, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2B, 0x52, 0x57, 
+  0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x57, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x52, 0x41, 0x4D, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x44, 0x56, 0x44, 0x2D, 0x41, 0x55, 0x44, 0x49, 0x4F, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x44, 0x41, 0x54, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x4C, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x48, 0x44, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x49, 0x43, 0x52, 0x4F, 0x2D, 0x4D, 0x56, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x4E, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 
+  0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x76, 0x65, 
+  0x6E, 0x64, 0x6F, 0x72, 0x2D, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 
+  0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x57, 0x72, 
+  0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 
+  0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x57, 0x52, 0x49, 0x54, 0x41, 0x42, 0x4C, 0x45, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x50, 0x52, 0x4F, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x54, 0x5F, 0x57, 0x52, 
+  0x49, 0x54, 0x41, 0x42, 0x4C, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x4E, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 
+  0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 
+  0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 
+  0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x50, 0x6C, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6B, 0x53, 0x74, 0x6F, 0x72, 0x61, 
+  0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 
+  0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+  0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 
+  0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 
+  0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 
+  0x75, 0x6D, 0x62, 0x65, 0x72, 0x4F, 0x66, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+  0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 
+  0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 
+  0x6D, 0x3E, 0x34, 0x32, 0x39, 0x34, 0x39, 0x36, 0x37, 0x32, 0x39, 0x35, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 
+  0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 
+  0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x53, 0x65, 0x65, 0x6B, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x41, 0x42, 0x53, 0x5F, 0x54, 0x49, 
+  0x4D, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x52, 0x45, 0x4C, 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x41, 0x42, 0x53, 0x5F, 
+  0x43, 0x4F, 0x55, 0x4E, 0x54, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x52, 0x45, 0x4C, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x54, 0x52, 0x41, 0x43, 0x4B, 0x5F, 0x4E, 0x52, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x48, 0x41, 0x4E, 0x4E, 0x45, 0x4C, 0x5F, 0x46, 
+  0x52, 0x45, 0x51, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x54, 0x41, 0x50, 0x45, 0x2D, 0x49, 0x4E, 0x44, 0x45, 0x58, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x46, 
+  0x52, 0x41, 0x4D, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 
+  0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x53, 0x65, 0x65, 0x6B, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 
+  0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69, 
+  0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 
+  0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 
+  0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x4F, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x5F, 0x4F, 0x43, 0x43, 0x55, 0x52, 0x52, 
+  0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x2D, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 
+  0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x53, 
+  0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x31, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x2D, 0x64, 0x65, 
+  0x66, 0x69, 0x6E, 0x65, 0x64, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
+NPT_UInt8 RDR_RenderingControlSCPD[27181] =
+{
+  0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+  0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+  0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+  0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+  0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 
+  0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 
+  0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 
+  0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x47, 0x65, 0x74, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 
+  0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 
+  0x72, 0x65, 0x6E, 0x74, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 
+  0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 
+  0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 
+  0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x42, 0x6C, 
+  0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 
+  0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 
+  0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 
+  0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 
+  0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6E, 
+  0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 
+  0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 
+  0x65, 0x6E, 0x74, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 
+  0x6F, 0x6C, 0x6F, 0x72, 0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 
+  0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 
+  0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x47, 0x65, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 
+  0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x47, 0x65, 0x74, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 
+  0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 
+  0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 
+  0x65, 0x6E, 0x74, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 
+  0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 
+  0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 
+  0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x47, 
+  0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 
+  0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x47, 0x72, 0x65, 0x65, 
+  0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x48, 0x6F, 0x72, 
+  0x69, 0x7A, 0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 
+  0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x48, 0x6F, 0x72, 0x69, 0x7A, 
+  0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x48, 0x6F, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 
+  0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 
+  0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 
+  0x65, 0x6E, 0x74, 0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x4D, 0x75, 0x74, 0x65, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 
+  0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 
+  0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 
+  0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 
+  0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 
+  0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x64, 0x56, 
+  0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 
+  0x74, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 
+  0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 
+  0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 
+  0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 
+  0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 
+  0x6E, 0x74, 0x53, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x53, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x74, 
+  0x69, 0x63, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 
+  0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 
+  0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x65, 0x72, 
+  0x74, 0x69, 0x63, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 
+  0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 
+  0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 
+  0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+  0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 
+  0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x56, 0x6F, 
+  0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 
+  0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 
+  0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x52, 0x61, 0x6E, 0x67, 
+  0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 
+  0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x4D, 0x69, 0x6E, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 
+  0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x4D, 0x61, 0x78, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 
+  0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4C, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 
+  0x74, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 
+  0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 
+  0x6E, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 
+  0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x65, 
+  0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 
+  0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 
+  0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 
+  0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x42, 
+  0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 
+  0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6E, 0x65, 0x73, 0x73, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x53, 0x65, 0x74, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 
+  0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 
+  0x64, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 
+  0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 
+  0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x43, 0x6F, 0x6E, 0x74, 
+  0x72, 0x61, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x73, 0x74, 
+  0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 
+  0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 
+  0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 
+  0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x47, 0x72, 0x65, 0x65, 0x6E, 
+  0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 
+  0x65, 0x74, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 
+  0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x47, 0x72, 0x65, 0x65, 
+  0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x47, 0x72, 
+  0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x48, 
+  0x6F, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 
+  0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+  0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x48, 0x6F, 0x72, 
+  0x69, 0x7A, 0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x48, 0x6F, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 
+  0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 
+  0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 
+  0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 
+  0x69, 0x72, 0x65, 0x64, 0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x4D, 0x75, 0x74, 0x65, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 
+  0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 
+  0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4D, 
+  0x75, 0x74, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 
+  0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 
+  0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 
+  0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 
+  0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x52, 
+  0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 
+  0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 
+  0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 
+  0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 
+  0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 
+  0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 
+  0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x53, 
+  0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x68, 0x61, 0x72, 
+  0x70, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 
+  0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 
+  0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 
+  0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 
+  0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 
+  0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 
+  0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 
+  0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 
+  0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 
+  0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+  0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 
+  0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 
+  0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x2D, 0x33, 0x32, 0x37, 0x36, 0x38, 0x3C, 
+  0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x33, 0x32, 0x37, 0x36, 0x37, 0x3C, 0x2F, 0x6D, 
+  0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4C, 0x61, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 
+  0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4C, 0x46, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x52, 0x46, 0x3C, 0x2F, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 
+  0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 
+  0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x4C, 0x6F, 0x75, 0x64, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 
+  0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x48, 0x6F, 0x72, 
+  0x69, 0x7A, 0x6F, 0x6E, 0x74, 0x61, 0x6C, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6F, 0x6E, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+  0x70, 0x65, 0x3E, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x2D, 0x33, 0x32, 0x37, 0x36, 0x38, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 
+  0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x33, 0x32, 0x37, 0x36, 0x37, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 
+  0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 
+  0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 
+  0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 
+  0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 
+  0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42, 0x6C, 0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 
+  0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 
+  0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 
+  0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 
+  0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 
+  0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 
+  0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 
+  0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 
+  0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x72, 
+  0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 
+  0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 
+  0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 
+  0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 
+  0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56, 
+  0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 
+  0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 
+  0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 
+  0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 0x6F, 
+  0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42, 0x72, 0x69, 0x67, 
+  0x68, 0x74, 0x6E, 0x65, 0x73, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 
+  0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 
+  0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 
+  0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x4C, 0x69, 0x73, 
+  0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x65, 
+  0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 
+  0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 
+  0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x46, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x44, 0x65, 0x66, 0x61, 
+  0x75, 0x6C, 0x74, 0x73, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6C, 0x6C, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 
+  0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x73, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x56, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x20, 0x64, 0x65, 0x66, 
+  0x69, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 
+  0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x54, 0x65, 0x6D, 0x70, 0x65, 0x72, 
+  0x61, 0x74, 0x75, 0x72, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 
+  0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 
+  0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x36, 0x35, 0x35, 0x33, 0x35, 0x3C, 
+  0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+  0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 
+  0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 
+  0x79, 0x70, 0x65, 0x3E, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x2D, 0x33, 0x32, 0x37, 0x36, 0x38, 0x3C, 0x2F, 0x6D, 0x69, 
+  0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x33, 0x32, 0x37, 0x36, 0x37, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 
+  0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x72, 
+  0x61, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 
+  0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 
+  0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 
+  0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 
+  0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x47, 0x72, 0x65, 0x65, 0x6E, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+  0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 
+  0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 
+  0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 
+  0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 
+  0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 
+  0x65, 0x64, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x42, 0x6C, 0x61, 0x63, 0x6B, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+  0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 
+  0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 
+  0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 
+  0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42, 0x6C, 
+  0x75, 0x65, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x47, 0x61, 0x69, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 
+  0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 
+  0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 
+  0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 
+  0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+  0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 
+  0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+  0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 
+  0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 
+  0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30, 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 
+  0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 
+  0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 
+  0x00
+};
+
+NPT_UInt8 RDR_ConnectionManagerSCPD[5428] =
+{
+    0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+    0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+    0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x27, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+    0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+    0x65, 0x2D, 0x31, 0x2D, 0x30, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 
+    0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 
+    0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 
+    0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 
+    0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+    0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+    0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 
+    0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+    0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+    0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 
+    0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+    0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+    0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+    0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 
+    0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+    0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+    0x5F, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+    0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+    0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+    0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+    0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 
+    0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+    0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+    0x61, 0x6D, 0x65, 0x3E, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 
+    0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+    0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+    0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+    0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x50, 0x65, 0x65, 0x72, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 
+    0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+    0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 
+    0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 
+    0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 
+    0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+    0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+    0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+    0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+    0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+    0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+    0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 
+    0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+    0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x74, 0x6F, 
+    0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 
+    0x75, 0x72, 0x63, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+    0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+    0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 
+    0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 
+    0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+    0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x50, 0x72, 0x6F, 0x74, 
+    0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+    0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+    0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 
+    0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+    0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 
+    0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+    0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 
+    0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+    0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+    0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 
+    0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+    0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 
+    0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 
+    0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 
+    0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+    0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 
+    0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61, 0x74, 
+    0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 
+    0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 
+    0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+    0x75, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x4D, 0x69, 0x73, 0x6D, 
+    0x61, 0x74, 0x63, 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+    0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 
+    0x65, 0x6E, 0x74, 0x42, 0x61, 0x6E, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+    0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x55, 
+    0x6E, 0x72, 0x65, 0x6C, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x61, 0x6C, 
+    0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+    0x75, 0x65, 0x3E, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+    0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 
+    0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 
+    0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x41, 0x56, 0x54, 0x72, 
+    0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 
+    0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+    0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 
+    0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 
+    0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 
+    0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+    0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+    0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+    0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 
+    0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+    0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 
+    0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 
+    0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 
+    0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 
+    0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+    0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 
+    0x69, 0x6E, 0x6B, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 
+    0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+    0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 
+    0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 
+    0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+    0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+    0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+    0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+    0x65, 0x3E, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 
+    0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+    0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+    0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 
+    0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 
+    0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 
+    0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+    0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x65, 
+    0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 
+    0x73, 0x63, 0x70, 0x64, 0x3E, 0x0D, 0x0A, 0x00
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,749 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+   <specVersion>
+      <major>1</major>
+      <minor>0</minor>
+   </specVersion>
+   <actionList>
+      <action>
+         <name>GetBlueVideoBlackLevel</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentBlueVideoBlackLevel</name>
+               <direction>out</direction>
+               <relatedStateVariable>BlueVideoBlackLevel</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetBlueVideoGain</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentBlueVideoGain</name>
+               <direction>out</direction>
+               <relatedStateVariable>BlueVideoGain</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetBrightness</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentBrightness</name>
+               <direction>out</direction>
+               <relatedStateVariable>Brightness</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetColorTemperature</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentColorTemperature</name>
+               <direction>out</direction>
+               <relatedStateVariable>ColorTemperature</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetContrast</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentContrast</name>
+               <direction>out</direction>
+               <relatedStateVariable>Contrast</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetGreenVideoBlackLevel</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentGreenVideoBlackLevel</name>
+               <direction>out</direction>
+               <relatedStateVariable>GreenVideoBlackLevel</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetGreenVideoGain</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentGreenVideoGain</name>
+               <direction>out</direction>
+               <relatedStateVariable>GreenVideoGain</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetHorizontalKeystone</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentHorizontalKeystone</name>
+               <direction>out</direction>
+               <relatedStateVariable>HorizontalKeystone</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetLoudness</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentLoudness</name>
+               <direction>out</direction>
+               <relatedStateVariable>Loudness</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetMute</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentMute</name>
+               <direction>out</direction>
+               <relatedStateVariable>Mute</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetRedVideoBlackLevel</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentRedVideoBlackLevel</name>
+               <direction>out</direction>
+               <relatedStateVariable>RedVideoBlackLevel</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetRedVideoGain</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentRedVideoGain</name>
+               <direction>out</direction>
+               <relatedStateVariable>RedVideoGain</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetSharpness</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentSharpness</name>
+               <direction>out</direction>
+               <relatedStateVariable>Sharpness</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetVerticalKeystone</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentVerticalKeystone</name>
+               <direction>out</direction>
+               <relatedStateVariable>VerticalKeystone</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetVolume</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentVolume</name>
+               <direction>out</direction>
+               <relatedStateVariable>Volume</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetVolumeDB</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentVolume</name>
+               <direction>out</direction>
+               <relatedStateVariable>VolumeDB</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>GetVolumeDBRange</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>MinValue</name>
+               <direction>out</direction>
+               <relatedStateVariable>VolumeDB</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>MaxValue</name>
+               <direction>out</direction>
+               <relatedStateVariable>VolumeDB</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>ListPresets</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>CurrentPresetNameList</name>
+               <direction>out</direction>
+               <relatedStateVariable>PresetNameList</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SelectPreset</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>PresetName</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_PresetName</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetBlueVideoBlackLevel</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredBlueVideoBlackLevel</name>
+               <direction>in</direction>
+               <relatedStateVariable>BlueVideoBlackLevel</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetBlueVideoGain</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredBlueVideoGain</name>
+               <direction>in</direction>
+               <relatedStateVariable>BlueVideoGain</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetBrightness</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredBrightness</name>
+               <direction>in</direction>
+               <relatedStateVariable>Brightness</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetColorTemperature</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredColorTemperature</name>
+               <direction>in</direction>
+               <relatedStateVariable>ColorTemperature</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetContrast</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredContrast</name>
+               <direction>in</direction>
+               <relatedStateVariable>Contrast</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetGreenVideoBlackLevel</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredGreenVideoBlackLevel</name>
+               <direction>in</direction>
+               <relatedStateVariable>GreenVideoBlackLevel</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetGreenVideoGain</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredGreenVideoGain</name>
+               <direction>in</direction>
+               <relatedStateVariable>GreenVideoGain</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetHorizontalKeystone</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredHorizontalKeystone</name>
+               <direction>in</direction>
+               <relatedStateVariable>HorizontalKeystone</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetLoudness</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredLoudness</name>
+               <direction>in</direction>
+               <relatedStateVariable>Loudness</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetMute</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredMute</name>
+               <direction>in</direction>
+               <relatedStateVariable>Mute</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetRedVideoBlackLevel</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredRedVideoBlackLevel</name>
+               <direction>in</direction>
+               <relatedStateVariable>RedVideoBlackLevel</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetRedVideoGain</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredRedVideoGain</name>
+               <direction>in</direction>
+               <relatedStateVariable>RedVideoGain</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetSharpness</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredSharpness</name>
+               <direction>in</direction>
+               <relatedStateVariable>Sharpness</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetVerticalKeystone</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredVerticalKeystone</name>
+               <direction>in</direction>
+               <relatedStateVariable>VerticalKeystone</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetVolume</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredVolume</name>
+               <direction>in</direction>
+               <relatedStateVariable>Volume</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+      <action>
+         <name>SetVolumeDB</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Channel</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DesiredVolume</name>
+               <direction>in</direction>
+               <relatedStateVariable>VolumeDB</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+   </actionList>
+   <serviceStateTable>
+      <stateVariable sendEvents="no">
+         <name>VerticalKeystone</name>
+         <dataType>i2</dataType>
+         <allowedValueRange>
+            <minimum>-32768</minimum>
+            <maximum>32767</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="yes">
+         <name>LastChange</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_Channel</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>Master</allowedValue>
+            <allowedValue>LF</allowedValue>
+            <allowedValue>RF</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>Loudness</name>
+         <dataType>boolean</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>HorizontalKeystone</name>
+         <dataType>i2</dataType>
+         <allowedValueRange>
+            <minimum>-32768</minimum>
+            <maximum>32767</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_InstanceID</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>BlueVideoBlackLevel</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>RedVideoGain</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>GreenVideoBlackLevel</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>Volume</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>Mute</name>
+         <dataType>boolean</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>Brightness</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>PresetNameList</name>
+         <dataType>string</dataType>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_PresetName</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>FactoryDefaults</allowedValue>
+            <allowedValue>InstallationDefaults</allowedValue>
+            <allowedValue>Vendor defined</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>ColorTemperature</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>65535</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>VolumeDB</name>
+         <dataType>i2</dataType>
+         <allowedValueRange>
+            <minimum>-32768</minimum>
+            <maximum>32767</maximum>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>Contrast</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>GreenVideoGain</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>RedVideoBlackLevel</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>BlueVideoGain</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+      <stateVariable sendEvents="no">
+         <name>Sharpness</name>
+         <dataType>ui2</dataType>
+         <allowedValueRange>
+            <minimum>0</minimum>
+            <maximum>100</maximum>
+            <step>1</step>
+         </allowedValueRange>
+      </stateVariable>
+   </serviceStateTable>
+</scpd>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns='urn:schemas-upnp-org:service-1-0'>
+	<specVersion>
+		<major>1</major>
+		<minor>0</minor>
+	</specVersion>
+	<actionList>
+		<action>
+			<name>GetCurrentConnectionInfo</name>
+			<argumentList>
+				<argument>
+					<name>ConnectionID</name>
+					<direction>in</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>RcsID</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>AVTransportID</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>ProtocolInfo</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>PeerConnectionManager</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>PeerConnectionID</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Direction</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Status</name>
+					<direction>out</direction>
+					<relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetProtocolInfo</name>
+			<argumentList>
+				<argument>
+					<name>Source</name>
+					<direction>out</direction>
+					<relatedStateVariable>SourceProtocolInfo</relatedStateVariable>
+				</argument>
+				<argument>
+					<name>Sink</name>
+					<direction>out</direction>
+					<relatedStateVariable>SinkProtocolInfo</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetCurrentConnectionIDs</name>
+			<argumentList>
+				<argument>
+					<name>ConnectionIDs</name>
+					<direction>out</direction>
+					<relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>
+				</argument>
+			</argumentList>
+		</action>
+	</actionList>
+	<serviceStateTable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ProtocolInfo</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ConnectionStatus</name>
+		    <dataType>string</dataType>
+		    <allowedValueList>
+		        <allowedValue>OK</allowedValue>
+		        <allowedValue>ContentFormatMismatch</allowedValue>
+		        <allowedValue>InsufficientBandwidth</allowedValue>
+		        <allowedValue>UnreliableChannel</allowedValue>
+		        <allowedValue>Unknown</allowedValue>
+		    </allowedValueList>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_AVTransportID</name>
+		    <dataType>i4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_RcsID</name>
+		    <dataType>i4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ConnectionID</name>
+		    <dataType>i4</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_ConnectionManager</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='yes'>
+		    <name>SourceProtocolInfo</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='yes'>
+		    <name>SinkProtocolInfo</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+		<stateVariable sendEvents='no'>
+		    <name>A_ARG_TYPE_Direction</name>
+		    <dataType>string</dataType>
+		    <allowedValueList>
+		        <allowedValue>Input</allowedValue>
+		        <allowedValue>Output</allowedValue>
+		    </allowedValueList>
+		</stateVariable>
+		<stateVariable sendEvents='yes'>
+		    <name>CurrentConnectionIDs</name>
+		    <dataType>string</dataType>
+		</stateVariable>
+	</serviceStateTable>
+</scpd>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+	<specVersion>
+		<major>1</major> 
+		<minor>0</minor> 
+	</specVersion>
+	<actionList>
+		<action>
+		<name>Browse</name> 
+		<argumentList>
+			<argument>
+				<name>ObjectID</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>BrowseFlag</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_BrowseFlag</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>Filter</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>StartingIndex</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>RequestedCount</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>SortCriteria</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>Result</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>NumberReturned</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>TotalMatches</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>UpdateID</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable> 
+			</argument>
+		</argumentList>
+		</action>
+		<action>
+			<name>GetSortCapabilities</name> 
+			<argumentList>
+				<argument>
+					<name>SortCaps</name> 
+					<direction>out</direction> 
+					<relatedStateVariable>SortCapabilities</relatedStateVariable> 
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetSystemUpdateID</name> 
+			<argumentList>
+				<argument>
+					<name>Id</name> 
+					<direction>out</direction> 
+					<relatedStateVariable>SystemUpdateID</relatedStateVariable> 
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetSearchCapabilities</name> 
+			<argumentList>
+				<argument>
+					<name>SearchCaps</name> 
+					<direction>out</direction> 
+					<relatedStateVariable>SearchCapabilities</relatedStateVariable> 
+				</argument>
+			</argumentList>
+		</action>
+	</actionList>
+	<serviceStateTable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_BrowseFlag</name> 
+			<dataType>string</dataType> 
+			<allowedValueList>
+				<allowedValue>BrowseMetadata</allowedValue> 
+				<allowedValue>BrowseDirectChildren</allowedValue> 
+			</allowedValueList>
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>ContainerUpdateIDs</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>SystemUpdateID</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Count</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_SortCriteria</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>SortCapabilities</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Index</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_ObjectID</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_UpdateID</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Result</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>SearchCapabilities</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Filter</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+	</serviceStateTable>
+</scpd>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.xml	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+	<specVersion>
+		<major>1</major> 
+		<minor>0</minor> 
+	</specVersion>
+	<actionList>
+		<action>
+		<name>Browse</name> 
+		<argumentList>
+			<argument>
+				<name>ObjectID</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>BrowseFlag</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_BrowseFlag</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>Filter</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>StartingIndex</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>RequestedCount</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>SortCriteria</name> 
+				<direction>in</direction> 
+				<relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>Result</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>NumberReturned</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>TotalMatches</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> 
+			</argument>
+			<argument>
+				<name>UpdateID</name> 
+				<direction>out</direction> 
+				<relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable> 
+			</argument>
+		</argumentList>
+		</action>
+		<action>
+			<name>GetSortCapabilities</name> 
+			<argumentList>
+				<argument>
+					<name>SortCaps</name> 
+					<direction>out</direction> 
+					<relatedStateVariable>SortCapabilities</relatedStateVariable> 
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetSystemUpdateID</name> 
+			<argumentList>
+				<argument>
+					<name>Id</name> 
+					<direction>out</direction> 
+					<relatedStateVariable>SystemUpdateID</relatedStateVariable> 
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+			<name>GetSearchCapabilities</name> 
+			<argumentList>
+				<argument>
+					<name>SearchCaps</name> 
+					<direction>out</direction> 
+					<relatedStateVariable>SearchCapabilities</relatedStateVariable> 
+				</argument>
+			</argumentList>
+		</action>
+		<action>
+		    <name>Search</name>
+            <argumentList>
+                <argument>
+                    <name>ContainerID</name>
+                    <direction>in</direction>         
+                    <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>SearchCriteria</name>
+                    <direction>in</direction>            
+                    <relatedStateVariable>A_ARG_TYPE_SearchCriteria</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>Filter</name>
+                    <direction>in</direction>
+                    <relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>StartingIndex</name>
+                    <direction>in</direction>
+                    <relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>RequestedCount</name>
+                    <direction>in</direction>
+                    <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>SortCriteria</name>
+                    <direction>in</direction>          
+                    <relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>Result</name>
+                    <direction>out</direction>
+                    <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>NumberReturned</name>
+                    <direction>out</direction>
+                    <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>TotalMatches</name>
+                    <direction>out</direction>
+                    <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+                </argument>
+                <argument>
+                    <name>UpdateID</name>
+                    <direction>out</direction>           
+                    <relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable>
+                </argument>
+            </argumentList>
+        </action>
+	</actionList>
+	<serviceStateTable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_BrowseFlag</name> 
+			<dataType>string</dataType> 
+			<allowedValueList>
+				<allowedValue>BrowseMetadata</allowedValue> 
+				<allowedValue>BrowseDirectChildren</allowedValue> 
+			</allowedValueList>
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>ContainerUpdateIDs</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="yes">
+			<name>SystemUpdateID</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Count</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_SortCriteria</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_SearchCriteria</name>
+			<dataType>string</dataType>
+		</stateVariable>    
+		<stateVariable sendEvents="no">
+			<name>SortCapabilities</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Index</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_ObjectID</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_UpdateID</name> 
+			<dataType>ui4</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Result</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>SearchCapabilities</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+		<stateVariable sendEvents="no">
+			<name>A_ARG_TYPE_Filter</name> 
+			<dataType>string</dataType> 
+		</stateVariable>
+	</serviceStateTable>
+</scpd>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltDidl.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,355 @@
+/*****************************************************************
+|
+|   Platinum - DIDL
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltDidl.h"
+#include "PltXmlHelper.h"
+#include "PltService.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.didl")
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+const char* didl_header         = "<DIDL-Lite xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\""
+                                            " xmlns:dc=\"http://purl.org/dc/elements/1.1/\""
+                                            " xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\""
+                                            " xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\">";
+const char* didl_footer         = "</DIDL-Lite>";
+const char* didl_namespace_dc   = "http://purl.org/dc/elements/1.1/";
+const char* didl_namespace_upnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
+const char* didl_namespace_dlna = "urn:schemas-dlna-org:metadata-1-0/";
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::ConvertFilterToMask
++---------------------------------------------------------------------*/
+NPT_UInt32 
+PLT_Didl::ConvertFilterToMask(NPT_String filter)
+{
+    // easy out
+    if (filter.GetLength() == 0) return PLT_FILTER_MASK_ALL;
+    
+    // a filter string is a comma delimited set of fields identifying
+    // a given DIDL property (or set of properties).  
+    // These fields are or start with: upnp:, @, res@, res, dc:, container@
+
+    NPT_UInt32  mask = 0;
+    const char* s = filter;
+    int         i = 0;
+
+    while (s[i] != '\0') {
+        int next_comma = filter.Find(',', i);
+        int len = ((next_comma < 0)?filter.GetLength():next_comma)-i;
+
+        if (NPT_String::CompareN(s+i, "*", 1) == 0) {
+            // return now, there's no point in parsing the rest
+            return PLT_FILTER_MASK_ALL;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CREATOR, len) == 0) {
+            mask |= PLT_FILTER_MASK_CREATOR;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ARTIST, len) == 0) {
+            mask |= PLT_FILTER_MASK_ARTIST;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ACTOR, len) == 0) {
+            mask |= PLT_FILTER_MASK_ACTOR;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_AUTHOR, len) == 0) {
+            mask |= PLT_FILTER_MASK_AUTHOR;       
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DATE, len) == 0) {
+            mask |= PLT_FILTER_MASK_DATE;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUM, len) == 0) {
+            mask |= PLT_FILTER_MASK_ALBUM;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_GENRE, len) == 0) {
+            mask |= PLT_FILTER_MASK_GENRE;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUMARTURI, len) == 0) {
+            mask |= PLT_FILTER_MASK_ALBUMARTURI;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DESCRIPTION, len) == 0) {
+            mask |= PLT_FILTER_MASK_DESCRIPTION;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ORIGINALTRACK, len) == 0) {
+            mask |= PLT_FILTER_MASK_ORIGINALTRACK;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SEARCHABLE, len) == 0) {
+            mask |= PLT_FILTER_MASK_SEARCHABLE;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_SEARCHABLE, len) == 0) {
+            mask |= PLT_FILTER_MASK_SEARCHABLE;       
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CHILDCOUNT, len) == 0) {
+            mask |= PLT_FILTER_MASK_CHILDCOUNT;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_CHILDCOUNT, len) == 0) {
+            mask |= PLT_FILTER_MASK_CHILDCOUNT;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_DURATION, len) == 0) {
+            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_DURATION;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_SIZE, len) == 0) {
+            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_SIZE;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_PROTECTION, len) == 0) {
+            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_PROTECTION;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_RESOLUTION, len) == 0) {
+            mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_RESOLUTION;
+        } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES, len) == 0) {
+            mask |= PLT_FILTER_MASK_RES;
+        } 
+
+        if (next_comma < 0) {
+            return mask;
+        }
+
+        i = next_comma + 1;
+    }
+
+    return mask;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::AppendXmlUnEscape
++---------------------------------------------------------------------*/
+void
+PLT_Didl::AppendXmlUnEscape(NPT_String& out, NPT_String& in)
+{
+    const char* input = (const char*) in;
+    unsigned int i=0;
+    while (i<in.GetLength()) {
+        if (NPT_String::CompareN(input+i, "&lt;", 4) == 0) {
+            out += '<';
+            i   +=4;
+        } else if (NPT_String::CompareN(input+i, "&gt;", 4) == 0) {
+            out += '>';
+            i   += 4;
+        } else if (NPT_String::CompareN(input+i, "&amp;", 5) == 0) {
+            out += '&';
+            i   += 5;
+        } else if (NPT_String::CompareN(input+i, "&quot;", 6) == 0) {
+            out += '"';
+            i   += 6;
+        } else if (NPT_String::CompareN(input+i, "&apos;", 6) == 0) {
+            out += '\'';
+            i   += 6;
+        } else {
+            out += *(input+i);
+            i++;
+        }
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::AppendXmlEscape
++---------------------------------------------------------------------*/
+void
+PLT_Didl::AppendXmlEscape(NPT_String& out, NPT_String& in)
+{
+    for (int i=0; i<(int)in.GetLength(); i++) {
+        if (in[i] == '<') {
+            out += "&lt;";
+        } else if (in[i] == '>') {
+            out += "&gt;";
+        } else if (in[i] == '&') {
+            out += "&amp;";
+        } else if (in[i] == '"') {
+            out += "&quot;";
+        }  else if (in[i] == '\'') {
+            out += "&apos;";
+        } else {
+            out += in[i];
+        }
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::FormatTimeStamp
++---------------------------------------------------------------------*/
+void
+PLT_Didl::FormatTimeStamp(NPT_String& out, NPT_UInt32 seconds)
+{
+    int hours = seconds/3600;
+    if (hours == 0) {
+        out += "00:";
+    } else {
+        if (hours < 10) {
+            out += '0';
+        }
+        out += NPT_String::FromInteger(hours) + ":";
+    }
+
+    int minutes = (seconds/60)%60;
+    if (minutes == 0) {
+        out += "00:";
+    } else {
+        if (minutes < 10) {
+            out += '0';
+        }
+        out += NPT_String::FromInteger(minutes) + ":";
+    }
+
+    int secs = seconds%60;
+    if (secs == 0) {
+        out += "00";
+    } else {
+        if (secs < 10) {
+            out += '0';
+        }
+        out += NPT_String::FromInteger(secs);
+    }
+
+    out += ".000";
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::ParseTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Didl::ParseTimeStamp(NPT_String timestamp, NPT_UInt32& seconds)
+{
+    // assume a timestamp in the format HH:MM:SS
+    int colon;
+    NPT_String str = timestamp;
+    NPT_UInt32 num;
+
+    // extract millisecondsfirst
+    if ((colon = timestamp.ReverseFind('.')) != -1) {
+        str = timestamp.SubString(colon + 1);
+        timestamp = timestamp.Left(colon);
+    }
+
+    // extract seconds first
+    str = timestamp;
+    if ((colon = timestamp.ReverseFind(':')) != -1) {
+        str = timestamp.SubString(colon + 1);
+        timestamp = timestamp.Left(colon);
+    }
+
+    if (NPT_FAILED(str.ToInteger(num))) {
+        return NPT_FAILURE;
+    }
+
+    seconds = num;
+
+    // extract minutes
+    str = timestamp;
+    if (timestamp.GetLength()) {
+        if ((colon = timestamp.ReverseFind(':')) != -1) {
+            str = timestamp.SubString(colon + 1);
+            timestamp = timestamp.Left(colon);
+        }
+
+        if (NPT_FAILED(str.ToInteger(num))) {
+            return NPT_FAILURE;
+        }
+
+        seconds += 60*num;
+    }
+
+    // extract hours
+    str = timestamp;
+    if (timestamp.GetLength()) {
+        if ((colon = timestamp.ReverseFind(':')) != -1) {
+            str = timestamp.SubString(colon + 1);
+            timestamp = timestamp.Left(colon);
+        }
+
+        if (NPT_FAILED(str.ToInteger(num))) {
+            return NPT_FAILURE;
+        }
+
+        seconds += 3600*num;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Didl::ToDidl(PLT_MediaObject& object, NPT_String filter, NPT_String& didl)
+{
+    NPT_UInt32 mask = ConvertFilterToMask(filter);
+
+    // Allocate enough space for the didl
+    didl.Reserve(2048);
+
+    return object.ToDidl(mask, didl);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_Didl::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result  
+PLT_Didl::FromDidl(const char* xml, PLT_MediaObjectListReference& objects)
+{
+    NPT_String          str;
+    PLT_MediaObject*    object = NULL;
+    NPT_XmlNode*        node = NULL;
+    NPT_XmlElementNode* didl = NULL;
+
+    NPT_LOG_FINE("Parsing Didl...");
+
+    NPT_XmlParser parser;
+    if (NPT_FAILED(parser.Parse(xml, node)) || !node || !node->AsElementNode()) {
+        goto cleanup;
+    }
+
+    didl = node->AsElementNode();
+
+    NPT_LOG_FINE("Processing Didl xml...");
+    if (didl->GetTag().Compare("DIDL-Lite", true)) {
+        goto cleanup;
+    }
+
+    // create entry list
+    objects = new PLT_MediaObjectList();
+
+    // for each child, find out if it's a container or not
+    // and then invoke the FromDidl on it
+    for (NPT_List<NPT_XmlNode*>::Iterator children = didl->GetChildren().GetFirstItem(); children; children++) {
+        NPT_XmlElementNode* child = (*children)->AsElementNode();
+        if (!child) continue;
+
+        if (child->GetTag().Compare("Container", true) == 0) {
+            object = new PLT_MediaContainer();
+        } else if (child->GetTag().Compare("item", true) == 0) {
+            object = new PLT_MediaItem();
+        } else {
+            goto cleanup;
+        }
+
+        if (NPT_FAILED(object->FromDidl(child))) {
+            goto cleanup;
+        }
+        objects->Add(object);
+    }
+
+    delete node;
+    return NPT_SUCCESS;
+
+cleanup:
+    objects = NULL;
+    delete node;
+    delete object;
+    return NPT_FAILURE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltDidl.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,118 @@
+/*****************************************************************
+|
+|   Platinum - DIDL handling
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_DIDL_H_
+#define _PLT_DIDL_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define PLT_FILTER_MASK_ALL                         0xFFFFFFFF
+
+#define PLT_FILTER_MASK_CREATOR                     0x00000001
+#define PLT_FILTER_MASK_ARTIST                      0x00000002
+#define PLT_FILTER_MASK_ALBUM                       0x00000004
+#define PLT_FILTER_MASK_GENRE                       0x00000008
+#define PLT_FILTER_MASK_ALBUMARTURI                 0x00000010
+#define PLT_FILTER_MASK_DESCRIPTION                 0x00000020
+#define PLT_FILTER_MASK_SEARCHABLE                  0x00000040
+#define PLT_FILTER_MASK_CHILDCOUNT                  0x00000080
+#define PLT_FILTER_MASK_ORIGINALTRACK               0x00000100
+#define PLT_FILTER_MASK_ACTOR                       0x00000200
+#define PLT_FILTER_MASK_AUTHOR                      0x00000400
+#define PLT_FILTER_MASK_DATE                        0x00000800
+
+#define PLT_FILTER_MASK_RES                         0x00010000
+#define PLT_FILTER_MASK_RES_DURATION                0x00020000
+#define PLT_FILTER_MASK_RES_SIZE                    0x00040000
+#define PLT_FILTER_MASK_RES_PROTECTION              0x00080000
+#define PLT_FILTER_MASK_RES_RESOLUTION              0x00100000
+
+#define PLT_FILTER_FIELD_CREATOR                    "dc:creator"
+#define PLT_FILTER_FIELD_DATE                       "dc:date"
+#define PLT_FILTER_FIELD_ARTIST                     "upnp:artist"
+#define PLT_FILTER_FIELD_ACTOR                      "upnp:actor"
+#define PLT_FILTER_FIELD_AUTHOR                     "upnp:author"
+#define PLT_FILTER_FIELD_ALBUM                      "upnp:album"
+#define PLT_FILTER_FIELD_GENRE                      "upnp:genre"
+#define PLT_FILTER_FIELD_ALBUMARTURI                "upnp:albumArtURI"
+#define PLT_FILTER_FIELD_DESCRIPTION                "upnp:longDescription"
+#define PLT_FILTER_FIELD_ORIGINALTRACK              "upnp:originalTrackNumber"
+#define PLT_FILTER_FIELD_SEARCHABLE                 "@searchable"
+#define PLT_FILTER_FIELD_CHILDCOUNT                 "@childcount"
+#define PLT_FILTER_FIELD_CONTAINER_CHILDCOUNT       "container@childCount"
+#define PLT_FILTER_FIELD_CONTAINER_SEARCHABLE       "container@searchable"
+
+#define PLT_FILTER_FIELD_RES                        "res"
+#define PLT_FILTER_FIELD_RES_DURATION               "res@duration"
+#define PLT_FILTER_FIELD_RES_SIZE                   "res@size"
+#define PLT_FILTER_FIELD_RES_PROTECTION             "res@protection"
+#define PLT_FILTER_FIELD_RES_RESOLUTION             "res@resolution"
+
+extern const char* didl_header;
+extern const char* didl_footer;
+extern const char* didl_namespace_dc;
+extern const char* didl_namespace_upnp;
+
+/*----------------------------------------------------------------------
+|   PLT_Didl class
++---------------------------------------------------------------------*/
+class PLT_Didl
+{
+public:
+    static NPT_Result  ToDidl(PLT_MediaObject& object, NPT_String filter, NPT_String& didl);
+    static NPT_Result  FromDidl(const char* didl, PLT_MediaObjectListReference& objects);
+
+    static void        AppendXmlEscape(NPT_String& out, NPT_String& in);
+    static void        AppendXmlUnEscape(NPT_String& out, NPT_String& in);
+    static NPT_Result  ParseTimeStamp(NPT_String timestamp, NPT_UInt32& seconds);
+    static void        FormatTimeStamp(NPT_String& out, NPT_UInt32 seconds);
+
+    static NPT_Result  ParseTimeStamp(NPT_String in, NPT_TimeStamp& timestamp) {
+        NPT_UInt32 seconds;
+        NPT_Result res = ParseTimeStamp(in, seconds);
+        timestamp = NPT_TimeStamp(seconds, 0);
+        return res;
+    }
+
+private:
+    static NPT_UInt32  ConvertFilterToMask(NPT_String filter);
+};
+
+#endif /* _PLT_DIDL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltFileMediaServer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,641 @@
+/*****************************************************************
+|
+|   Platinum - File Media Server
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltFileMediaServer.h"
+#include "PltMediaItem.h"
+#include "PltService.h"
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltDidl.h"
+#include "PltMetadataHandler.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.file")
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::PLT_FileMediaServer
++---------------------------------------------------------------------*/
+PLT_FileMediaServer::PLT_FileMediaServer(const char*  path, 
+                                         const char*  friendly_name, 
+                                         bool         show_ip     /* = false */, 
+                                         const char*  uuid        /* = NULL */, 
+                                         NPT_UInt16   port        /* = 0 */,
+                                         bool         port_rebind /* = false */) :	
+    PLT_MediaServer(friendly_name, 
+                    show_ip,
+                    uuid, 
+                    port,
+                    port_rebind)
+{
+    /* set up the server root path */
+    m_Path  = path;
+    m_Path.TrimRight("/\\");
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::~PLT_FileMediaServer
++---------------------------------------------------------------------*/
+PLT_FileMediaServer::~PLT_FileMediaServer()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::AddMetadataHandler
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileMediaServer::AddMetadataHandler(PLT_MetadataHandler* handler) 
+{
+    // make sure we don't have a metadatahandler registered for the same extension
+/*    PLT_MetadataHandler* prev_handler;
+    NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, PLT_MetadataHandlerFinder(handler->GetExtension()), prev_handler);
+    if (NPT_SUCCEEDED(ret)) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    } */
+
+    m_MetadataHandlers.Add(handler);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::SetupDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServer::SetupDevice()
+{
+    // FIXME: hack for now: find the first valid non local ip address
+    // to use in item resources. TODO: we should advertise all ips as
+    // multiple resources instead.
+    NPT_List<NPT_String> ips;
+    PLT_UPnPMessageHelper::GetIPAddresses(ips);
+    if (ips.GetItemCount() == 0) return NPT_ERROR_INTERNAL;
+
+    // set the base paths for content and album arts
+    m_FileBaseUri     = NPT_HttpUrl(*ips.GetFirstItem(), GetPort(), "/content");
+    m_AlbumArtBaseUri = NPT_HttpUrl(*ips.GetFirstItem(), GetPort(), "/albumart");
+
+    return PLT_MediaServer::SetupDevice();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::ProcessHttpRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileMediaServer::ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                        const NPT_HttpRequestContext& context,
+                                        NPT_HttpResponse&             response)
+{
+    if (request.GetUrl().GetPath().StartsWith(m_FileBaseUri.GetPath()) || 
+        request.GetUrl().GetPath().StartsWith(m_AlbumArtBaseUri.GetPath())) {
+        return ProcessFileRequest(request, context, response);
+    }
+
+    return PLT_MediaServer::ProcessHttpRequest(request, context, response);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::ProcessGetDescription
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileMediaServer::ProcessGetDescription(NPT_HttpRequest&              request,
+                                           const NPT_HttpRequestContext& context,
+                                           NPT_HttpResponse&             response)
+{
+    NPT_String m_OldModelName   = m_ModelName;
+    NPT_String m_OldModelNumber = m_ModelNumber;
+
+    // change some things based on User-Agent header
+    NPT_HttpHeader* user_agent = request.GetHeaders().GetHeader(NPT_HTTP_HEADER_USER_AGENT);
+    if (user_agent && user_agent->GetValue().Find("Sonos", 0, true)>=0) {
+        // Force "Rhapsody" so that Sonos is happy to find us
+        m_ModelName   = "Rhapsody";
+        m_ModelNumber = "3.0";
+
+        // return modified description
+        NPT_String doc;
+        NPT_Result res = GetDescription(doc);
+
+        // reset to old values now
+        m_ModelName   = m_OldModelName;
+        m_ModelNumber = m_OldModelNumber;
+
+        NPT_CHECK_FATAL(res);
+
+        PLT_HttpHelper::SetBody(response, doc);    
+        PLT_HttpHelper::SetContentType(response, "text/xml");
+
+        return NPT_SUCCESS;
+    }
+
+    return PLT_MediaServer::ProcessGetDescription(request, context, response);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::ExtractResourcePath
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServer::ExtractResourcePath(const NPT_HttpUrl& url, NPT_String& file_path)
+{
+    // Extract uri path from url
+    NPT_String uri_path = NPT_Uri::PercentDecode(url.GetPath());
+    
+    // extract file path from query
+    NPT_HttpUrlQuery query(url.GetQuery());
+    file_path = query.GetField("path");
+    if (file_path.GetLength()) return NPT_SUCCESS;
+
+    // hack for XBMC support for 360, we urlencoded the ? to that the 360 doesn't strip out the query
+    // but then the query ends being parsed as part of the path
+    int index = uri_path.Find("path=");
+    if (index>0) {
+        file_path = uri_path.Right(uri_path.GetLength()-index-5);
+        return NPT_SUCCESS;
+    }
+    
+    uri_path = url.GetPath();
+    if (uri_path.StartsWith(m_FileBaseUri.GetPath(), true)) {
+        file_path = NPT_Uri::PercentDecode(uri_path.SubString(m_FileBaseUri.GetPath().GetLength()));
+        return NPT_SUCCESS;
+    } else if (uri_path.StartsWith(m_AlbumArtBaseUri.GetPath(), true)) {
+        file_path = NPT_Uri::PercentDecode(uri_path.SubString(m_AlbumArtBaseUri.GetPath().GetLength()));
+        return NPT_SUCCESS;
+    }
+    
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::ProcessFileRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileMediaServer::ProcessFileRequest(NPT_HttpRequest&              request, 
+                                        const NPT_HttpRequestContext& context,
+                                        NPT_HttpResponse&             response)
+{
+    NPT_LOG_FINE("PLT_FileMediaServer::ProcessFileRequest Received Request:");
+    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);
+
+    response.GetHeaders().SetHeader("Accept-Ranges", "bytes");
+
+    if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) {
+        response.SetStatus(500, "Internal Server Error");
+        return NPT_SUCCESS;
+    }
+
+    // Extract file path from url
+    NPT_String file_path;
+    NPT_CHECK_LABEL_WARNING(ExtractResourcePath(request.GetUrl(), file_path),  
+                            failure);
+                            
+    // Serve file now
+    if (request.GetUrl().GetPath().StartsWith(m_FileBaseUri.GetPath(), true)) {
+        NPT_CHECK_WARNING(ServeFile(request, context, response, NPT_FilePath::Create(m_Path, file_path)));
+        return NPT_SUCCESS;
+    } else if (request.GetUrl().GetPath().StartsWith(m_AlbumArtBaseUri.GetPath(), true)) {
+        NPT_CHECK_WARNING(OnAlbumArtRequest(response, NPT_FilePath::Create(m_Path, file_path)));
+        return NPT_SUCCESS;
+    }
+
+    // fallthrough
+
+failure:
+    response.SetStatus(404, "File Not Found");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::ServeFile
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileMediaServer::ServeFile(NPT_HttpRequest&              request, 
+                               const NPT_HttpRequestContext& context,
+                               NPT_HttpResponse&             response,
+                               const NPT_String&             file_path)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    NPT_Position start, end;
+    PLT_HttpHelper::GetRange(request, start, end);
+        
+    return PLT_FileServer::ServeFile(response,
+                                     file_path, 
+                                     start, 
+                                     end, 
+                                     !request.GetMethod().Compare("HEAD"));
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::OnAlbumArtRequest
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_FileMediaServer::OnAlbumArtRequest(NPT_HttpResponse& response,
+                                       NPT_String        file_path)
+{
+    NPT_LargeSize            total_len;
+    NPT_File                 file(file_path);
+    NPT_InputStreamReference stream;
+
+    // prevent hackers from accessing files outside of our root
+    if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0)) {
+        goto filenotfound;
+    }
+
+    if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || 
+        NPT_FAILED(file.GetInputStream(stream))        || 
+        NPT_FAILED(stream->GetSize(total_len)) || (total_len == 0)) {
+        goto filenotfound;
+    } else {
+        NPT_String extension = NPT_FilePath::FileExtension(file_path);
+        if (extension.GetLength() == 0) {
+            goto filenotfound;
+        }
+
+        PLT_MetadataHandler* metadataHandler = NULL;
+        char* caData;
+        int   caDataLen;
+        NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, 
+                                           PLT_MetadataHandlerFinder(extension), 
+                                           metadataHandler);
+        if (NPT_FAILED(ret) || metadataHandler == NULL) {
+            goto filenotfound;
+        }
+        // load the metadatahandler and read the cover art
+        if (NPT_FAILED(metadataHandler->Load(*stream)) || 
+            NPT_FAILED(metadataHandler->GetCoverArtData(caData, caDataLen))) {
+            goto filenotfound;
+        }
+        
+        PLT_HttpHelper::SetContentType(response, "application/octet-stream");
+        PLT_HttpHelper::SetBody(response, caData, caDataLen);
+        delete caData;
+        return NPT_SUCCESS;
+    }
+
+filenotfound:
+    response.SetStatus(404, "File Not Found");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::OnBrowseMetadata
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServer::OnBrowseMetadata(PLT_ActionReference&          action, 
+                                      const char*                   object_id, 
+                                      const PLT_HttpRequestContext& context)
+{
+    NPT_String didl;
+    PLT_MediaObjectReference item;
+
+    /* locate the file from the object ID */
+    NPT_String filepath;
+    if (NPT_FAILED(GetFilePath(object_id, filepath))) {
+        /* error */
+        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found.");
+        action->SetError(701, "No Such Object.");
+        return NPT_FAILURE;
+    }
+
+    item = BuildFromFilePath(filepath, context, true);
+
+    if (item.IsNull()) return NPT_FAILURE;
+
+    NPT_String filter;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+
+    NPT_String tmp;    
+    NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp));
+
+    /* add didl header and footer */
+    didl = didl_header + tmp + didl_footer;
+
+    NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", "1"));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", "1"));
+
+    // update ID may be wrong here, it should be the one of the container?
+    // TODO: We need to keep track of the overall updateID of the CDS
+    NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1"));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::OnBrowseDirectChildren
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServer::OnBrowseDirectChildren(PLT_ActionReference&          action, 
+                                            const char*                   object_id, 
+                                            const PLT_HttpRequestContext& context)
+{
+    /* locate the file from the object ID */
+    NPT_String dir;
+    if (NPT_FAILED(GetFilePath(object_id, dir))) {
+        /* error */
+        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found.");
+        action->SetError(701, "No Such Object.");
+        return NPT_FAILURE;
+    }
+
+    /* retrieve the item type */
+    NPT_FileInfo info;
+    NPT_Result res = NPT_File::GetInfo(dir, &info);
+    if (NPT_FAILED(res)) {
+        /* Object does not exist */
+        NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN failed for item %s", dir.GetChars());
+        action->SetError(800, "Can't retrieve info " + dir);
+        return NPT_FAILURE;
+    }
+
+    if (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY) {
+        /* error */
+        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN not allowed on an item.");
+        action->SetError(710, "item is not a container.");
+        return NPT_FAILURE;
+    }
+
+    NPT_String filter;
+    NPT_String startingInd;
+    NPT_String reqCount;
+
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+    NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd));
+    NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); 
+    
+    // in case someone forgot to pass a filter
+    if (filter.GetLength() == 0) filter = "*";
+
+    NPT_UInt32 start_index, req_count;
+    if (NPT_FAILED(startingInd.ToInteger(start_index)) ||
+        NPT_FAILED(reqCount.ToInteger(req_count))) {        
+        action->SetError(412, "Precondition failed");
+        return NPT_FAILURE;
+    }
+
+    NPT_List<NPT_String> entries;
+    res = NPT_File::ListDirectory(dir, entries, 0, 0);
+    if (NPT_FAILED(res)) {
+        NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowseDirectChildren - failed to open dir %s", (const char*) dir);
+        return res;
+    }
+
+    unsigned long cur_index = 0;
+    unsigned long num_returned = 0;
+    unsigned long total_matches = 0;
+    NPT_String didl = didl_header;
+
+    PLT_MediaObjectReference item;
+    for (NPT_List<NPT_String>::Iterator it = entries.GetFirstItem();
+         it;
+         ++it) {
+        NPT_String filepath = NPT_FilePath::Create(dir, *it);
+        
+        // verify we want to process this file first
+        if (!ProcessFile(filepath)) continue;
+        
+        item = BuildFromFilePath(
+            filepath, 
+            context,
+            true);
+
+        if (!item.IsNull()) {
+            if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) {
+                NPT_String tmp;
+                NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp));
+
+                didl += tmp;
+                num_returned++;
+            }
+            cur_index++;
+            total_matches++;        
+        }
+    };
+
+    didl += didl_footer;
+
+    NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned)));
+    NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); // 0 means we don't know how many we have but most browsers don't like that!!
+    NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1"));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::GetFilePath
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServer::GetFilePath(const char* object_id, 
+                                 NPT_String& filepath) 
+{
+    if (!object_id) return NPT_ERROR_INVALID_PARAMETERS;
+
+    filepath = m_Path;
+
+    if (NPT_StringLength(object_id) > 2 || object_id[0]!='0') {
+        filepath += (const char*)object_id + (object_id[0]=='0'?1:0);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::BuildResourceUri
++---------------------------------------------------------------------*/
+NPT_String
+PLT_FileMediaServer::BuildResourceUri(const NPT_HttpUrl& base_uri, 
+                                      const char*        host, 
+                                      const char*        file_path)
+{
+    NPT_String result;
+    NPT_HttpUrl uri = base_uri;
+    
+    if (host) uri.SetHost(host);
+
+    if (file_path) {
+        NPT_HttpUrlQuery query(uri.GetQuery());
+        query.AddField("path", file_path);
+        uri.SetQuery(query.ToString());
+    }
+    
+    // 360 hack: force inclusion of port
+    result = uri.ToStringWithDefaultPort(0);
+
+    // 360 hack: it removes the query, so we make it look like a path
+    // and we replace + with urlencoded value of space
+    result.Replace('?', "%3F");
+    result.Replace('+', "%20");
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer::BuildFromFilePath
++---------------------------------------------------------------------*/
+PLT_MediaObject*
+PLT_FileMediaServer::BuildFromFilePath(const NPT_String&             filepath, 
+                                       const PLT_HttpRequestContext& context,
+                                       bool                          with_count /* = true */,
+                                       bool                          keep_extension_in_title /* = false */)
+{
+    NPT_String            root = m_Path;
+    PLT_MediaItemResource resource;
+    PLT_MediaObject*      object = NULL;
+    
+    NPT_LOG_INFO_1("Building didl for file '%s'", (const char*)filepath);
+
+    /* retrieve the entry type (directory or file) */
+    NPT_FileInfo info; 
+    NPT_CHECK_LABEL_FATAL(NPT_File::GetInfo(filepath, &info), failure);
+
+    if (info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR) {
+        object = new PLT_MediaItem();
+
+        /* Set the title using the filename for now */
+        object->m_Title = NPT_FilePath::BaseName(filepath, keep_extension_in_title);
+        if (object->m_Title.GetLength() == 0) goto failure;
+
+        /* make sure we return something with a valid mimetype */
+        if (NPT_StringsEqual(PLT_MediaItem::GetMimeType(filepath), "application/unknown")) 
+            goto failure;
+        
+        /* Set the protocol Info from the extension */
+        resource.m_ProtocolInfo = PLT_MediaItem::GetProtInfo(filepath, context);
+        if (resource.m_ProtocolInfo.GetLength() == 0)  goto failure;
+
+        /* Set the resource file size */
+        resource.m_Size = info.m_Size;
+ 
+        /* format the resource URI */
+        NPT_String url = filepath.SubString(root.GetLength()+1);
+
+        // get list of ip addresses
+        NPT_List<NPT_String> ips;
+        NPT_CHECK_LABEL_SEVERE(PLT_UPnPMessageHelper::GetIPAddresses(ips), failure);
+
+        // if we're passed an interface where we received the request from
+        // move the ip to the top
+        if (context.GetLocalAddress().GetIpAddress().ToString() != "0.0.0.0") {
+            ips.Remove(context.GetLocalAddress().GetIpAddress().ToString());
+            ips.Insert(ips.GetFirstItem(), context.GetLocalAddress().GetIpAddress().ToString());
+        }
+
+        // iterate through list and build list of resources
+        NPT_List<NPT_String>::Iterator ip = ips.GetFirstItem();
+        
+        /* Look to see if a metadatahandler exists for this extension */
+        PLT_MetadataHandler* handler = NULL;
+        NPT_Result res = NPT_ContainerFind(
+            m_MetadataHandlers, 
+            PLT_MetadataHandlerFinder(NPT_FilePath::FileExtension(filepath)), 
+            handler);
+        if (NPT_SUCCEEDED(res) && handler) {
+            /* if it failed loading data, reset the metadatahandler so we don't use it */
+            if (NPT_SUCCEEDED(handler->LoadFile(filepath))) {
+                /* replace the title with the one from the Metadata */
+                NPT_String newTitle;
+                if (handler->GetTitle(newTitle) != NULL) {
+                    object->m_Title = newTitle;
+                }
+
+                /* assign description */
+                handler->GetDescription(object->m_Description.long_description);
+
+                /* assign album art uri if we haven't yet */
+                /* prepend the album art base URI and url encode it */ 
+                if (object->m_ExtraInfo.album_art_uri.GetLength() == 0) {
+                    object->m_ExtraInfo.album_art_uri = 
+                        NPT_Uri::PercentEncode(BuildResourceUri(m_AlbumArtBaseUri, *ip, url), 
+                                               NPT_Uri::UnsafeCharsToEncode);
+                }
+
+                /* duration */
+                handler->GetDuration(resource.m_Duration);
+
+                /* protection */
+                handler->GetProtection(resource.m_Protection);
+            }
+        }
+        
+        object->m_ObjectClass.type = PLT_MediaItem::GetUPnPClass(filepath, context);
+        
+        while (ip) {
+            /* prepend the base URI and url encode it */ 
+            //resource.m_Uri = NPT_Uri::Encode(uri.ToString(), NPT_Uri::UnsafeCharsToEncode);
+            resource.m_Uri = BuildResourceUri(m_FileBaseUri, *ip, url);
+            object->m_Resources.Add(resource);
+            ++ip;
+        }
+    } else {
+        object = new PLT_MediaContainer;
+
+        /* Assign a title for this container */
+        if (filepath.Compare(root, true) == 0) {
+            object->m_Title = "Root";
+        } else {
+            object->m_Title = NPT_FilePath::BaseName(filepath, keep_extension_in_title);
+            if (object->m_Title.GetLength() == 0) goto failure;
+        }
+
+        /* Get the number of children for this container */
+        NPT_Cardinal count = 0;
+        if (with_count && NPT_SUCCEEDED(NPT_File::GetCount(filepath, count))) {
+            ((PLT_MediaContainer*)object)->m_ChildrenCount = count;
+        }
+
+        object->m_ObjectClass.type = "object.container.storageFolder";
+    }
+
+    /* is it the root? */
+    if (filepath.Compare(root, true) == 0) {
+        object->m_ParentID = "-1";
+        object->m_ObjectID = "0";
+    } else {
+        NPT_String directory = NPT_FilePath::DirectoryName(filepath);
+        /* is the parent path the root? */
+        if (directory.GetLength() == root.GetLength()) {
+            object->m_ParentID = "0";
+        } else {
+            object->m_ParentID = "0" + filepath.SubString(root.GetLength(), directory.GetLength() - root.GetLength());
+        }
+        object->m_ObjectID = "0" + filepath.SubString(root.GetLength());
+    }
+
+    return object;
+
+failure:
+    delete object;
+    return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltFileMediaServer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,118 @@
+/*****************************************************************
+|
+|   Platinum - File Media Server
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FILE_MEDIA_SERVER_H_
+#define _PLT_FILE_MEDIA_SERVER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaServer.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define MAX_PATH_LENGTH 1024
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_MetadataHandler;
+
+/*----------------------------------------------------------------------
+|   PLT_FileMediaServer class
++---------------------------------------------------------------------*/
+class PLT_FileMediaServer : public PLT_MediaServer
+{
+public:
+    PLT_FileMediaServer(const char*  path, 
+                        const char*  friendly_name,
+                        bool         show_ip = false,
+                        const char*  uuid = NULL,
+                        NPT_UInt16   port = 0,
+                        bool         port_rebind = false);
+
+    // overridable
+    virtual NPT_Result AddMetadataHandler(PLT_MetadataHandler* handler);
+    virtual NPT_Result ExtractResourcePath(const NPT_HttpUrl& url, NPT_String& file_path);
+    virtual NPT_String BuildResourceUri(const NPT_HttpUrl& base_uri, const char* host, const char* file_path);
+
+protected:
+    virtual ~PLT_FileMediaServer();
+
+    // overridable
+    virtual NPT_Result ProcessFileRequest(NPT_HttpRequest&              request, 
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse&             response);
+    // PLT_DeviceHost methods
+    virtual NPT_Result SetupDevice();
+    virtual NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request, 
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse&             response);
+    virtual NPT_Result ProcessGetDescription(NPT_HttpRequest&              request,
+                                             const NPT_HttpRequestContext& context,
+                                             NPT_HttpResponse&             response);
+    // PLT_MediaServer methods
+    virtual NPT_Result OnBrowseMetadata(PLT_ActionReference&          action, 
+                                        const char*                   object_id, 
+                                        const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference&          action, 
+                                              const char*                   object_id, 
+                                              const PLT_HttpRequestContext& context);
+    virtual NPT_Result ServeFile(NPT_HttpRequest&              request, 
+                                 const NPT_HttpRequestContext& context,
+                                 NPT_HttpResponse&             response,
+                                 const NPT_String&             file_path);
+    virtual NPT_Result OnAlbumArtRequest(NPT_HttpResponse& response, 
+                                         NPT_String        file_path);
+    virtual NPT_Result GetFilePath(const char* object_id, NPT_String& filepath);
+    virtual bool       ProcessFile(const NPT_String&) { return true;}
+    virtual PLT_MediaObject* BuildFromFilePath(const NPT_String&             filepath, 
+                                               const PLT_HttpRequestContext& context,
+                                               bool                          with_count = true,
+                                               bool                          keep_extension_in_title = false);
+
+public:
+    NPT_UInt16                     m_FileServerPort;
+
+protected:
+    friend class PLT_MediaItem;
+
+    NPT_String                     m_Path;
+    NPT_HttpUrl                    m_FileBaseUri;
+    NPT_HttpUrl                    m_AlbumArtBaseUri;
+    NPT_List<PLT_MetadataHandler*> m_MetadataHandlers;
+};
+
+#endif /* _PLT_FILE_MEDIA_SERVER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaBrowser.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,314 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Browser (Media Server Control Point)
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaBrowser.h"
+#include "PltDidl.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.browser")
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::PLT_MediaBrowser
++---------------------------------------------------------------------*/
+PLT_MediaBrowser::PLT_MediaBrowser(PLT_CtrlPointReference&   ctrl_point,
+                                   PLT_MediaBrowserDelegate* delegate /* = NULL */) :
+    m_CtrlPoint(ctrl_point),
+    m_Delegate(delegate)
+{
+    m_CtrlPoint->AddListener(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::~PLT_MediaBrowser
++---------------------------------------------------------------------*/
+PLT_MediaBrowser::~PLT_MediaBrowser()
+{
+    m_CtrlPoint->RemoveListener(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::OnDeviceAdded
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnDeviceAdded(PLT_DeviceDataReference& device)
+{
+    // verify the device implements the function we need
+    PLT_Service* serviceCDS;
+    PLT_Service* serviceCMR;
+    NPT_String type;
+    
+    type = "urn:schemas-upnp-org:service:ContentDirectory:1";
+    if (NPT_FAILED(device->FindServiceByType(type, serviceCDS))) {
+        NPT_LOG_WARNING_2("Service %s not found in device \"%s\"", 
+            type.GetChars(),
+            device->GetFriendlyName().GetChars());
+        return NPT_FAILURE;
+    }
+    
+    type = "urn:schemas-upnp-org:service:ConnectionManager:1";
+    if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) {
+        NPT_LOG_WARNING_2("Service %s not found in device \"%s\"", 
+            type.GetChars(), 
+            device->GetFriendlyName().GetChars());
+        return NPT_FAILURE;
+    }    
+    
+    {
+        NPT_AutoLock lock(m_MediaServers);
+
+        PLT_DeviceDataReference data;
+        NPT_String uuid = device->GetUUID();
+        // is it a new device?
+        if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) {
+            NPT_LOG_WARNING_1("Device (%s) is already in our list!", (const char*)uuid);
+            return NPT_FAILURE;
+        }
+
+        NPT_LOG_FINE("Device Found:");
+        device->ToLog(NPT_LOG_LEVEL_FINE);
+
+        m_MediaServers.Add(device);
+    }
+
+    if (m_Delegate && m_Delegate->OnMSAdded(device)) {
+        m_CtrlPoint->Subscribe(serviceCDS);
+        m_CtrlPoint->Subscribe(serviceCMR);
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::OnDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaBrowser::OnDeviceRemoved(PLT_DeviceDataReference& device)
+{
+    PLT_DeviceDataReference data;
+
+    {
+        NPT_AutoLock lock(m_MediaServers);
+
+        // only release if we have kept it around
+        NPT_String uuid = device->GetUUID();
+        // is it a new device?
+        if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) {
+            NPT_LOG_WARNING_1("Device (%s) not found in our list!", (const char*)uuid);
+            return NPT_FAILURE;
+        }
+
+        NPT_LOG_FINE("Device Removed:");
+        device->ToLog(NPT_LOG_LEVEL_FINE);
+
+        m_MediaServers.Remove(device);
+    }
+    
+    if (m_Delegate) {
+        m_Delegate->OnMSRemoved(device);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::Browse
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaBrowser::Browse(PLT_DeviceDataReference&   device, 
+                         const char*                obj_id,
+                         NPT_UInt32                 start_index,
+                         NPT_UInt32                 count,
+                         bool                       browse_metadata,
+                         const char*                filter,
+                         const char*                sort_criteria,
+                         void*                      userdata)
+{
+    // look for the service
+    PLT_Service* service;
+    NPT_String type;
+
+    type = "urn:schemas-upnp-org:service:ContentDirectory:1";
+    if (NPT_FAILED(device->FindServiceByType(type, service))) {
+        NPT_LOG_WARNING_1("Service %s not found", (const char*)type);
+        return NPT_FAILURE;
+    }
+
+    PLT_ActionDesc* action_desc = service->FindActionDesc("Browse");
+    if (action_desc == NULL) {
+        NPT_LOG_WARNING("Action Browse not found in service");
+        return NPT_FAILURE;
+    }
+
+    PLT_ActionReference action(new PLT_Action(action_desc));
+
+    // Set the object id
+    PLT_Arguments args;
+    if (NPT_FAILED(action->SetArgumentValue("ObjectID", obj_id))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the browse_flag
+    if (NPT_FAILED(action->SetArgumentValue("BrowseFlag", browse_metadata?"BrowseMetadata":"BrowseDirectChildren"))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+ 
+    // set the Filter
+    if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the Starting Index
+    if (NPT_FAILED(action->SetArgumentValue("StartingIndex", NPT_String::FromInteger(start_index)))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the Requested Count
+    if (NPT_FAILED(action->SetArgumentValue("RequestedCount", NPT_String::FromInteger(count)))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the Requested Count
+    if (NPT_FAILED(action->SetArgumentValue("SortCriteria", sort_criteria))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // invoke the action
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::OnActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata)
+{
+    if (m_Delegate == NULL) return NPT_SUCCESS;
+
+    PLT_DeviceDataReference device;
+    {
+        NPT_AutoLock lock(m_MediaServers);
+        NPT_String uuid = action->GetActionDesc()->GetService()->GetDevice()->GetUUID();
+        if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), device))) {
+            NPT_LOG_WARNING_1("Device (%s) not found in our list of servers", (const char*)uuid);
+            return NPT_FAILURE;
+        }
+    }
+
+    NPT_String actionName = action->GetActionDesc()->GetName();
+
+    // Browse action response
+    if (actionName.Compare("Browse", true) == 0) {
+        return OnBrowseResponse(res, device, action, userdata);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::OnBrowseResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnBrowseResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata)
+{
+    NPT_String value;
+    PLT_BrowseInfo info;
+    NPT_String unescaped;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("ObjectID", info.object_id)))  {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("UpdateID", value)) || 
+        value.GetLength() == 0 || 
+        NPT_FAILED(value.ToInteger(info.uid))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("NumberReturned", value)) || 
+        value.GetLength() == 0 || 
+        NPT_FAILED(value.ToInteger(info.nr))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("TotalMatches", value)) || 
+        value.GetLength() == 0 || 
+        NPT_FAILED(value.ToInteger(info.tm))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("Result", value)) || 
+        value.GetLength() == 0) {
+        goto bad_action;
+    }
+    
+    if (NPT_FAILED(PLT_Didl::FromDidl(value, info.items))) {
+        goto bad_action;
+    }
+
+    m_Delegate->OnBrowseResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnBrowseResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser::OnEventNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
+{
+    if (!m_Delegate) return NPT_SUCCESS;
+
+    PLT_DeviceDataReference data;
+
+    {
+        NPT_AutoLock lock(m_MediaServers);
+        NPT_String uuid = service->GetDevice()->GetUUID();
+        if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) {
+            NPT_LOG_WARNING_1("Device (%s) not found in our list!", (const char*)uuid);
+            return NPT_FAILURE;
+        }
+    }
+
+    if (m_Delegate) m_Delegate->OnMSStateVariablesChanged(service, vars);
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaBrowser.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,123 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Browser (Media Server Control Point)
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_BROWSER_H_
+#define _PLT_MEDIA_BROWSER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltCtrlPoint.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+|   PLT_BrowseInfo
++---------------------------------------------------------------------*/
+struct PLT_BrowseInfo {
+    NPT_String                   object_id;
+    PLT_MediaObjectListReference items;
+    NPT_UInt32                   nr;
+    NPT_UInt32                   tm;
+    NPT_UInt32                   uid;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowserDelegate class
++---------------------------------------------------------------------*/
+class PLT_MediaBrowserDelegate
+{
+public:
+    virtual ~PLT_MediaBrowserDelegate() {}
+    
+    virtual bool OnMSAdded(PLT_DeviceDataReference& /* device */) { return true; }
+    virtual void OnMSRemoved(PLT_DeviceDataReference& /* device */) {}
+    virtual void OnMSStateVariablesChanged(
+        PLT_Service*                  /*service*/, 
+        NPT_List<PLT_StateVariable*>* /*vars*/) {}
+
+    // ContentDirectory
+    virtual void OnBrowseResult(
+        NPT_Result               /*res*/, 
+        PLT_DeviceDataReference& /*device*/, 
+        PLT_BrowseInfo*          /*info*/, 
+        void*                    /*userdata*/) {}
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaBrowser class
++---------------------------------------------------------------------*/
+class PLT_MediaBrowser : public PLT_CtrlPointListener
+{
+public:
+    PLT_MediaBrowser(PLT_CtrlPointReference&   ctrl_point,
+                     PLT_MediaBrowserDelegate* delegate = NULL);
+    virtual ~PLT_MediaBrowser();
+
+    // ContentDirectory service
+    virtual NPT_Result Browse(PLT_DeviceDataReference& device, 
+                              const char*              object_id, 
+                              NPT_UInt32               start_index,
+                              NPT_UInt32               count,
+                              bool                     browse_metadata = false,
+                              const char*              filter = "*",
+                              const char*              sort_criteria = "",
+                              void*                    userdata = NULL);
+
+    // accessor methods
+    virtual const NPT_Lock<PLT_DeviceDataReferenceList>& GetMediaServers() { 
+        return m_MediaServers; 
+    }
+    virtual void SetDelegate(PLT_MediaBrowserDelegate* delegate) {
+        m_Delegate = delegate;
+    }
+
+protected:
+    // PLT_CtrlPointListener methods
+    virtual NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device);
+    virtual NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device);
+    virtual NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata);
+    virtual NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars);
+    
+    // ContentDirectory service responses
+    virtual NPT_Result OnBrowseResponse(NPT_Result               res, 
+                                        PLT_DeviceDataReference& device, 
+                                        PLT_ActionReference&     action, 
+                                        void*                    userdata);
+
+protected:
+    PLT_CtrlPointReference                m_CtrlPoint;
+    PLT_MediaBrowserDelegate*             m_Delegate;
+    NPT_Lock<PLT_DeviceDataReferenceList> m_MediaServers;
+};
+
+#endif /* _PLT_MEDIA_BROWSER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaCache.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,155 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Cache
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltMediaCache.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.cache")
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::PLT_MediaCache
++---------------------------------------------------------------------*/
+PLT_MediaCache::PLT_MediaCache()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::~PLT_MediaCache
++---------------------------------------------------------------------*/
+PLT_MediaCache::~PLT_MediaCache()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::GenerateKey
++---------------------------------------------------------------------*/
+NPT_String
+PLT_MediaCache::GenerateKey(const char* device_uuid, 
+                            const char* item_id)
+{
+    NPT_String key = "upnp://";
+    key += device_uuid;
+    key += "/";
+    key += item_id;
+
+    return key;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::Clear
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaCache::Clear(const char* device_uuid, 
+                      const char* item_id)
+{
+    NPT_AutoLock lock(m_Mutex);
+    
+    NPT_String key = GenerateKey(device_uuid, item_id);
+    if (key.GetLength() == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+    NPT_List<PLT_MediaCacheEntry*>::Iterator entries = m_Items.GetEntries().GetFirstItem();
+    NPT_List<PLT_MediaCacheEntry*>::Iterator entry;
+    while (entries) {
+        entry = entries++;
+        if ((*entry)->GetKey() == (key)) {
+            m_Items.Erase(key);
+            return NPT_SUCCESS;
+        }
+    }
+
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::Clear
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaCache::Clear(const char* device_uuid)
+{
+    NPT_AutoLock lock(m_Mutex);
+
+    if (!device_uuid) return m_Items.Clear();
+
+    NPT_String key = GenerateKey(device_uuid, "");
+    NPT_List<PLT_MediaCacheEntry*>::Iterator entries = m_Items.GetEntries().GetFirstItem();
+    NPT_List<PLT_MediaCacheEntry*>::Iterator entry;
+    while (entries) {
+        entry = entries++;
+        NPT_String entry_key = (*entry)->GetKey();
+        if (entry_key.StartsWith(key)) {
+            m_Items.Erase(entry_key);
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::Put
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaCache::Put(const char*                   device_uuid,
+                    const char*                   item_id, 
+                    PLT_MediaObjectListReference& list)
+{
+    NPT_AutoLock lock(m_Mutex);
+
+    NPT_String key = GenerateKey(device_uuid, item_id);
+    if (key.GetLength() == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+    m_Items.Erase(key);
+    return m_Items.Put(key, list);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache::Get
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaCache::Get(const char*                   device_uuid,
+                    const char*                   item_id, 
+                    PLT_MediaObjectListReference& list)
+{
+    NPT_AutoLock lock(m_Mutex);
+
+    NPT_String key = GenerateKey(device_uuid, item_id);
+    if (key.GetLength() == 0) return NPT_ERROR_INVALID_PARAMETERS;
+    
+    PLT_MediaObjectListReference* val = NULL;
+    NPT_CHECK_FINE(m_Items.Get(key, val));
+
+    list = *val;
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaCache.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,75 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Cache
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_CACHE_H_
+#define _PLT_MEDIA_CACHE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaItem.h"
+#include "PltDeviceData.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+|   typedefs
++---------------------------------------------------------------------*/
+typedef NPT_Map<NPT_String, PLT_MediaObjectListReference>::Entry PLT_MediaCacheEntry;
+
+/*----------------------------------------------------------------------
+|   PLT_MediaCache class
++---------------------------------------------------------------------*/
+class PLT_MediaCache
+{
+public:
+    PLT_MediaCache();
+    virtual ~PLT_MediaCache();
+
+    NPT_Result Put(const char* device_uuid, const char* item_id, PLT_MediaObjectListReference& list);
+    NPT_Result Get(const char* device_uuid, const char* item_id, PLT_MediaObjectListReference& list);
+    NPT_Result Clear(const char* device_uuid, const char* item_id);
+    NPT_Result Clear(const char* device_uuid = NULL);
+
+private:
+    NPT_String GenerateKey(const char* device_uuid, const char* item_id);
+
+private:
+    NPT_Mutex m_Mutex;
+    NPT_Map<NPT_String, PLT_MediaObjectListReference> m_Items;
+};
+
+#endif /* _PLT_MEDIA_CACHE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,701 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Item
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltMediaItem.h"
+#include "PltMediaServer.h"
+#include "PltMetadataHandler.h"
+#include "PltDidl.h"
+#include "PltXmlHelper.h"
+#include "PltService.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.item")
+
+extern const char* didl_namespace_dc;
+extern const char* didl_namespace_upnp;
+
+/*----------------------------------------------------------------------
+|   PLT_PersonRoles::AddPerson
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PersonRoles::Add(const NPT_String& name, const NPT_String& role /* = "" */)
+{
+    PLT_PersonRole person;
+    person.name = name;
+    person.role = role;
+
+    return NPT_List<PLT_PersonRole>::Add(person);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PersonRoles::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PersonRoles::ToDidl(NPT_String& didl, const NPT_String& tag)
+{
+    NPT_String tmp;
+    for (NPT_List<PLT_PersonRole>::Iterator it = 
+         NPT_List<PLT_PersonRole>::GetFirstItem(); it; it++) {
+        // if there's an empty artist, allow it only if there's nothing else
+        if (it->name.IsEmpty() && m_ItemCount>1 && !tmp.IsEmpty()) continue;
+
+        tmp += "<upnp:" + tag;
+        if (!it->role.IsEmpty()) {
+            tmp += " role=\"";
+            PLT_Didl::AppendXmlEscape(tmp, it->role);
+            tmp += "\"";
+        }
+        tmp += ">";
+        PLT_Didl::AppendXmlEscape(tmp, it->name);
+        tmp += "</upnp:" + tag + ">";
+    }
+
+    didl += tmp;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PersonRoles::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PersonRoles::FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes)
+{
+    for (NPT_Cardinal i=0; i<nodes.GetItemCount(); i++) {
+        PLT_PersonRole person;
+        const NPT_String* name = nodes[i]->GetText();
+        const NPT_String* role = nodes[i]->GetAttribute("role");
+        if (name) person.name = *name;
+        if (role) person.role = *role;
+        NPT_CHECK(NPT_List<PLT_PersonRole>::Add(person));
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItemResource::PLT_MediaItemResource
++---------------------------------------------------------------------*/
+PLT_MediaItemResource::PLT_MediaItemResource()
+{
+    m_Uri             = "";
+    m_ProtocolInfo    = "";
+    m_Duration        = (NPT_UInt32)-1;
+    m_Size            = (NPT_Size)-1;
+    m_Protection      = "";
+    m_Bitrate         = (NPT_UInt32)-1;
+    m_BitsPerSample   = (NPT_UInt32)-1;
+    m_SampleFrequency = (NPT_UInt32)-1;
+    m_NbAudioChannels = (NPT_UInt32)-1;
+    m_Resolution      = "";
+    m_ColorDepth      = (NPT_UInt32)-1;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
++---------------------------------------------------------------------*/
+typedef struct PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry {
+    const char* mime_type;
+    const char* dlna_ext;
+} PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry ;
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry 
+PLT_HttpFileRequestHandler_DefaultDlnaMap[] = {
+    {"image/gif",      "DLNA.ORG_PN=GIF_LRG"},
+    {"image/jpeg",     "DLNA.ORG_PN=JPEG_LRG"},
+    {"image/jp2",      "DLNA.ORG_PN=JPEG_LRG"},
+    {"image/png",      "DLNA.ORG_PN=PNG_LRG"},
+    {"image/bmp",      "DLNA.ORG_PN=BMP_LRG"},
+    {"image/tiff",     "DLNA.ORG_PN=TIFF_LRG"},
+    {"audio/mpeg",     "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"audio/mp4",      "DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"audio/x-ms-wma", "DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"audio/x-wav",    "DLNA.ORG_PN=WAV;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"video/avi",      "DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"video/mp4",      "DLNA.ORG_PN=MPEG4_P2_SP_AAC;DLNA.ORG_CI=0"},
+    {"video/mpeg",     "DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"video/x-ms-wmv", "DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+    {"video/x-ms-asf", "DLNA.ORG_OP=01;DLNA.ORG_CI=0"}
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry 
+PLT_HttpFileRequestHandler_360DlnaMap[] = {
+    {"video/mp4",  "DLNA.ORG_OP=01;DLNA.ORG_CI=0"}
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry 
+PLT_HttpFileRequestHandler_PS3DlnaMap[] = {
+    {"image/jpg",  "DLNA.ORG_OP=01"},
+    {"image/png",  "DLNA.ORG_OP=01"}
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::GetMimeType
++---------------------------------------------------------------------*/
+const char* 
+PLT_MediaObject::GetMimeType(const NPT_String& filename)
+{
+    int last_dot = filename.ReverseFind('.');
+    if (last_dot > 0) {
+        NPT_String extension = filename.GetChars()+last_dot+1;
+        extension.MakeLowercase();
+
+        for (unsigned int i=0; i<NPT_ARRAY_SIZE(NPT_HttpFileRequestHandler_DefaultFileTypeMap); i++) {
+            if (extension == NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].extension) {
+                return NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].mime_type;
+            }
+        }
+    }
+
+    return "application/unknown";
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::GetDlnaExtension
++---------------------------------------------------------------------*/
+const char* 
+PLT_MediaObject::GetDlnaExtension(const char*                   mime_type,
+                                  const PLT_HttpRequestContext& context)
+{
+    NPT_String _mime_type = mime_type;
+    _mime_type.MakeLowercase();
+    
+    // look for special case for 360
+    NPT_HttpRequest& request = (NPT_HttpRequest&)context.GetRequest();
+    const NPT_String* agent = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_USER_AGENT);
+    if (agent && (agent->Find("XBox", 0, true) >= 0 || agent->Find("Xenon", 0, true) >= 0)) {
+        for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_360DlnaMap); i++) {
+            if (_mime_type == PLT_HttpFileRequestHandler_360DlnaMap[i].mime_type) {
+                return PLT_HttpFileRequestHandler_360DlnaMap[i].dlna_ext;
+            }
+        }
+        
+        return "*"; // Should we try default dlna instead?
+    }
+        
+    const NPT_String* hdr = request.GetHeaders().GetHeaderValue("X-AV-Client-Info");
+    if (hdr && hdr->Find("PLAYSTATION 3", 0, true) >= 0) {
+        for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_PS3DlnaMap); i++) {
+            if (_mime_type == PLT_HttpFileRequestHandler_PS3DlnaMap[i].mime_type) {
+                return PLT_HttpFileRequestHandler_PS3DlnaMap[i].dlna_ext;
+            }
+        }
+        
+        return "DLNA.ORG_OP=01"; // Should we try default dlna instead?
+    }
+    
+    for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_DefaultDlnaMap); i++) {
+        if (_mime_type == PLT_HttpFileRequestHandler_DefaultDlnaMap[i].mime_type) {
+            return PLT_HttpFileRequestHandler_DefaultDlnaMap[i].dlna_ext;
+        }
+    }
+
+    return "*";
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::GetProtInfo
++---------------------------------------------------------------------*/
+NPT_String
+PLT_MediaObject::GetProtInfo(const char*                   filepath, 
+                             const PLT_HttpRequestContext& context)
+{
+    NPT_String mime_type = GetMimeType(filepath);
+    return "http-get:*:"+mime_type+":"+GetDlnaExtension(mime_type, context);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::GetUPnPClass
++---------------------------------------------------------------------*/
+const char*
+PLT_MediaObject::GetUPnPClass(const char*                   filepath, 
+                              const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    const char* ret = NULL;
+    NPT_String mime_type = GetMimeType(filepath);
+
+    if (mime_type.StartsWith("audio")) {
+        ret = "object.item.audioItem.musicTrack";
+    } else if (mime_type.StartsWith("video")) {
+        ret = "object.item.videoItem"; //Note: 360 wants "object.item.videoItem" and not "object.item.videoItem.Movie"
+    } else if (mime_type.StartsWith("image")) {
+        ret = "object.item.imageItem.photo";
+    } else {
+        ret = "object.item";
+    }
+
+    return ret;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::Reset
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::Reset() 
+{
+    m_ObjectClass.type = "";
+    m_ObjectClass.friendly_name = "";
+    m_ObjectID = "";
+    m_ParentID = "";
+
+    m_Title = "";
+    m_Creator = "";
+    m_Date = "";
+    m_Restricted = true;
+
+    m_People.actors.Clear();
+    m_People.artists.Clear();    
+    m_People.authors.Clear();
+
+    m_Affiliation.album     = "";
+    m_Affiliation.genre.Clear();
+    m_Affiliation.playlist  = "";
+
+    m_Description.description = "";
+    m_Description.long_description = "";
+    m_ExtraInfo.album_art_uri = "";
+    m_ExtraInfo.artist_discography_uri = "";
+
+    m_MiscInfo.original_track_number = 0;
+    m_MiscInfo.dvdregioncode = 0;
+    m_MiscInfo.toc = "";
+    m_MiscInfo.user_annotation = "";
+
+    m_Resources.Clear();
+
+    m_Didl = "";
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::ToDidl(NPT_UInt32 mask, NPT_String& didl)
+{
+    // title is required
+    didl += "<dc:title>";
+    PLT_Didl::AppendXmlEscape(didl, m_Title);
+    didl += "</dc:title>";
+
+    // creator
+    if (mask & PLT_FILTER_MASK_CREATOR && !m_Creator.IsEmpty()) {
+        didl += "<dc:creator>";
+        PLT_Didl::AppendXmlEscape(didl, m_Creator);
+        didl += "</dc:creator>";
+    }
+
+    // date
+    if (mask & PLT_FILTER_MASK_DATE && !m_Date.IsEmpty()) {
+        didl += "<dc:date>";
+        PLT_Didl::AppendXmlEscape(didl, m_Date);
+        didl += "</dc:date>";
+    } 
+
+    // artist
+    if (mask & PLT_FILTER_MASK_ARTIST) {
+        // force an empty artist just in case
+        if (m_People.artists.GetItemCount() == 0) m_People.artists.Add("");
+        m_People.artists.ToDidl(didl, "artist");
+    }
+
+    // actor
+    if (mask & PLT_FILTER_MASK_ACTOR) {
+        m_People.actors.ToDidl(didl, "actor");
+    }
+
+    // actor
+    if (mask & PLT_FILTER_MASK_AUTHOR) {
+        m_People.authors.ToDidl(didl, "author");
+    }
+    
+    // album
+    if (mask & PLT_FILTER_MASK_ALBUM && !m_Affiliation.album.IsEmpty()) {
+        didl += "<upnp:album>";
+        PLT_Didl::AppendXmlEscape(didl, m_Affiliation.album);
+        didl += "</upnp:album>";
+    }
+
+    // genre
+    if (mask & PLT_FILTER_MASK_GENRE) {
+        for (NPT_List<NPT_String>::Iterator it = 
+             m_Affiliation.genre.GetFirstItem(); it; ++it) {
+            didl += "<upnp:genre>";
+            PLT_Didl::AppendXmlEscape(didl, (*it));
+            didl += "</upnp:genre>";        
+        }
+    }
+
+    // album art URI
+    if (mask & PLT_FILTER_MASK_ALBUMARTURI && !m_ExtraInfo.album_art_uri.IsEmpty()) {
+        didl += "<upnp:albumArtURI";
+        if (!m_ExtraInfo.album_art_uri_dlna_profile.IsEmpty()) {
+            didl += " dlna:profileID=\"";
+            PLT_Didl::AppendXmlEscape(didl, m_ExtraInfo.album_art_uri_dlna_profile);
+            didl += "\"";
+        }
+        didl += ">";
+        PLT_Didl::AppendXmlEscape(didl, m_ExtraInfo.album_art_uri);
+        didl += "</upnp:albumArtURI>";
+    }
+
+    // description
+    if (mask & PLT_FILTER_MASK_DESCRIPTION && !m_Description.long_description.IsEmpty()) {
+        didl += "<upnp:longDescription>";
+        PLT_Didl::AppendXmlEscape(didl, m_Description.long_description);
+        didl += "</upnp:longDescription>";
+    }
+
+    // original track number
+    if (mask & PLT_FILTER_MASK_ORIGINALTRACK && m_MiscInfo.original_track_number > 0) {
+        didl += "<upnp:originalTrackNumber>";
+        didl += NPT_String::FromInteger(m_MiscInfo.original_track_number);
+        didl += "</upnp:originalTrackNumber>";
+    }
+
+    // resource
+    if (mask & PLT_FILTER_MASK_RES) {
+        for (NPT_Cardinal i=0; i<m_Resources.GetItemCount(); i++) {
+            if (m_Resources[i].m_ProtocolInfo.GetLength() > 0) {
+                // protocol info is required
+                didl += "<res";
+
+                if (mask & PLT_FILTER_MASK_RES_DURATION && m_Resources[i].m_Duration != (NPT_UInt32)-1) {
+                    didl += " duration=\"";
+                    PLT_Didl::FormatTimeStamp(didl, m_Resources[i].m_Duration);
+                    didl += "\"";
+                }
+
+                if (mask & PLT_FILTER_MASK_RES_SIZE && m_Resources[i].m_Size != (NPT_Size)-1) {
+                    didl += " size=\"";
+                    didl += NPT_String::FromIntegerU(m_Resources[i].m_Size);
+                    didl += "\"";
+                }
+
+                if (mask & PLT_FILTER_MASK_RES_PROTECTION && !m_Resources[i].m_Protection.IsEmpty()) {
+                    didl += " protection=\"";
+                    PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_Protection);
+                    didl += "\"";
+                }
+                
+                if (mask & PLT_FILTER_MASK_RES_RESOLUTION && !m_Resources[i].m_Resolution.IsEmpty()) {
+                    didl += " resolution=\"";
+                    PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_Resolution);
+                    didl += "\"";
+                }
+                
+                didl += " protocolInfo=\"";
+                PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_ProtocolInfo);
+                didl += "\">";
+                PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_Uri);
+                didl += "</res>";
+            }
+        }
+    }
+
+    // class is required
+    didl += "<upnp:class>";
+    PLT_Didl::AppendXmlEscape(didl, m_ObjectClass.type);
+    didl += "</upnp:class>";
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::FromDidl(NPT_XmlElementNode* entry)
+{
+    NPT_String str, xml;
+    NPT_Array<NPT_XmlElementNode*> children;
+    NPT_Result res;
+
+    // serialize the entry Didl as a we might need to pass it to a renderer
+    res = PLT_XmlHelper::Serialize(*entry, xml);
+    NPT_CHECK_LABEL_SEVERE(res, cleanup);
+    
+    m_Didl = didl_header + xml + didl_footer;    
+
+    // check if item is restricted (is default true?)
+    if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "restricted", str))) {
+        m_Restricted = PLT_Service::IsTrue(str);
+    }
+
+    res = PLT_XmlHelper::GetAttribute(entry, "id", m_ObjectID);
+    NPT_CHECK_LABEL_SEVERE(res, cleanup);
+
+    res = PLT_XmlHelper::GetAttribute(entry, "parentID", m_ParentID);
+    NPT_CHECK_LABEL_SEVERE(res, cleanup);
+
+    res = PLT_XmlHelper::GetChildText(entry, "title", m_Title, didl_namespace_dc);
+    NPT_CHECK_LABEL_SEVERE(res, cleanup);
+
+    res = PLT_XmlHelper::GetChildText(entry, "class", m_ObjectClass.type, didl_namespace_upnp);
+    NPT_CHECK_LABEL_SEVERE(res, cleanup);
+
+    // read non-required elements
+    PLT_XmlHelper::GetChildText(entry, "creator", m_Creator, didl_namespace_dc);
+    PLT_XmlHelper::GetChildText(entry, "date", m_Date, didl_namespace_dc);
+
+    PLT_XmlHelper::GetChildren(entry, children, "artist", didl_namespace_upnp);
+    m_People.artists.FromDidl(children);
+
+    PLT_XmlHelper::GetChildText(entry, "album", m_Affiliation.album, didl_namespace_upnp);
+
+    children.Clear();
+    PLT_XmlHelper::GetChildren(entry, children, "genre", didl_namespace_upnp);
+    for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+        if (children[i]->GetText()) {
+            m_Affiliation.genre.Add(*children[i]->GetText());
+        }
+    }
+
+    PLT_XmlHelper::GetChildText(entry, "albumArtURI", m_ExtraInfo.album_art_uri, didl_namespace_upnp);
+    PLT_XmlHelper::GetChildText(entry, "longDescription", m_Description.long_description, didl_namespace_upnp);
+    PLT_XmlHelper::GetChildText(entry, "originalTrackNumber", str, didl_namespace_upnp);
+    NPT_UInt32 value;
+    if (NPT_FAILED(str.ToInteger(value))) value = 0;
+    m_MiscInfo.original_track_number = value;
+
+    children.Clear();
+    PLT_XmlHelper::GetChildren(entry, children, "res");
+    if (children.GetItemCount() > 0) {
+        for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+            PLT_MediaItemResource resource;
+            if (children[i]->GetText() == NULL) {
+                goto cleanup;
+            }
+
+            resource.m_Uri = *children[i]->GetText();
+            if (NPT_FAILED(PLT_XmlHelper::GetAttribute(children[i], "protocolInfo", resource.m_ProtocolInfo))) {
+                goto cleanup;
+            }
+            
+            PLT_XmlHelper::GetAttribute(children[i], "protection", resource.m_Protection);
+            PLT_XmlHelper::GetAttribute(children[i], "resolution", resource.m_Resolution);
+
+            if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(children[i], "size", str))) {
+                if (NPT_FAILED(str.ToInteger(resource.m_Size))) resource.m_Size = (NPT_Size)-1;
+            }
+
+            if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(children[i], "duration", str))) {
+                if (NPT_FAILED(PLT_Didl::ParseTimeStamp(str, resource.m_Duration))) {
+                    // if error while converting, ignore and set to -1 to indicate we don't know the duration
+                    resource.m_Duration = (NPT_UInt32)-1;
+                }
+            }    
+            m_Resources.Add(resource);
+        }
+    }
+
+    return NPT_SUCCESS;
+
+cleanup:
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObjectList::PLT_MediaObjectList
++---------------------------------------------------------------------*/
+PLT_MediaObjectList::PLT_MediaObjectList()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObjectList::~PLT_MediaObjectList
++---------------------------------------------------------------------*/
+PLT_MediaObjectList::~PLT_MediaObjectList()
+{
+    Apply(NPT_ObjectDeleter<PLT_MediaObject>());
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItem::PLT_MediaItem
++---------------------------------------------------------------------*/
+PLT_MediaItem::PLT_MediaItem()
+{
+    Reset();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItem::~PLT_MediaItem
++---------------------------------------------------------------------*/
+PLT_MediaItem::~PLT_MediaItem()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItem::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaItem::ToDidl(NPT_UInt32 mask, NPT_String& didl)
+{
+    NPT_String tmp;
+    // Allocate enough space for a big string we're going to concatenate in
+    tmp.Reserve(2048);
+
+    tmp = "<item id=\"";
+
+    PLT_Didl::AppendXmlEscape(tmp, m_ObjectID);
+    tmp += "\" parentID=\"";
+    PLT_Didl::AppendXmlEscape(tmp, m_ParentID);
+    tmp += "\" restricted=\"";
+    tmp += m_Restricted?"1\"":"0\"";
+
+    tmp += ">";
+
+    NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, tmp));
+
+    /* close tag */
+    tmp += "</item>";
+
+    didl += tmp;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItem::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaItem::FromDidl(NPT_XmlElementNode* entry)
+{
+    /* reset first */
+    Reset();
+
+    if (entry->GetTag().Compare("item", true) != 0)
+        return NPT_ERROR_INTERNAL;
+
+    return PLT_MediaObject::FromDidl(entry);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainer::PLT_MediaContainer
++---------------------------------------------------------------------*/
+PLT_MediaContainer::PLT_MediaContainer()
+{
+    Reset();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainer::~PLT_MediaContainer
++---------------------------------------------------------------------*/
+PLT_MediaContainer::~PLT_MediaContainer(void)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainer::Reset
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::Reset() 
+{
+    m_SearchClasses.Clear();
+    m_Searchable = true;
+    m_ChildrenCount = -1;
+
+    return PLT_MediaObject::Reset();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainer::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::ToDidl(NPT_UInt32 mask, NPT_String& didl)
+{
+    NPT_String tmp;
+    // Allocate enough space for a big string we're going to concatenate in
+    tmp.Reserve(2048);
+
+    tmp = "<container id=\"";
+
+    PLT_Didl::AppendXmlEscape(tmp, m_ObjectID);
+    tmp += "\" parentID=\"";
+    PLT_Didl::AppendXmlEscape(tmp, m_ParentID);
+    tmp += "\" restricted=\"";
+    tmp += m_Restricted?"1\"":"0\"";
+
+    if (mask & PLT_FILTER_MASK_SEARCHABLE) {
+        tmp += " searchable=\"";
+        tmp += m_Searchable?"1\"":"0\"";
+    }
+    
+    if (mask & PLT_FILTER_MASK_CHILDCOUNT && m_ChildrenCount != -1) {
+        tmp += " childCount=\"";
+        tmp += NPT_String::FromInteger(m_ChildrenCount);
+        tmp += "\"";
+    }
+
+    tmp += ">";
+
+    NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, tmp));
+
+    /* close tag */
+    tmp += "</container>";
+
+    didl += tmp;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainer::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::FromDidl(NPT_XmlElementNode* entry)
+{
+    NPT_String str;
+
+    /* reset first */
+    Reset();
+
+    // check entry type
+    if (entry->GetTag().Compare("Container", true) != 0) 
+        return NPT_ERROR_INTERNAL;
+
+    // check if item is searchable (is default true?)
+    if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "searchable", str))) {
+        m_Searchable = PLT_Service::IsTrue(str);
+    }
+
+    // look for childCount
+    if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "childCount", str))) {
+        NPT_UInt32 count;
+        NPT_CHECK_SEVERE(str.ToInteger(count));
+        m_ChildrenCount = count;
+    }
+
+    return PLT_MediaObject::FromDidl(entry);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaItem.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,262 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Item
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_ITEM_H_
+#define _PLT_MEDIA_ITEM_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class PLT_MediaServer;
+
+/*----------------------------------------------------------------------
+|   typedefs
++---------------------------------------------------------------------*/
+typedef struct { 
+    NPT_String type;
+    NPT_String friendly_name;
+} PLT_ObjectClass;
+
+typedef struct { 
+    NPT_String type;
+    NPT_String friendly_name;
+    bool       include_derived;
+} PLT_SearchClass;
+
+typedef struct {
+    NPT_String name;
+    NPT_String role;
+} PLT_PersonRole;
+
+class PLT_PersonRoles  : public NPT_List<PLT_PersonRole>
+{
+public:
+    NPT_Result Add(const NPT_String& name, const NPT_String& role = "");
+    NPT_Result ToDidl(NPT_String& didl, const NPT_String& tag);
+    NPT_Result FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes);
+};
+
+typedef struct {
+    NPT_String allowed_use; // (CSV)
+    NPT_String validity_start;
+    NPT_String validity_end;
+    NPT_String remaining_time;
+    NPT_String usage_info;
+    NPT_String rights_info_uri;
+    NPT_String content_info_uri;
+} PLT_Constraint;
+
+typedef struct {
+    PLT_PersonRoles artists;
+    PLT_PersonRoles actors;
+    PLT_PersonRoles authors;
+    NPT_String      producer;
+    NPT_String      director;
+    NPT_String      publisher;
+    NPT_String      contributor; // should match m_Creator (dc:creator)
+} PLT_PeopleInfo;
+
+typedef struct {
+    NPT_List<NPT_String> genre;
+    NPT_String album;
+    NPT_String playlist; // dc:title of the playlist item the content belongs too
+} PLT_AffiliationInfo;
+
+typedef struct {
+    NPT_String description;
+    NPT_String long_description;
+    NPT_String icon_uri;
+    NPT_String region;
+    NPT_String rating;
+    NPT_String rights;
+    NPT_String date;
+    NPT_String language;
+} PLT_Description;
+
+typedef struct {
+    NPT_String album_art_uri;
+    NPT_String album_art_uri_dlna_profile;
+    NPT_String artist_discography_uri;
+    NPT_String lyrics_uri;
+    NPT_List<NPT_String> relation; // dc:relation
+} PLT_ExtraInfo;
+
+typedef struct {
+    NPT_UInt32 dvdregioncode;
+    NPT_UInt32 original_track_number;
+    NPT_String toc;
+    NPT_String user_annotation;
+} PLT_MiscInfo;
+
+typedef struct {
+    int         total;
+    int         used;
+    int         free;
+    int         max_partition;
+    NPT_String  medium;
+} PLT_StorageInfo;
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItemResource class
++---------------------------------------------------------------------*/
+class PLT_MediaItemResource
+{
+public:
+    PLT_MediaItemResource();
+    ~PLT_MediaItemResource() {}
+
+    NPT_String    m_Uri;
+    NPT_String    m_ProtocolInfo;
+    NPT_UInt32    m_Duration; /* seconds */
+    NPT_LargeSize m_Size;
+    NPT_String    m_Protection;
+    NPT_UInt32    m_Bitrate; /* bytes/seconds */
+    NPT_UInt32    m_BitsPerSample;
+    NPT_UInt32    m_SampleFrequency;
+    NPT_UInt32    m_NbAudioChannels;
+    NPT_String    m_Resolution;
+    NPT_UInt32    m_ColorDepth;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObject class
++---------------------------------------------------------------------*/
+class PLT_MediaObject
+{
+public:
+    PLT_MediaObject() {}
+    virtual ~PLT_MediaObject() {}
+
+    bool IsContainer() { return m_ObjectClass.type.StartsWith("object.container"); }
+
+    static const char* GetMimeType(const NPT_String& filename);
+    static NPT_String  GetProtInfo(const char* filename, const PLT_HttpRequestContext& context);
+    static const char* GetUPnPClass(const char* filename, const PLT_HttpRequestContext& context);
+    static const char* GetDlnaExtension(const char* mime_type, const PLT_HttpRequestContext& context);
+
+    virtual NPT_Result Reset();
+    virtual NPT_Result ToDidl(NPT_UInt32 mask, NPT_String& didl);
+    virtual NPT_Result FromDidl(NPT_XmlElementNode* entry);
+
+public:
+    /* common properties */
+    PLT_ObjectClass     m_ObjectClass;
+    NPT_String          m_ObjectID;
+    NPT_String          m_ParentID;
+
+    /* metadata */
+    NPT_String          m_Title;
+    NPT_String          m_Creator;
+    NPT_String          m_Date;
+    PLT_PeopleInfo      m_People;
+    PLT_AffiliationInfo m_Affiliation;
+    PLT_Description     m_Description;
+
+    /* properties */
+    bool m_Restricted;
+
+    /* extras */
+    PLT_ExtraInfo m_ExtraInfo;
+
+    /* miscellaneous info */
+    PLT_MiscInfo m_MiscInfo;
+
+    /* resources related */
+    NPT_Array<PLT_MediaItemResource> m_Resources;
+
+    /* original DIDL for Control Points to pass to a renderer when invoking SetAVTransportURI */
+    NPT_String m_Didl;    
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItem class
++---------------------------------------------------------------------*/
+class PLT_MediaItem : public PLT_MediaObject
+{
+public:
+    PLT_MediaItem();
+    virtual ~PLT_MediaItem();
+
+    // PLT_MediaObject methods
+    NPT_Result ToDidl(NPT_UInt32 mask, NPT_String& didl);
+    NPT_Result FromDidl(NPT_XmlElementNode* entry);
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainer class
++---------------------------------------------------------------------*/
+class PLT_MediaContainer : public PLT_MediaObject
+{
+public:
+    PLT_MediaContainer();
+    virtual ~PLT_MediaContainer();
+
+    // PLT_MediaObject methods
+    NPT_Result Reset();
+    NPT_Result ToDidl(NPT_UInt32 mask, NPT_String& didl);
+    NPT_Result FromDidl(NPT_XmlElementNode* entry);
+
+public:
+    NPT_List<PLT_SearchClass> m_SearchClasses;
+
+    /* properties */
+    bool m_Searchable;
+
+    /* container info related */
+    NPT_Int32 m_ChildrenCount;    
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaObjectList class
++---------------------------------------------------------------------*/
+class PLT_MediaObjectList : public NPT_List<PLT_MediaObject*>
+{
+public:
+    PLT_MediaObjectList();
+
+protected:
+    virtual ~PLT_MediaObjectList(void);
+    friend class NPT_Reference<PLT_MediaObjectList>;
+};
+
+typedef NPT_Reference<PLT_MediaObjectList> PLT_MediaObjectListReference;
+typedef NPT_Reference<PLT_MediaObject> PLT_MediaObjectReference;
+
+
+#endif /* _PLT_MEDIA_ITEM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaPlaylist.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Playlist
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltMediaPlaylist.h"
+
+/*----------------------------------------------------------------------
+|   PLT_MediaPlaylist::PLT_MediaPlaylist
++---------------------------------------------------------------------*/
+PLT_MediaPlaylist::PLT_MediaPlaylist()
+{
+    m_List = new PLT_MediaItemList();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaPlaylist::~PLT_MediaPlaylist
++---------------------------------------------------------------------*/
+PLT_MediaPlaylist::~PLT_MediaPlaylist(void)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaPlaylist::Clear
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaPlaylist::Clear(void)
+{
+    m_List->Apply(NPT_ObjectDeleter<PLT_MediaItem>());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaPlaylist::Clear
++---------------------------------------------------------------------*/
+NPT_Result  
+PLT_MediaPlaylist::Queue(PLT_MediaItem* item)
+{
+    PLT_MediaItem* new_item = new PLT_MediaItem(*item);
+    m_List->Add(new_item);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaPlaylist::Queue
++---------------------------------------------------------------------*/
+NPT_Result  
+PLT_MediaPlaylist::Queue(PLT_MediaItemList* list)
+{
+    list->Apply(PLT_MediaItemQueueIterator(this));
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaPlaylist.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,85 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Playlist
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_PLAYLIST_H_
+#define _PLT_MEDIA_PLAYLIST_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+|   typedefs
++---------------------------------------------------------------------*/
+typedef NPT_List<PLT_MediaItem*> PLT_MediaItemList;
+typedef NPT_Reference<PLT_MediaItemList> PLT_MediaItemListReference;
+
+/*----------------------------------------------------------------------
+|   PLT_MediaPlaylist class
++---------------------------------------------------------------------*/
+class PLT_MediaPlaylist
+{
+public:
+    PLT_MediaPlaylist();
+    ~PLT_MediaPlaylist(void);
+
+    NPT_Result  Clear();
+    NPT_Result  Queue(PLT_MediaItem* item);
+    NPT_Result  Queue(PLT_MediaItemList* list);
+    template <typename X> 
+    NPT_Result  Apply(const X& function) {
+        return m_List->Apply(function);
+    }
+
+private:
+    PLT_MediaItemListReference m_List;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaItemQueueIterator class
++---------------------------------------------------------------------*/
+class PLT_MediaItemQueueIterator
+{
+public:
+    PLT_MediaItemQueueIterator(PLT_MediaPlaylist* playlist) : m_Playlist(playlist) {}
+    NPT_Result operator()(PLT_MediaItem*& item) const {
+        return m_Playlist->Queue(item);
+    }
+
+private:
+    PLT_MediaPlaylist* m_Playlist;
+};
+
+#endif /* _PLT_MEDIA_PLAYLIST_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,417 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Server Device
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltMediaServer.h"
+#include "PltMediaItem.h"
+#include "PltService.h"
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltDidl.h"
+#include "PltMetadataHandler.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server")
+
+/*----------------------------------------------------------------------
+|   forward references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 MS_ConnectionManagerSCPD[];
+extern NPT_UInt8 MS_ContentDirectorySCPD[];
+extern NPT_UInt8 MS_ContentDirectorywSearchSCPD[];
+
+const char* BrowseFlagsStr[] = {
+    "BrowseMetadata",
+    "BrowseDirectChildren"
+};
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::PLT_MediaServer
++---------------------------------------------------------------------*/
+PLT_MediaServer::PLT_MediaServer(const char*  friendly_name, 
+                                 bool         show_ip     /* = false */, 
+                                 const char*  uuid        /* = NULL */, 
+                                 NPT_UInt16   port        /* = 0 */,
+                                 bool         port_rebind /* = false */) :	
+    PLT_DeviceHost("/DeviceDescription.xml", 
+                   uuid, 
+                   "urn:schemas-upnp-org:device:MediaServer:1", 
+                   friendly_name, 
+                   show_ip, 
+                   port,
+                   port_rebind)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::~PLT_MediaServer
++---------------------------------------------------------------------*/
+PLT_MediaServer::~PLT_MediaServer()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::SetupServices(PLT_DeviceData& data)
+{
+    PLT_Service* service;
+
+    {
+        service = new PLT_Service(
+            &data,
+            "urn:schemas-upnp-org:service:ContentDirectory:1", 
+            "urn:upnp-org:serviceId:CDS_1-0");
+        NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ContentDirectorywSearchSCPD));
+        NPT_CHECK_FATAL(service->InitURLs("ContentDirectory", data.GetUUID()));
+        NPT_CHECK_FATAL(data.AddService(service));
+        
+        service->SetStateVariable("ContainerUpdateIDs", "0");
+        service->SetStateVariableRate("ContainerUpdateIDs", NPT_TimeInterval(2, 0));
+        service->SetStateVariable("SystemUpdateID", "0");
+        service->SetStateVariableRate("SystemUpdateID", NPT_TimeInterval(2, 0));
+        service->SetStateVariable("SearchCapability", "upnp:class");
+        service->SetStateVariable("SortCapability", "");
+    }
+
+    {
+        service = new PLT_Service(
+            &data,
+            "urn:schemas-upnp-org:service:ConnectionManager:1", 
+            "urn:upnp-org:serviceId:CMGR_1-0");
+        NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ConnectionManagerSCPD));
+        NPT_CHECK_FATAL(service->InitURLs("ConnectionManager", data.GetUUID()));
+        NPT_CHECK_FATAL(data.AddService(service));
+        
+        service->SetStateVariable("CurrentConnectionIDs", "0");
+        service->SetStateVariable("SinkProtocolInfo", "");
+        service->SetStateVariable("SourceProtocolInfo", "http-get:*:*:*");
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnAction(PLT_ActionReference&          action, 
+                          const PLT_HttpRequestContext& context)
+{
+    /* parse the action name */
+    NPT_String name = action->GetActionDesc()->GetName();
+
+    // ContentDirectory
+    if (name.Compare("Browse", true) == 0) {
+        return OnBrowse(action, context);
+    }
+    if (name.Compare("Search", true) == 0) {
+        return OnSearch(action, context);
+    }
+    if (name.Compare("GetSystemUpdateID", true) == 0) {
+        return OnGetSystemUpdateID(action, context);
+    }
+    if (name.Compare("GetSortCapabilities", true) == 0) {
+        return OnGetSortCapabilities(action, context);
+    }  
+    if (name.Compare("GetSearchCapabilities", true) == 0) {
+        return OnGetSearchCapabilities(action, context);
+    }  
+
+    // ConnectionMananger
+    if (name.Compare("GetCurrentConnectionIDs", true) == 0) {
+        return OnGetCurrentConnectionIDs(action, context);
+    }
+    if (name.Compare("GetProtocolInfo", true) == 0) {
+        return OnGetProtocolInfo(action, context);
+    }    
+    if (name.Compare("GetCurrentConnectionInfo", true) == 0) {
+        return OnGetCurrentConnectionInfo(action, context);
+    }
+
+    action->SetError(401,"No Such Action.");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnGetCurrentConnectionIDs
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnGetCurrentConnectionIDs(PLT_ActionReference&          action,
+                                           const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnGetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnGetProtocolInfo(PLT_ActionReference&          action,
+                                   const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnGetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetCurrentConnectionInfo(PLT_ActionReference&          action, 
+                                            const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    if (NPT_FAILED(action->VerifyArgumentValue("ConnectionID", "0"))) {
+        action->SetError(706,"No Such Connection.");
+        return NPT_FAILURE;
+    }
+
+    if (NPT_FAILED(action->SetArgumentValue("RcsID", "-1"))){
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("AVTransportID", "-1"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("ProtocolInfo", "http-get:*:*:*"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("PeerConnectionManager", "/"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("PeerConnectionID", "-1"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("Direction", "Output"))) {
+        return NPT_FAILURE;
+    }
+    if (NPT_FAILED(action->SetArgumentValue("Status", "Unknown"))) {
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnGetSortCapabilities
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnGetSortCapabilities(PLT_ActionReference&          action,
+                                       const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnGetSearchCapabilities
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnGetSearchCapabilities(PLT_ActionReference&          action, 
+                                         const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnGetSystemUpdateID
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnGetSystemUpdateID(PLT_ActionReference&          action, 
+                                     const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::GetBrowseFlag
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::GetBrowseFlag(const char* str, BrowseFlags& flag) 
+{
+    if (NPT_String::Compare(str, BrowseFlagsStr[0], true) == 0) {
+        flag = BROWSEMETADATA;
+        return NPT_SUCCESS;
+    }
+    if (NPT_String::Compare(str, BrowseFlagsStr[1], true) == 0) {
+        flag = BROWSEDIRECTCHILDREN;
+        return NPT_SUCCESS;
+    }
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnBrowse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnBrowse(PLT_ActionReference&          action, 
+                          const PLT_HttpRequestContext& context)
+{
+    NPT_Result res;
+    NPT_String object_id;
+    NPT_String browse_flag_val;
+
+    if (NPT_FAILED(action->GetArgumentValue("ObjectId", object_id)) || 
+        NPT_FAILED(action->GetArgumentValue("BrowseFlag",  browse_flag_val))) {
+        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments.");
+        return NPT_SUCCESS;
+    }
+
+    /* we don't support sorting yet */
+//    PLT_Argument* sortCritArg = action->GetArgument("SortCriteria");
+//     if (sortCritArg != NULL)  {
+//         NPT_String sortCrit = sortCritArg->GetValue();
+//         if (sortCrit.GetLength() > 0) {
+//             /* error */
+//             PLT_Log(PLT_LOG_LEVEL_1, "PLT_FileMediaServer::OnBrowse - SortCriteria not allowed.");
+//             action->SetError(709, "MediaServer does not support sorting.");
+//             return NPT_FAILURE;
+//         }
+//     }
+
+    /* extract flag */
+    BrowseFlags flag;
+    if (NPT_FAILED(GetBrowseFlag(browse_flag_val, flag))) {
+        /* error */
+        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BrowseFlag value not allowed.");
+        action->SetError(402,"Invalid BrowseFlag arg.");
+        return NPT_SUCCESS;
+    }
+
+    NPT_LOG_FINE_2("PLT_FileMediaServer::On%s - id = %s", 
+                   (const char*)browse_flag_val, 
+                   (const char*)object_id);
+
+    /* Invoke the browse function */
+    if (flag == BROWSEMETADATA) {
+        res = OnBrowseMetadata(action, object_id, context);
+    } else {
+        res = OnBrowseDirectChildren(action, object_id, context);
+    }
+
+    if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) {
+        action->SetError(800, "Internal error");
+    }
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnSearch
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnSearch(PLT_ActionReference&          action, 
+                          const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(context);
+
+    NPT_Result res;
+    NPT_String container_id;
+    NPT_String search_criteria;
+
+    NPT_CHECK_FATAL(action->GetArgumentValue("SearchCriteria", search_criteria));
+    NPT_CHECK_FATAL(action->GetArgumentValue("ContainerId", container_id));
+
+    NPT_LOG_FINE_1("PLT_FileMediaServer::OnSearch - id = %s", (const char*)container_id);
+    
+    if(search_criteria.IsEmpty()) {
+        res = OnBrowseDirectChildren(action, container_id, context);
+    } else {
+        res = OnSearch(action, container_id, search_criteria, context);
+    }
+
+    if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) {
+        action->SetError(800, "Internal error");
+    }
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnBrowseMetadata
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnBrowseMetadata(PLT_ActionReference&          action, 
+                                  const char*                   object_id, 
+                                  const PLT_HttpRequestContext& context)
+{ 
+    NPT_COMPILER_UNUSED(action);
+    NPT_COMPILER_UNUSED(object_id);
+    NPT_COMPILER_UNUSED(context);
+
+    return NPT_ERROR_NOT_IMPLEMENTED; 
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnBrowseDirectChildren
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaServer::OnBrowseDirectChildren(PLT_ActionReference&          action, 
+                                        const char*                   object_id, 
+                                        const PLT_HttpRequestContext& context) 
+{ 
+    NPT_COMPILER_UNUSED(action);
+    NPT_COMPILER_UNUSED(object_id);
+    NPT_COMPILER_UNUSED(context);
+
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer::OnSearch
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnSearch(PLT_ActionReference&          action, 
+                          const NPT_String&             object_id, 
+                          const NPT_String&             search_criteria,
+                          const PLT_HttpRequestContext& context)
+{
+    NPT_COMPILER_UNUSED(action);
+    NPT_COMPILER_UNUSED(object_id);
+    NPT_COMPILER_UNUSED(search_criteria);
+    NPT_COMPILER_UNUSED(context);
+
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaServer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,116 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Server Device
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_SERVER_H_
+#define _PLT_MEDIA_SERVER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltDeviceHost.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define MAX_PATH_LENGTH 1024
+
+/* BrowseFlags */
+enum BrowseFlags {
+    BROWSEMETADATA,
+    BROWSEDIRECTCHILDREN
+};
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+extern const char* BrowseFlagsStr[];
+class PLT_HttpFileServerHandler;
+
+/*----------------------------------------------------------------------
+|   PLT_MediaServer class
++---------------------------------------------------------------------*/
+class PLT_MediaServer : public PLT_DeviceHost
+{
+public:
+    PLT_MediaServer(const char*  friendly_name,
+                    bool         show_ip = false,
+                    const char*  uuid = NULL,
+                    NPT_UInt16   port = 0,
+                    bool         port_rebind = false);
+    virtual ~PLT_MediaServer();
+
+    // PLT_DeviceHost methods
+    virtual NPT_Result SetupServices(PLT_DeviceData& data);
+    virtual NPT_Result OnAction(PLT_ActionReference&          action, 
+                                const PLT_HttpRequestContext& context);
+
+    // class methods
+    static NPT_Result  GetBrowseFlag(const char* str, BrowseFlags& flag);
+
+protected:
+    // ConnectionManager
+    virtual NPT_Result OnGetCurrentConnectionIDs(PLT_ActionReference&          action, 
+                                                 const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnGetProtocolInfo(PLT_ActionReference&          action, 
+                                         const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference&          action, 
+                                                  const PLT_HttpRequestContext& context);
+
+    // ContentDirectory
+    virtual NPT_Result OnGetSortCapabilities(PLT_ActionReference&          action, 
+                                             const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnGetSearchCapabilities(PLT_ActionReference&          action, 
+                                               const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnGetSystemUpdateID(PLT_ActionReference&          action, 
+                                           const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnBrowse(PLT_ActionReference&          action, 
+                                const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnSearch(PLT_ActionReference&          action, 
+                                const PLT_HttpRequestContext& context);
+
+    // overridable methods
+    virtual NPT_Result OnBrowseMetadata(PLT_ActionReference&          action, 
+                                        const char*                   object_id, 
+                                        const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference&          action, 
+                                              const char*                   object_id, 
+                                              const PLT_HttpRequestContext& context);
+    virtual NPT_Result OnSearch(PLT_ActionReference&          action,
+                                const NPT_String&             object_id, 
+                                const NPT_String&             searchCriteria, 
+                                const PLT_HttpRequestContext& context);
+};
+
+#endif /* _PLT_MEDIA_SERVER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltMediaServerSCPDs.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,899 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Server Device SCPDs
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+NPT_UInt8 MS_ContentDirectorySCPD[4409] =
+{
+  0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+  0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+  0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+  0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+  0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 
+  0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 
+  0x6E, 0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42, 
+  0x72, 0x6F, 0x77, 0x73, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4F, 0x62, 
+  0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+  0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 
+  0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 
+  0x78, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6F, 0x75, 
+  0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 
+  0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 
+  0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 
+  0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x4D, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 
+  0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 
+  0x72, 0x74, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x72, 
+  0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 
+  0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x49, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74, 
+  0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 
+  0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 
+  0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x65, 0x72, 
+  0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 
+  0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 
+  0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+  0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 
+  0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 
+  0x73, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x43, 0x68, 0x69, 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x3C, 0x2F, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 
+  0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 
+  0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 
+  0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 
+  0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+  0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 
+  0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 
+  0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 
+  0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 
+  0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 
+  0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 
+  0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 
+  0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 
+  0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 
+  0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 
+  0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 
+  0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 
+  0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 
+  0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+  0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x55, 0x70, 0x64, 
+  0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+  0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 
+  0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+  0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 
+  0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 
+  0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 
+  0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 
+  0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 
+  0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 
+  0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
+NPT_UInt8 MS_ConnectionManagerSCPD[5428] =
+{
+    0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+    0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+    0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x27, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+    0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+    0x65, 0x2D, 0x31, 0x2D, 0x30, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 
+    0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 
+    0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 
+    0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 
+    0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+    0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 
+    0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 
+    0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+    0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+    0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 
+    0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+    0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+    0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+    0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 
+    0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+    0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+    0x5F, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+    0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+    0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+    0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+    0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 
+    0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 
+    0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 
+    0x61, 0x6D, 0x65, 0x3E, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 
+    0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+    0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+    0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+    0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x50, 0x65, 0x65, 0x72, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 
+    0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+    0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 
+    0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 
+    0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 
+    0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+    0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+    0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+    0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+    0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+    0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 
+    0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 
+    0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+    0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+    0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x74, 0x6F, 
+    0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 
+    0x75, 0x72, 0x63, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+    0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+    0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 
+    0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 
+    0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+    0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x50, 0x72, 0x6F, 0x74, 
+    0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+    0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+    0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 
+    0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 
+    0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+    0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 
+    0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 
+    0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 
+    0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+    0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+    0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 
+    0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+    0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 
+    0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 
+    0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 
+    0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+    0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 
+    0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61, 0x74, 
+    0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 
+    0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 
+    0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 
+    0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+    0x75, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x4D, 0x69, 0x73, 0x6D, 
+    0x61, 0x74, 0x63, 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 
+    0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 
+    0x65, 0x6E, 0x74, 0x42, 0x61, 0x6E, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+    0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x55, 
+    0x6E, 0x72, 0x65, 0x6C, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x61, 0x6C, 
+    0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 
+    0x75, 0x65, 0x3E, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 
+    0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 
+    0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 
+    0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x41, 0x56, 0x54, 0x72, 
+    0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+    0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+    0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 
+    0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+    0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 
+    0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 
+    0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 
+    0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+    0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+    0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+    0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 
+    0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 
+    0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 
+    0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+    0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+    0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 
+    0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 
+    0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 
+    0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 
+    0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+    0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 
+    0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 
+    0x69, 0x6E, 0x6B, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 
+    0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+    0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 
+    0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+    0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 
+    0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+    0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+    0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+    0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+    0x65, 0x3E, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 
+    0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 
+    0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 
+    0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+    0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+    0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 
+    0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 
+    0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 
+    0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 
+    0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 
+    0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x65, 
+    0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 
+    0x73, 0x63, 0x70, 0x64, 0x3E, 0x0D, 0x0A, 0x00
+};
+
+NPT_UInt8 MS_ContentDirectorywSearchSCPD[7058] =
+{
+  0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20, 
+  0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 
+  0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 
+  0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 
+  0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 
+  0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 
+  0x6E, 0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42, 
+  0x72, 0x6F, 0x77, 0x73, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4F, 0x62, 
+  0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 
+  0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 
+  0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 
+  0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 
+  0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 
+  0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 
+  0x78, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6F, 0x75, 
+  0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 
+  0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 
+  0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 
+  0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 
+  0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 
+  0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 
+  0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 
+  0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 
+  0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 
+  0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x4D, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 
+  0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 
+  0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 
+  0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 
+  0x72, 0x74, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x72, 
+  0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 
+  0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 
+  0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 
+  0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x49, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 
+  0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74, 
+  0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+  0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 
+  0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 
+  0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 
+  0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x43, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x65, 0x72, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 
+  0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 
+  0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 
+  0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 
+  0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 
+  0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 
+  0x74, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 
+  0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x49, 
+  0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 
+  0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 
+  0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6F, 0x75, 0x6E, 0x74, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 
+  0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 
+  0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 
+  0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 
+  0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 
+  0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 
+  0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 
+  0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 
+  0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 
+  0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 
+  0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 
+  0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 
+  0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 
+  0x54, 0x6F, 0x74, 0x61, 0x6C, 0x4D, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 
+  0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 
+  0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 
+  0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61, 0x74, 
+  0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 
+  0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 
+  0x59, 0x50, 0x45, 0x5F, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 
+  0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 
+  0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 
+  0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 
+  0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 
+  0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 
+  0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 
+  0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 
+  0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 
+  0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 
+  0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 
+  0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x44, 0x69, 0x72, 
+  0x65, 0x63, 0x74, 0x43, 0x68, 0x69, 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 
+  0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 
+  0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 
+  0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 
+  0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 
+  0x6E, 0x74, 0x61, 0x69, 0x6E, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 
+  0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 
+  0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 
+  0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 
+  0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 
+  0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+  0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 
+  0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 
+  0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 
+  0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 
+  0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 
+  0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 
+  0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 
+  0x50, 0x45, 0x5F, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 
+  0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 
+  0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x20, 0x20, 0x20, 
+  0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 
+  0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 
+  0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 
+  0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 
+  0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 
+  0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 
+  0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 
+  0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 
+  0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 
+  0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 
+  0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 
+  0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 
+  0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 
+  0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 
+  0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 
+  0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 
+  0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 
+  0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 
+  0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 
+  0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 
+  0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 
+  0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 
+  0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 
+  0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 
+  0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 
+  0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 
+  0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 
+  0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 
+  0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 
+  0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 
+  0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 
+  0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 
+  0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,316 @@
+/*****************************************************************
+|
+|   Platinum - Synchronous Media Browser
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltSyncMediaBrowser.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.syncbrowser")
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::PLT_SyncMediaBrowser
++---------------------------------------------------------------------*/
+PLT_SyncMediaBrowser::PLT_SyncMediaBrowser(PLT_CtrlPointReference&            ctrlPoint,
+                                           bool                               use_cache /* = false */, 
+                                           PLT_MediaContainerChangesListener* listener /* = NULL */) :
+    PLT_MediaBrowser(ctrlPoint),
+    m_ContainerListener(listener),
+    m_UseCache(use_cache)
+{
+    SetDelegate(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::~PLT_SyncMediaBrowser
++---------------------------------------------------------------------*/
+PLT_SyncMediaBrowser::~PLT_SyncMediaBrowser()
+{
+}
+
+/*  Blocks forever waiting for a response from a request
+ *  It is expected the request to succeed or to timeout and return an error eventually
+ */
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::WaitForResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::WaitForResponse(NPT_SharedVariable& shared_var)
+{
+    return shared_var.WaitUntilEquals(1, 30000);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::OnDeviceAdded
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::OnDeviceAdded(PLT_DeviceDataReference& device)
+{
+    NPT_String uuid = device->GetUUID();
+
+    // test if it's a media server
+    PLT_Service* service;
+    if (NPT_SUCCEEDED(device->FindServiceByType("urn:schemas-upnp-org:service:ContentDirectory:1", service))) {
+        NPT_AutoLock lock(m_MediaServers);
+        m_MediaServers.Put(uuid, device);
+    }
+    
+    return PLT_MediaBrowser::OnDeviceAdded(device);
+}
+    
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::OnDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::OnDeviceRemoved(PLT_DeviceDataReference& device)
+{
+    NPT_String uuid = device->GetUUID();
+
+    // Remove from our list of servers first if found
+    {
+        NPT_AutoLock lock(m_MediaServers);
+        m_MediaServers.Erase(uuid);
+    }
+
+    // clear cache for that device
+    if (m_UseCache) m_Cache.Clear(device.AsPointer()->GetUUID());
+    
+    return PLT_MediaBrowser::OnDeviceRemoved(device);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::Find
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::Find(const char* ip, PLT_DeviceDataReference& device)
+{
+    NPT_AutoLock lock(m_MediaServers);
+    const NPT_List<PLT_DeviceMapEntry*>::Iterator it = 
+        m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByIp(ip));
+    if (it) {
+        device = (*it)->GetValue();
+        return NPT_SUCCESS;
+    }
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::OnBrowseResult
++---------------------------------------------------------------------*/
+void
+PLT_SyncMediaBrowser::OnBrowseResult(NPT_Result               res, 
+                                     PLT_DeviceDataReference& device, 
+                                     PLT_BrowseInfo*          info, 
+                                     void*                    userdata)
+{
+    NPT_COMPILER_UNUSED(device);
+
+    if (!userdata) return;
+
+    PLT_BrowseDataReference* data = (PLT_BrowseDataReference*) userdata;
+    (*data)->res = res;
+    if (NPT_SUCCEEDED(res) && info) {
+        (*data)->info = *info;
+    }
+    (*data)->shared_var.SetValue(1);
+    delete data;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::OnMSStateVariablesChanged
++---------------------------------------------------------------------*/
+void 
+PLT_SyncMediaBrowser::OnMSStateVariablesChanged(PLT_Service*                  service, 
+                                                NPT_List<PLT_StateVariable*>* vars)
+{
+    NPT_AutoLock lock(m_MediaServers);
+    
+    PLT_DeviceDataReference device;
+    const NPT_List<PLT_DeviceMapEntry*>::Iterator it = 
+        m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByUUID(service->GetDevice()->GetUUID()));
+    if (!it) return; // device with this service has gone away
+
+    device = (*it)->GetValue();
+    PLT_StateVariable* var = PLT_StateVariable::Find(*vars, "ContainerUpdateIDs");
+    if (var) {
+        // variable found, parse value
+        NPT_String value = var->GetValue();
+        NPT_String item_id, update_id;
+        int index;
+
+        while (value.GetLength()) {
+            // look for container id
+            index = value.Find(',');
+            if (index < 0) break;
+            item_id = value.Left(index);
+            value = value.SubString(index+1);
+
+            // look for update id
+            if (value.GetLength()) {
+                index = value.Find(',');
+                update_id = (index<0)?value:value.Left(index);
+                value = (index<0)?"":value.SubString(index+1);
+
+                // clear cache for that device
+                if (m_UseCache) m_Cache.Clear(device->GetUUID(), item_id);
+
+                // notify listener
+                if (m_ContainerListener) m_ContainerListener->OnContainerChanged(device, item_id, update_id);
+            }       
+        }
+    }        
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::BrowseSync
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_SyncMediaBrowser::BrowseSync(PLT_BrowseDataReference& browse_data,
+                                 PLT_DeviceDataReference& device, 
+                                 const char*              object_id, 
+                                 NPT_Int32                index, 
+                                 NPT_Int32                count,
+                                 bool                     browse_metadata,
+                                 const char*              filter, 
+                                 const char*              sort)
+{
+    NPT_Result res;
+
+    browse_data->shared_var.SetValue(0);
+
+    // send off the browse packet.  Note that this will
+    // not block.  There is a call to WaitForResponse in order
+    // to block until the response comes back.
+    res = PLT_MediaBrowser::Browse(device,
+        (const char*)object_id,
+        index,
+        count,
+        browse_metadata,
+        filter,
+        sort,
+        new PLT_BrowseDataReference(browse_data));		
+    NPT_CHECK_SEVERE(res);
+
+    return WaitForResponse(browse_data->shared_var);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::BrowseSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::BrowseSync(PLT_DeviceDataReference&      device, 
+                                 const char*                   object_id, 
+                                 PLT_MediaObjectListReference& list)
+{
+    NPT_Result res = NPT_FAILURE;
+    NPT_Int32  index = 0;
+
+    // reset output params
+    list = NULL;
+
+    // look into cache first
+    if (m_UseCache && NPT_SUCCEEDED(m_Cache.Get(device->GetUUID(), object_id, list))) return NPT_SUCCESS;
+
+    do {	
+        PLT_BrowseDataReference browse_data(new PLT_BrowseData());
+
+        // send off the browse packet.  Note that this will
+        // not block.  There is a call to WaitForResponse in order
+        // to block until the response comes back.
+        res = BrowseSync(
+            browse_data,
+            device,
+            (const char*)object_id,
+            index,
+            1024,
+            false,
+            "*",
+            "");		
+        NPT_CHECK_LABEL_WARNING(res, done);
+        
+        if (NPT_FAILED(browse_data->res)) {
+            res = browse_data->res;
+            NPT_CHECK_LABEL_WARNING(res, done);
+        }
+
+        if (browse_data->info.items->GetItemCount() == 0)
+            break;
+
+        if (list.IsNull()) {
+            list = browse_data->info.items;
+        } else {
+            list->Add(*browse_data->info.items);
+            // clear the list items so that the data inside is not
+            // cleaned up by PLT_MediaItemList dtor since we copied
+            // each pointer into the new list.
+            browse_data->info.items->Clear();
+        }
+
+        // stop now if our list contains exactly what the server said it had
+        if (browse_data->info.tm && browse_data->info.tm == list->GetItemCount())
+            break;
+
+        // ask for the next chunk of entries
+        index = list->GetItemCount();
+    } while(1);
+
+done:
+    // cache the result
+    if (m_UseCache && NPT_SUCCEEDED(res) && !list.IsNull() && list->GetItemCount()) {
+        m_Cache.Put(device->GetUUID(), object_id, list);
+    }
+
+    // clear entire cache data for device if failed, the device could be gone
+    if (NPT_FAILED(res) && m_UseCache) m_Cache.Clear(device->GetUUID());
+    
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser::IsCached
++---------------------------------------------------------------------*/
+bool
+PLT_SyncMediaBrowser::IsCached(const char* uuid, const char* object_id)
+{
+    NPT_AutoLock lock(m_MediaServers);
+    const NPT_List<PLT_DeviceMapEntry*>::Iterator it = 
+        m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByUUID(uuid));
+    if (!it) {
+        m_Cache.Clear(uuid);
+        return false; // device with this service has gone away
+    }
+    
+    PLT_MediaObjectListReference list;
+    return NPT_SUCCEEDED(m_Cache.Get(uuid, object_id, list))?true:false;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,165 @@
+/*****************************************************************
+|
+|   Platinum - Synchronous Media Browser
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_SYNC_MEDIA_BROWSER_
+#define _PLT_SYNC_MEDIA_BROWSER_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltCtrlPoint.h"
+#include "PltMediaBrowser.h"
+#include "PltMediaCache.h"
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef NPT_Map<NPT_String, PLT_DeviceDataReference>         PLT_DeviceMap;
+typedef NPT_Map<NPT_String, PLT_DeviceDataReference>::Entry  PLT_DeviceMapEntry;
+
+typedef struct PLT_BrowseData {
+    NPT_SharedVariable shared_var;
+    NPT_Result         res;
+    PLT_BrowseInfo     info;
+} PLT_BrowseData;
+
+typedef NPT_Reference<PLT_BrowseData> PLT_BrowseDataReference;
+
+/*----------------------------------------------------------------------
+|   PLT_MediaContainerListener
++---------------------------------------------------------------------*/
+class PLT_MediaContainerChangesListener
+{
+public:
+    virtual ~PLT_MediaContainerChangesListener() {}
+    virtual void OnContainerChanged(PLT_DeviceDataReference& device, 
+                                    const char*              item_id, 
+                                    const char*              update_id) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_SyncMediaBrowser
++---------------------------------------------------------------------*/
+class PLT_SyncMediaBrowser : public PLT_MediaBrowser,
+                             public PLT_MediaBrowserDelegate
+{
+public:
+    PLT_SyncMediaBrowser(PLT_CtrlPointReference&            ctrlPoint, 
+                         bool                               use_cache = false, 
+                         PLT_MediaContainerChangesListener* listener = NULL);
+    virtual ~PLT_SyncMediaBrowser();
+
+    // PLT_MediaBrowser methods
+    virtual NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device);
+    virtual NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device);
+
+    // PLT_MediaBrowserDelegate methods
+    virtual void OnMSStateVariablesChanged(PLT_Service*                  service, 
+                                           NPT_List<PLT_StateVariable*>* vars);
+    virtual void OnBrowseResult(NPT_Result               res, 
+                                PLT_DeviceDataReference& device, 
+                                PLT_BrowseInfo*          info, 
+                                void*                    userdata);
+
+    // methods
+    void       SetContainerListener(PLT_MediaContainerChangesListener* listener) {
+        m_ContainerListener = listener;
+    }
+    NPT_Result BrowseSync(PLT_DeviceDataReference&      device, 
+                          const char*                   id, 
+                          PLT_MediaObjectListReference& list);
+
+    const NPT_Lock<PLT_DeviceMap>& GetMediaServersMap() const { return m_MediaServers; }
+    bool IsCached(const char* uuid, const char* object_id);
+
+protected:
+    NPT_Result BrowseSync(PLT_BrowseDataReference& browse_data,
+                          PLT_DeviceDataReference& device, 
+                          const char*              object_id,
+                          NPT_Int32                index, 
+                          NPT_Int32                count,
+                          bool                     browse_metadata = false,
+                          const char*              filter = "*", 
+                          const char*              sort = "");
+private:
+    NPT_Result Find(const char* ip, PLT_DeviceDataReference& device);
+    NPT_Result WaitForResponse(NPT_SharedVariable& shared_var);
+
+private:
+    NPT_Lock<PLT_DeviceMap>              m_MediaServers;
+    PLT_MediaContainerChangesListener*   m_ContainerListener;
+    bool                                 m_UseCache;
+    PLT_MediaCache                       m_Cache;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceMapFinderByIp
++---------------------------------------------------------------------*/
+class PLT_DeviceMapFinderByIp
+{
+public:
+    // methods
+    PLT_DeviceMapFinderByIp(const char* ip) : m_IP(ip) {}
+
+    bool operator()(const PLT_DeviceMapEntry* const& entry) const {
+        PLT_DeviceDataReference device = entry->GetValue();
+        return (device->GetURLBase().GetHost() == m_IP);
+    }
+
+private:
+    // members
+    NPT_String m_IP;
+};
+
+/*----------------------------------------------------------------------
+|   PLT_DeviceFinderByUUID
++---------------------------------------------------------------------*/
+class PLT_DeviceMapFinderByUUID
+{
+public:
+    // methods
+    PLT_DeviceMapFinderByUUID(const char* uuid) : m_UUID(uuid) {}
+
+    bool operator()(const PLT_DeviceMapEntry* const& entry) const {
+        PLT_DeviceDataReference device = entry->GetValue();
+        return device->GetUUID() == m_UUID;
+    }
+
+private:
+    // members
+    NPT_String m_UUID;
+};
+
+#endif /* _PLT_SYNC_MEDIA_BROWSER_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Build/Targets/x86-microsoft-win32-vs2008/Neptune.sln	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,199 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Neptune", "Neptune\Neptune.vcproj", "{12AFF2E5-6D95-4809-9728-9551677C078A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XmlTest1", "XmlTest1\XmlTest1.vcproj", "{21C242CD-B371-4970-94BE-7ED2522872BA}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetPump", "NetPump\NetPump.vcproj", "{0B04D92B-B644-4AED-90C6-A24303C78658}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StringsTest1", "StringsTest1\StringsTest1.vcproj", "{569179D6-7767-4840-9708-D1ADAFB012DB}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessagesTest1", "MessagesTest1\MessagesTest1.vcproj", "{40A4B71C-5481-4A70-8216-E7AE6E431313}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessagesTest2", "MessagesTest2\MessagesTest2.vcproj", "{B6D74CB4-CAB6-40E4-A5DB-BC54A8038FBD}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetConfig", "NetConfig\NetConfig.vcproj", "{0E80CEA0-5817-4B9C-B2D8-733D955A7673}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RingBufferTest1", "RingBufferTest1\RingBufferTest1.vcproj", "{59C1FCBE-7987-41F2-A0EB-E0114D5B2972}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetEcho", "NetEcho\NetEcho.vcproj", "{7228CB90-1ACE-43A3-A013-D437BF0E50F3}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetPing", "NetPing\NetPing.vcproj", "{9C1CAC88-8D92-4743-8330-CE8E7836D3BF}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UdpTest1", "UdpTest1\UdpTest1.vcproj", "{C025608F-9193-4040-B2F8-941746648CE2}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArraysTest1", "ArraysTest1\ArraysTest1.vcproj", "{0978344F-DBD7-4B3E-809C-5E58FB1FFD43}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BufferedStreamsTest1", "BufferedStreamsTest1\BufferedStreamsTest1.vcproj", "{F85C32FD-20B2-4066-B1B0-CE43A7BAA988}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpClientTest1", "HttpClientTest1\HttpClientTest1.vcproj", "{589435E9-3451-45B0-83BD-E5FD0D875CBB}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ListsTest1", "ListsTest1\ListsTest1.vcproj", "{AB6911DF-1EB4-4D37-B4A5-AD577761C188}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MiscTest1", "MiscTest1\MiscTest1.vcproj", "{85255DB0-110B-460E-8AC9-406516F790BB}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpServerTest1", "HttpServerTest1\HttpServerTest1.vcproj", "{77FD5430-1AB3-414A-BE15-E63D38F1A5FC}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UrlTest1", "UrlTest1\UrlTest1.vcproj", "{DBC6965C-D575-4DBC-9A0A-E6D9D9674282}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MapsTest1", "MapsTest1\MapsTest1.vcproj", "{257C9F75-2708-4136-BFA9-621ACD0B9BD1}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadsTest1", "ThreadsTest1\ThreadsTest1.vcproj", "{D1355CEF-E9CF-4FDF-A48F-69ACBE5622DC}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LoggingTest1", "LoggingTest1\LoggingTest1.vcproj", "{6A729FAF-D757-4699-8BB4-CF48B2F4BC20}"
+	ProjectSection(ProjectDependencies) = postProject
+		{12AFF2E5-6D95-4809-9728-9551677C078A} = {12AFF2E5-6D95-4809-9728-9551677C078A}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Debug|Win32.Build.0 = Debug|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Release|Win32.ActiveCfg = Release|Win32
+		{12AFF2E5-6D95-4809-9728-9551677C078A}.Release|Win32.Build.0 = Release|Win32
+		{21C242CD-B371-4970-94BE-7ED2522872BA}.Debug|Win32.ActiveCfg = Debug|Win32
+		{21C242CD-B371-4970-94BE-7ED2522872BA}.Debug|Win32.Build.0 = Debug|Win32
+		{21C242CD-B371-4970-94BE-7ED2522872BA}.Release|Win32.ActiveCfg = Release|Win32
+		{21C242CD-B371-4970-94BE-7ED2522872BA}.Release|Win32.Build.0 = Release|Win32
+		{0B04D92B-B644-4AED-90C6-A24303C78658}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0B04D92B-B644-4AED-90C6-A24303C78658}.Debug|Win32.Build.0 = Debug|Win32
+		{0B04D92B-B644-4AED-90C6-A24303C78658}.Release|Win32.ActiveCfg = Release|Win32
+		{0B04D92B-B644-4AED-90C6-A24303C78658}.Release|Win32.Build.0 = Release|Win32
+		{569179D6-7767-4840-9708-D1ADAFB012DB}.Debug|Win32.ActiveCfg = Debug|Win32
+		{569179D6-7767-4840-9708-D1ADAFB012DB}.Debug|Win32.Build.0 = Debug|Win32
+		{569179D6-7767-4840-9708-D1ADAFB012DB}.Release|Win32.ActiveCfg = Release|Win32
+		{569179D6-7767-4840-9708-D1ADAFB012DB}.Release|Win32.Build.0 = Release|Win32
+		{40A4B71C-5481-4A70-8216-E7AE6E431313}.Debug|Win32.ActiveCfg = Debug|Win32
+		{40A4B71C-5481-4A70-8216-E7AE6E431313}.Debug|Win32.Build.0 = Debug|Win32
+		{40A4B71C-5481-4A70-8216-E7AE6E431313}.Release|Win32.ActiveCfg = Release|Win32
+		{40A4B71C-5481-4A70-8216-E7AE6E431313}.Release|Win32.Build.0 = Release|Win32
+		{B6D74CB4-CAB6-40E4-A5DB-BC54A8038FBD}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B6D74CB4-CAB6-40E4-A5DB-BC54A8038FBD}.Debug|Win32.Build.0 = Debug|Win32
+		{B6D74CB4-CAB6-40E4-A5DB-BC54A8038FBD}.Release|Win32.ActiveCfg = Release|Win32
+		{B6D74CB4-CAB6-40E4-A5DB-BC54A8038FBD}.Release|Win32.Build.0 = Release|Win32
+		{0E80CEA0-5817-4B9C-B2D8-733D955A7673}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0E80CEA0-5817-4B9C-B2D8-733D955A7673}.Debug|Win32.Build.0 = Debug|Win32
+		{0E80CEA0-5817-4B9C-B2D8-733D955A7673}.Release|Win32.ActiveCfg = Release|Win32
+		{0E80CEA0-5817-4B9C-B2D8-733D955A7673}.Release|Win32.Build.0 = Release|Win32
+		{59C1FCBE-7987-41F2-A0EB-E0114D5B2972}.Debug|Win32.ActiveCfg = Debug|Win32
+		{59C1FCBE-7987-41F2-A0EB-E0114D5B2972}.Debug|Win32.Build.0 = Debug|Win32
+		{59C1FCBE-7987-41F2-A0EB-E0114D5B2972}.Release|Win32.ActiveCfg = Release|Win32
+		{59C1FCBE-7987-41F2-A0EB-E0114D5B2972}.Release|Win32.Build.0 = Release|Win32
+		{7228CB90-1ACE-43A3-A013-D437BF0E50F3}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7228CB90-1ACE-43A3-A013-D437BF0E50F3}.Debug|Win32.Build.0 = Debug|Win32
+		{7228CB90-1ACE-43A3-A013-D437BF0E50F3}.Release|Win32.ActiveCfg = Release|Win32
+		{7228CB90-1ACE-43A3-A013-D437BF0E50F3}.Release|Win32.Build.0 = Release|Win32
+		{9C1CAC88-8D92-4743-8330-CE8E7836D3BF}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9C1CAC88-8D92-4743-8330-CE8E7836D3BF}.Debug|Win32.Build.0 = Debug|Win32
+		{9C1CAC88-8D92-4743-8330-CE8E7836D3BF}.Release|Win32.ActiveCfg = Release|Win32
+		{9C1CAC88-8D92-4743-8330-CE8E7836D3BF}.Release|Win32.Build.0 = Release|Win32
+		{C025608F-9193-4040-B2F8-941746648CE2}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C025608F-9193-4040-B2F8-941746648CE2}.Debug|Win32.Build.0 = Debug|Win32
+		{C025608F-9193-4040-B2F8-941746648CE2}.Release|Win32.ActiveCfg = Release|Win32
+		{C025608F-9193-4040-B2F8-941746648CE2}.Release|Win32.Build.0 = Release|Win32
+		{0978344F-DBD7-4B3E-809C-5E58FB1FFD43}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0978344F-DBD7-4B3E-809C-5E58FB1FFD43}.Debug|Win32.Build.0 = Debug|Win32
+		{0978344F-DBD7-4B3E-809C-5E58FB1FFD43}.Release|Win32.ActiveCfg = Release|Win32
+		{0978344F-DBD7-4B3E-809C-5E58FB1FFD43}.Release|Win32.Build.0 = Release|Win32
+		{F85C32FD-20B2-4066-B1B0-CE43A7BAA988}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F85C32FD-20B2-4066-B1B0-CE43A7BAA988}.Debug|Win32.Build.0 = Debug|Win32
+		{F85C32FD-20B2-4066-B1B0-CE43A7BAA988}.Release|Win32.ActiveCfg = Release|Win32
+		{F85C32FD-20B2-4066-B1B0-CE43A7BAA988}.Release|Win32.Build.0 = Release|Win32
+		{589435E9-3451-45B0-83BD-E5FD0D875CBB}.Debug|Win32.ActiveCfg = Debug|Win32
+		{589435E9-3451-45B0-83BD-E5FD0D875CBB}.Debug|Win32.Build.0 = Debug|Win32
+		{589435E9-3451-45B0-83BD-E5FD0D875CBB}.Release|Win32.ActiveCfg = Release|Win32
+		{589435E9-3451-45B0-83BD-E5FD0D875CBB}.Release|Win32.Build.0 = Release|Win32
+		{AB6911DF-1EB4-4D37-B4A5-AD577761C188}.Debug|Win32.ActiveCfg = Debug|Win32
+		{AB6911DF-1EB4-4D37-B4A5-AD577761C188}.Debug|Win32.Build.0 = Debug|Win32
+		{AB6911DF-1EB4-4D37-B4A5-AD577761C188}.Release|Win32.ActiveCfg = Release|Win32
+		{AB6911DF-1EB4-4D37-B4A5-AD577761C188}.Release|Win32.Build.0 = Release|Win32
+		{85255DB0-110B-460E-8AC9-406516F790BB}.Debug|Win32.ActiveCfg = Debug|Win32
+		{85255DB0-110B-460E-8AC9-406516F790BB}.Debug|Win32.Build.0 = Debug|Win32
+		{85255DB0-110B-460E-8AC9-406516F790BB}.Release|Win32.ActiveCfg = Release|Win32
+		{85255DB0-110B-460E-8AC9-406516F790BB}.Release|Win32.Build.0 = Release|Win32
+		{77FD5430-1AB3-414A-BE15-E63D38F1A5FC}.Debug|Win32.ActiveCfg = Debug|Win32
+		{77FD5430-1AB3-414A-BE15-E63D38F1A5FC}.Debug|Win32.Build.0 = Debug|Win32
+		{77FD5430-1AB3-414A-BE15-E63D38F1A5FC}.Release|Win32.ActiveCfg = Release|Win32
+		{77FD5430-1AB3-414A-BE15-E63D38F1A5FC}.Release|Win32.Build.0 = Release|Win32
+		{DBC6965C-D575-4DBC-9A0A-E6D9D9674282}.Debug|Win32.ActiveCfg = Debug|Win32
+		{DBC6965C-D575-4DBC-9A0A-E6D9D9674282}.Debug|Win32.Build.0 = Debug|Win32
+		{DBC6965C-D575-4DBC-9A0A-E6D9D9674282}.Release|Win32.ActiveCfg = Release|Win32
+		{DBC6965C-D575-4DBC-9A0A-E6D9D9674282}.Release|Win32.Build.0 = Release|Win32
+		{257C9F75-2708-4136-BFA9-621ACD0B9BD1}.Debug|Win32.ActiveCfg = Debug|Win32
+		{257C9F75-2708-4136-BFA9-621ACD0B9BD1}.Debug|Win32.Build.0 = Debug|Win32
+		{257C9F75-2708-4136-BFA9-621ACD0B9BD1}.Release|Win32.ActiveCfg = Release|Win32
+		{257C9F75-2708-4136-BFA9-621ACD0B9BD1}.Release|Win32.Build.0 = Release|Win32
+		{D1355CEF-E9CF-4FDF-A48F-69ACBE5622DC}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D1355CEF-E9CF-4FDF-A48F-69ACBE5622DC}.Debug|Win32.Build.0 = Debug|Win32
+		{D1355CEF-E9CF-4FDF-A48F-69ACBE5622DC}.Release|Win32.ActiveCfg = Release|Win32
+		{D1355CEF-E9CF-4FDF-A48F-69ACBE5622DC}.Release|Win32.Build.0 = Release|Win32
+		{6A729FAF-D757-4699-8BB4-CF48B2F4BC20}.Debug|Win32.ActiveCfg = Debug|Win32
+		{6A729FAF-D757-4699-8BB4-CF48B2F4BC20}.Debug|Win32.Build.0 = Debug|Win32
+		{6A729FAF-D757-4699-8BB4-CF48B2F4BC20}.Release|Win32.ActiveCfg = Release|Win32
+		{6A729FAF-D757-4699-8BB4-CF48B2F4BC20}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Build/Targets/x86-microsoft-win32-vs2008/Neptune/Neptune.vcproj	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,508 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="Neptune"
+	ProjectGUID="{12AFF2E5-6D95-4809-9728-9551677C078A}"
+	RootNamespace="Neptune"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				WholeProgramOptimization="false"
+				AdditionalIncludeDirectories="..\..\..\..\Source\Core;..\..\..\..\Source\System\Win32;&quot;..\..\..\..\ThirdParty\zlib-1.2.3&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;NPT_CONFIG_ENABLE_LOGGING"
+				MinimalRebuild="true"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalDependencies="ws2_32.lib"
+				OutputFile="$(OutDir)/Neptune.lib"
+				SuppressStartupBanner="false"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				OmitFramePointers="true"
+				WholeProgramOptimization="false"
+				AdditionalIncludeDirectories="..\..\..\..\Source\Core;..\..\..\..\Source\System\Win32;&quot;..\..\..\..\ThirdParty\zlib-1.2.3&quot;"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;NPT_CONFIG_ENABLE_LOGGING"
+				StringPooling="true"
+				ExceptionHandling="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="true"
+				EnableFunctionLevelLinking="true"
+				FloatingPointModel="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalDependencies="ws2_32.lib"
+				OutputFile="$(OutDir)/Neptune.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptBase64.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Bsd\NptBsdSockets.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptBufferedStreams.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptCommon.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptConsole.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptDataBuffer.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptDebug.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptFile.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptHttp.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptList.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptLogging.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptMessaging.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptNetwork.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Posix\NptPosixFile.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptQueue.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptResults.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptRingBuffer.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSimpleMessageQueue.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSockets.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\StdC\NptStdcEnvironment.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\StdC\NptStdcFile.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptStreams.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptStrings.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSystem.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptThreads.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptTime.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptUri.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptUtils.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Console.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Debug.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32File.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32MessageQueue.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Network.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Queue.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32SerialPort.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32System.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Threads.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptXml.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptZip.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\..\..\Source\Core\Neptune.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptArray.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptBase64.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptBufferedStreams.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptCommon.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptConfig.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptConsole.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptConstants.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptDataBuffer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptDebug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptDefs.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptFile.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptHttp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptInterfaces.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptList.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptLogging.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptMap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptMessaging.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptNetwork.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptQueue.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptReferences.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptResults.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptRingBuffer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSelectableMessageQueue.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSerialPort.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSimpleMessageQueue.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSockets.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptStack.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptStreams.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptStrings.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptSystem.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptThreads.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptTime.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptTypes.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptUri.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptUtils.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptVersion.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32MessageQueue.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Network.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\System\Win32\NptWin32Threads.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptXml.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\..\Source\Core\NptZip.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/README.txt	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,29 @@
+Neptune C++ Runtime System
+--------------------------
+
+This software is provided under the following license:
+
+* Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the <organization> nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/Neptune.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+|   Neptune - Toplevel Include
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NEPTUNE_H_
+#define _NEPTUNE_H_
+
+/*----------------------------------------------------------------------
+|   flags
++---------------------------------------------------------------------*/
+#define NPT_EXTERNAL_USE /* do not expose internal definitions */
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptCommon.h"
+#include "NptResults.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptReferences.h"
+#include "NptStreams.h"
+#include "NptBufferedStreams.h"
+#include "NptFile.h"
+#include "NptNetwork.h"
+#include "NptSockets.h"
+#include "NptTime.h"
+#include "NptThreads.h"
+#include "NptSystem.h"
+#include "NptMessaging.h"
+#include "NptQueue.h"
+#include "NptSimpleMessageQueue.h"
+#include "NptSelectableMessageQueue.h"
+#include "NptXml.h"
+#include "NptStrings.h"
+#include "NptArray.h"
+#include "NptList.h"
+#include "NptMap.h"
+#include "NptStack.h"
+#include "NptUri.h"
+#include "NptHttp.h"
+#include "NptDataBuffer.h"
+#include "NptUtils.h"
+#include "NptRingBuffer.h"
+#include "NptBase64.h"
+#include "NptConsole.h"
+#include "NptLogging.h"
+#include "NptSerialPort.h"
+#include "NptVersion.h"
+#include "NptDynamicLibraries.h"
+
+// optional modules
+#include "NptZip.h"
+#include "NptTls.h"
+
+#endif // _NEPTUNE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptArray.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,522 @@
+/*****************************************************************
+|
+|   Neptune - Arrays
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_ARRAY_H_
+#define _NPT_ARRAY_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#if defined(NPT_CONFIG_HAVE_NEW_H)
+#include <new>
+#endif
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ARRAY_INITIAL_MAX_SIZE = 128; // bytes
+
+/*----------------------------------------------------------------------
+|   NPT_Array
++---------------------------------------------------------------------*/
+template <typename T> 
+class NPT_Array 
+{
+public:
+    // types
+    typedef T Element;
+    typedef T* Iterator;
+
+    // methods
+    NPT_Array<T>(): m_Capacity(0), m_ItemCount(0), m_Items(0) {}
+    explicit NPT_Array<T>(NPT_Cardinal count);
+    NPT_Array<T>(NPT_Cardinal count, const T& item);
+    NPT_Array<T>(const T* items, NPT_Cardinal item_count);
+   ~NPT_Array<T>();
+    NPT_Array<T>(const NPT_Array<T>& copy);
+    NPT_Array<T>& operator=(const NPT_Array<T>& copy);
+    bool          operator==(const NPT_Array<T>& other) const;
+    bool          operator!=(const NPT_Array<T>& other) const;
+    NPT_Cardinal GetItemCount() const { return m_ItemCount; }
+    NPT_Result   Add(const T& item);
+    T& operator[](NPT_Ordinal pos)             { return m_Items[pos]; }
+    const T& operator[](NPT_Ordinal pos) const { return m_Items[pos]; }
+    NPT_Result   Erase(Iterator which);
+    NPT_Result   Erase(NPT_Ordinal which) { return Erase(&m_Items[which]); }
+    NPT_Result   Erase(Iterator first, Iterator last);
+    NPT_Result   Erase(NPT_Ordinal first, NPT_Ordinal last) { return Erase(&m_Items[first], &m_Items[last]); }
+    NPT_Result   Insert(Iterator where, const T& item, NPT_Cardinal count = 1);
+    NPT_Result   Reserve(NPT_Cardinal count);
+    NPT_Cardinal GetCapacity() const { return m_Capacity; }
+    NPT_Result   Resize(NPT_Cardinal count);
+    NPT_Result   Resize(NPT_Cardinal count, const T& fill);
+    NPT_Result   Clear();
+    bool         Contains(const T& data) const;
+    Iterator     GetFirstItem() const { return m_ItemCount?&m_Items[0]:NULL; }
+    Iterator     GetLastItem() const  { return m_ItemCount?&m_Items[m_ItemCount-1]:NULL; }
+    Iterator     GetItem(NPT_Ordinal n) { return n<m_ItemCount?&m_Items[n]:NULL; }
+
+    // template list operations
+    // keep these template members defined here because MSV6 does not let
+    // us define them later
+    template <typename X> 
+    NPT_Result Apply(const X& function) const
+    {                                  
+        for (unsigned int i=0; i<m_ItemCount; i++) function(m_Items[i]);
+        return NPT_SUCCESS;
+    }
+
+    template <typename X, typename P>
+    NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
+    {                                  
+        for (unsigned int i=0; i<m_ItemCount; i++) {
+            NPT_Result return_value;
+            if (predicate(function(m_Items[i]), return_value)) {
+                if (match) *match = true;
+                return return_value;
+            }
+        }
+        if (match) *match = false;
+        return NPT_SUCCESS;
+    }
+
+    template <typename X> 
+    T* Find(const X& predicate, NPT_Ordinal n=0, NPT_Ordinal* pos = NULL) const
+    {
+        if (pos) *pos = -1;
+
+        for (unsigned int i=0; i<m_ItemCount; i++) {
+            if (predicate(m_Items[i])) {
+                if (pos) *pos = i;
+                if (n == 0) return &m_Items[i];
+                --n;
+            }
+        }
+        return NULL;
+    }
+
+protected:
+    // methods
+    T* Allocate(NPT_Cardinal count, NPT_Cardinal& allocated);
+
+    // members
+    NPT_Cardinal m_Capacity;
+    NPT_Cardinal m_ItemCount;
+    T*           m_Items;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(NPT_Cardinal count) :
+    m_Capacity(0),
+    m_ItemCount(0),
+    m_Items(0)
+{
+    Reserve(count);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(const NPT_Array<T>& copy) :
+    m_Capacity(0),
+    m_ItemCount(0),
+    m_Items(0)
+{
+    Reserve(copy.GetItemCount());
+    for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
+        new ((void*)&m_Items[i]) T(copy.m_Items[i]);
+    }
+    m_ItemCount = copy.m_ItemCount;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(NPT_Cardinal count, const T& item) :
+    m_Capacity(0),
+    m_ItemCount(count),
+    m_Items(0)    
+{
+    Reserve(count);
+    for (NPT_Ordinal i=0; i<count; i++) {
+        new ((void*)&m_Items[i]) T(item);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::NPT_Array(const T* items, NPT_Cardinal item_count) :
+    m_Capacity(0),
+    m_ItemCount(item_count),
+    m_Items(0)    
+{
+    Reserve(item_count);
+    for (NPT_Ordinal i=0; i<item_count; i++) {
+        new ((void*)&m_Items[i]) T(items[i]);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::~NPT_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Array<T>::~NPT_Array()
+{
+    // remove all items
+    Clear();
+
+    // free the memory
+    ::operator delete((void*)m_Items);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::operator=
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Array<T>&
+NPT_Array<T>::operator=(const NPT_Array<T>& copy)
+{
+    // do nothing if we're assigning to ourselves
+    if (this == &copy) return *this;
+
+    // destroy all elements
+    Clear();
+
+    // copy all elements from the other object
+    Reserve(copy.GetItemCount());
+    m_ItemCount = copy.m_ItemCount;
+    for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
+        new ((void*)&m_Items[i]) T(copy.m_Items[i]);
+    }
+
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Clear
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Clear()
+{
+    // destroy all items
+    for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
+        m_Items[i].~T();
+    }
+
+    m_ItemCount = 0;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Allocate
++---------------------------------------------------------------------*/
+template <typename T>
+T*
+NPT_Array<T>::Allocate(NPT_Cardinal count, NPT_Cardinal& allocated) 
+{
+    if (m_Capacity) {
+        allocated = 2*m_Capacity;
+    } else {
+        // start with just enough elements to fill 
+        // NPT_ARRAY_INITIAL_MAX_SIZE worth of memory
+        allocated = NPT_ARRAY_INITIAL_MAX_SIZE/sizeof(T);
+        if (allocated == 0) allocated = 1;
+    }
+    if (allocated < count) allocated = count;
+
+    // allocate the items
+    return (T*)::operator new(allocated*sizeof(T));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Reserve
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Reserve(NPT_Cardinal count)
+{
+    if (count <= m_Capacity) return NPT_SUCCESS;
+
+    // (re)allocate the items
+    NPT_Cardinal new_capacity;
+    T* new_items = Allocate(count, new_capacity);
+    if (new_items == NULL) {
+        return NPT_ERROR_OUT_OF_MEMORY;
+    }
+    if (m_ItemCount && m_Items) {
+        for (unsigned int i=0; i<m_ItemCount; i++) {
+            // construct the copy
+            new ((void*)&new_items[i])T(m_Items[i]);
+
+            // destroy the item
+            m_Items[i].~T();
+        }
+    }
+    ::operator delete((void*)m_Items);
+    m_Items = new_items;
+    m_Capacity = new_capacity;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_Array<T>::Add(const T& item)
+{
+    // ensure capacity
+    NPT_Result result = Reserve(m_ItemCount+1);
+    if (result != NPT_SUCCESS) return result;
+
+    // store the item
+    new ((void*)&m_Items[m_ItemCount++]) T(item);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Erase
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_Array<T>::Erase(Iterator which)
+{
+    return Erase(which, which);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Erase
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Erase(Iterator first, Iterator last)
+{
+    // check parameters
+    if (first == NULL || last == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // check the bounds
+    NPT_Ordinal first_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(first-m_Items));
+    NPT_Ordinal last_index  = (NPT_Ordinal)(NPT_POINTER_TO_LONG(last-m_Items));
+    if (first_index >= m_ItemCount ||
+        last_index  >= m_ItemCount ||
+        first_index > last_index) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // shift items to the left
+    NPT_Cardinal interval = last_index-first_index+1;
+    NPT_Cardinal shifted = m_ItemCount-last_index-1;
+    for (NPT_Ordinal i=first_index; i<first_index+shifted; i++) {
+        m_Items[i] = m_Items[i+interval];
+    }
+
+    // destruct the remaining items
+    for (NPT_Ordinal i=first_index+shifted; i<m_ItemCount; i++) {
+        m_Items[i].~T();
+    }
+
+    // update the item count
+    m_ItemCount -= interval;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Insert(Iterator where, const T& item, NPT_Cardinal repeat)
+{
+    // check bounds
+    NPT_Ordinal where_index = where?((NPT_Ordinal)NPT_POINTER_TO_LONG(where-m_Items)):m_ItemCount;
+    if (where > &m_Items[m_ItemCount] || repeat == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+    NPT_Cardinal needed = m_ItemCount+repeat;
+    if (needed > m_Capacity) {
+        // allocate more memory
+        NPT_Cardinal new_capacity;
+        T* new_items = Allocate(needed, new_capacity);
+        if (new_items == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+        m_Capacity = new_capacity;
+
+        // move the items before the insertion point
+        for (NPT_Ordinal i=0; i<where_index; i++) {
+            new((void*)&new_items[i])T(m_Items[i]);
+            m_Items[i].~T();
+        }
+
+        // move the items after the insertion point
+        for (NPT_Ordinal i=where_index; i<m_ItemCount; i++) {
+            new((void*)&new_items[i+repeat])T(m_Items[i]);
+            m_Items[i].~T();
+        }
+
+        // use the new items instead of the current ones
+        ::operator delete((void*)m_Items);
+        m_Items = new_items;
+    } else {
+        // shift items after the insertion point to the right
+        for (NPT_Ordinal i=m_ItemCount; i>where_index; i--) {
+            new((void*)&m_Items[i+repeat-1])T(m_Items[i-1]);
+            m_Items[i-1].~T();
+        }
+    }
+
+    // insert the new items
+    for (NPT_Cardinal i=where_index; i<where_index+repeat; i++) {
+        new((void*)&m_Items[i])T(item);
+    }
+
+    // update the item count
+    m_ItemCount += repeat;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Resize
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Resize(NPT_Cardinal size)
+{
+    if (size < m_ItemCount) {
+        // shrink
+        for (NPT_Ordinal i=size; i<m_ItemCount; i++) {
+            m_Items[i].~T();
+        }
+        m_ItemCount = size;
+    } else if (size > m_ItemCount) {
+        return Resize(size, T());
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Resize
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_Array<T>::Resize(NPT_Cardinal size, const T& fill)
+{
+    if (size < m_ItemCount) {
+        return Resize(size);
+    } else if (size > m_ItemCount) {
+        Reserve(size);
+        for (NPT_Ordinal i=m_ItemCount; i<size; i++) {
+            new ((void*)&m_Items[i]) T(fill);
+        }
+        m_ItemCount = size;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::Contains
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_Array<T>::Contains(const T& data) const
+{
+    for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
+        if (m_Items[i] == data) return true;
+    }
+
+    return false;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::operator==
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_Array<T>::operator==(const NPT_Array<T>& other) const
+{
+    // we need the same number of items
+    if (other.m_ItemCount != m_ItemCount) return false;
+
+    // compare all items
+    for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
+        if (!(m_Items[i] == other.m_Items[i])) return false;
+    }
+
+    return true;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Array<T>::operator!=
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+bool
+NPT_Array<T>::operator!=(const NPT_Array<T>& other) const
+{
+    return !(*this == other);
+}
+
+#endif // _NPT_ARRAY_H_
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptBase64.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,192 @@
+/*****************************************************************
+|
+|   Neptune - Base64
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptBase64.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+static const signed char NPT_Base64_Bytes[128] = {
+      -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+      -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+      -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, 0x3E,   -1,   -1,   -1, 0x3F,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,   -1,   -1,   -1, 0x7F,   -1,   -1,
+      -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 
+    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,   -1,   -1,   -1,   -1,   -1,
+      -1, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 
+    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,   -1,   -1,   -1,   -1,   -1
+};
+
+static const char NPT_Base64_Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+const char NPT_BASE64_PAD_CHAR = '=';
+const char NPT_BASE64_PAD_BYTE = 0x7F;
+
+/*----------------------------------------------------------------------
+|   NPT_Base64::Decode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Base64::Decode(const char*     base64, 
+                   NPT_Size        size,
+                   NPT_DataBuffer& data,
+                   bool            url_safe /* = false */)
+{
+    // estimate the data size
+    data.SetBufferSize(size);
+
+    // reset the buffer
+    data.SetDataSize(0);
+
+    // keep a pointer to the buffer
+    unsigned char* buffer = data.UseData();
+    NPT_Size       data_size = 0;
+
+    // iterate over all characters
+    unsigned char codes[4];
+    unsigned int code_count = 0;
+    while (size--) {
+        unsigned char c = *base64++;
+        if (c >= NPT_ARRAY_SIZE(NPT_Base64_Bytes)) continue;
+        if (url_safe) {
+            // remap some characters
+            if (c == '-') {
+                c = '+';
+            } else if (c == '_') {
+                c = '/';
+            }
+        }
+        signed char code = NPT_Base64_Bytes[c];
+        if (code >= 0) {
+            // valid code
+            codes[code_count++] = code;
+            if (code_count == 4) {
+                // group complete
+                if (codes[0] == NPT_BASE64_PAD_BYTE || codes[1] == NPT_BASE64_PAD_BYTE) {
+                    return NPT_ERROR_INVALID_FORMAT;
+                }
+                if (codes[2] == NPT_BASE64_PAD_BYTE) {
+                    // pad at char 3
+                    if (codes[3] == NPT_BASE64_PAD_BYTE) {
+                        // double padding
+                        unsigned int packed = (codes[0]<<2)|(codes[1]>>4);
+                        buffer[data_size++] = (unsigned char)packed;
+                    } else {
+                        // invalid padding
+                        return NPT_ERROR_INVALID_FORMAT;
+                    }
+                } else if (codes[3] == NPT_BASE64_PAD_BYTE) {
+                    // single padding
+                    unsigned int packed = (codes[0]<<10)|(codes[1]<<4)|(codes[2]>>2);
+                    buffer[data_size++] = (unsigned char)(packed >> 8);
+                    buffer[data_size++] = (unsigned char)(packed     );
+                } else {
+                    // no padding
+                    unsigned int packed = (codes[0]<<18)|(codes[1]<<12)|(codes[2]<<6)|codes[3];
+                    buffer[data_size++] = (unsigned char)(packed >> 16);
+                    buffer[data_size++] = (unsigned char)(packed >>  8);
+                    buffer[data_size++] = (unsigned char)(packed      );
+                }
+                code_count = 0;
+            }
+        }
+    }
+
+    if (code_count) return NPT_ERROR_INVALID_FORMAT;
+
+    // update the data size
+    data.SetDataSize(data_size);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Base64::Encode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Base64::Encode(const NPT_Byte* data, 
+                   NPT_Size        size, 
+                   NPT_String&     base64, 
+                   NPT_Cardinal    max_blocks_per_line /* = 0 */, 
+                   bool            url_safe /* = false */)
+{
+    unsigned int block_count = 0;
+    unsigned int           i = 0;
+
+    // reserve space for the string
+    base64.Reserve(4*((size+3)/3) + 2*(max_blocks_per_line?(size/(3*max_blocks_per_line)):0));
+    char* buffer = base64.UseChars();
+
+    // encode each byte
+    while (size >= 3) {
+        // output a block
+        *buffer++ = NPT_Base64_Chars[ (data[i  ] >> 2) & 0x3F];
+        *buffer++ = NPT_Base64_Chars[((data[i  ] & 0x03) << 4) | ((data[i+1] >> 4) & 0x0F)];
+        *buffer++ = NPT_Base64_Chars[((data[i+1] & 0x0F) << 2) | ((data[i+2] >> 6) & 0x03)];
+        *buffer++ = NPT_Base64_Chars[  data[i+2] & 0x3F];
+
+        size -= 3;
+        i += 3;
+        if (++block_count == max_blocks_per_line) {
+            *buffer++ = '\r';
+            *buffer++ = '\n';
+            block_count = 0;
+        }
+    }
+
+    // deal with the tail
+    if (size == 2) {
+        *buffer++ = NPT_Base64_Chars[ (data[i  ] >> 2) & 0x3F];
+        *buffer++ = NPT_Base64_Chars[((data[i  ] & 0x03) << 4) | ((data[i+1] >> 4) & 0x0F)];
+        *buffer++ = NPT_Base64_Chars[ (data[i+1] & 0x0F) << 2];
+        *buffer++ = NPT_BASE64_PAD_CHAR;
+    } else if (size == 1) {
+        *buffer++ = NPT_Base64_Chars[(data[i] >> 2) & 0x3F];
+        *buffer++ = NPT_Base64_Chars[(data[i] & 0x03) << 4];
+        *buffer++ = NPT_BASE64_PAD_CHAR;
+        *buffer++ = NPT_BASE64_PAD_CHAR;
+    }
+
+    // update the string size
+    NPT_ASSERT((NPT_Size)(buffer-base64.GetChars()) <= base64.GetCapacity());
+    base64.SetLength((NPT_Size)(buffer-base64.GetChars()));
+
+    // deal with url safe remapping
+    if (url_safe) {
+        base64.Replace('+','-');
+        base64.Replace('/','_');
+    }
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptBase64.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+|   Neptune - Base64
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_BASE64_H_
+#define _NPT_BASE64_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptDataBuffer.h"
+#include "NptStrings.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const NPT_Cardinal NPT_BASE64_MIME_BLOCKS_PER_LINE = 19;
+const NPT_Cardinal NPT_BASE64_PEM_BLOCKS_PER_LINE  = 16;
+
+/*----------------------------------------------------------------------
+|   NPT_Base64
++---------------------------------------------------------------------*/
+class NPT_Base64 {
+public:
+    // class methods
+    static NPT_Result Decode(const char*     base64, 
+                             NPT_Size        size,
+                             NPT_DataBuffer& data,
+                             bool            url_safe = false);
+    static NPT_Result Encode(const NPT_Byte* data, 
+                             NPT_Size        size, 
+                             NPT_String&     base64, 
+                             NPT_Cardinal    max_blocks_per_line = 0, 
+                             bool            url_safe = false);
+
+private: 
+    // this class is purely static
+    NPT_Base64();
+};
+
+#endif // _NPT_BASE64_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptBufferedStreams.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,373 @@
+/*****************************************************************
+|
+|   Neptune - Buffered Streams
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptInterfaces.h"
+#include "NptConstants.h"
+#include "NptBufferedStreams.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::NPT_BufferedInputStream
++---------------------------------------------------------------------*/
+NPT_BufferedInputStream::NPT_BufferedInputStream(NPT_InputStreamReference& source, NPT_Size buffer_size) :
+    m_Source(source),
+    m_SkipNewline(false),
+    m_Eos(false)
+{
+    // setup the read buffer
+    m_Buffer.data     = NULL;
+    m_Buffer.offset   = 0;
+    m_Buffer.valid    = 0;
+    m_Buffer.size     = buffer_size;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::~NPT_BufferedInputStream
++---------------------------------------------------------------------*/
+NPT_BufferedInputStream::~NPT_BufferedInputStream()
+{
+    // release the buffer
+    delete[] m_Buffer.data;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::SetBufferSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::SetBufferSize(NPT_Size size)
+{
+    if (m_Buffer.data != NULL) {
+        // we already have a buffer
+        if (m_Buffer.size < size) {
+            // the current buffer is too small, reallocate
+            NPT_Byte* buffer = new NPT_Byte[size];
+            if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+
+            // copy existing data
+            NPT_Size need_to_copy = m_Buffer.valid - m_Buffer.offset;
+            if (need_to_copy) {
+                NPT_CopyMemory((void*)buffer, 
+                               m_Buffer.data+m_Buffer.offset,
+                               need_to_copy);
+            }
+
+            // use the new buffer
+            delete[] m_Buffer.data;
+            m_Buffer.data = buffer;
+            m_Buffer.valid -= m_Buffer.offset;
+            m_Buffer.offset = 0;
+        }
+    }
+    m_Buffer.size = size;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::FillBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::FillBuffer()
+{
+    // shortcut
+    if (m_Eos) return NPT_ERROR_EOS;
+
+    // check that there is nothing left in the buffer and the buffer
+    // size is not 0
+    NPT_ASSERT(m_Buffer.valid == m_Buffer.offset);
+    NPT_ASSERT(m_Buffer.size != 0);
+
+    // allocate the read buffer if it has not been done yet
+    if (m_Buffer.data == NULL) {
+        m_Buffer.data = new NPT_Byte[m_Buffer.size];
+        if (m_Buffer.data == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+    }
+
+    // refill the buffer
+    m_Buffer.offset = 0;
+    NPT_Result result = m_Source->Read(m_Buffer.data, m_Buffer.size, &m_Buffer.valid);
+    if (NPT_FAILED(result)) m_Buffer.valid = 0;
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::ReleaseBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::ReleaseBuffer()
+{
+    NPT_ASSERT(m_Buffer.size == 0);
+    NPT_ASSERT(m_Buffer.offset == m_Buffer.valid);
+
+    delete[] m_Buffer.data;
+    m_Buffer.data = NULL;
+    m_Buffer.offset = 0;
+    m_Buffer.valid = 0;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::ReadLine
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::ReadLine(char*     buffer, 
+                                  NPT_Size  size, 
+                                  NPT_Size* chars_read,
+                                  bool      break_on_cr)
+{
+    NPT_Result result = NPT_SUCCESS;
+    char*      buffer_start = buffer;
+    bool       skip_newline = false;
+
+    // check parameters
+    if (buffer == NULL || size < 1) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // read until EOF or newline
+    while (buffer-buffer_start < (long)(size-1)) {
+        while (m_Buffer.offset != m_Buffer.valid) {
+            // there is some data left in the buffer
+            NPT_Byte c = m_Buffer.data[m_Buffer.offset++];
+            if (c == '\r') {
+                if (break_on_cr) {
+                    skip_newline = true;
+                    goto done;
+                }
+            } else if (c == '\n') {
+                if (m_SkipNewline && (buffer == buffer_start)) {
+                    continue;
+                }
+                goto done;
+            } else {
+                *buffer++ = c;
+            }
+        }
+
+        if (m_Buffer.size == 0 && !m_Eos) {
+            // unbuffered mode
+            if (m_Buffer.data != NULL) ReleaseBuffer();
+            while (NPT_SUCCEEDED(result = m_Source->Read(buffer, 1, NULL))) {
+                if (*buffer == '\r') {
+                    if (break_on_cr) {
+                        skip_newline = true;
+                        goto done;
+                    }
+                } else if (*buffer == '\n') {
+                    goto done;
+                } else {
+                    ++buffer;
+                }
+            }
+        } else {
+            // refill the buffer
+            result = FillBuffer();
+        }
+        if (NPT_FAILED(result)) goto done;
+    }
+
+done:
+    // update the newline skipping state
+    m_SkipNewline = skip_newline;
+
+    // NULL-terminate the line
+    *buffer = '\0';
+
+    // return what we have
+    if (chars_read) *chars_read = (NPT_Size)(buffer-buffer_start);
+    if (result == NPT_ERROR_EOS) {
+        m_Eos = true;
+        if (buffer != buffer_start) {
+            // we have reached the end of the stream, but we have read
+            // some chars, so do not return EOS now
+            return NPT_SUCCESS;
+        }
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::ReadLine
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BufferedInputStream::ReadLine(NPT_String& line,
+                                  NPT_Size    max_chars,
+                                  bool        break_on_cr)
+{
+    // clear the line
+    line.SetLength(0);
+
+    // reserve space for the chars
+    line.Reserve(max_chars);
+
+    // read the line
+    NPT_Size chars_read = 0;
+    NPT_CHECK(ReadLine(line.UseChars(), max_chars, &chars_read, break_on_cr));
+
+    // adjust the length of the string object
+    line.SetLength(chars_read);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BufferedInputStream::Read(void*     buffer, 
+                              NPT_Size  bytes_to_read, 
+                              NPT_Size* bytes_read)
+{
+    NPT_Result result = NPT_SUCCESS;
+    NPT_Size   total_read = 0;
+    NPT_Size   buffered;
+
+    // check for a possible shortcut
+    if (bytes_to_read == 0) return NPT_SUCCESS;
+
+    // skip a newline char if needed
+    if (m_SkipNewline) {
+        m_SkipNewline = false;
+        result = Read(buffer, 1, NULL);
+        if (NPT_FAILED(result)) goto done;
+        NPT_Byte c = *(NPT_Byte*)buffer;
+        if (c != '\n') {
+            buffer = (void*)((NPT_Byte*)buffer+1);
+            --bytes_to_read;
+            total_read = 1;
+        }
+    }
+
+    // compute how much is buffered
+    buffered = m_Buffer.valid-m_Buffer.offset;
+    if (bytes_to_read > buffered) {
+        // there is not enough in the buffer, take what's there
+        if (buffered) {
+            NPT_CopyMemory(buffer, 
+                           m_Buffer.data + m_Buffer.offset,
+                           buffered);
+            buffer = (void*)((NPT_Byte*)buffer+buffered);
+            m_Buffer.offset += buffered;
+            bytes_to_read -= buffered;
+            total_read += buffered;
+            goto done;
+        }
+        
+        // read the rest from the source
+        if (m_Buffer.size == 0) {
+            // unbuffered mode, read directly into the supplied buffer
+            if (m_Buffer.data != NULL) ReleaseBuffer(); // cleanup if necessary
+            NPT_Size local_read = 0;
+            result = m_Source->Read(buffer, bytes_to_read, &local_read);
+            if (NPT_SUCCEEDED(result)) {
+                total_read += local_read; 
+            }
+            goto done;
+        } else {
+            // refill the buffer
+            result = FillBuffer();
+            if (NPT_FAILED(result)) goto done;
+            buffered = m_Buffer.valid;
+            if (bytes_to_read > buffered) bytes_to_read = buffered;
+        }
+    }
+
+    // get what we can from the buffer
+    if (bytes_to_read) {
+        NPT_CopyMemory(buffer, 
+                       m_Buffer.data + m_Buffer.offset,
+                       bytes_to_read);
+        m_Buffer.offset += bytes_to_read;
+        total_read += bytes_to_read;
+    }
+    
+done:
+    if (bytes_read) *bytes_read = total_read;
+    if (result == NPT_ERROR_EOS) { 
+        m_Eos = true;
+        if (total_read != 0) {
+            // we have reached the end of the stream, but we have read
+            // some chars, so do not return EOS now
+            return NPT_SUCCESS;
+        }
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BufferedInputStream::Seek(NPT_Position /*offset*/)
+{
+    // not implemented yet
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BufferedInputStream::Tell(NPT_Position& offset)
+{
+    // not implemented yet
+    offset = 0;
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BufferedInputStream::GetSize(NPT_LargeSize& size)
+{
+    return m_Source->GetSize(size);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BufferedInputStream::GetAvailable(NPT_LargeSize& available)
+{
+    NPT_LargeSize source_available = 0;
+    NPT_Result    result = m_Source->GetAvailable(source_available);
+    if (NPT_SUCCEEDED(result)) {
+        available = m_Buffer.valid-m_Buffer.offset + source_available;
+        return NPT_SUCCESS;
+    } else {
+        available = m_Buffer.valid-m_Buffer.offset;
+        return available?NPT_SUCCESS:result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptBufferedStreams.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,98 @@
+/*****************************************************************
+|
+|   Neptune - Buffered Byte Stream
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_BUFFERED_STREAMS_H_
+#define _NPT_BUFFERED_STREAMS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptStreams.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedStream
++---------------------------------------------------------------------*/
+const NPT_Size NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE = 4096;
+
+/*----------------------------------------------------------------------
+|   NPT_BufferedInputStream
++---------------------------------------------------------------------*/
+class NPT_BufferedInputStream : public NPT_InputStream
+{
+public:
+    // constructors and destructor
+    NPT_BufferedInputStream(NPT_InputStreamReference& stream,
+                            NPT_Size buffer_size = NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE);
+    virtual ~NPT_BufferedInputStream();
+
+    // methods
+    virtual NPT_Result ReadLine(NPT_String& line,
+                                NPT_Size    max_chars = 4096,
+                                bool        break_on_cr = false);
+    virtual NPT_Result ReadLine(char*     buffer, 
+                                NPT_Size  buffer_size,
+                                NPT_Size* chars_read = NULL,
+                                bool      break_on_cr = false);
+    virtual NPT_Result SetBufferSize(NPT_Size size);
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read = NULL);
+    NPT_Result Seek(NPT_Position offset);
+    NPT_Result Tell(NPT_Position& offset);
+    NPT_Result GetSize(NPT_LargeSize& size);
+    NPT_Result GetAvailable(NPT_LargeSize& available);
+
+protected:
+    // members
+    NPT_InputStreamReference m_Source;
+    bool                     m_SkipNewline;
+    bool                     m_Eos;
+    struct {
+        NPT_Byte* data;
+        NPT_Size  offset;
+        NPT_Size  valid;
+        NPT_Size  size;
+    } m_Buffer;
+
+    // methods
+    virtual NPT_Result FillBuffer();
+    virtual NPT_Result ReleaseBuffer();
+};
+
+typedef NPT_Reference<NPT_BufferedInputStream> NPT_BufferedInputStreamReference;
+
+#endif // _NPT_BUFFERED_STREAMS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptCommon.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,38 @@
+/*****************************************************************
+|
+|   Neptune - Common Classes
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptCommon.h"
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptCommon.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,156 @@
+/*****************************************************************
+|
+|   Neptune - Common Definitions
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_COMMON_H_
+#define _NPT_COMMON_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   NPT_ObjectDeleter
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_ObjectDeleter {
+public:
+    void operator()(T* object) const {
+        delete object;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ObjectComparator
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_ObjectComparator {
+public:
+    NPT_ObjectComparator(T& object) : m_Object(object) {}
+    bool operator()(const T& object) const {
+        return object == m_Object;
+    }
+private:
+    T& m_Object;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ContainerFind
++---------------------------------------------------------------------*/
+template <typename T, typename P>
+NPT_Result NPT_ContainerFind(T&                   container, 
+                             const P&             predicate, 
+                             typename T::Element& item, 
+                             NPT_Ordinal          n=0) 
+{
+    typename T::Iterator found = container.Find(predicate, n);
+    if (found) {
+        item = *found;
+        return NPT_SUCCESS;
+    } else {
+        return NPT_ERROR_NO_SUCH_ITEM;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UntilResultEquals
++---------------------------------------------------------------------*/
+class NPT_UntilResultEquals
+{
+public:
+    // methods
+    NPT_UntilResultEquals(NPT_Result condition_result, 
+                          NPT_Result return_value = NPT_SUCCESS) :
+      m_ConditionResult(condition_result),
+      m_ReturnValue(return_value) {}
+    bool operator()(NPT_Result result, NPT_Result& return_value) const {
+        if (result == m_ConditionResult) {
+            return_value = m_ReturnValue;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+private:
+    // members
+    NPT_Result m_ConditionResult;
+    NPT_Result m_ReturnValue;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_UntilResultNotEquals
++---------------------------------------------------------------------*/
+class NPT_UntilResultNotEquals
+{
+public:
+    // methods
+    NPT_UntilResultNotEquals(NPT_Result condition_result) :
+      m_ConditionResult(condition_result) {}
+    bool operator()(NPT_Result result, NPT_Result& return_value) const {
+        if (result != m_ConditionResult) {
+            return_value = result;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+private:
+    // members
+    NPT_Result m_ConditionResult;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_PropertyValue
++---------------------------------------------------------------------*/
+class NPT_PropertyValue
+{
+ public:
+    // typedefs
+    typedef enum {UNKNOWN, INTEGER, STRING} Type;
+
+    // methods
+    NPT_PropertyValue() : m_Type(UNKNOWN), m_Integer(0) {}
+    NPT_PropertyValue(int value)         : m_Type(INTEGER), m_Integer(value) {}
+    NPT_PropertyValue(const char* value) : m_Type(STRING),  m_String(value)  {}
+
+    // members
+    Type m_Type;
+    union {
+        int         m_Integer;
+        const char* m_String;
+    };
+};
+
+#endif // _NPT_COMMON_H_
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptConfig.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,299 @@
+/*****************************************************************
+|
+|   Neptune - Configuration
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_CONFIG_H_
+#define _NPT_CONFIG_H_
+
+/*----------------------------------------------------------------------
+|   defaults
++---------------------------------------------------------------------*/
+#define NPT_CONFIG_HAVE_ASSERT_H
+#define NPT_CONFIG_HAVE_STD_C
+#define NPT_CONFIG_HAVE_STDLIB_H
+#define NPT_CONFIG_HAVE_STDIO_H
+#define NPT_CONFIG_HAVE_STDARG_H
+#define NPT_CONFIG_HAVE_STRING_H
+#define NPT_CONFIG_HAVE_LIMITS_H
+
+/*----------------------------------------------------------------------
+|   standard C runtime
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_HAVE_STD_C)
+#define NPT_CONFIG_HAVE_MALLOC
+#define NPT_CONFIG_HAVE_CALLOC
+#define NPT_CONFIG_HAVE_REALLOC
+#define NPT_CONFIG_HAVE_FREE
+#define NPT_CONFIG_HAVE_MEMCPY
+#define NPT_CONFIG_HAVE_MEMSET
+#define NPT_CONFIG_HAVE_MEMCMP
+#define NPT_CONFIG_HAVE_GETENV
+#define NPT_CONFIG_HAVE_READDIR_R
+#endif /* NPT_CONFIG_HAS_STD_C */
+
+#if defined(NPT_CONFIG_HAVE_STRING_H)
+#define NPT_CONFIG_HAVE_STRCMP
+#define NPT_CONFIG_HAVE_STRNCMP
+#define NPT_CONFIG_HAVE_STRDUP
+#define NPT_CONFIG_HAVE_STRLEN
+#define NPT_CONFIG_HAVE_STRCPY
+#define NPT_CONFIG_HAVE_STRNCPY
+#endif /* NPT_CONFIG_HAVE_STRING_H */
+
+#if defined(NPT_CONFIG_HAVE_STDIO_H)
+#define NPT_CONFIG_HAVE_SPRINTF
+#define NPT_CONFIG_HAVE_SNPRINTF
+#define NPT_CONFIG_HAVE_VSPRINTF
+#define NPT_CONFIG_HAVE_VSNPRINTF
+#endif /* NPT_CONFIG_HAVE_STDIO_H */
+
+#if defined(NPT_CONFIG_HAVE_LIMITS_H)
+#define NPT_CONFIG_HAVE_INT_MIN
+#define NPT_CONFIG_HAVE_INT_MAX
+#define NPT_CONFIG_HAVE_UINT_MAX
+#define NPT_CONFIG_HAVE_LONG_MIN
+#define NPT_CONFIG_HAVE_LONG_MAX
+#define NPT_CONFIG_HAVE_ULONG_MAX
+#endif
+
+/*----------------------------------------------------------------------
+|   standard C++ runtime
++---------------------------------------------------------------------*/
+#define NPT_CONFIG_HAVE_NEW_H
+
+/*----------------------------------------------------------------------
+|   sockets
++---------------------------------------------------------------------*/
+#define NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+
+/*----------------------------------------------------------------------
+|   platform specifics
++---------------------------------------------------------------------*/
+/* Windows 32 */
+#if defined(_WIN32) || defined(_XBOX)
+#if !defined(STRICT)
+#define STRICT
+#endif
+
+/* Visual Studio 2008 defines vsnprintf */
+#if _MSC_VER < 1500
+#define vsnprintf _vsnprintf
+#endif
+#define snprintf  _snprintf
+#endif
+
+/* XBox */
+#if defined(_XBOX)
+#define NPT_CONFIG_THREAD_STACK_SIZE 0x10000
+#endif
+
+/* QNX */
+#if defined(__QNX__)
+#endif
+
+/* cygwin */
+#if defined(__CYGWIN__)
+#undef NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+#endif
+
+/* linux */
+#if defined(__linux__)
+#undef NPT_CONFIG_HAVE_SOCKADDR_SA_LEN
+#endif
+
+/* symbian */
+#if defined(__SYMBIAN32__)
+/* If defined, specify the stack size of each NPT_Thread. */
+#define NPT_CONFIG_THREAD_STACK_SIZE   0x14000
+#endif
+
+/*----------------------------------------------------------------------
+|   compiler specifics
++---------------------------------------------------------------------*/
+/* GCC */
+#if defined(__GNUC__)
+#define NPT_LocalFunctionName __FUNCTION__
+#define NPT_COMPILER_UNUSED(p) (void)p
+#else
+#define NPT_COMPILER_UNUSED(p) 
+#endif
+
+/* TriMedia C/C++ Compiler */
+#if defined(__TCS__)
+#undef NPT_CONFIG_HAVE_ASSERT_H
+#undef NPT_CONFIG_HAVE_SNPRINTF
+#undef NPT_CONFIG_HAVE_VSNPRINTF
+#endif
+
+/* palmos compiler */
+#if defined(__PALMOS__)
+#if __PALMOS__ <= 0x05000000
+#undef NPT_CONFIG_HAVE_ASSERT_H
+#undef NPT_CONFIG_HAVE_SNPRINTF
+#undef NPT_CONFIG_HAVE_VSNPRINTF
+#endif
+#endif
+
+/* Microsoft C/C++ Compiler */
+#if defined(_MSC_VER)
+#define NPT_FORMAT_64 "I64"
+#define NPT_CONFIG_INT64_TYPE __int64
+#define NPT_INT64_MIN _I64_MIN
+#define NPT_INT64_MAX _I64_MAX
+#define NPT_UINT64_MAX _UI64_MAX
+#define NPT_INT64_C(_x) _x##i64
+#define NPT_UINT64_C(_x) _x##ui64
+#define NPT_LocalFunctionName __FUNCTION__
+#if !defined(_WIN32_WCE)
+#define NPT_fseek _fseeki64
+#define NPT_ftell _ftelli64
+#else
+#define NPT_fseek(a,b,c) fseek((a),(long)(b), (c))
+#define NPT_ftell ftell
+#endif
+#define NPT_stat  NPT_stat_utf8
+#define NPT_stat_struct struct __stat64
+#if defined(_WIN64)
+typedef __int64 NPT_PointerLong;
+#else
+#if _MSC_VER >= 1400
+typedef __w64 long NPT_PointerLong;
+#else
+typedef long NPT_PointerLong;
+#endif
+#endif
+#define NPT_POINTER_TO_LONG(_p) ((NPT_PointerLong) (_p) )
+#if _MSC_VER >= 1400 && !defined(_WIN32_WCE)
+#define NPT_CONFIG_HAVE_FOPEN_S
+#define NPT_CONFIG_HAVE_FSOPEN
+#define NPT_CONFIG_HAVE_SHARE_H
+#define NPT_vsnprintf(s,c,f,a)  _vsnprintf_s(s,c,_TRUNCATE,f,a)
+#define NPT_snprintf(s,c,f,...) _snprintf_s(s,c,_TRUNCATE,f,__VA_ARGS__)
+#define NPT_strncpy(d,s,c)       strncpy_s(d,c+1,s,c)
+#define NPT_strcpy(d,s)          strcpy_s(d,strlen(s)+1,s)
+#undef NPT_CONFIG_HAVE_GETENV
+#define NPT_CONFIG_HAVE_DUPENV_S
+#define dupenv_s _dupenv_s
+#else
+#define NPT_vsnprintf  _vsnprintf
+#define NPT_snprintf   _snprintf
+#endif
+#if defined(_DEBUG)
+#define _CRTDBG_MAP_ALLOC
+#endif
+#endif
+
+/* Windows CE */
+#if defined(_WIN32_WCE)
+#if defined(NPT_CONFIG_HAVE_FOPEN_S)
+#undef NPT_CONFIG_HAVE_FOPEN_S
+#endif
+#endif
+
+/* Symbian */
+#if defined(__SYMBIAN32__)
+#undef NPT_CONFIG_HAVE_NEW_H
+#include "e32std.h"
+#define explicit
+#define NPT_fseek fseek  // no fseeko ?
+#define NPT_ftell ftell  // no ftello ?
+#endif
+
+/*----------------------------------------------------------------------
+|   defaults
++---------------------------------------------------------------------*/
+#if !defined(NPT_FORMAT_64)
+#define NPT_FORMAT_64 "ll"
+#endif
+
+#if !defined(NPT_POINTER_TO_LONG)
+#define NPT_POINTER_TO_LONG(_p) ((long)(_p))
+#endif
+
+#if !defined(NPT_CONFIG_INT64_TYPE)
+#define NPT_CONFIG_INT64_TYPE long long
+#endif
+
+#if !defined(NPT_INT64_C)
+#define NPT_INT64_C(_x) _x##LL
+#endif
+
+#if !defined(NPT_UINT64_C)
+#define NPT_UINT64_C(_x) _x##ULL
+#endif
+
+#if !defined(NPT_snprintf)
+#define NPT_snprintf snprintf
+#endif
+
+#if !defined(NPT_strcpy)
+#define NPT_strcpy strcpy
+#endif
+
+#if !defined(NPT_strncpy)
+#define NPT_strncpy strncpy
+#endif
+
+#if !defined(NPT_vsnprintf)
+#define NPT_vsnprintf vsnprintf
+#endif
+
+#if !defined(NPT_LocalFunctionName)
+#define NPT_LocalFunctionName (NULL)
+#endif
+
+#if !defined(NPT_CONFIG_THREAD_STACK_SIZE)
+#define NPT_CONFIG_THREAD_STACK_SIZE 0
+#endif
+
+#if !defined(NPT_fseek)
+#define NPT_fseek fseeko
+#endif
+
+#if !defined(NPT_ftell)
+#define NPT_ftell ftello
+#endif
+
+#if !defined(NPT_stat)
+#define NPT_stat stat
+#endif
+
+#if !defined(NPT_stat_struct)
+#define NPT_stat_struct struct stat
+#endif
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#if defined(DMALLOC)
+#include <dmalloc.h>
+#endif
+
+#endif // _NPT_CONFIG_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptConsole.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,67 @@
+/*****************************************************************
+|
+|   Neptune - Console
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+#if defined(NPT_CONFIG_HAVE_STDARG_H)
+#include <stdarg.h>
+#endif
+
+#include "NptConfig.h"
+#include "NptConsole.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   NPT_ConsoleOutputFunction
++---------------------------------------------------------------------*/
+static void
+NPT_ConsoleOutputFunction(void*, const char* message)
+{
+    NPT_Console::Output(message);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ConsoleOutputF
++---------------------------------------------------------------------*/
+void 
+NPT_Console::OutputF(const char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    
+    NPT_FormatOutput(NPT_ConsoleOutputFunction, NULL, format, args);
+
+    va_end(args);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptConsole.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,55 @@
+/*****************************************************************
+|
+|   Neptune - Console
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+/** @file
+* Header file for console support
+*/
+
+#ifndef _NPT_CONSOLE_H_
+#define _NPT_CONSOLE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   prototypes
++---------------------------------------------------------------------*/
+class NPT_Console {
+public:
+    // class methods
+    static void Output(const char* message);
+    static void OutputF(const char* format, ...);
+};
+
+
+#endif /* _NPT_CONSOLE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptConstants.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,44 @@
+/*****************************************************************
+|
+|   Neptune - Constants
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_CONSTANTS_H_
+#define _NPT_CONSTANTS_H_
+
+/*----------------------------------------------------------------------
+|   constants       
++---------------------------------------------------------------------*/
+#ifndef NULL
+#define NULL 0
+#endif
+
+const int NPT_TIMEOUT_INFINITE = -1;
+
+#endif // _NPT_CONSTANTS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptDataBuffer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,256 @@
+/*****************************************************************
+|
+|   Neptune - Data Buffer
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptDataBuffer.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer() :
+    m_BufferIsLocal(true),
+    m_Buffer(NULL),
+    m_BufferSize(0),
+    m_DataSize(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer(NPT_Size bufferSize) :
+    m_BufferIsLocal(true),
+    m_Buffer(bufferSize?new NPT_Byte[bufferSize]:NULL),
+    m_BufferSize(bufferSize),
+    m_DataSize(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer(const void* data, NPT_Size data_size, bool copy) :
+    m_BufferIsLocal(copy),
+    m_Buffer(copy?(data_size?new NPT_Byte[data_size]:NULL):reinterpret_cast<NPT_Byte*>(const_cast<void*>(data))),
+    m_BufferSize(data_size),
+    m_DataSize(data_size)
+{
+    if (copy && data_size) NPT_CopyMemory(m_Buffer, data, data_size);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::NPT_DataBuffer(const NPT_DataBuffer& other) :
+    m_BufferIsLocal(true),
+    m_Buffer(NULL),
+    m_BufferSize(other.m_DataSize),
+    m_DataSize(other.m_DataSize)
+{
+    if (m_BufferSize) {
+        m_Buffer = new NPT_Byte[m_BufferSize];
+        NPT_CopyMemory(m_Buffer, other.m_Buffer, m_BufferSize);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::~NPT_DataBuffer
++---------------------------------------------------------------------*/
+NPT_DataBuffer::~NPT_DataBuffer()
+{
+    Clear();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::Clear
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::Clear()
+{
+    if (m_BufferIsLocal) {
+        delete[] m_Buffer;
+    }
+    m_Buffer = NULL;
+    m_DataSize = 0;
+    m_BufferSize = 0;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::operator=
++---------------------------------------------------------------------*/
+NPT_DataBuffer&
+NPT_DataBuffer::operator=(const NPT_DataBuffer& copy)
+{
+    // do nothing if we're assigning to ourselves
+    if (this != &copy) {
+        Clear();
+
+        m_BufferIsLocal = true;
+        m_BufferSize    = copy.m_BufferSize;
+        m_DataSize      = copy.m_DataSize;
+
+        if (m_BufferSize) {
+            m_Buffer = new NPT_Byte[m_BufferSize];
+            NPT_CopyMemory(m_Buffer, copy.m_Buffer, m_BufferSize);
+        }
+    }
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::operator==
++---------------------------------------------------------------------*/
+bool
+NPT_DataBuffer::operator==(const NPT_DataBuffer& other) const
+{
+    // check that the sizes match
+    if (m_DataSize != other.m_DataSize) return false;
+
+    return NPT_MemoryEqual(m_Buffer,
+                           other.m_Buffer,
+                           m_DataSize);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::SetBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetBuffer(NPT_Byte* buffer, NPT_Size buffer_size)
+{
+    Clear();
+
+    // we're now using an external buffer
+    m_BufferIsLocal = false;
+    m_Buffer = buffer;
+    m_BufferSize = buffer_size;
+    m_DataSize = 0;
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::SetBufferSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetBufferSize(NPT_Size buffer_size)
+{
+    if (m_BufferIsLocal) {
+        return ReallocateBuffer(buffer_size);
+    } else {
+        return NPT_ERROR_NOT_SUPPORTED; // you cannot change the
+                                        // buffer management mode
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::Reserve
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::Reserve(NPT_Size size)
+{
+    if (size <= m_BufferSize) return NPT_SUCCESS;
+
+    // try doubling the buffer to accomodate for the new size
+    NPT_Size new_size = m_BufferSize*2;
+    if (new_size < size) new_size = size;
+    return SetBufferSize(new_size);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::SetDataSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetDataSize(NPT_Size size)
+{
+    if (size > m_BufferSize) {
+        // the buffer is too small, we need to reallocate it
+        if (m_BufferIsLocal) {
+            NPT_CHECK(ReallocateBuffer(size));
+        } else { 
+            // we cannot reallocate an external buffer
+            return NPT_ERROR_NOT_SUPPORTED;
+        }
+    }
+    m_DataSize = size;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::SetData
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::SetData(const NPT_Byte* data, NPT_Size size)
+{
+    if (size > m_BufferSize) {
+        if (m_BufferIsLocal) {
+            NPT_CHECK(ReallocateBuffer(size));
+        } else {
+            return NPT_ERROR_INVALID_STATE;
+        }
+    }
+    if (data) NPT_CopyMemory(m_Buffer, data, size);
+    m_DataSize = size;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer::ReallocateBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_DataBuffer::ReallocateBuffer(NPT_Size size)
+{
+    // check that the existing data fits
+    if (m_DataSize > size) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // allocate a new buffer
+    NPT_Byte* newBuffer = new NPT_Byte[size];
+
+    // copy the contents of the previous buffer, if any
+    if (m_Buffer && m_DataSize) {
+        NPT_CopyMemory(newBuffer, m_Buffer, m_DataSize);
+    }
+
+    // destroy the previous buffer
+    delete[] m_Buffer;
+
+    // use the new buffer
+    m_Buffer = newBuffer;
+    m_BufferSize = size;
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptDataBuffer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+|   Neptune - Datagram Packets
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DATA_BUFFER_H_
+#define _NPT_DATA_BUFFER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|   NPT_DataBuffer
++---------------------------------------------------------------------*/
+class NPT_DataBuffer 
+{
+ public:
+    // constructors & destructor
+    NPT_DataBuffer();              // size unknown until first set 
+    NPT_DataBuffer(NPT_Size size); // initial size specified
+    NPT_DataBuffer(const void* data, NPT_Size size, bool copy = true); // initial data and size specified
+    NPT_DataBuffer(const NPT_DataBuffer& other);
+    virtual ~NPT_DataBuffer();
+
+    // operators
+    NPT_DataBuffer& operator=(const NPT_DataBuffer& copy);
+    bool            operator==(const NPT_DataBuffer& other) const;
+
+    // data buffer handling methods
+    virtual NPT_Result SetBuffer(NPT_Byte* buffer, NPT_Size bufferSize);
+    virtual NPT_Result SetBufferSize(NPT_Size bufferSize);
+    virtual NPT_Size   GetBufferSize() const { return m_BufferSize; }
+    virtual NPT_Result Reserve(NPT_Size size);
+    virtual NPT_Result Clear();
+
+    // data handling methods
+    virtual const NPT_Byte* GetData() const { return m_Buffer; }
+    virtual NPT_Byte*       UseData() { return m_Buffer; };
+    virtual NPT_Size        GetDataSize() const { return m_DataSize; }
+    virtual NPT_Result      SetDataSize(NPT_Size size);
+    virtual NPT_Result      SetData(const NPT_Byte* data, NPT_Size dataSize);
+
+ protected:
+    // members
+    bool      m_BufferIsLocal;
+    NPT_Byte* m_Buffer;
+    NPT_Size  m_BufferSize;
+    NPT_Size  m_DataSize;
+
+    // methods
+    NPT_Result ReallocateBuffer(NPT_Size size);
+};
+
+#endif // _NPT_DATA_BUFFER_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptDebug.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,31 @@
+/*****************************************************************
+|
+|   Neptune - Debug Utilities
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptDebug.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,55 @@
+/*****************************************************************
+|
+|   Neptune - Debug Utilities
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DEBUG_H_
+#define _NPT_DEBUG_H_
+
+/*----------------------------------------------------------------------
+|    includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+/*----------------------------------------------------------------------
+|    standard macros
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_HAVE_ASSERT_H) && defined(NPT_DEBUG)
+#include <assert.h>
+#define NPT_ASSERT(x) assert(x)
+#else
+#define NPT_ASSERT(x) ((void)0)
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_Debug
++---------------------------------------------------------------------*/
+extern void NPT_Debug(const char* format, ...);
+
+#endif // _NPT_DEBUG_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptDynamicLibraries.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,36 @@
+/*****************************************************************
+|
+|   Neptune - Dynamic Libraries
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptDynamicLibraries.h"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptDynamicLibraries.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,84 @@
+/*****************************************************************
+|
+|   Neptune - Dynamic Libraries
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_DYNAMIC_LIBRARIES_H_
+#define _NPT_DYNAMIC_LIBRARIES_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define NPT_DYANMIC_LIBRARY_LOAD_FLAG_NOW 1
+
+/*----------------------------------------------------------------------
+|   NPT_DynamicLibraryInterface
++---------------------------------------------------------------------*/
+class NPT_DynamicLibraryInterface
+{
+public:
+    virtual ~NPT_DynamicLibraryInterface() {}
+    virtual NPT_Result FindSymbol(const char* name, void*& symbol) = 0;
+    virtual NPT_Result Unload() = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_DynamicLibrary
++---------------------------------------------------------------------*/
+class NPT_DynamicLibrary : public NPT_DynamicLibraryInterface
+{
+public:
+    // class methods
+    static NPT_Result Load(const char* name, NPT_Flags flags, NPT_DynamicLibrary*& library);
+    
+    // destructor
+    ~NPT_DynamicLibrary() { delete m_Delegate; }
+    
+    // NPT_DynamicLibraryInterface methods
+    virtual NPT_Result FindSymbol(const char* name, void*& symbol) {
+        return m_Delegate->FindSymbol(name, symbol);
+    }
+    virtual NPT_Result Unload() {
+        return m_Delegate->Unload();
+    }
+    
+private:
+    // methods
+    NPT_DynamicLibrary(NPT_DynamicLibraryInterface* delegate) : m_Delegate(delegate) {}
+    
+    // members
+    NPT_DynamicLibraryInterface* m_Delegate;
+};
+
+#endif // _NPT_DYNAMIC_LIBRARIES_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptFile.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,335 @@
+/*****************************************************************
+|
+|   Neptune - Files
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptFile.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+#include "NptStreams.h"
+#include "NptDataBuffer.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.file")
+
+/*----------------------------------------------------------------------
+|   NPT_FilePath::BaseName
++---------------------------------------------------------------------*/
+NPT_String 
+NPT_FilePath::BaseName(const char* path, bool with_extension /* = true */)
+{
+    NPT_String result = path;
+    int separator = result.ReverseFind(Separator);
+    if (separator >= 0) {
+        result = path+separator+NPT_StringLength(Separator);
+    } 
+
+    if (!with_extension) {
+        separator = result.ReverseFind('.');
+        if (separator >= 0) {
+            result.SetLength(separator);
+        }
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_FilePath::DirectoryName
++---------------------------------------------------------------------*/
+NPT_String 
+NPT_FilePath::DirectoryName(const char* path)
+{
+    NPT_String result = path;
+    int separator = result.ReverseFind(Separator);
+    if (separator >= 0) {
+        if (separator == 0) {
+            result.SetLength(NPT_StringLength(Separator));
+        } else {
+            result.SetLength(separator);
+        }
+    } else {
+        result.SetLength(0);
+    } 
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_FilePath::FileExtension
++---------------------------------------------------------------------*/
+NPT_String 
+NPT_FilePath::FileExtension(const char* path)
+{
+    NPT_String result = path;
+    int separator = result.ReverseFind('.');
+    if (separator >= 0) {
+        result = path+separator;
+    } else {
+        result.SetLength(0);
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_FilePath::Create
++---------------------------------------------------------------------*/
+NPT_String 
+NPT_FilePath::Create(const char* directory, const char* base)
+{
+    if (!directory || NPT_StringLength(directory) == 0) return base;
+
+    NPT_String result = directory;
+    result.TrimRight(Separator);
+    NPT_String _base = base;
+    _base.TrimLeft(Separator);
+    
+    return result + Separator + _base;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetCount
++---------------------------------------------------------------------*/
+NPT_Result        
+NPT_File::GetCount(const char* path, NPT_Cardinal& count)
+{
+    NPT_File file(path);
+    return file.GetCount(count);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Load(const char* path, NPT_DataBuffer& buffer, NPT_FileInterface::OpenMode mode)
+{
+    // create and open the file
+    NPT_File file(path);
+    NPT_Result result = file.Open(mode);
+    if (NPT_FAILED(result)) return result;
+    
+    // load the file
+    result = file.Load(buffer);
+
+    // close the file
+    file.Close();
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Load(const char* path, NPT_String& data, NPT_FileInterface::OpenMode mode)
+{
+    NPT_DataBuffer buffer;
+
+    // reset ouput params
+    data = "";
+
+    // create and open the file
+    NPT_File file(path);
+    NPT_Result result = file.Open(mode);
+    if (NPT_FAILED(result)) return result;
+    
+    // load the file
+    result = file.Load(buffer);
+
+    if (NPT_SUCCEEDED(result) && buffer.GetDataSize() > 0) {
+        data.Assign((const char*)buffer.GetData(), buffer.GetDataSize());
+        data.SetLength(buffer.GetDataSize());
+    }
+
+    // close the file
+    file.Close();
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Save
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Save(const char* filename, NPT_String& data)
+{
+    NPT_DataBuffer buffer(data.GetChars(), data.GetLength());
+    return NPT_File::Save(filename, buffer);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Save
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Save(const char* filename, const NPT_DataBuffer& buffer)
+{
+    // create and open the file
+    NPT_File file(filename);
+    NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_WRITE | NPT_FILE_OPEN_MODE_CREATE | NPT_FILE_OPEN_MODE_TRUNCATE);
+    if (NPT_FAILED(result)) return result;
+
+    // load the file
+    result = file.Save(buffer);
+
+    // close the file
+    file.Close();
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Load(NPT_DataBuffer& buffer)
+{
+    NPT_InputStreamReference input;
+
+    // get the input stream for the file
+    NPT_CHECK_WARNING(GetInputStream(input));
+
+    // read the stream
+    return input->Load(buffer);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Save
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Save(const NPT_DataBuffer& buffer)
+{
+    NPT_OutputStreamReference output;
+
+    // get the output stream for the file
+    NPT_CHECK_FATAL(GetOutputStream(output));
+
+    // write to the stream
+    return output->WriteFully(buffer.GetData(), buffer.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetInfo(NPT_FileInfo& info)
+{
+    NPT_Result result = NPT_SUCCESS;
+    
+    // get the file info if we don't already have it
+    if (m_Info.m_Type == NPT_FileInfo::FILE_TYPE_NONE) {
+        result = GetInfo(m_Path.GetChars(), &m_Info);
+    }
+    
+    info = m_Info;
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetSize
++---------------------------------------------------------------------*/
+/*NPT_Result
+NPT_File::GetSize(NPT_LargeSize& size)
+{
+    // default value
+    size = 0;
+    
+    // get the size from the info (call GetInfo() in case it has not
+    // yet been called)
+    NPT_FileInfo info;
+    NPT_CHECK_FATAL(GetInfo(info));
+    size = info.m_Size;
+    
+    return NPT_SUCCESS;
+}*/
+
+/*----------------------------------------------------------------------
+|   NPT_File::Delete
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_File::Delete(const char* path)
+{
+    NPT_FileInfo info;
+
+    // make sure the path exists
+    NPT_CHECK(GetInfo(path, &info));
+
+    if (info.m_Type == NPT_FileInfo::FILE_TYPE_DIRECTORY) {
+        return DeleteDirectory(path);
+    } else {
+        return DeleteFile(path);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Rename
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Rename(const char* path)
+{
+    NPT_Result result = Rename(m_Path.GetChars(), path);
+    if (NPT_SUCCEEDED(result)) {
+        m_Path = path;
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::ListDirectory
++---------------------------------------------------------------------*/
+NPT_Result        
+NPT_File::ListDirectory(NPT_List<NPT_String>& entries)
+{
+    entries.Clear();
+    return ListDirectory(m_Path.GetChars(), entries);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetCount
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetCount(NPT_Cardinal& count)
+{
+    // reset output params
+    count = 0;
+
+    NPT_List<NPT_String> entries;
+    NPT_CHECK(ListDirectory(entries));
+    
+    count = entries.GetItemCount();
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptFile.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,201 @@
+/*****************************************************************
+|
+|   Neptune - Files
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_FILE_H_
+#define _NPT_FILE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_NO_SUCH_FILE          = NPT_ERROR_BASE_FILE - 0;
+const int NPT_ERROR_FILE_NOT_OPEN         = NPT_ERROR_BASE_FILE - 1;
+const int NPT_ERROR_FILE_BUSY             = NPT_ERROR_BASE_FILE - 2;
+const int NPT_ERROR_FILE_ALREADY_OPEN     = NPT_ERROR_BASE_FILE - 3;
+const int NPT_ERROR_FILE_NOT_READABLE     = NPT_ERROR_BASE_FILE - 4;
+const int NPT_ERROR_FILE_NOT_WRITABLE     = NPT_ERROR_BASE_FILE - 5;
+const int NPT_ERROR_FILE_NOT_DIRECTORY    = NPT_ERROR_BASE_FILE - 6;
+const int NPT_ERROR_FILE_ALREADY_EXISTS   = NPT_ERROR_BASE_FILE - 7;
+const int NPT_ERROR_FILE_NOT_ENOUGH_SPACE = NPT_ERROR_BASE_FILE - 8;
+const int NPT_ERROR_DIRECTORY_NOT_EMPTY   = NPT_ERROR_BASE_FILE - 9;
+
+const unsigned int NPT_FILE_OPEN_MODE_READ       = 0x01;
+const unsigned int NPT_FILE_OPEN_MODE_WRITE      = 0x02;
+const unsigned int NPT_FILE_OPEN_MODE_CREATE     = 0x04;
+const unsigned int NPT_FILE_OPEN_MODE_TRUNCATE   = 0x08;
+const unsigned int NPT_FILE_OPEN_MODE_UNBUFFERED = 0x10;
+const unsigned int NPT_FILE_OPEN_MODE_APPEND     = 0x20;
+
+const unsigned int NPT_FILE_ATTRIBUTE_READ_ONLY = 0x01;
+const unsigned int NPT_FILE_ATTRIBUTE_LINK      = 0x02;
+
+#define NPT_FILE_STANDARD_INPUT  "@STDIN"
+#define NPT_FILE_STANDARD_OUTPUT "@STDOUT"
+#define NPT_FILE_STANDARD_ERROR  "@STDERR"
+
+/*----------------------------------------------------------------------
+|   class references
++---------------------------------------------------------------------*/
+class NPT_DataBuffer;
+
+/*----------------------------------------------------------------------
+|   NPT_FileInfo
++---------------------------------------------------------------------*/
+struct NPT_FileInfo
+{
+    // types
+    typedef enum {
+        FILE_TYPE_NONE,
+        FILE_TYPE_REGULAR,
+        FILE_TYPE_DIRECTORY,
+        FILE_TYPE_SPECIAL,
+        FILE_TYPE_OTHER
+    } FileType;
+    
+    // constructor
+    NPT_FileInfo() : m_Type(FILE_TYPE_NONE), m_Size(0), m_AttributesMask(0), m_Attributes(0) {}
+    
+    // members
+    FileType   m_Type;
+    NPT_UInt64 m_Size;
+    NPT_Flags  m_AttributesMask;
+    NPT_Flags  m_Attributes;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_FilePath
++---------------------------------------------------------------------*/
+class NPT_FilePath
+{
+public:
+    // class members
+    static const NPT_String Separator;
+
+    // class methods
+    static NPT_String BaseName(const char* path, bool with_extension = true);
+    static NPT_String DirectoryName(const char* path);
+    static NPT_String FileExtension(const char* path);
+    static NPT_String Create(const char* directory, const char* base);
+    
+private:
+    NPT_FilePath() {} // this class can't have instances
+};
+
+/*----------------------------------------------------------------------
+|   NPT_FileInterface
++---------------------------------------------------------------------*/
+class NPT_FileInterface
+{
+public:
+    // types
+    typedef unsigned int OpenMode;
+
+    // constructors and destructor
+    virtual ~NPT_FileInterface() {}
+
+    // methods
+    virtual NPT_Result Open(OpenMode mode) = 0;
+    virtual NPT_Result Close() = 0;
+    virtual NPT_Result GetSize(NPT_LargeSize& size) = 0;
+    virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream) = 0;
+    virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_File
++---------------------------------------------------------------------*/
+class NPT_File : public NPT_FileInterface
+{
+public:
+    // class methods
+    static NPT_Result GetRoots(NPT_List<NPT_String>& roots);
+    static NPT_Result GetInfo(const char* path, NPT_FileInfo* info = NULL);
+    static NPT_Result GetCount(const char* path, NPT_Cardinal& count);
+    static bool       Exists(const char* path) { return NPT_SUCCEEDED(GetInfo(path)); }
+    static NPT_Result Delete(const char* path);
+    static NPT_Result DeleteFile(const char* path);
+    static NPT_Result DeleteDirectory(const char* path);
+    static NPT_Result Rename(const char* from_path, const char* to_path);
+    static NPT_Result ListDirectory(const char* path, NPT_List<NPT_String>& entries, NPT_Ordinal start = 0, NPT_Cardinal count = 0);
+    static NPT_Result CreateDirectory(const char* path);
+    static NPT_Result GetWorkingDirectory(NPT_String& path);
+    static NPT_Result Load(const char* path, NPT_DataBuffer& buffer, NPT_FileInterface::OpenMode mode = NPT_FILE_OPEN_MODE_READ);
+    static NPT_Result Load(const char* path, NPT_String& data, NPT_FileInterface::OpenMode mode = NPT_FILE_OPEN_MODE_READ);
+    static NPT_Result Save(const char* path, NPT_String& data);
+    static NPT_Result Save(const char* path, const NPT_DataBuffer& buffer);
+
+    // constructors and destructor
+    NPT_File(const char* path);
+   ~NPT_File() { delete m_Delegate; }
+
+    // methods
+    NPT_Result          Load(NPT_DataBuffer& buffer);
+    NPT_Result          Save(const NPT_DataBuffer& buffer);
+    const NPT_String&   GetPath() { return m_Path; }
+    //NPT_Result          GetSize(NPT_LargeSize &size);
+    NPT_Result          GetInfo(NPT_FileInfo& info);
+    NPT_Result          ListDirectory(NPT_List<NPT_String>& entries);
+    NPT_Result          Rename(const char* path);
+    NPT_Result          GetCount(NPT_Cardinal& count);
+    
+    // NPT_FileInterface methods
+    NPT_Result Open(OpenMode mode) {
+        return m_Delegate->Open(mode);
+    }
+    NPT_Result Close() {
+        return m_Delegate->Close();
+    }
+    NPT_Result GetSize(NPT_LargeSize& size) {
+        return m_Delegate->GetSize(size);
+    }
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream) {
+        return m_Delegate->GetInputStream(stream);
+    }
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) {
+        return m_Delegate->GetOutputStream(stream);
+    }
+
+    // operators
+    NPT_File& operator=(const NPT_File& file);
+
+protected:
+    // members
+    NPT_FileInterface* m_Delegate;
+    NPT_String         m_Path;
+    NPT_FileInfo       m_Info;
+};
+
+#endif // _NPT_FILE_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptHttp.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1789 @@
+/*****************************************************************
+|
+|   Neptune - HTTP Protocol
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptHttp.h"
+#include "NptSockets.h"
+#include "NptBufferedStreams.h"
+#include "NptDebug.h"
+#include "NptVersion.h"
+#include "NptUtils.h"
+#include "NptFile.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.http")
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+NPT_String NPT_HttpClient::m_UserAgentHeader = "Neptune/" NPT_NEPTUNE_VERSION_STRING;
+NPT_String NPT_HttpServer::m_ServerHeader    = "Neptune/" NPT_NEPTUNE_VERSION_STRING;
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_HTTP_MAX_REDIRECTS = 20;
+
+/*----------------------------------------------------------------------
+|   NPT_HttpUrl::NPT_HttpUrl
++---------------------------------------------------------------------*/
+NPT_HttpUrl::NPT_HttpUrl(const char* url, bool ignore_scheme) :
+    NPT_Url(url, ignore_scheme?SCHEME_ID_UNKNOWN:SCHEME_ID_HTTP, NPT_HTTP_DEFAULT_PORT)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpUrl::NPT_HttpUrl
++---------------------------------------------------------------------*/
+NPT_HttpUrl::NPT_HttpUrl(const char* host, 
+                         NPT_UInt16  port, 
+                         const char* path,
+                         const char* query,
+                         const char* fragment) :
+    NPT_Url("http", host, port, path, query, fragment)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpUrl::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_HttpUrl::ToString(bool with_fragment) const
+{
+    return NPT_Url::ToStringWithDefaultPort(NPT_HTTP_DEFAULT_PORT, with_fragment);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeader::NPT_HttpHeader
++---------------------------------------------------------------------*/
+NPT_HttpHeader::NPT_HttpHeader(const char* name, const char* value):
+    m_Name(name), 
+    m_Value(value)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeader::~NPT_HttpHeader
++---------------------------------------------------------------------*/
+NPT_HttpHeader::~NPT_HttpHeader()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeader::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeader::Emit(NPT_OutputStream& stream) const
+{
+    stream.WriteString(m_Name.ToUppercase());
+    stream.WriteFully(": ", 2);
+    stream.WriteString(m_Value);
+    stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeader::SetName
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpHeader::SetName(const char* name)
+{
+    m_Name = name;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeader::~NPT_HttpHeader
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpHeader::SetValue(const char* value)
+{
+    m_Value = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::NPT_HttpHeaders
++---------------------------------------------------------------------*/
+NPT_HttpHeaders::NPT_HttpHeaders()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::~NPT_HttpHeaders
++---------------------------------------------------------------------*/
+NPT_HttpHeaders::~NPT_HttpHeaders()
+{
+    m_Headers.Apply(NPT_ObjectDeleter<NPT_HttpHeader>());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::Parse
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpHeaders::Parse(NPT_BufferedInputStream& stream)
+{
+    NPT_String header_name;
+    NPT_String header_value;
+    bool       header_pending = false;
+    NPT_String line;
+
+    while (NPT_SUCCEEDED(stream.ReadLine(line, NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH))) {
+        if (line.GetLength() == 0) {
+            // empty line, end of headers
+            break;
+        }
+        if (header_pending && (line[0] == ' ' || line[0] == '\t')) {
+            // continuation (folded header)
+            header_value.Append(line.GetChars()+1, line.GetLength()-1);
+        } else {
+            // add the pending header to the list
+            if (header_pending) {
+                header_value.Trim();
+                AddHeader(header_name, header_value);
+                header_pending = false;
+                NPT_LOG_FINEST_2("NPT_HttpHeaders::Parse - %s: %s", 
+                                 header_name.GetChars(),
+                                 header_value.GetChars());
+            }
+
+            // find the colon separating the name and the value
+            int colon_index = line.Find(':');
+            if (colon_index < 1) {
+                // invalid syntax, ignore
+                continue;
+            }
+            header_name = line.Left(colon_index);
+
+            // the field value starts at the first non-whitespace
+            const char* value = line.GetChars()+colon_index+1;
+            while (*value == ' ' || *value == '\t') {
+                value++;
+            }
+            header_value = value;
+           
+            // the header is pending
+            header_pending = true;
+        }
+    }
+
+    // if we have a header pending, add it now
+    if (header_pending) {
+        header_value.Trim();
+        AddHeader(header_name, header_value);
+        header_pending = false;
+        NPT_LOG_FINEST_2("NPT_HttpHeaders::Parse - %s: %s", 
+                         header_name.GetChars(),
+                         header_value.GetChars());
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::Emit(NPT_OutputStream& stream) const
+{
+    // for each header in the list
+    NPT_List<NPT_HttpHeader*>::Iterator header = m_Headers.GetFirstItem();
+    while (header) {
+        // emit the header
+        NPT_CHECK_WARNING((*header)->Emit(stream));
+        ++header;
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::GetHeader
++---------------------------------------------------------------------*/
+NPT_HttpHeader*
+NPT_HttpHeaders::GetHeader(const char* name) const
+{
+    // check args
+    if (name == NULL) return NULL;
+
+    // find a matching header
+    NPT_List<NPT_HttpHeader*>::Iterator header = m_Headers.GetFirstItem();
+    while (header) {
+        if ((*header)->GetName().Compare(name, true) == 0) {
+            return *header;
+        }
+        ++header;
+    }
+
+    // not found
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::AddHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::AddHeader(const char* name, const char* value)
+{
+    return m_Headers.Add(new NPT_HttpHeader(name, value));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::SetHeader
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpHeaders::SetHeader(const char* name, const char* value, bool replace)
+{
+    NPT_HttpHeader* header = GetHeader(name);
+    if (header == NULL) {
+        return AddHeader(name, value);
+    } else if (replace) {
+        return header->SetValue(value);
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders::GetHeaderValue
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_HttpHeaders::GetHeaderValue(const char* name) const
+{
+    NPT_HttpHeader* header = GetHeader(name);
+    if (header == NULL) {
+        return NULL;
+    } else {
+        return &header->GetValue();
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::NPT_HttpEntity
++---------------------------------------------------------------------*/
+NPT_HttpEntity::NPT_HttpEntity() :
+    m_ContentLength(0),
+    m_HasContentLength(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::NPT_HttpEntity
++---------------------------------------------------------------------*/
+NPT_HttpEntity::NPT_HttpEntity(const NPT_HttpHeaders& headers) :
+    m_ContentLength(0),
+    m_HasContentLength(false)
+{
+    NPT_HttpHeader* header;
+    
+    // Content-Length
+    header = headers.GetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH);
+    if (header != NULL) {
+        m_HasContentLength = true;
+        NPT_LargeSize length;
+        if (NPT_SUCCEEDED(header->GetValue().ToInteger(length))) {
+            m_ContentLength = length;
+        } else {
+            m_ContentLength = 0;
+        }
+    }
+
+    // Content-Type
+    header = headers.GetHeader(NPT_HTTP_HEADER_CONTENT_TYPE);
+    if (header != NULL) {
+        m_ContentType = header->GetValue();
+    }
+
+    // Content-Encoding
+    header = headers.GetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING);
+    if (header != NULL) {
+        m_ContentEncoding = header->GetValue();
+    }
+
+    // Transfer-Encoding
+    header = headers.GetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING);
+    if (header != NULL) {
+        m_TransferEncoding = header->GetValue();
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::~NPT_HttpEntity
++---------------------------------------------------------------------*/
+NPT_HttpEntity::~NPT_HttpEntity()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::GetInputStream(NPT_InputStreamReference& stream)
+{
+    stream = m_InputStream;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetInputStream(const NPT_InputStreamReference& stream,
+                               bool update_content_length /* = false */)
+{
+    m_InputStream = stream;
+
+    // get the content length from the stream
+    if (update_content_length) {
+        m_HasContentLength = true;
+        m_ContentLength = 0;
+        if (!stream.IsNull()) {
+            if (NPT_FAILED(stream->GetSize(m_ContentLength))) {
+                m_ContentLength = 0;
+            }
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetInputStream(const void* data, NPT_Size data_size)
+{
+    NPT_MemoryStream* memory_stream = new NPT_MemoryStream(data, data_size);
+    NPT_InputStreamReference body(memory_stream);
+    return SetInputStream(body, true);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetInputStream(const char* string)
+{
+    if (string == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    NPT_MemoryStream* memory_stream = new NPT_MemoryStream((const void*)string, 
+                                                           NPT_StringLength(string));
+    NPT_InputStreamReference body(memory_stream);
+    return SetInputStream(body, true);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetInputStream(const NPT_String& string)
+{
+    NPT_MemoryStream* memory_stream = new NPT_MemoryStream((const void*)string.GetChars(), 
+                                                           string.GetLength());
+    NPT_InputStreamReference body(memory_stream);
+    return SetInputStream(body, true);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpEntity::Load(NPT_DataBuffer& buffer)
+{
+    // check that we have an input stream
+    if (m_InputStream.IsNull()) return NPT_ERROR_INVALID_STATE;
+
+    // load the stream into the buffer
+    if (m_ContentLength != (NPT_Size)m_ContentLength) return NPT_ERROR_OUT_OF_RANGE;
+    return m_InputStream->Load(buffer, (NPT_Size)m_ContentLength);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetContentLength
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetContentLength(NPT_LargeSize length)
+{
+    m_ContentLength = length;
+    m_HasContentLength = true;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetContentType
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetContentType(const char* type)
+{
+    m_ContentType = type;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity::SetContentEncoding
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpEntity::SetContentEncoding(const char* encoding)
+{
+    m_ContentEncoding = encoding;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage::NPT_HttpMessage
++---------------------------------------------------------------------*/
+NPT_HttpMessage::NPT_HttpMessage(const char* protocol) :
+    m_Protocol(protocol),
+    m_Entity(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage::NPT_HttpMessage
++---------------------------------------------------------------------*/
+NPT_HttpMessage::~NPT_HttpMessage()
+{
+    delete m_Entity;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage::SetEntity
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpMessage::SetEntity(NPT_HttpEntity* entity)
+{
+    delete m_Entity;
+    m_Entity = entity;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage::ParseHeaders
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpMessage::ParseHeaders(NPT_BufferedInputStream& stream)
+{
+    return m_Headers.Parse(stream);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::NPT_HttpRequest
++---------------------------------------------------------------------*/
+NPT_HttpRequest::NPT_HttpRequest(const NPT_HttpUrl& url, 
+                                 const char*        method, 
+                                 const char*        protocol) :
+    NPT_HttpMessage(protocol),
+    m_Url(url),
+    m_Method(method)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::NPT_HttpRequest
++---------------------------------------------------------------------*/
+NPT_HttpRequest::NPT_HttpRequest(const char* url, 
+                                 const char* method, 
+                                 const char* protocol) :
+    NPT_HttpMessage(protocol),
+    m_Url(url),
+    m_Method(method)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::SetUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::SetUrl(const char* url)
+{
+    m_Url = url;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::SetUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::SetUrl(const NPT_HttpUrl& url)
+{
+    m_Url = url;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::Parse(NPT_BufferedInputStream& stream, 
+                       const NPT_SocketAddress* endpoint,
+                       NPT_HttpRequest*&        request)
+{
+    // default return value
+    request = NULL;
+
+    // read the response line
+    NPT_String line;
+    NPT_CHECK_WARNING(stream.ReadLine(line, NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH));
+
+    // check the request line
+    int first_space = line.Find(' ');
+    if (first_space < 0) return NPT_ERROR_HTTP_INVALID_REQUEST_LINE;
+    int second_space = line.Find(' ', first_space+1);
+    if (second_space < 0) {
+        return NPT_ERROR_HTTP_INVALID_REQUEST_LINE;
+    }
+
+    // parse the request line
+    NPT_String method   = line.SubString(0, first_space);
+    NPT_String uri      = line.SubString(first_space+1, second_space-first_space-1);
+    NPT_String protocol = line.SubString(second_space+1);
+
+    // create a request
+    bool proxy_style_request = false;
+    if (uri.StartsWith("http://", true)) {
+        // proxy-style request with absolute URI
+        request = new NPT_HttpRequest(uri, method, protocol);
+        proxy_style_request = true;
+    } else {
+        // normal absolute path request
+        request = new NPT_HttpRequest("http:", method, protocol);
+    }
+
+    // parse headers
+    NPT_Result result = request->ParseHeaders(stream);
+    if (NPT_FAILED(result)) {
+        delete request;
+        request = NULL;
+        return result;
+    }
+
+    // update the URL
+    if (!proxy_style_request) {
+        request->m_Url.SetScheme("http");
+        request->m_Url.SetPathPlus(uri);
+        request->m_Url.SetPort(NPT_HTTP_DEFAULT_PORT);
+
+        // check for a Host: header
+        NPT_HttpHeader* host_header = request->GetHeaders().GetHeader(NPT_HTTP_HEADER_HOST);
+        if (host_header) {
+            request->m_Url.SetHost(host_header->GetValue());
+        } else {
+            // use the endpoint as the host
+            if (endpoint) {
+                request->m_Url.SetHost(endpoint->ToString());
+            } else {
+                // use defaults
+                request->m_Url.SetHost("localhost");
+            }
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::~NPT_HttpRequest
++---------------------------------------------------------------------*/
+NPT_HttpRequest::~NPT_HttpRequest()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpRequest::Emit(NPT_OutputStream& stream, bool use_proxy) const
+{
+    // write the request line
+    stream.WriteString(m_Method);
+    stream.WriteFully(" ", 1);
+    if (use_proxy) {
+        stream.WriteString(m_Url.ToString(false));
+    } else {
+        stream.WriteString(m_Url.ToRequestString());
+    }
+    stream.WriteFully(" ", 1);
+    stream.WriteString(m_Protocol);
+    stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+    // emit headers
+    m_Headers.Emit(stream);
+
+    // finish with an empty line
+    stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse::NPT_HttpResponse
++---------------------------------------------------------------------*/
+NPT_HttpResponse::NPT_HttpResponse(NPT_HttpStatusCode status_code,
+                                   const char*        reason_phrase,
+                                   const char*        protocol) :
+    NPT_HttpMessage(protocol),
+    m_StatusCode(status_code),
+    m_ReasonPhrase(reason_phrase)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse::~NPT_HttpResponse
++---------------------------------------------------------------------*/
+NPT_HttpResponse::~NPT_HttpResponse()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse::SetStatus
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::SetStatus(NPT_HttpStatusCode status_code,
+                            const char*        reason_phrase,
+                            const char*        protocol)
+{
+    m_Protocol = protocol;
+    m_StatusCode = status_code;
+    m_ReasonPhrase = reason_phrase;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse::Emit
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::Emit(NPT_OutputStream& stream) const
+{
+    // write the request line
+    stream.WriteString(m_Protocol);
+    stream.WriteFully(" ", 1);
+    stream.WriteString(NPT_String::FromInteger(m_StatusCode));
+    stream.WriteFully(" ", 1);
+    stream.WriteString(m_ReasonPhrase);
+    stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+    // emit headers
+    m_Headers.Emit(stream);
+
+    // finish with an empty line
+    stream.WriteFully(NPT_HTTP_LINE_TERMINATOR, 2);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponse::Parse(NPT_BufferedInputStream& stream, 
+                        NPT_HttpResponse*&       response)
+{
+    // default return value
+    response = NULL;
+
+    // read the response line
+    NPT_String line;
+    NPT_CHECK(stream.ReadLine(line, NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH));
+    
+    // check the response line
+    int first_space = line.Find(' ');
+    if (first_space < 0) return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+    int second_space = line.Find(' ', first_space+1);
+    if (second_space < 0 || second_space-first_space != 4) {
+        return NPT_ERROR_HTTP_INVALID_RESPONSE_LINE;
+    }
+
+    // parse the response line
+    NPT_String protocol = line.SubString(0, first_space);
+    NPT_String status_code = line.SubString(first_space+1, 3);
+    NPT_String reason_phrase = line.SubString(first_space+1+3+1, 
+                                              line.GetLength()-(first_space+1+3+1));
+
+    // create a response object
+    NPT_UInt32 status_code_int = 0;
+    status_code.ToInteger(status_code_int);
+    response = new NPT_HttpResponse(status_code_int, reason_phrase, protocol);
+
+    // parse headers
+    NPT_Result result = response->ParseHeaders(stream);
+    if (NPT_FAILED(result)) {
+        delete response;
+        response = NULL;
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpTcpConnector
++---------------------------------------------------------------------*/
+class NPT_HttpTcpConnector : public NPT_HttpClient::Connector
+{
+    virtual NPT_Result Connect(const char*                   hostname, 
+                               NPT_UInt16                    port, 
+                               NPT_Timeout                   connection_timeout,
+                               NPT_Timeout                   io_timeout,
+                               NPT_Timeout                   name_resolver_timeout,
+                               NPT_InputStreamReference&     input_stream, 
+                               NPT_OutputStreamReference&    output_stream);
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpTcpConnector::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpTcpConnector::Connect(const char*                hostname, 
+                              NPT_UInt16                 port, 
+                              NPT_Timeout                connection_timeout,
+                              NPT_Timeout                io_timeout,
+                              NPT_Timeout                name_resolver_timeout,
+                              NPT_InputStreamReference&  input_stream, 
+                              NPT_OutputStreamReference& output_stream)
+{
+    // get the address and port to which we need to connect
+    NPT_IpAddress address;
+    NPT_CHECK(address.ResolveName(hostname, name_resolver_timeout));
+
+    // connect to the server
+    NPT_LOG_FINE_2("will connect to %s:%d", hostname, port);
+    NPT_TcpClientSocket connection;
+    connection.SetReadTimeout(io_timeout);
+    connection.SetWriteTimeout(io_timeout);
+    NPT_SocketAddress socket_address(address, port);
+    NPT_CHECK(connection.Connect(socket_address, connection_timeout));
+
+    // get the streams
+    NPT_CHECK(connection.GetInputStream(input_stream));
+    NPT_CHECK(connection.GetOutputStream(output_stream));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpProxySelector::GetSystemDefault()
++---------------------------------------------------------------------*/
+//// temporary place holder implementation
+NPT_HttpProxySelector*
+NPT_HttpProxySelector::GetSystemDefault()
+{
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticProxySelector
++---------------------------------------------------------------------*/
+class NPT_HttpStaticProxySelector : public NPT_HttpProxySelector
+{
+public:
+    // constructor
+    NPT_HttpStaticProxySelector(const char* hostname, NPT_UInt16 port);
+
+    // NPT_HttpProxySelector methods
+    NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy);
+
+private:
+    // members
+    NPT_HttpProxyAddress m_Proxy;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticProxySelector::NPT_HttpStaticProxySelector
++---------------------------------------------------------------------*/
+NPT_HttpStaticProxySelector::NPT_HttpStaticProxySelector(const char* hostname, NPT_UInt16 port) :
+    m_Proxy(hostname, port)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticProxySelector::GetProxyForUrl
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpStaticProxySelector::GetProxyForUrl(const NPT_HttpUrl& /* url */, 
+                                            NPT_HttpProxyAddress& proxy)
+{
+    proxy = m_Proxy;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::NPT_HttpClient
++---------------------------------------------------------------------*/
+NPT_HttpClient::NPT_HttpClient(Connector* connector) :
+    m_ProxySelector(NPT_HttpProxySelector::GetSystemDefault()),
+    m_ProxySelectorIsOwned(false),
+    m_Connector(connector)
+{
+    m_Config.m_FollowRedirect      = true;
+    m_Config.m_ConnectionTimeout   = NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT;
+    m_Config.m_IoTimeout           = NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT;
+    m_Config.m_NameResolverTimeout = NPT_HTTP_CLIENT_DEFAULT_NAME_RESOLVER_TIMEOUT;
+
+    if (connector == NULL) m_Connector = new NPT_HttpTcpConnector();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::~NPT_HttpClient
++---------------------------------------------------------------------*/
+NPT_HttpClient::~NPT_HttpClient()
+{
+    if (m_ProxySelectorIsOwned) {
+        delete m_ProxySelector;
+    }
+    delete m_Connector;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SetConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetConfig(const Config& config)
+{
+    m_Config = config;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SetProxy
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetProxy(const char* hostname, NPT_UInt16 port)
+{
+    if (m_ProxySelectorIsOwned) {
+        delete m_ProxySelector;
+        m_ProxySelector = NULL;
+        m_ProxySelectorIsOwned = false;
+    }
+
+    // only set a proxy selector is hostname is not null, disable the
+    // proxy otherwise
+    if (hostname != NULL && port != NPT_HTTP_INVALID_PORT) {
+        m_ProxySelector = new NPT_HttpStaticProxySelector(hostname, port);
+        m_ProxySelectorIsOwned = true;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SetProxy
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpClient::SetProxySelector(NPT_HttpProxySelector* selector)
+{
+    if (m_ProxySelectorIsOwned) {
+        delete m_ProxySelector;
+    }
+    m_ProxySelector = selector;
+    m_ProxySelectorIsOwned = false;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SetConnector
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpClient::SetConnector(Connector* connector)
+{
+    delete m_Connector;
+    m_Connector = connector;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SetTimeouts
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SetTimeouts(NPT_Timeout connection_timeout, 
+                            NPT_Timeout io_timeout,
+                            NPT_Timeout name_resolver_timeout)
+{
+    m_Config.m_ConnectionTimeout   = connection_timeout;
+    m_Config.m_IoTimeout           = io_timeout;
+    m_Config.m_NameResolverTimeout = name_resolver_timeout;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SendRequestOnce
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SendRequestOnce(NPT_HttpRequest&   request, 
+                                NPT_HttpResponse*& response)
+{
+    // setup default values
+    response = NULL;
+
+    // get the address and port to which we need to connect
+    NPT_HttpProxyAddress proxy;
+    bool                 use_proxy = false;
+    if (m_ProxySelector) {
+        // we have a proxy selector, ask it to select a proxy for this URL
+        NPT_Result result = m_ProxySelector->GetProxyForUrl(request.GetUrl(), proxy);
+        if (NPT_FAILED(result) && result != NPT_ERROR_HTTP_NO_PROXY) {
+            NPT_LOG_WARNING_1("NPT_HttpClient::SendRequestOnce - proxy selector failure (%d)", result);
+            return result;
+        }
+        use_proxy = true;
+    }
+
+    // decide which host we need to connect to
+    const char* server_hostname;
+    NPT_UInt16  server_port;
+    if (use_proxy) {
+        // the proxy is set
+        server_hostname = (const char*)proxy.GetHostName();
+        server_port = proxy.GetPort();
+    } else {
+        // no proxy selector, so no proxy: connect directly
+        server_hostname = (const char*)request.GetUrl().GetHost();
+        server_port = request.GetUrl().GetPort();
+    }
+
+    // connect to the server or proxy
+    NPT_InputStreamReference  input_stream;
+    NPT_OutputStreamReference output_stream;
+    NPT_CHECK_WARNING(m_Connector->Connect(server_hostname,
+                                           server_port,
+                                           m_Config.m_ConnectionTimeout,
+                                           m_Config.m_IoTimeout,
+                                           m_Config.m_NameResolverTimeout,
+                                           input_stream,
+                                           output_stream));
+
+    // add any headers that may be missing
+    NPT_HttpHeaders& headers = request.GetHeaders();
+    headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close", false); // set but don't replace
+    headers.SetHeader(NPT_HTTP_HEADER_USER_AGENT, m_UserAgentHeader, false); // set but don't replace
+                      
+    NPT_String host = request.GetUrl().GetHost();
+    if (request.GetUrl().GetPort() != NPT_HTTP_DEFAULT_PORT) {
+        host += ":";
+        host += NPT_String::FromInteger(request.GetUrl().GetPort());
+    }
+    headers.SetHeader(NPT_HTTP_HEADER_HOST, host);
+
+    // get the request entity to set additional headers
+    NPT_InputStreamReference body_stream;
+    NPT_HttpEntity* entity = request.GetEntity();
+    if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
+        // content length (only set if valid)
+        if (entity->HasContentLength()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, 
+                NPT_String::FromInteger(entity->GetContentLength()));
+        }
+
+        // content type
+        NPT_String content_type = entity->GetContentType();
+        if (!content_type.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+        }
+
+        // content encoding
+        NPT_String content_encoding = entity->GetContentEncoding();
+        if (!content_encoding.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+        }
+    } else {
+        // force content length to 0 is there is no message body
+        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
+    }
+    
+    // create a memory stream to buffer the headers
+    NPT_MemoryStream header_stream;
+
+    // emit the request headers into the header buffer
+    request.Emit(header_stream, use_proxy);
+
+    // send the headers
+    NPT_CHECK_WARNING(output_stream->WriteFully(header_stream.GetData(), header_stream.GetDataSize()));
+
+    // send request body
+    if (!body_stream.IsNull()) {
+        NPT_CHECK_FATAL(NPT_StreamToStreamCopy(*body_stream.AsPointer(), *output_stream.AsPointer(), 0, entity->GetContentLength()));
+    }
+
+    // flush the output stream so that everything is sent to the server
+    output_stream->Flush();
+
+    // create a buffered stream for this socket stream
+    NPT_BufferedInputStreamReference buffered_input_stream(new NPT_BufferedInputStream(input_stream));
+
+    // parse the response
+    NPT_CHECK_WARNING(NPT_HttpResponse::Parse(*buffered_input_stream, response));
+    NPT_LOG_FINE_2("got response, code=%d, msg=%s",
+                   response->GetStatusCode(),
+                   response->GetReasonPhrase().GetChars());
+    
+    // unbuffer the stream
+    buffered_input_stream->SetBufferSize(0);
+
+    // create an entity if one is expected in the response
+    if (request.GetMethod() == NPT_HTTP_METHOD_GET || request.GetMethod() == NPT_HTTP_METHOD_POST) {
+        NPT_HttpEntity* response_entity = new NPT_HttpEntity(response->GetHeaders());
+        // Transfer-Encoding: chunked ?
+        if (response_entity->GetTransferEncoding() == "chunked") {
+            NPT_InputStreamReference resp_body_stream(new NPT_HttpChunkedDecoderInputStream(buffered_input_stream));
+            response_entity->SetInputStream((NPT_InputStreamReference)resp_body_stream);
+        } else {
+            response_entity->SetInputStream((NPT_InputStreamReference)buffered_input_stream);
+        }
+        response->SetEntity(response_entity);
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient::SendRequest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpClient::SendRequest(NPT_HttpRequest&   request, 
+                            NPT_HttpResponse*& response)
+{
+    NPT_Cardinal watchdog = NPT_HTTP_MAX_REDIRECTS;
+    bool         keep_going;
+    NPT_Result   result;
+
+    // default value
+    response = NULL;
+    
+    // check that for GET requests there is no entity
+    if (request.GetEntity() != NULL &&
+        request.GetMethod() == NPT_HTTP_METHOD_GET) {
+        return NPT_ERROR_HTTP_INVALID_REQUEST;
+    }
+    
+    do {
+        keep_going = false;
+        result = SendRequestOnce(request, response);
+        if (NPT_FAILED(result)) break;
+        if (response && m_Config.m_FollowRedirect &&
+            (request.GetMethod() == NPT_HTTP_METHOD_GET ||
+             request.GetMethod() == NPT_HTTP_METHOD_HEAD) &&
+            (response->GetStatusCode() == 301 ||
+             response->GetStatusCode() == 302 ||
+             response->GetStatusCode() == 303 ||
+             response->GetStatusCode() == 307)) {
+            // handle redirect
+            NPT_HttpHeader* location = response->GetHeaders().GetHeader(NPT_HTTP_HEADER_LOCATION);
+            if (location) {
+                // replace the request url
+                if (NPT_SUCCEEDED(request.SetUrl(location->GetValue()))) {
+                    NPT_LOG_FINE_1("redirecting to %s", location->GetValue().GetChars());
+                    keep_going = true;
+                    delete response;
+                    response = NULL;
+                }
+            }
+        } else if (response && response->GetStatusCode() == 100) {
+            NPT_LOG_FINE("NPT_HttpClient::SendRequest - received 100 continue\n");
+            keep_going = true;
+            delete response;
+            response = NULL;
+        }
+    } while (keep_going && watchdog--);
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequestContext::NPT_HttpRequestContext
++---------------------------------------------------------------------*/
+NPT_HttpRequestContext::NPT_HttpRequestContext(const NPT_SocketAddress* local_address,
+                                               const NPT_SocketAddress* remote_address)
+{
+    if (local_address) m_LocalAddress   = *local_address;
+    if (remote_address) m_RemoteAddress = *remote_address;
+}
+                           
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::NPT_HttpServer
++---------------------------------------------------------------------*/
+NPT_HttpServer::NPT_HttpServer(NPT_UInt16 listen_port, 
+                               bool       reuse_address /* = true */) :
+    m_BoundPort(0)
+{
+    m_Config.m_ListenAddress     = NPT_IpAddress::Any;
+    m_Config.m_ListenPort        = listen_port;
+    m_Config.m_IoTimeout         = NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT;
+    m_Config.m_ConnectionTimeout = NPT_HTTP_SERVER_DEFAULT_CONNECTION_TIMEOUT;
+    m_Config.m_ReuseAddress      = reuse_address;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::~NPT_HttpServer
++---------------------------------------------------------------------*/
+NPT_HttpServer::~NPT_HttpServer()
+{
+    m_RequestHandlers.Apply(NPT_ObjectDeleter<HandlerConfig>());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::Bind
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::Bind()
+{
+    // check if we're already bound
+    if (m_BoundPort != 0) return NPT_SUCCESS;
+
+    // bind
+    NPT_Result result = m_Socket.Bind(
+        NPT_SocketAddress(m_Config.m_ListenAddress, m_Config.m_ListenPort), 
+        m_Config.m_ReuseAddress);
+    if (NPT_FAILED(result)) return result;
+
+    // remember that we're bound
+    NPT_SocketInfo info;
+    m_Socket.GetInfo(info);
+    m_BoundPort = info.local_address.GetPort();
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::SetConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetConfig(const Config& config)
+{
+    m_Config = config;
+
+    // check that we can bind to this listen port
+    return Bind();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::SetListenPort
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetListenPort(NPT_UInt16 port, bool reuse_address)
+{
+    m_Config.m_ListenPort = port;
+    m_Config.m_ReuseAddress = reuse_address;
+    return Bind();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::SetTimeouts
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::SetTimeouts(NPT_Timeout connection_timeout, 
+                            NPT_Timeout io_timeout)
+{
+    m_Config.m_ConnectionTimeout = connection_timeout;
+    m_Config.m_IoTimeout         = io_timeout;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::Abort
++---------------------------------------------------------------------*/
+void
+NPT_HttpServer::Abort()
+{
+    m_Socket.Disconnect();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::WaitForNewClient
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::WaitForNewClient(NPT_InputStreamReference&  input,
+                                 NPT_OutputStreamReference& output,
+                                 NPT_HttpRequestContext*    context)
+{
+    // ensure that we're bound 
+    NPT_CHECK(Bind());
+
+    // wait for a connection
+    NPT_Socket*         client;
+    NPT_LOG_FINE_1("waiting for connection on port %d...", m_Config.m_ListenPort);
+    NPT_CHECK_WARNING(m_Socket.WaitForNewClient(client, m_Config.m_ConnectionTimeout));
+    if (client == NULL) return NPT_ERROR_INTERNAL;
+
+    // get the client info
+    if (context) {
+        NPT_SocketInfo client_info;
+        client->GetInfo(client_info);
+
+        context->SetLocalAddress(client_info.local_address);
+        context->SetRemoteAddress(client_info.remote_address);
+
+        NPT_LOG_FINE_2("client connected (%s)",
+                       client_info.local_address.ToString().GetChars(),
+                       client_info.remote_address.ToString().GetChars());
+    }
+
+    // configure the socket
+    client->SetReadTimeout(m_Config.m_IoTimeout);
+    client->SetWriteTimeout(m_Config.m_IoTimeout);
+
+    // get the streams
+    client->GetInputStream(input);
+    client->GetOutputStream(output);
+
+    // we don't need the socket anymore
+    delete client;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::Loop
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpServer::Loop()
+{
+    NPT_InputStreamReference  input;
+    NPT_OutputStreamReference output;
+    NPT_HttpRequestContext    context;
+    NPT_Result                result;
+    
+    do {
+        result = WaitForNewClient(input, output, &context);
+        NPT_LOG_FINE_2("WaitForNewClient returned %d (%s)", 
+                       result,
+                       NPT_ResultText(result));
+        if (NPT_FAILED(result)) break;
+
+        result = RespondToClient(input, output, context);
+        NPT_LOG_FINE_2("ResponToClient returned %d", 
+                       result,
+                       NPT_ResultText(result));
+    } while (NPT_SUCCEEDED(result));
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::HandlerConfig::HandlerConfig
++---------------------------------------------------------------------*/
+NPT_HttpServer::HandlerConfig::HandlerConfig(NPT_HttpRequestHandler* handler, 
+                                             const char*             path, 
+                                             bool                    include_children) :
+    m_Handler(handler),
+    m_Path(path),
+    m_IncludeChildren(include_children)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::HandlerConfig::~HandlerConfig
++---------------------------------------------------------------------*/
+NPT_HttpServer::HandlerConfig::~HandlerConfig()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::AddRequestHandler
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpServer::AddRequestHandler(NPT_HttpRequestHandler* handler, 
+                                  const char*             path, 
+                                  bool                    include_children)
+{
+    return m_RequestHandlers.Add(new HandlerConfig(handler, path, include_children));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::FindRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpRequestHandler* 
+NPT_HttpServer::FindRequestHandler(NPT_HttpRequest& request)
+{
+    for (NPT_List<HandlerConfig*>::Iterator it = m_RequestHandlers.GetFirstItem();
+         it;
+         ++it) {
+         HandlerConfig* config = *it;
+         if (config->m_IncludeChildren) {
+             if (request.GetUrl().GetPath().StartsWith(config->m_Path)) {
+                 return config->m_Handler;
+             }  
+         } else {
+             if (request.GetUrl().GetPath() == config->m_Path) {
+                 return config->m_Handler;
+             }
+         }
+    }
+
+    // not found
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer::RespondToClient
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpServer::RespondToClient(NPT_InputStreamReference&     input,
+                                NPT_OutputStreamReference&    output,
+                                const NPT_HttpRequestContext& context)
+{
+    NPT_HttpRequest*  request;
+    NPT_HttpResponse* response;
+    NPT_Result        result = NPT_SUCCESS;
+
+    NPT_HttpResponder responder(input, output);
+    NPT_CHECK_WARNING(responder.ParseRequest(request, &context.GetLocalAddress()));
+
+    NPT_HttpRequestHandler* handler = FindRequestHandler(*request);
+    if (handler == NULL) {
+        response = new NPT_HttpResponse(404, "Not Found", NPT_HTTP_PROTOCOL_1_0);
+    } else {
+        // create a response object
+        response = new NPT_HttpResponse(200, "OK", NPT_HTTP_PROTOCOL_1_0);
+
+        // prepare the response
+        response->SetEntity(new NPT_HttpEntity());
+
+        // ask the handler to setup the response
+        if (NPT_FAILED(handler->SetupResponse(*request, context, *response))) {
+            response->SetStatus(500, "Internal Server Error");
+        }
+    }
+
+    // send the response
+    result = responder.SendResponse(*response, request->GetMethod()==NPT_HTTP_METHOD_HEAD);
+
+    // cleanup
+    delete response;
+    delete request;
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder::NPT_HttpResponder
++---------------------------------------------------------------------*/
+NPT_HttpResponder::NPT_HttpResponder(NPT_InputStreamReference&  input,
+                                     NPT_OutputStreamReference& output) :
+    m_Input(new NPT_BufferedInputStream(input)),
+    m_Output(output)
+{
+    m_Config.m_IoTimeout = NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder::~NPT_HttpResponder
++---------------------------------------------------------------------*/
+NPT_HttpResponder::~NPT_HttpResponder()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder::SetConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::SetConfig(const Config& config)
+{
+    m_Config = config;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder::SetTimeout
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::SetTimeout(NPT_Timeout io_timeout)
+{
+    m_Config.m_IoTimeout = io_timeout;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder::ParseRequest
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::ParseRequest(NPT_HttpRequest*&        request,
+                                const NPT_SocketAddress* local_address)
+{
+    // parse the request
+    NPT_CHECK(NPT_HttpRequest::Parse(*m_Input, local_address, request));
+
+    // unbuffer the stream
+    m_Input->SetBufferSize(0);
+
+    // don't create entity if no body is expected
+    if (request->GetMethod() == NPT_HTTP_METHOD_GET ||
+        request->GetMethod() == NPT_HTTP_METHOD_HEAD) {
+        return NPT_SUCCESS;
+    }
+
+    // set the entity info
+    NPT_HttpEntity* entity = new NPT_HttpEntity(request->GetHeaders());
+    entity->SetInputStream(m_Input);
+    request->SetEntity(entity);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder::SendResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpResponder::SendResponse(NPT_HttpResponse& response, 
+                                bool              headers_only)
+{
+    // add default headers
+    NPT_HttpHeaders& headers = response.GetHeaders();
+    headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close", false);
+    headers.SetHeader(NPT_HTTP_HEADER_SERVER, NPT_HttpServer::m_ServerHeader, false);
+
+    // add computed headers
+    NPT_HttpEntity* entity = response.GetEntity();
+    if (entity) {
+        // content length (only set if valid)
+        if (entity->HasContentLength()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, 
+                              NPT_String::FromInteger(entity->GetContentLength()));
+        }
+
+        // content type
+        NPT_String content_type = entity->GetContentType();
+        if (!content_type.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+        }
+
+        // content encoding
+        NPT_String content_encoding = entity->GetContentEncoding();
+        if (!content_encoding.IsEmpty()) {
+            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+        }
+    } else {
+        // force content length to 0 if there is no message body
+        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
+    }
+    
+    // create a memory stream to buffer the response line and headers
+    NPT_MemoryStream buffer;
+
+    // emit the response line
+    NPT_CHECK_WARNING(response.Emit(buffer));
+
+    // send the buffer
+    NPT_CHECK_WARNING(m_Output->WriteFully(buffer.GetData(), buffer.GetDataSize()));
+
+    // send the body
+    if (entity && !headers_only) {
+        NPT_InputStreamReference body_stream;
+        entity->GetInputStream(body_stream);
+        if (!body_stream.IsNull()) return NPT_StreamToStreamCopy(*body_stream, *m_Output);
+    }
+
+    // flush
+    m_Output->Flush();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler(const void* data, 
+                                                           NPT_Size    size, 
+                                                           const char* mime_type,
+                                                           bool        copy) :
+    m_MimeType(mime_type),
+    m_Buffer(data, size, copy)
+{}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpStaticRequestHandler::NPT_HttpStaticRequestHandler(const char* document, 
+                                                           const char* mime_type,
+                                                           bool        copy) :
+    m_MimeType(mime_type),
+    m_Buffer(document, NPT_StringLength(document), copy)
+{}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticRequestHandler::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpStaticRequestHandler::SetupResponse(NPT_HttpRequest&              /*request*/, 
+                                            const NPT_HttpRequestContext& /*context*/,
+                                            NPT_HttpResponse&             response)
+{
+    NPT_HttpEntity* entity = response.GetEntity();
+    if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+    entity->SetContentType(m_MimeType);
+    entity->SetInputStream(m_Buffer.GetData(), m_Buffer.GetDataSize());
+
+    return NPT_SUCCESS;
+}
+
+const NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry 
+NPT_HttpFileRequestHandler_DefaultFileTypeMap[27] = {
+    {"xml",  "text/html"},
+    {"htm",  "text/html"},
+    {"html", "text/html"},
+    {"gif",  "image/gif"},
+    {"thm",  "image/jpeg"},
+    {"jpg",  "image/jpeg"},
+    {"jpeg", "image/jpeg"},
+    {"jpe",  "image/jpeg"},
+    {"jp2",  "image/jp2"},
+    {"png",  "image/png"},
+    {"bmp",  "image/bmp"},
+    {"tiff", "image/tiff"},
+    {"css",  "text/css"},
+    {"js",   "application/javascript"},
+    {"mp3",  "audio/mpeg"},
+    {"m4a",  "audio/mp4"},
+    {"wma",  "audio/x-ms-wma"},
+    {"wav",  "audio/x-wav"},
+    {"avi",  "video/avi"},
+    {"divx", "video/avi"},
+    {"xvid", "video/avi"},
+    {"mov",  "video/mp4"},
+    {"mp4",  "video/mp4"},
+    {"mpg",  "video/mpeg"},
+    {"mpeg", "video/mpeg"},
+    {"wmv",  "video/x-ms-wmv"},
+    {"asf",  "video/x-ms-asf"}
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpFileRequestHandler::NPT_HttpFileRequestHandler
++---------------------------------------------------------------------*/
+NPT_HttpFileRequestHandler::NPT_HttpFileRequestHandler(const char* url_root,
+                                                       const char* file_root) :
+    m_UrlRoot(url_root),
+    m_FileRoot(file_root),
+    m_DefaultMimeType("text/html"),
+    m_UseDefaultFileTypeMap(true)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpFileRequestHandler::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpFileRequestHandler::SetupResponse(NPT_HttpRequest&              request,
+                                          const NPT_HttpRequestContext& /* context */,
+                                          NPT_HttpResponse&             response)
+{
+    NPT_HttpEntity* entity = response.GetEntity();
+    if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+    // check the method
+    if (request.GetMethod() != NPT_HTTP_METHOD_GET &&
+        request.GetMethod() != NPT_HTTP_METHOD_HEAD) {
+        response.SetStatus(405, "Method Not Allowed");
+        return NPT_SUCCESS;
+    }
+
+    // TODO: we need to normalize the request path
+
+    // check that the request's path is an entry under the url root
+    if (!request.GetUrl().GetPath().StartsWith(m_UrlRoot)) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // compute the filename
+    NPT_String filename = m_FileRoot;
+    filename += request.GetUrl().GetPath().GetChars()+m_UrlRoot.GetLength();
+    
+    // open the file
+    NPT_File file(filename);
+    NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_READ);
+    if (NPT_FAILED(result)) {
+        response.SetStatus(404, "Not Found");
+        return NPT_SUCCESS;
+    }
+    NPT_InputStreamReference stream;
+    file.GetInputStream(stream);
+    entity->SetContentType(GetContentType(filename));
+    entity->SetInputStream(stream, true);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpFileRequestHandler::GetContentType
++---------------------------------------------------------------------*/
+const char*
+NPT_HttpFileRequestHandler::GetContentType(const NPT_String& filename)
+{
+    int last_dot = filename.ReverseFind('.');
+    if (last_dot > 0) {
+        NPT_String extension = filename.GetChars()+last_dot+1;
+        extension.MakeLowercase();
+        NPT_String* mime_type;
+        if (NPT_SUCCEEDED(m_FileTypeMap.Get(extension, mime_type))) {
+            return mime_type->GetChars();
+        }
+
+        // not found, look in the default map if necessary
+        if (m_UseDefaultFileTypeMap) {
+            for (unsigned int i=0; i<NPT_ARRAY_SIZE(NPT_HttpFileRequestHandler_DefaultFileTypeMap); i++) {
+                if (extension == NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].extension) {
+                    return NPT_HttpFileRequestHandler_DefaultFileTypeMap[i].mime_type;
+                }
+            }
+        }
+    }
+
+    return m_DefaultMimeType;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::NPT_HttpChunkedDecoderInputStream
++---------------------------------------------------------------------*/
+NPT_HttpChunkedDecoderInputStream::NPT_HttpChunkedDecoderInputStream(
+    NPT_BufferedInputStreamReference& stream) :
+    m_Source(stream),
+    m_ChunkSize(0),
+    m_InChunk(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::~NPT_HttpChunkedDecoderInputStream
++---------------------------------------------------------------------*/
+NPT_HttpChunkedDecoderInputStream::~NPT_HttpChunkedDecoderInputStream()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::NPT_HttpChunkedDecoderInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HttpChunkedDecoderInputStream::Read(void*     buffer, 
+                                        NPT_Size  bytes_to_read, 
+                                        NPT_Size* bytes_read /* = NULL */)
+{
+    // update output params first
+    if (bytes_read) *bytes_read = 0;
+
+    // read next chunk size
+    if (!m_InChunk) {
+        // buffered mode
+        m_Source->SetBufferSize(4096);
+
+        NPT_String size_line;
+        NPT_CHECK(m_Source->ReadLine(size_line));
+
+        // decode line
+        int delimiter = size_line.Find(';');
+        if (delimiter) size_line = size_line.Left(delimiter);
+        NPT_Int32 size;
+        NPT_CHECK(NPT_ParseInteger(size_line, size));
+
+        // 0 = end of body
+        if (size == 0) {
+            // read footers until empty line
+            NPT_String footer;
+            do {
+                NPT_CHECK(m_Source->ReadLine(footer));
+                if (footer.IsEmpty()) return NPT_ERROR_EOS;
+            } while (1);
+        }
+
+        // read chunk now
+        m_ChunkSize = size;
+        m_InChunk = true;
+
+        // unbuffer source
+        m_Source->SetBufferSize(0);
+    }
+
+    // read no more than what's left in chunk
+    NPT_Size tmp;
+    bytes_to_read = (m_ChunkSize>bytes_to_read)?bytes_to_read:m_ChunkSize;
+    NPT_CHECK(m_Source->Read(buffer, bytes_to_read, &tmp));
+
+    // ready to go to next chunk?
+    m_ChunkSize -= tmp;
+    if (m_ChunkSize == 0) {
+        m_InChunk = false;
+
+        // when a chunk is finished, a \r\n follows
+        NPT_String emptyline;
+        NPT_CHECK(m_Source->ReadLine(emptyline));
+    }
+
+    // update output params
+    if (bytes_read) *bytes_read = tmp;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpChunkedDecoderInputStream::Seek(NPT_Position /*offset*/)
+{
+    // not implemented yet
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpChunkedDecoderInputStream::Tell(NPT_Position& offset)
+{
+    // not implemented yet
+    offset = 0;
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpChunkedDecoderInputStream::GetSize(NPT_LargeSize& size)
+{
+    return m_Source->GetSize(size);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_HttpChunkedDecoderInputStream::GetAvailable(NPT_LargeSize& available)
+{
+    return m_Source->GetAvailable(available);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptHttp.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,642 @@
+/*****************************************************************
+|
+|   Neptune - HTTP Protocol
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_HTTP_H_
+#define _NPT_HTTP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptUri.h"
+#include "NptTypes.h"
+#include "NptList.h"
+#include "NptBufferedStreams.h"
+#include "NptSockets.h"
+#include "NptMap.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_HTTP_DEFAULT_PORT = 80;
+const unsigned int NPT_HTTP_INVALID_PORT = 0;
+
+const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT    = 30000;
+const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_IO_TIMEOUT            = 30000;
+const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_NAME_RESOLVER_TIMEOUT = 60000;
+
+const NPT_Timeout NPT_HTTP_SERVER_DEFAULT_CONNECTION_TIMEOUT    = NPT_TIMEOUT_INFINITE;
+const NPT_Timeout NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT            = 60000;
+
+const int NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH  = 8192;
+const int NPT_HTTP_PROTOCOL_MAX_HEADER_COUNT = 100;
+
+#define NPT_HTTP_PROTOCOL_1_0   "HTTP/1.0"
+#define NPT_HTTP_PROTOCOL_1_1   "HTTP/1.1"
+#define NPT_HTTP_METHOD_GET     "GET"
+#define NPT_HTTP_METHOD_HEAD    "HEAD"
+#define NPT_HTTP_METHOD_POST    "POST"
+
+#define NPT_HTTP_HEADER_HOST                "Host"
+#define NPT_HTTP_HEADER_CONNECTION          "Connection"
+#define NPT_HTTP_HEADER_USER_AGENT          "User-Agent"
+#define NPT_HTTP_HEADER_SERVER              "Server"
+#define NPT_HTTP_HEADER_CONTENT_LENGTH      "Content-Length"
+#define NPT_HTTP_HEADER_CONTENT_TYPE        "Content-Type"
+#define NPT_HTTP_HEADER_CONTENT_ENCODING    "Content-Encoding"
+#define NPT_HTTP_HEADER_TRANSFER_ENCODING   "Transfer-Encoding"
+#define NPT_HTTP_HEADER_LOCATION            "Location"
+#define NPT_HTTP_HEADER_RANGE               "Range"
+#define NPT_HTTP_HEADER_CONTENT_RANGE       "Content-Range"
+#define NPT_HTTP_HEADER_COOKIE              "Cookie"
+
+const int NPT_ERROR_HTTP_INVALID_RESPONSE_LINE = NPT_ERROR_BASE_HTTP - 0;
+const int NPT_ERROR_HTTP_INVALID_REQUEST_LINE  = NPT_ERROR_BASE_HTTP - 1;
+const int NPT_ERROR_HTTP_NO_PROXY              = NPT_ERROR_BASE_HTTP - 2;
+const int NPT_ERROR_HTTP_INVALID_REQUEST       = NPT_ERROR_BASE_HTTP - 3;
+
+#define NPT_HTTP_LINE_TERMINATOR "\r\n"
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef unsigned int NPT_HttpStatusCode;
+typedef NPT_UrlQuery NPT_HttpUrlQuery; // for backward compatibility
+
+/*----------------------------------------------------------------------
+|   NPT_HttpUrl
++---------------------------------------------------------------------*/
+class NPT_HttpUrl : public NPT_Url {
+public:
+    // constructors
+    NPT_HttpUrl() {}
+    NPT_HttpUrl(const char* host, 
+                NPT_UInt16  port, 
+                const char* path,
+                const char* query = NULL,
+                const char* fragment = NULL);
+    NPT_HttpUrl(const char* url, bool ignore_scheme = false);
+
+    // methods
+    virtual NPT_String ToString(bool with_fragment = true) const;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpProtocol
++---------------------------------------------------------------------*/
+class NPT_HttpProtocol
+{
+public:
+    // class methods
+    const char* GetStatusCodeString(NPT_HttpStatusCode status_code);
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeader
++---------------------------------------------------------------------*/
+class NPT_HttpHeader {
+public:
+    // constructors and destructor
+    NPT_HttpHeader(const char* name, const char* value);
+    ~NPT_HttpHeader();
+
+    // methods
+    NPT_Result        Emit(NPT_OutputStream& stream) const;
+    const NPT_String& GetName()  const { return m_Name;  }
+    const NPT_String& GetValue() const { return m_Value; }
+    NPT_Result        SetName(const char* name);
+    NPT_Result        SetValue(const char* value);
+
+private:
+    // members
+    NPT_String m_Name;
+    NPT_String m_Value;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpHeaders
++---------------------------------------------------------------------*/
+class NPT_HttpHeaders {
+public:
+    // constructors and destructor
+     NPT_HttpHeaders();
+    ~NPT_HttpHeaders();
+
+    // methods
+    NPT_Result Parse(NPT_BufferedInputStream& stream);
+    NPT_Result Emit(NPT_OutputStream& stream) const;
+    NPT_List<NPT_HttpHeader*>& GetHeaders() { return m_Headers; }
+    NPT_HttpHeader*   GetHeader(const char* name) const;
+    const NPT_String* GetHeaderValue(const char* name) const;
+    NPT_Result        SetHeader(const char* name, const char* value, bool replace=true);
+    NPT_Result        AddHeader(const char* name, const char* value);
+
+private:
+    // members
+    NPT_List<NPT_HttpHeader*> m_Headers;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpEntity
++---------------------------------------------------------------------*/
+class NPT_HttpEntity {
+public:
+    // constructors and destructor
+             NPT_HttpEntity();
+             NPT_HttpEntity(const NPT_HttpHeaders& headers);
+    virtual ~NPT_HttpEntity();
+
+    // methods
+    NPT_Result SetInputStream(const NPT_InputStreamReference& stream,
+                              bool update_content_length = false);
+    NPT_Result SetInputStream(const void* data, NPT_Size size);
+    NPT_Result SetInputStream(const NPT_String& string);
+    NPT_Result SetInputStream(const char* string);
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result Load(NPT_DataBuffer& buffer);
+    NPT_Result SetHeaders(const NPT_HttpHeaders& headers);
+
+    // field access
+    NPT_Result        SetContentType(const char* type);
+    NPT_Result        SetContentEncoding(const char* encoding);
+    NPT_Result        SetContentLength(NPT_LargeSize length);
+    NPT_LargeSize     GetContentLength()   { return m_ContentLength;   }
+    const NPT_String& GetContentType()     { return m_ContentType;     }
+    const NPT_String& GetContentEncoding() { return m_ContentEncoding; }
+    const NPT_String& GetTransferEncoding(){ return m_TransferEncoding;}
+    bool              HasContentLength()   { return m_HasContentLength;}
+
+private:
+    // members
+    NPT_InputStreamReference m_InputStream;
+    NPT_LargeSize            m_ContentLength;
+    NPT_String               m_ContentType;
+    NPT_String               m_ContentEncoding;
+    NPT_String               m_TransferEncoding;
+    bool                     m_HasContentLength;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpMessage
++---------------------------------------------------------------------*/
+class NPT_HttpMessage {
+public:
+    // constructors and destructor
+    virtual ~NPT_HttpMessage();
+
+    // methods
+    const NPT_String& GetProtocol() const { 
+        return m_Protocol; 
+    }
+    NPT_Result SetProtocol(const char* protocol) {
+        m_Protocol = protocol;
+        return NPT_SUCCESS;
+    }
+    NPT_HttpHeaders& GetHeaders() { 
+        return m_Headers;  
+    }
+    NPT_Result SetEntity(NPT_HttpEntity* entity);
+    NPT_HttpEntity* GetEntity() {
+        return m_Entity;
+    }
+    virtual NPT_Result ParseHeaders(NPT_BufferedInputStream& stream);
+
+protected:
+    // constructors
+    NPT_HttpMessage(const char* protocol);
+
+    // members
+    NPT_String      m_Protocol;
+    NPT_HttpHeaders m_Headers;
+    NPT_HttpEntity* m_Entity;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequest
++---------------------------------------------------------------------*/
+class NPT_HttpRequest : public NPT_HttpMessage {
+public:
+    // class methods
+    static NPT_Result Parse(NPT_BufferedInputStream& stream, 
+                            const NPT_SocketAddress* endpoint,
+                            NPT_HttpRequest*&        request);
+
+    // constructors and destructor
+    NPT_HttpRequest(const NPT_HttpUrl& url,
+                    const char*        method,
+                    const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
+    NPT_HttpRequest(const char*        url,
+                    const char*        method,
+                    const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
+    virtual ~NPT_HttpRequest();
+
+    // methods
+    const NPT_HttpUrl& GetUrl() const { return m_Url; }
+    NPT_HttpUrl&       GetUrl()       { return m_Url; }
+    NPT_Result         SetUrl(const char* url);
+    NPT_Result         SetUrl(const NPT_HttpUrl& url);
+    const NPT_String&  GetMethod() const { return m_Method; }
+    virtual NPT_Result Emit(NPT_OutputStream& stream, bool use_proxy=false) const;
+    
+protected:
+    // members
+    NPT_HttpUrl m_Url;
+    NPT_String  m_Method;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponse
++---------------------------------------------------------------------*/
+class NPT_HttpResponse : public NPT_HttpMessage {
+public:
+    // class methods
+    static NPT_Result Parse(NPT_BufferedInputStream& stream, 
+                            NPT_HttpResponse*&       response);
+
+    // constructors and destructor
+             NPT_HttpResponse(NPT_HttpStatusCode status_code,
+                              const char*        reason_phrase,
+                              const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
+    virtual ~NPT_HttpResponse();
+
+    // methods
+    NPT_Result         SetStatus(NPT_HttpStatusCode status_code,
+                                 const char*        reason_phrase,
+                                 const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
+    NPT_HttpStatusCode GetStatusCode()   { return m_StatusCode;   }
+    NPT_String&        GetReasonPhrase() { return m_ReasonPhrase; }
+    virtual NPT_Result Emit(NPT_OutputStream& stream) const;
+
+protected:
+    // members
+    NPT_HttpStatusCode m_StatusCode;
+    NPT_String         m_ReasonPhrase;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpProxyAddress
++---------------------------------------------------------------------*/
+class NPT_HttpProxyAddress
+{
+public:
+    NPT_HttpProxyAddress() : m_Port(NPT_HTTP_INVALID_PORT) {}
+    NPT_HttpProxyAddress(const char* hostname, NPT_UInt16 port) :
+        m_HostName(hostname), m_Port(port) {}
+
+    const NPT_String& GetHostName() const { return m_HostName; } 
+    void              SetHostName(const char* hostname) { m_HostName = hostname; }
+    NPT_UInt16        GetPort() const { return m_Port; }
+    void              SetPort(NPT_UInt16 port) { m_Port = port; }
+
+private:
+    NPT_String m_HostName;
+    NPT_UInt16 m_Port;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpProxySelector
++---------------------------------------------------------------------*/
+class NPT_HttpProxySelector
+{
+public:
+    // class methods
+    static NPT_HttpProxySelector* GetSystemDefault();
+
+    // methods
+    virtual ~NPT_HttpProxySelector() {};
+    virtual NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpClient
++---------------------------------------------------------------------*/
+class NPT_HttpClient {
+public:
+    // types
+    struct Config {
+        NPT_Timeout m_ConnectionTimeout;
+        NPT_Timeout m_IoTimeout;
+        NPT_Timeout m_NameResolverTimeout;
+        bool        m_FollowRedirect;
+    };
+
+    class Connector {
+    public:
+        virtual ~Connector() {}
+
+        virtual NPT_Result Connect(const char*                hostname, 
+                                   NPT_UInt16                 port, 
+                                   NPT_Timeout                connection_timeout,
+                                   NPT_Timeout                io_timeout,
+                                   NPT_Timeout                name_resolver_timeout,
+                                   NPT_InputStreamReference&  input_stream,
+                                   NPT_OutputStreamReference& output_stream) = 0;
+
+    };
+
+    /**
+     * @param connector Pointer to a Connector instance, or NULL to use 
+     * the default (TCP) connector.
+     */
+    NPT_HttpClient(Connector* connector = NULL);
+
+    virtual ~NPT_HttpClient();
+
+    // methods
+    NPT_Result SendRequest(NPT_HttpRequest&   request,
+                           NPT_HttpResponse*& response);
+    NPT_Result SetConfig(const Config& config);
+    NPT_Result SetProxy(const char* hostname, NPT_UInt16 port);
+    NPT_Result SetProxySelector(NPT_HttpProxySelector* selector);
+    NPT_Result SetConnector(Connector* connector);
+    NPT_Result SetTimeouts(NPT_Timeout connection_timeout,
+                           NPT_Timeout io_timeout,
+                           NPT_Timeout name_resolver_timeout);
+
+protected:
+    // methods
+    NPT_Result SendRequestOnce(NPT_HttpRequest&   request,
+                               NPT_HttpResponse*& response);
+
+    // members
+    Config                 m_Config;
+    NPT_HttpProxySelector* m_ProxySelector;
+    bool                   m_ProxySelectorIsOwned;
+    Connector*             m_Connector;
+    
+public:
+    static NPT_String m_UserAgentHeader;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequestContext
++---------------------------------------------------------------------*/
+class NPT_HttpRequestContext
+{
+public:
+    // constructor
+    NPT_HttpRequestContext() {}
+    NPT_HttpRequestContext(const NPT_SocketAddress* local_address,
+                           const NPT_SocketAddress* remote_address);
+                  
+    // methods
+    const NPT_SocketAddress& GetLocalAddress()   const { return m_LocalAddress;  }
+    const NPT_SocketAddress& GetRemoteAddress() const { return m_RemoteAddress; }
+    void SetLocalAddress(const NPT_SocketAddress& address) {
+        m_LocalAddress = address;
+    }
+    void SetRemoteAddress(const NPT_SocketAddress& address) {
+        m_RemoteAddress = address;
+    }
+    
+private:
+    // members
+    NPT_SocketAddress m_LocalAddress;
+    NPT_SocketAddress m_RemoteAddress;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpRequestHandler
++---------------------------------------------------------------------*/
+class NPT_HttpRequestHandler 
+{
+public:
+    // destructor
+    virtual ~NPT_HttpRequestHandler() {}
+
+    // methods
+    virtual NPT_Result SetupResponse(NPT_HttpRequest&              request,
+                                     const NPT_HttpRequestContext& context,
+                                     NPT_HttpResponse&             response) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpStaticRequestHandler
++---------------------------------------------------------------------*/
+class NPT_HttpStaticRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+    // constructors
+    NPT_HttpStaticRequestHandler(const char* document, 
+                                 const char* mime_type = "text/html",
+                                 bool        copy = true);
+    NPT_HttpStaticRequestHandler(const void* data,
+                                 NPT_Size    size,
+                                 const char* mime_type = "text/html",
+                                 bool        copy = true);
+
+    // NPT_HttpRequetsHandler methods
+    virtual NPT_Result SetupResponse(NPT_HttpRequest&              request, 
+                                     const NPT_HttpRequestContext& context,
+                                     NPT_HttpResponse&             response);
+
+private:
+    NPT_String     m_MimeType;
+    NPT_DataBuffer m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpFileRequestHandler_DefaultFileTypeMap
++---------------------------------------------------------------------*/
+typedef struct NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry {
+    const char* extension;
+    const char* mime_type;
+} NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry;
+
+// specify size here so NPT_ARRAY_SIZE can work
+extern const NPT_HttpFileRequestHandler_DefaultFileTypeMapEntry NPT_HttpFileRequestHandler_DefaultFileTypeMap[27];
+
+/*----------------------------------------------------------------------
+|   NPT_HttpFileRequestHandler
++---------------------------------------------------------------------*/
+class NPT_HttpFileRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+    // constructors
+    NPT_HttpFileRequestHandler(const char* url_root,
+                               const char* file_root);
+
+    // NPT_HttpRequetsHandler methods
+    virtual NPT_Result SetupResponse(NPT_HttpRequest&              request, 
+                                     const NPT_HttpRequestContext& context,
+                                     NPT_HttpResponse&             response);
+
+    // accessors
+    NPT_Map<NPT_String,NPT_String>& GetFileTypeMap() { return m_FileTypeMap; }
+    void SetDefaultMimeType(const char* mime_type) {
+        m_DefaultMimeType = mime_type;
+    }
+    void SetUseDefaultFileTypeMap(bool use_default) {
+        m_UseDefaultFileTypeMap = use_default;
+    }
+
+protected:
+    // methods
+    const char* GetContentType(const NPT_String& filename);
+
+private:
+    NPT_String                      m_UrlRoot;
+    NPT_String                      m_FileRoot;
+    NPT_Map<NPT_String, NPT_String> m_FileTypeMap;
+    NPT_String                      m_DefaultMimeType;
+    bool                            m_UseDefaultFileTypeMap;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpServer
++---------------------------------------------------------------------*/
+class NPT_HttpServer {
+public:
+    // types
+    struct Config {
+        NPT_Timeout   m_ConnectionTimeout;
+        NPT_Timeout   m_IoTimeout;
+        NPT_IpAddress m_ListenAddress;
+        NPT_UInt16    m_ListenPort;
+        bool          m_ReuseAddress;
+    };
+
+    // constructors and destructor
+    NPT_HttpServer(NPT_UInt16 listen_port = NPT_HTTP_DEFAULT_PORT,
+                   bool       reuse_address = true);
+    virtual ~NPT_HttpServer();
+
+    // methods
+    NPT_Result SetConfig(const Config& config);
+    NPT_Result SetListenPort(NPT_UInt16 port, bool reuse_address = true);
+    NPT_Result SetTimeouts(NPT_Timeout connection_timeout, NPT_Timeout io_timeout);
+    void       Abort();
+    NPT_Result WaitForNewClient(NPT_InputStreamReference&  input,
+                                NPT_OutputStreamReference& output,
+                                NPT_HttpRequestContext*    context);
+    NPT_Result Loop();
+    
+    /**
+     * Add a request handler. The ownership of the handler is NOT transfered to this object,
+     * so the caller is responsible for the lifetime management of the handler object.
+     */
+    NPT_Result AddRequestHandler(NPT_HttpRequestHandler* handler, const char* path, bool include_children = false);
+    NPT_HttpRequestHandler* FindRequestHandler(NPT_HttpRequest& request);
+
+    /**
+     * Parse the request from a new client, form a response, and send it back. 
+     */
+    NPT_Result RespondToClient(NPT_InputStreamReference&     input,
+                               NPT_OutputStreamReference&    output,
+                               const NPT_HttpRequestContext& context);
+
+protected:
+    // types
+    struct HandlerConfig {
+        HandlerConfig(NPT_HttpRequestHandler* handler,
+                      const char*             path,
+                      bool                    include_children);
+        ~HandlerConfig();
+
+        // methods
+        bool WillHandle(NPT_HttpRequest& request);
+
+        // members
+        NPT_HttpRequestHandler* m_Handler;
+        NPT_String              m_Path;
+        bool                    m_IncludeChildren;
+    };
+
+    // methods
+    NPT_Result Bind();
+
+    // members
+    NPT_TcpServerSocket      m_Socket;
+    NPT_UInt16               m_BoundPort;
+    Config                   m_Config;
+    NPT_List<HandlerConfig*> m_RequestHandlers;
+    
+public:
+    static NPT_String m_ServerHeader;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpResponder
++---------------------------------------------------------------------*/
+class NPT_HttpResponder {
+public:
+    // types
+    struct Config {
+        NPT_Timeout m_IoTimeout;
+    };
+
+    // constructors and destructor
+    NPT_HttpResponder(NPT_InputStreamReference&  input,
+                      NPT_OutputStreamReference& output);
+    virtual ~NPT_HttpResponder();
+
+    // methods
+    NPT_Result SetConfig(const Config& config);
+    NPT_Result SetTimeout(NPT_Timeout io_timeout);
+    NPT_Result ParseRequest(NPT_HttpRequest*&        request,
+                            const NPT_SocketAddress* local_address = NULL);
+    NPT_Result SendResponse(NPT_HttpResponse& response,
+                            bool              headers_only = false);
+
+protected:
+    // members
+    Config                           m_Config;
+    NPT_BufferedInputStreamReference m_Input;
+    NPT_OutputStreamReference        m_Output;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_HttpChunkedDecoderInputStream
++---------------------------------------------------------------------*/
+class NPT_HttpChunkedDecoderInputStream : public NPT_InputStream
+{
+public:
+    // constructors and destructor
+    NPT_HttpChunkedDecoderInputStream(NPT_BufferedInputStreamReference& stream);
+    virtual ~NPT_HttpChunkedDecoderInputStream();
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read = NULL);
+    NPT_Result Seek(NPT_Position offset);
+    NPT_Result Tell(NPT_Position& offset);
+    NPT_Result GetSize(NPT_LargeSize& size);
+    NPT_Result GetAvailable(NPT_LargeSize& available);
+
+protected:
+    // members
+    NPT_BufferedInputStreamReference m_Source;
+    NPT_Size m_ChunkSize;
+    bool     m_InChunk;
+};
+
+#endif // _NPT_HTTP_H_
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptInterfaces.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,138 @@
+/*****************************************************************
+|
+|   Neptune - Interfaces
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_INTERFACES_H_
+#define _NPT_INTERFACES_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptCommon.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_NO_SUCH_INTERFACE = NPT_ERROR_BASE_INTERFACES - 0;
+
+#if 0 // disabled, use NPT_Reference instead
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#define NPT_RELEASE(o) do { if (o) (o)->Release(); (o) = NULL; } while (0)
+#define NPT_ADD_REFERENCE(o) do { if (o) (o)->AddReference(); } while (0)
+
+/*----------------------------------------------------------------------
+|   NPT_Referenceable
++---------------------------------------------------------------------*/
+class NPT_Referenceable
+{
+ public:
+    // methods
+    virtual void AddReference() = 0;
+    virtual void Release() = 0;
+
+protected:
+    // constructors and destructor
+    NPT_Referenceable() {}
+    virtual ~NPT_Referenceable() {}
+};
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_InterfaceId
++---------------------------------------------------------------------*/
+class NPT_InterfaceId
+{
+ public:
+    // methods
+    bool operator==(const NPT_InterfaceId& id) const {
+        return ((id.m_Id == m_Id) && (id.m_Version == m_Version));
+    }
+
+    // members
+    unsigned long m_Id;
+    unsigned long m_Version;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Polymorphic
++---------------------------------------------------------------------*/
+class NPT_Polymorphic
+{
+public:
+    // destructor
+    virtual ~NPT_Polymorphic() {}
+     
+    // methods
+    virtual NPT_Result GetInterface(const NPT_InterfaceId& id, 
+                                    NPT_Interface*&        iface) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Interruptible
++---------------------------------------------------------------------*/
+class NPT_Interruptible
+{
+public:
+    // destructor
+    virtual ~NPT_Interruptible() {}
+
+    // methods
+    virtual NPT_Result Interrupt() = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Configurable
++---------------------------------------------------------------------*/
+class NPT_Configurable
+{
+public:
+    // destructor
+    virtual ~NPT_Configurable() {}
+     
+    // methods
+    virtual NPT_Result SetProperty(const char* /*name*/, 
+                                   const char* /*value*/) { 
+        return NPT_ERROR_NO_SUCH_PROPERTY;
+    }
+    virtual NPT_Result SetProperty(const char* /*name*/, 
+                                   int         /*value*/) { 
+        return NPT_ERROR_NO_SUCH_PROPERTY;
+    }
+    virtual NPT_Result GetProperty(const char*        /*name*/, 
+                                   NPT_PropertyValue& /*value*/) {
+        return NPT_ERROR_NO_SUCH_PROPERTY;
+    }
+};
+
+#endif // _NPT_INTERFACES_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptList.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,34 @@
+/*****************************************************************
+|
+|      Neptune - Lists
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptList.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,605 @@
+/*****************************************************************
+|
+|   Neptune - Lists
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_LIST_H_
+#define _NPT_LIST_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptResults.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptCommon.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_LIST_EMPTY              = NPT_ERROR_BASE_LIST - 0;
+const int NPT_ERROR_LIST_OPERATION_ABORTED  = NPT_ERROR_BASE_LIST - 1;
+const int NPT_ERROR_LIST_OPERATION_CONTINUE = NPT_ERROR_BASE_LIST - 2;
+
+/*----------------------------------------------------------------------
+|   NPT_List
++---------------------------------------------------------------------*/
+template <typename T> 
+class NPT_List 
+{
+protected:
+    class Item;
+
+public:
+    // types
+    typedef T Element;
+
+    class Iterator {
+    public:
+        Iterator() : m_Item(NULL) {}
+        explicit Iterator(Item* item) : m_Item(item) {}
+        Iterator(const Iterator& copy) : m_Item(copy.m_Item) {}
+        T&  operator*()  const { return m_Item->m_Data; }
+        T*  operator->() const { return &m_Item->m_Data;}
+        Iterator& operator++()  { // prefix
+            m_Item = m_Item->m_Next;
+            return (*this); 
+        }
+        Iterator operator++(int) { // postfix
+            Iterator saved_this = *this;
+            m_Item = m_Item->m_Next;
+            return saved_this;
+        }
+        Iterator& operator--() { // prefix
+            m_Item = m_Item->m_Prev;
+            return (*this); 
+        }
+        Iterator operator--(int) { // postfix
+            Iterator saved_this = *this;
+            m_Item = m_Item->m_Prev;
+            return saved_this;
+        }
+        operator bool() const {
+            return m_Item != NULL;
+        }
+        bool operator==(const Iterator& other) const {
+            return m_Item == other.m_Item;
+        }
+        bool operator!=(const Iterator& other) const {
+            return m_Item != other.m_Item;
+        }
+        void operator=(const Iterator& other) {
+            m_Item = other.m_Item;
+        }
+        void operator=(Item* item) {
+            m_Item = item;
+        }
+
+    private:
+        Item* m_Item;
+
+        // friends
+        friend class NPT_List<T>;
+    };
+
+    // methods
+                 NPT_List<T>();
+                 NPT_List<T>(const NPT_List<T>& list);
+                ~NPT_List<T>();
+    NPT_Result   Add(const T& data);
+    NPT_Result   Insert(const Iterator where, const T& data);
+    NPT_Result   Remove(const T& data, bool all=false);
+    NPT_Result   Erase(const Iterator position);
+    NPT_Result   PopHead(T& data);
+    bool         Contains(const T& data) const;
+    NPT_Result   Clear();
+    NPT_Result   Get(NPT_Ordinal index, T& data) const;
+    NPT_Result   Get(NPT_Ordinal index, T*& data) const;
+    NPT_Cardinal GetItemCount() const { return m_ItemCount; }
+    Iterator     GetFirstItem() const { return Iterator(m_Head); }
+    Iterator     GetLastItem() const  { return Iterator(m_Tail); }
+    Iterator     GetItem(NPT_Ordinal index) const;
+
+    // list manipulation
+    NPT_Result   Add(NPT_List<T>& list);
+    NPT_Result   Remove(const NPT_List<T>& list, bool all=false);
+
+    // item manipulation
+    NPT_Result   Add(Item& item);
+    NPT_Result   Detach(Item& item);
+    NPT_Result   Insert(const Iterator where, Item& item);
+
+    // list operations
+    // keep these template members defined here because MSV6 does not let
+    // us define them later
+    template <typename X> 
+    NPT_Result Apply(const X& function) const
+    {                          
+        Item* item = m_Head;
+        while (item) {
+            function(item->m_Data);
+            item = item->m_Next;
+        }
+
+        return NPT_SUCCESS;
+    }
+
+    template <typename X, typename P> 
+    NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
+    {                          
+        Item* item = m_Head;
+        while (item) {
+            NPT_Result return_value;
+            if (predicate(function(item->m_Data), return_value)) {
+                if (match) *match = true;
+                return return_value;
+            }
+            item = item->m_Next;
+        }
+        
+        if (match) *match = false;
+        return NPT_SUCCESS;
+    }
+
+    template <typename P> 
+    Iterator Find(const P& predicate, NPT_Ordinal n=0) const
+    {
+        Item* item = m_Head;
+        while (item) {
+            if (predicate(item->m_Data)) {
+                if (n == 0) {
+                    return Iterator(item);
+                }
+                --n;
+            }
+            item = item->m_Next;
+        }
+
+        return Iterator(NULL);
+    }
+
+    // operators
+    void operator=(const NPT_List<T>& other);
+    bool operator==(const NPT_List<T>& other) const;
+    bool operator!=(const NPT_List<T>& other) const;
+
+protected:
+    // types
+    class Item 
+    {
+    public:
+        // methods
+        Item(const T& data) : m_Next(0), m_Prev(0), m_Data(data) {}
+
+        // members
+        Item* m_Next;
+        Item* m_Prev;
+        T     m_Data;
+
+        // friends
+        //friend class NPT_List<T>;
+        //friend class NPT_List<T>::Iterator;
+    };
+
+    // members
+    NPT_Cardinal m_ItemCount;
+    Item*        m_Head;
+    Item*        m_Tail;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::NPT_List
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_List<T>::NPT_List() : m_ItemCount(0), m_Head(0), m_Tail(0) 
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::NPT_List
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_List<T>::NPT_List(const NPT_List<T>& list) : m_ItemCount(0), m_Head(0), m_Tail(0) 
+{
+    *this = list;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::~NPT_List<T>
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_List<T>::~NPT_List()
+{
+    Clear();
+}
+ 
+/*----------------------------------------------------------------------
+|   NPT_List<T>::operator=
++---------------------------------------------------------------------*/
+template <typename T>
+void
+NPT_List<T>::operator=(const NPT_List<T>& list)
+{
+    // cleanup
+    Clear();
+
+    // copy the new list
+    Item* item = list.m_Head;
+    while (item) {
+        Add(item->m_Data);
+        item = item->m_Next;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::operator==
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_List<T>::operator==(const NPT_List<T>& other) const
+{
+    // quick test
+    if (m_ItemCount != other.m_ItemCount) return false;
+
+    // compare all elements one by one
+    Item* our_item = m_Head;
+    Item* their_item = other.m_Head;
+    while (our_item && their_item) {
+        if (our_item->m_Data != their_item->m_Data) return false;
+        our_item   = our_item->m_Next;
+        their_item = their_item->m_Next;
+    }
+    
+    return our_item == NULL && their_item == NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::operator!=
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+bool
+NPT_List<T>::operator!=(const NPT_List<T>& other) const
+{
+    return !(*this == other);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Clear
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Clear()
+{
+    // delete all items
+    Item* item = m_Head;
+    while (item) {
+        Item* next = item->m_Next;
+        delete item;
+        item = next;
+    }
+
+    m_ItemCount = 0;
+    m_Head      = NULL;
+    m_Tail      = NULL;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Add(Item& item)
+{
+    // add element at the tail
+    if (m_Tail) {
+        item.m_Prev = m_Tail;
+        item.m_Next = NULL;
+        m_Tail->m_Next = &item;
+        m_Tail = &item;
+    } else {
+        m_Head = &item;
+        m_Tail = &item;
+        item.m_Next = NULL;
+        item.m_Prev = NULL;
+    }
+
+    // one more item in the list now
+    ++m_ItemCount;
+ 
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Add(NPT_List<T>& list)
+{
+    // copy the new list
+    Item* item = list.m_Head;
+    while (item) {
+        Add(item->m_Data);
+        item = item->m_Next;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+NPT_Result
+NPT_List<T>::Add(const T& data)
+{
+    return Add(*new Item(data));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::GetItem
++---------------------------------------------------------------------*/
+template <typename T>
+typename NPT_List<T>::Iterator
+NPT_List<T>::GetItem(NPT_Ordinal n) const
+{
+    Iterator result;
+    if (n >= m_ItemCount) return result;
+    
+    result = m_Head;
+    for (unsigned int i=0; i<n; i++) {
+        ++result;
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+inline NPT_Result
+NPT_List<T>::Insert(Iterator where, const T&data)
+{
+    return Insert(where, *new Item(data));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Insert(Iterator where, Item& item)
+{
+    // insert the item in the list
+    Item* position = where.m_Item;
+    if (position) {
+        // insert at position
+        item.m_Next = position;
+        item.m_Prev = position->m_Prev;
+        position->m_Prev = &item;
+        if (item.m_Prev) {
+            item.m_Prev->m_Next = &item;
+        } else {
+            // this is the new head
+            m_Head = &item;
+        }
+
+        // one more item in the list now
+        ++m_ItemCount;
+    } else {
+        // insert at tail
+        return Add(item);
+    }
+ 
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Erase
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Erase(Iterator position) 
+{
+    if (!position) return NPT_ERROR_NO_SUCH_ITEM;
+    Detach(*position.m_Item);
+    delete position.m_Item;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Remove
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Remove(const T& data, bool all)
+{
+    Item* item = m_Head;
+    NPT_Cardinal matches = 0;
+
+    while (item) {
+        Item* next = item->m_Next;
+        if (item->m_Data == data) {
+            // we found a match
+            ++matches;
+
+            // detach item
+            Detach(*item);
+            
+            // destroy the item
+            delete item;
+
+            if (!all) return NPT_SUCCESS;
+        }
+        item = next;
+    }
+ 
+    return matches?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Remove
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Remove(const NPT_List<T>& list, bool all)
+{
+    Item* item = list.m_Head;
+    while (item) {
+        Remove(item->m_Data, all);
+        item = item->m_Next;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Detach
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Detach(Item& item)
+{
+    // remove item
+    if (item.m_Prev) {
+        // item is not the head
+        if (item.m_Next) {
+            // item is not the tail
+            item.m_Next->m_Prev = item.m_Prev;
+            item.m_Prev->m_Next = item.m_Next;
+        } else {
+            // item is the tail
+            m_Tail = item.m_Prev;
+            m_Tail->m_Next = NULL;
+        }
+    } else {
+        // item is the head
+        m_Head = item.m_Next;
+        if (m_Head) {
+            // item is not the tail
+            m_Head->m_Prev = NULL;
+        } else {
+            // item is also the tail
+            m_Tail = NULL;
+        }
+    }
+
+    // one less item in the list now
+    --m_ItemCount;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Get
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Get(NPT_Ordinal index, T& data) const
+{
+    T* data_pointer;
+    NPT_CHECK(Get(index, data_pointer));
+    data = *data_pointer;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Get
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::Get(NPT_Ordinal index, T*& data) const
+{
+    Item* item = m_Head;
+
+    if (index < m_ItemCount) {
+        while (index--) item = item->m_Next;
+        data = &item->m_Data;
+        return NPT_SUCCESS;
+    } else {
+        data = NULL;
+        return NPT_ERROR_NO_SUCH_ITEM;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::PopHead
++---------------------------------------------------------------------*/
+template <typename T>
+NPT_Result
+NPT_List<T>::PopHead(T& data)
+{
+    // check that we have an element
+    if (m_Head == NULL) return NPT_ERROR_LIST_EMPTY;
+
+    // copy the head item's data
+    data = m_Head->m_Data;
+
+    // discard the head item
+    Item* head = m_Head;
+    m_Head = m_Head->m_Next;
+    if (m_Head) {
+        m_Head->m_Prev = NULL;
+    } else {
+        m_Tail = NULL;
+    }
+    delete head;
+
+    // update the count
+    --m_ItemCount;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_List<T>::Contains
++---------------------------------------------------------------------*/
+template <typename T>
+bool
+NPT_List<T>::Contains(const T& data) const
+{
+    Item* item = m_Head;
+    while (item) {
+        if (item->m_Data == data) return true;
+        item = item->m_Next;
+    }
+
+    return false;
+}
+
+#endif // _NPT_LIST_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptLogging.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1185 @@
+/*****************************************************************
+|
+|   Neptune - Logging Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+/** @file
+* Implementation file for logging
+*/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <stdarg.h>
+
+#include "NptLogging.h"
+#include "NptList.h"
+#include "NptStreams.h"
+#include "NptSockets.h"
+#include "NptUtils.h"
+#include "NptFile.h"
+#include "NptSystem.h"
+#include "NptConsole.h"
+#include "NptThreads.h"
+//#include "NptDirectory.h"
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+class NPT_LogConsoleHandler : public NPT_LogHandler {
+public:
+    // class methods
+    static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+    // methods
+    void Log(const NPT_LogRecord& record);
+
+private:
+    // members
+    bool      m_UseColors;
+    NPT_Flags m_FormatFilter;
+};
+
+class NPT_LogFileHandler : public NPT_LogHandler {
+public:
+    // class methods
+    static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+    // methods
+    void Log(const NPT_LogRecord& record);
+
+private:
+    NPT_Result Open(bool append = true);
+    
+private:
+    // members
+    NPT_String                m_Filename;
+    NPT_Flags                 m_FormatFilter;
+    NPT_Mutex                 m_RecycleLock;
+    NPT_LargeSize             m_Recycle;
+    NPT_InputStreamReference  m_InputStream;
+    NPT_OutputStreamReference m_OutputStream;
+};
+
+class NPT_LogTcpHandler : public NPT_LogHandler {
+public:
+    // class methods
+    static NPT_Result Create(const char* logger_name, NPT_LogHandler*& handler);
+
+    // methods
+    void Log(const NPT_LogRecord& record);
+
+private:
+    // methods
+    NPT_Result Connect();
+
+    // members
+    NPT_String                m_Host;
+    NPT_UInt16                m_Port;
+    NPT_OutputStreamReference m_Stream;
+};
+
+class NPT_LogNullHandler : public NPT_LogHandler {
+public:
+    // class methods
+    static NPT_Result Create(NPT_LogHandler*& handler);
+
+    // methods
+    void Log(const NPT_LogRecord& record);
+};
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define NPT_LOG_HEAP_BUFFER_INCREMENT 4096
+#define NPT_LOG_STACK_BUFFER_MAX_SIZE 512
+#define NPT_LOG_HEAP_BUFFER_MAX_SIZE  65536
+
+#if !defined(NPT_LOG_CONFIG_ENV)
+#define NPT_LOG_CONFIG_ENV "NEPTUNE_LOG_CONFIG"
+#endif
+
+#if !defined(NPT_LOG_DEFAULT_CONFIG_SOURCE)
+#define NPT_LOG_DEFAULT_CONFIG_SOURCE "file:neptune-logging.properties"
+#endif
+
+#define NPT_LOG_ROOT_DEFAULT_LOG_LEVEL NPT_LOG_LEVEL_INFO
+#define NPT_LOG_ROOT_DEFAULT_HANDLER   "ConsoleHandler"
+#if !defined(NPT_LOG_ROOT_DEFAULT_FILE_HANDLER_FILENAME)
+#define NPT_LOG_ROOT_DEFAULT_FILE_HANDLER_FILENAME "_neptune.log"
+#endif
+
+#define NPT_LOG_TCP_HANDLER_DEFAULT_PORT            7723
+#define NPT_LOG_TCP_HANDLER_DEFAULT_CONNECT_TIMEOUT 5000 /* 5 seconds */
+
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__APPLE__)
+#define NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE false
+#else
+#define NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE true
+#endif
+
+#define NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE 20000000
+
+#define NPT_LOG_FORMAT_FILTER_NO_SOURCE         1
+#define NPT_LOG_FORMAT_FILTER_NO_TIMESTAMP      2
+#define NPT_LOG_FORMAT_FILTER_NO_LOGGER_NAME    4
+#define NPT_LOG_FORMAT_FILTER_NO_FUNCTION_NAME  8
+#define NPT_LOG_FORMAT_FILTER_NO_SOURCEPATH    16
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+static NPT_LogManager LogManager;
+const char*           LogManagerConfig = NULL;
+bool                  LogManagerEnabled = true;
+    
+/*----------------------------------------------------------------------
+|   NPT_LogHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogHandler::Create(const char*      logger_name,
+                       const char*      handler_name,
+                       NPT_LogHandler*& handler)
+{
+    handler = NULL;
+
+    if (NPT_StringsEqual(handler_name, "NullHandler")) {
+        return NPT_LogNullHandler::Create(handler);
+    } else if (NPT_StringsEqual(handler_name, "FileHandler")) {
+        return NPT_LogFileHandler::Create(logger_name, handler);
+    } else if (NPT_StringsEqual(handler_name, "ConsoleHandler")) {
+        return NPT_LogConsoleHandler::Create(logger_name, handler);
+    } else if (NPT_StringsEqual(handler_name, "TcpHandler")) {
+        return NPT_LogTcpHandler::Create(logger_name, handler);
+    }
+
+    return NPT_ERROR_NO_SUCH_CLASS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Log::GetLogLevel
++---------------------------------------------------------------------*/
+int 
+NPT_Log::GetLogLevel(const char* name)
+{
+    if (       NPT_StringsEqual(name, "FATAL")) {
+        return NPT_LOG_LEVEL_SEVERE;
+    } else if (NPT_StringsEqual(name, "SEVERE")) {
+        return NPT_LOG_LEVEL_WARNING;
+    } else if (NPT_StringsEqual(name, "WARNING")) {
+        return NPT_LOG_LEVEL_WARNING;
+    } else if (NPT_StringsEqual(name, "INFO")) {
+        return NPT_LOG_LEVEL_INFO;
+    } else if (NPT_StringsEqual(name, "FINE")) {
+        return NPT_LOG_LEVEL_FINE;
+    } else if (NPT_StringsEqual(name, "FINER")) {
+        return NPT_LOG_LEVEL_FINER;
+    } else if (NPT_StringsEqual(name, "FINEST")) {
+        return NPT_LOG_LEVEL_FINEST;
+    } else if (NPT_StringsEqual(name, "ALL")) {
+        return NPT_LOG_LEVEL_ALL;
+    } else if (NPT_StringsEqual(name, "OFF")) {
+        return NPT_LOG_LEVEL_OFF;
+    } else {
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Log::GetLogLevelName
++---------------------------------------------------------------------*/
+const char*
+NPT_Log::GetLogLevelName(int level)
+{
+    switch (level) {
+        case NPT_LOG_LEVEL_FATAL:   return "FATAL";
+        case NPT_LOG_LEVEL_SEVERE:  return "SEVERE";
+        case NPT_LOG_LEVEL_WARNING: return "WARNING";
+        case NPT_LOG_LEVEL_INFO:    return "INFO";
+        case NPT_LOG_LEVEL_FINE:    return "FINE";
+        case NPT_LOG_LEVEL_FINER:   return "FINER";
+        case NPT_LOG_LEVEL_FINEST:  return "FINEST";
+        case NPT_LOG_LEVEL_OFF:     return "OFF";
+        default:                    return "";
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Log::GetLogLevelAnsiColor
++---------------------------------------------------------------------*/
+const char*
+NPT_Log::GetLogLevelAnsiColor(int level)
+{
+    switch (level) {
+        case NPT_LOG_LEVEL_FATAL:   return "31";
+        case NPT_LOG_LEVEL_SEVERE:  return "31";
+        case NPT_LOG_LEVEL_WARNING: return "33";
+        case NPT_LOG_LEVEL_INFO:    return "32";
+        case NPT_LOG_LEVEL_FINE:    return "34";
+        case NPT_LOG_LEVEL_FINER:   return "35";
+        case NPT_LOG_LEVEL_FINEST:  return "36";
+        default:                    return NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Log::FormatRecordToStream
++---------------------------------------------------------------------*/
+void
+NPT_Log::FormatRecordToStream(const NPT_LogRecord& record,
+                              NPT_OutputStream&    stream,
+                              bool                 use_colors,
+                              NPT_Flags            format_filter)
+{
+    const char* level_name = GetLogLevelName(record.m_Level);
+    NPT_String  level_string;
+
+    /* format and emit the record */
+    if (level_name[0] == '\0') {
+        level_string = NPT_String::FromInteger(record.m_Level);
+        level_name = level_string;
+    }
+    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_SOURCE) == 0) {
+        int start = 0;
+        /* remove source file path if requested */
+        if (format_filter & NPT_LOG_FORMAT_FILTER_NO_SOURCEPATH) {
+            for (start = NPT_StringLength(record.m_SourceFile);
+                 start;
+                 --start) {
+                if (record.m_SourceFile[start-1] == '\\' ||
+                    record.m_SourceFile[start-1] == '/') {
+                    break;
+                }
+            }
+        }
+        stream.WriteString(record.m_SourceFile + start);
+        stream.Write("(", 1, NULL);
+        stream.WriteString(NPT_String::FromIntegerU(record.m_SourceLine));
+        stream.Write("): ", 3, NULL);
+    }
+    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_LOGGER_NAME) == 0) {
+        stream.Write("[", 1, NULL);
+        stream.WriteString(record.m_LoggerName);
+        stream.Write("] ", 2, NULL);
+    }
+    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_TIMESTAMP) == 0) {
+        stream.WriteString(NPT_String::FromIntegerU(record.m_TimeStamp.m_Seconds));
+        stream.WriteString(":");
+        NPT_String ms = NPT_String::FromIntegerU(record.m_TimeStamp.m_NanoSeconds/1000000L);
+        if (ms.GetLength() < 3) stream.Write("0", 1);
+        if (ms.GetLength() < 2) stream.Write("0", 1);
+        stream.WriteString(ms);
+        stream.Write(" ", 1);
+    }
+    if ((format_filter & NPT_LOG_FORMAT_FILTER_NO_FUNCTION_NAME) == 0) {
+        stream.WriteFully("[",1);
+        if (record.m_SourceFunction) {
+            stream.WriteString(record.m_SourceFunction);
+        }
+        stream.WriteFully("] ",2);
+    }
+    const char* ansi_color = NULL;
+    if (use_colors) {
+        ansi_color = GetLogLevelAnsiColor(record.m_Level);
+        if (ansi_color) {
+            stream.Write("\033[", 2, NULL);
+            stream.WriteString(ansi_color);
+            stream.Write(";1m", 3, NULL);
+        }
+    }
+    stream.WriteString(level_name);
+    if (use_colors && ansi_color) {
+        stream.Write("\033[0m", 4, NULL);
+    }
+    stream.Write(": ", 2, NULL);
+    stream.WriteString(record.m_Message);
+    stream.Write("\n", 1, NULL);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::NPT_LogManager
++---------------------------------------------------------------------*/
+NPT_LogManager::NPT_LogManager() :
+    m_Configured(false),
+    m_Configuring(false),
+    m_Root(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::~NPT_LogManager
++---------------------------------------------------------------------*/
+NPT_LogManager::~NPT_LogManager()
+{
+    /* destroy everything we've created */
+    for (NPT_List<NPT_Logger*>::Iterator i = m_Loggers.GetFirstItem();
+         i;
+         ++i) {
+        NPT_Logger* logger = *i;
+        delete logger;
+    }
+
+    /* destroy the root logger */
+    delete m_Root;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::EnableLogging
++---------------------------------------------------------------------*/
+void
+NPT_LogManager::EnableLogging(bool value)
+{
+    LogManagerEnabled = value;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::SetConfig
++---------------------------------------------------------------------*/
+void
+NPT_LogManager::SetConfig(const char* config) 
+{
+    LogManagerConfig = config;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::Configure
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::Configure() 
+{
+    NPT_String  config_sources_env;
+    const char* config_sources = NPT_LOG_DEFAULT_CONFIG_SOURCE;
+
+    // exit if we're already initialized
+    if (m_Configured) return NPT_SUCCESS;
+    
+    // we're starting to configure ourselves
+    m_Configuring = true;
+
+    /* set some default config values */
+    SetConfigValue(".handlers", NPT_LOG_ROOT_DEFAULT_HANDLER);
+
+    if (!LogManagerConfig) {
+        /* see if the config sources have been set to non-default values */
+        if (NPT_SUCCEEDED(NPT_GetEnvironment(NPT_LOG_CONFIG_ENV, config_sources_env))) {
+            config_sources = config_sources_env;
+        }
+    } else {
+        config_sources = LogManagerConfig;
+    }
+
+    /* load all configs */
+    NPT_String config_source;
+    const char* cursor = config_sources; 
+    const char* source = config_sources;
+    for (;;) {
+        if (*cursor == '\0' || *cursor == '|') {
+            if (cursor != source) {
+                config_source.Assign(source, (NPT_Size)(cursor-source));
+                config_source.Trim(" \t");
+                ParseConfigSource(config_source);
+            }
+            if (*cursor == '\0') break;
+        }
+        cursor++;
+    }
+
+    /* create the root logger */
+    LogManager.m_Root = new NPT_Logger("");
+    LogManager.m_Root->m_Level = NPT_LOG_ROOT_DEFAULT_LOG_LEVEL;
+    LogManager.m_Root->m_LevelIsInherited = false;
+    ConfigureLogger(LogManager.m_Root);
+
+    // we're initialized now
+    m_Configured = true;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::ConfigValueIsBooleanTrue
++---------------------------------------------------------------------*/
+bool
+NPT_LogManager::ConfigValueIsBooleanTrue(NPT_String& value)
+{
+    return 
+        value.Compare("true", true) == 0 ||
+        value.Compare("yes",  true) == 0 ||
+        value.Compare("on",   true) == 0 ||
+        value.Compare("1",    true) == 0;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::ConfigValueIsBooleanFalse
++---------------------------------------------------------------------*/
+bool
+NPT_LogManager::ConfigValueIsBooleanFalse(NPT_String& value)
+{
+    return 
+        value.Compare("false", true) == 0  ||
+        value.Compare("no",    true) == 0  ||
+        value.Compare("off",   true) == 0  ||
+        value.Compare("0",     true) == 0;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::GetConfigValue
++---------------------------------------------------------------------*/
+NPT_String*
+NPT_LogManager::GetConfigValue(const char* prefix, const char* suffix)
+{
+    NPT_Size prefix_length = prefix?NPT_StringLength(prefix):0;
+    NPT_Size suffix_length = suffix?NPT_StringLength(suffix):0;
+    NPT_Size key_length    = prefix_length+suffix_length;
+    for (NPT_List<NPT_LogConfigEntry>::Iterator i = LogManager.m_Config.GetFirstItem();
+         i;
+         ++i) {
+        NPT_LogConfigEntry& entry = *i;
+        if ((entry.m_Key.GetLength() == key_length) &&
+            (prefix == NULL || entry.m_Key.StartsWith(prefix)) &&
+            (suffix == NULL || entry.m_Key.EndsWith(suffix  )) ) {
+            return &entry.m_Value;
+        }
+    }
+
+    // not found
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::SetConfigValue
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::SetConfigValue(const char* key, const char* value)
+{
+    NPT_String* value_string = GetConfigValue(key, NULL);
+    if (value_string) {
+        /* the key already exists, replace the value */
+        *value_string = value;
+    } else {
+        /* the value does not already exist, create a new one */
+        NPT_CHECK(LogManager.m_Config.Add(NPT_LogConfigEntry(key, value)));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::ParseConfig
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ParseConfig(const char* config,
+                            NPT_Size    config_size) 
+{
+    const char* cursor    = config;
+    const char* line      = config;
+    const char* separator = NULL;
+    NPT_String  key;
+    NPT_String  value;
+
+    /* parse all entries */
+    while (cursor <= config+config_size) {
+        /* separators are newlines, ';' or end of buffer */
+        if ( cursor == config+config_size ||
+            *cursor == '\n'              || 
+            *cursor == '\r'              || 
+            *cursor == ';') {
+            /* newline or end of buffer */
+            if (separator && line[0] != '#') {
+                /* we have a property */
+                key.Assign(line, (NPT_Size)(separator-line));
+                value.Assign(line+(separator+1-line), (NPT_Size)(cursor-(separator+1)));
+                key.Trim(" \t");
+                value.Trim(" \t");
+            
+                SetConfigValue((const char*)key, (const char*)value);
+            }
+            line = cursor+1;
+            separator = NULL;
+        } else if (*cursor == '=' && separator == NULL) {
+            separator = cursor;
+        }
+        cursor++;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::ParseConfigFile
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ParseConfigFile(const char* filename) 
+{
+    NPT_Result result;
+
+    /* load the file */
+    NPT_DataBuffer buffer;
+    result = NPT_File::Load(filename, buffer);
+    if (NPT_FAILED(result)) return result;
+
+    /* parse the config */
+    return ParseConfig((const char*)buffer.GetData(), buffer.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::ParseConfigSource
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ParseConfigSource(NPT_String& source) 
+{
+    if (source.StartsWith("file:")) {
+        /* file source */
+        ParseConfigFile(source.GetChars()+5);
+    } else if (source.StartsWith("plist:")) {
+        /* property list source */
+        ParseConfig(source.GetChars()+6, source.GetLength()-6);
+    } else {
+        return NPT_ERROR_INVALID_SYNTAX;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::HaveLoggerConfig
++---------------------------------------------------------------------*/
+bool
+NPT_LogManager::HaveLoggerConfig(const char* name)
+{
+    NPT_Size name_length = NPT_StringLength(name);
+    for (NPT_List<NPT_LogConfigEntry>::Iterator i = m_Config.GetFirstItem();
+         i;
+         ++i) {
+        NPT_LogConfigEntry& entry = *i;
+        if (entry.m_Key.StartsWith(name)) {
+            const char* suffix = entry.m_Key.GetChars()+name_length;
+            if (NPT_StringsEqual(suffix, ".level") ||
+                NPT_StringsEqual(suffix, ".handlers") ||
+                NPT_StringsEqual(suffix, ".forward")) {
+                return true;
+            }
+        }
+    }
+
+    /* no config found */
+    return false;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::ConfigureLogger
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogManager::ConfigureLogger(NPT_Logger* logger)
+{
+    /* configure the level */
+    NPT_String* level_value = GetConfigValue(logger->m_Name,".level");
+    if (level_value) {
+        NPT_Int32 value;
+        /* try a symbolic name */
+        value = NPT_Log::GetLogLevel(*level_value);
+        if (value < 0) {
+            /* try a numeric value */
+            if (NPT_FAILED(level_value->ToInteger(value, false))) {
+                value = -1;
+            }
+        }
+        if (value >= 0) {
+            logger->m_Level = value;
+            logger->m_LevelIsInherited = false;
+        }
+    }
+
+    /* configure the handlers */
+    NPT_String* handlers = GetConfigValue(logger->m_Name,".handlers");
+    if (handlers) {
+        const char*     handlers_list = handlers->GetChars();
+        const char*     cursor = handlers_list;
+        const char*     name_start = handlers_list;
+        NPT_String      handler_name;
+        NPT_LogHandler* handler;
+        for (;;) {
+            if (*cursor == '\0' || *cursor == ',') {
+                if (cursor != name_start) {
+                    handler_name.Assign(name_start, (NPT_Size)(cursor-name_start));
+                    handler_name.Trim(" \t");
+                    
+                    /* create a handler */
+                    if (NPT_SUCCEEDED(
+                        NPT_LogHandler::Create(logger->m_Name, handler_name, handler))) {
+                        logger->AddHandler(handler);
+                    }
+
+                }
+                if (*cursor == '\0') break;
+                name_start = cursor+1;
+            }
+            ++cursor;
+        }
+    }
+
+    /* configure the forwarding */
+    NPT_String* forward = GetConfigValue(logger->m_Name,".forward");
+    if (forward && !ConfigValueIsBooleanTrue(*forward)) {
+        logger->m_ForwardToParent = false;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::FindLogger
++---------------------------------------------------------------------*/
+NPT_Logger*
+NPT_LogManager::FindLogger(const char* name)
+{
+    for (NPT_List<NPT_Logger*>::Iterator i = LogManager.m_Loggers.GetFirstItem();
+         i;
+         ++i) {
+        NPT_Logger* logger = *i;
+        if (logger->m_Name == name) {
+            return logger;
+        }
+    }
+
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogManager::GetLogger
++---------------------------------------------------------------------*/
+NPT_Logger*
+NPT_LogManager::GetLogger(const char* name)
+{
+    NPT_Logger* logger;
+
+    /* check that LogManager was not turned off */
+    if (!LogManagerEnabled) return NULL;
+        
+    /* check that the manager is initialized */
+    if (!LogManager.m_Configured) {    
+        /* check that we're not in the middle of configuration */
+        if (LogManager.m_Configuring) return NULL;
+        
+        /* init the manager */
+        LogManager.Configure();
+        NPT_ASSERT(LogManager.m_Configured);
+    }
+
+    /* check if this logger is already configured */
+    logger = LogManager.FindLogger(name);
+    if (logger) return logger;
+
+    /* create a new logger */
+    logger = new NPT_Logger(name);
+    if (logger == NULL) return NULL;
+
+    /* configure the logger */
+    LogManager.ConfigureLogger(logger);
+
+    /* find which parent to attach to */
+    NPT_Logger* parent = LogManager.m_Root;
+    NPT_String  parent_name = name;
+    for (;;) {
+        NPT_Logger* candidate_parent;
+
+        /* find the last dot */
+        int dot = parent_name.ReverseFind('.');
+        if (dot < 0) break;
+        parent_name.SetLength(dot);
+        
+        /* see if the parent exists */
+        candidate_parent = LogManager.FindLogger(parent_name);
+        if (candidate_parent) {
+            parent = candidate_parent;
+            break;
+        }
+
+        /* this parent name does not exist, see if we need to create it */
+        if (LogManager.HaveLoggerConfig(parent_name)) {
+            parent = GetLogger(parent_name);
+            break;
+        }
+    }
+
+    /* attach to the parent */
+    logger->SetParent(parent);
+
+    /* add this logger to the list */
+    LogManager.m_Loggers.Add(logger);
+
+    return logger;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Logger::NPT_Logger
++---------------------------------------------------------------------*/
+NPT_Logger::NPT_Logger(const char* name) :
+    m_Name(name),
+    m_Level(NPT_LOG_LEVEL_OFF),
+    m_LevelIsInherited(true),
+    m_ForwardToParent(true),
+    m_Parent(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Logger::~NPT_Logger
++---------------------------------------------------------------------*/
+NPT_Logger::~NPT_Logger()
+{
+    /* destroy all handlers */
+    for (NPT_List<NPT_LogHandler*>::Iterator i = m_Handlers.GetFirstItem();
+         i;
+         ++i) {
+        NPT_LogHandler* handler = *i;
+        delete handler;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Logger::Log
++---------------------------------------------------------------------*/
+void
+NPT_Logger::Log(int          level, 
+                const char*  source_file,
+                unsigned int source_line,
+                const char*  source_function,
+                const char*  msg, 
+                             ...)
+{
+    char     buffer[NPT_LOG_STACK_BUFFER_MAX_SIZE];
+    NPT_Size buffer_size = sizeof(buffer);
+    char*    message = buffer;
+    int      result;
+    va_list  args;
+
+    va_start(args, msg);
+
+    /* check the log level (in case filtering has not already been done) */
+    if (level < m_Level) return;
+        
+    for(;;) {
+        /* try to format the message (it might not fit) */
+        result = NPT_FormatStringVN(message, buffer_size-1, msg, args);
+        if (result >= (int)(buffer_size-1)) result = -1;
+        message[buffer_size-1] = 0; /* force a NULL termination */
+        if (result >= 0) break;
+
+        /* the buffer was too small, try something bigger */
+        buffer_size = (buffer_size+NPT_LOG_HEAP_BUFFER_INCREMENT)*2;
+        if (buffer_size > NPT_LOG_HEAP_BUFFER_MAX_SIZE) break;
+        if (message != buffer) delete[] message;
+        message = new char[buffer_size];
+        if (message == NULL) return;
+    }
+
+    /* the message is formatted, publish it to the handlers */
+    NPT_LogRecord record;
+    NPT_Logger*   logger = this;
+    
+    /* setup the log record */
+    record.m_LoggerName     = logger->m_Name,
+    record.m_Level          = level;
+    record.m_Message        = message;
+    record.m_SourceFile     = source_file;
+    record.m_SourceLine     = source_line;
+    record.m_SourceFunction = source_function;
+    NPT_System::GetCurrentTimeStamp(record.m_TimeStamp);
+
+    /* call all handlers for this logger and parents */
+    while (logger) {
+        /* call all handlers for the current logger */
+        for (NPT_List<NPT_LogHandler*>::Iterator i = logger->m_Handlers.GetFirstItem();
+             i;
+             ++i) {
+            NPT_LogHandler* handler = *i;
+            handler->Log(record);
+        }
+
+        /* forward to the parent unless this logger does not forward */
+        if (logger->m_ForwardToParent) {
+            logger = logger->m_Parent;
+        } else {
+            break;
+        }
+    }
+
+    /* free anything we may have allocated */
+    if (message != buffer) delete[] message;
+
+    va_end(args);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Logger::AddHandler
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Logger::AddHandler(NPT_LogHandler* handler)
+{
+    /* check parameters */
+    if (handler == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+    return m_Handlers.Add(handler);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Logger::SetParent
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Logger::SetParent(NPT_Logger* parent)
+{
+    /* set our new parent */
+    m_Parent = parent;
+
+    /* find the first ancestor with its own log level */
+    NPT_Logger* logger = this;
+    while (logger->m_LevelIsInherited && logger->m_Parent) {
+        logger = logger->m_Parent;
+    }
+    if (logger != this) m_Level = logger->m_Level;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogNullHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogNullHandler::Create(NPT_LogHandler*& handler)
+{
+    handler = new NPT_LogNullHandler();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogNullHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogNullHandler::Log(const NPT_LogRecord& /*record*/)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogConsoleHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogConsoleHandler::Create(const char*      logger_name,
+                              NPT_LogHandler*& handler)
+{
+    /* compute a prefix for the configuration of this handler */
+    NPT_String logger_prefix = logger_name;
+    logger_prefix += ".ConsoleHandler";
+
+    /* allocate a new object */
+    NPT_LogConsoleHandler* instance = new NPT_LogConsoleHandler();
+    handler = instance;
+
+    /* configure the object */
+    NPT_String* colors;
+    instance->m_UseColors = NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE;
+    colors = LogManager.GetConfigValue(logger_prefix,".colors");
+    if (colors) {
+        if (NPT_LogManager::ConfigValueIsBooleanTrue(*colors)) {
+            instance->m_UseColors = true;
+        } else if (NPT_LogManager::ConfigValueIsBooleanFalse(*colors)) {
+            instance->m_UseColors = false;
+        }
+    }
+    NPT_String* filter;
+    instance->m_FormatFilter = 30; // default to nothing
+    filter = LogManager.GetConfigValue(logger_prefix,".filter");
+    if (filter) {
+        NPT_Int32 flags = 0;
+        filter->ToInteger(flags, true);
+        instance->m_FormatFilter = flags;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogConsoleHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogConsoleHandler::Log(const NPT_LogRecord& record)
+{
+    NPT_MemoryStream memory_stream(4096);
+
+    NPT_Log::FormatRecordToStream(record, memory_stream, m_UseColors, m_FormatFilter);
+    memory_stream.Write("\0", 1);
+    NPT_Console::Output((const char*)memory_stream.GetData());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogFileHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogFileHandler::Log(const NPT_LogRecord& record)
+{
+    if (m_Recycle > 0) {
+        m_RecycleLock.Lock();
+
+        /* get log size */
+        NPT_LargeSize size;
+        if (!m_InputStream.IsNull()) m_InputStream->GetSize(size);
+
+        /* time to recycle ? */
+        if (size > m_Recycle) {
+            /* release streams to force a reopen later */
+            m_OutputStream = NULL;
+            m_InputStream  = NULL;
+
+            /* move file */
+            NPT_TimeStamp now;
+            NPT_System::GetCurrentTimeStamp(now);
+
+            NPT_String new_name = NPT_FilePath::Create(
+                NPT_FilePath::DirectoryName(m_Filename),
+                NPT_FilePath::BaseName(m_Filename) + "-" + NPT_String::FromIntegerU(now.m_Seconds) + ".log");
+
+            NPT_File::Rename(m_Filename, new_name);
+        }
+    }
+    
+    /* try to reopen the file if it failed to open previously or if we recycled it */
+    if (m_InputStream.IsNull() || m_OutputStream.IsNull()) {
+        Open();
+    }
+    
+    if (m_InputStream.AsPointer() && m_OutputStream.AsPointer()) {
+        /* seek output stream to end of file */
+        NPT_LargeSize size;
+        m_InputStream->GetSize(size);
+        m_OutputStream->Seek(size);
+        
+        NPT_Debug("NPT_LogFileHandler told to seek to position %d\n", size);
+
+        NPT_Log::FormatRecordToStream(record, *m_OutputStream, false, m_FormatFilter);
+
+        /* force flushing */
+        m_OutputStream->Flush();
+    }
+
+    if (m_Recycle > 0) m_RecycleLock.Unlock();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogFileHandler::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogFileHandler::Open(bool append /* = true */)
+{
+    /* reset streams just in case */
+    m_OutputStream = NULL;
+    m_InputStream  = NULL;
+            
+    /* open the log file */
+    NPT_File file(m_Filename);
+    NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_CREATE |
+                                  NPT_FILE_OPEN_MODE_READ   |
+                                  NPT_FILE_OPEN_MODE_WRITE  |
+                                  (append?NPT_FILE_OPEN_MODE_APPEND:NPT_FILE_OPEN_MODE_TRUNCATE));
+    if (NPT_FAILED(result)) {
+        NPT_Debug("NPT_LogFileHandler::Open - cannot open log file '%s' (%d)\n", 
+            m_Filename.GetChars(), result);
+        return result;
+    }
+
+    NPT_CHECK(file.GetInputStream(m_InputStream));
+    NPT_CHECK(file.GetOutputStream(m_OutputStream));
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogFileHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogFileHandler::Create(const char*      logger_name,
+                           NPT_LogHandler*& handler)
+{
+    /* compute a prefix for the configuration of this handler */
+    NPT_String logger_prefix = logger_name;
+    logger_prefix += ".FileHandler";
+
+    /* allocate a new object */
+    NPT_LogFileHandler* instance = new NPT_LogFileHandler();
+    handler = instance;
+
+    /* filename */
+    NPT_String* filename_conf = LogManager.GetConfigValue(logger_prefix, ".filename");
+    if (filename_conf) {
+        instance->m_Filename = *filename_conf;
+    } else if (logger_name[0]) {
+        NPT_String filename_synth = logger_name;
+        filename_synth += ".log";
+        instance->m_Filename = filename_synth;
+    } else {
+        /* default name for the root logger */
+        instance->m_Filename = NPT_LOG_ROOT_DEFAULT_FILE_HANDLER_FILENAME;
+    }
+
+    /* append mode */
+    bool append = true;
+    NPT_String* append_mode = LogManager.GetConfigValue(logger_prefix, ".append");
+    if (append_mode && NPT_LogManager::ConfigValueIsBooleanFalse(*append_mode)) {
+        append = false;
+    }
+
+    /* filter */
+    NPT_String* filter;
+    instance->m_FormatFilter = 0;
+    filter = LogManager.GetConfigValue(logger_prefix,".filter");
+    if (filter) {
+        NPT_Int32 flags = 0;
+        filter->ToInteger(flags, true);
+        instance->m_FormatFilter = flags;
+    }
+
+    /* recycle */
+    NPT_String* recycle;
+    instance->m_Recycle = 0;
+    recycle = LogManager.GetConfigValue(logger_prefix,".recycle");
+    if (recycle) {
+        NPT_Int32 size = 0;
+        recycle->ToInteger(size, true);
+        if (size > NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE) {
+            instance->m_Recycle = size;
+        } else {
+            instance->m_Recycle = NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE;
+        }
+    }
+
+    /* open the log file */
+    return instance->Open(append);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogTcpHandler::Create
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogTcpHandler::Create(const char* logger_name, NPT_LogHandler*& handler)
+{
+    /* compute a prefix for the configuration of this handler */
+    NPT_String logger_prefix = logger_name;
+    logger_prefix += ".TcpHandler";
+
+    /* allocate a new object */
+    NPT_LogTcpHandler* instance = new NPT_LogTcpHandler();
+    handler = instance;
+
+    /* configure the object */
+    const NPT_String* hostname = LogManager.GetConfigValue(logger_prefix, ".hostname");
+    if (hostname) {
+        instance->m_Host = *hostname;
+    } else {
+        /* default hostname */
+        instance->m_Host = "localhost";
+    }
+    const NPT_String* port = LogManager.GetConfigValue(logger_prefix, ".port");
+    if (port) {
+        NPT_Int32 port_int;
+        if (NPT_SUCCEEDED(port->ToInteger(port_int, true))) {
+            instance->m_Port = (NPT_UInt16)port_int;
+        } else {
+            instance->m_Port = NPT_LOG_TCP_HANDLER_DEFAULT_PORT;
+        }
+    } else {
+        /* default port */
+        instance->m_Port = NPT_LOG_TCP_HANDLER_DEFAULT_PORT;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogTcpHandler::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_LogTcpHandler::Connect()
+{
+    /* create a socket */
+    NPT_Socket tcp_socket = new NPT_TcpClientSocket();
+
+    /* connect to the host */
+    NPT_IpAddress ip_address;
+    NPT_CHECK(ip_address.ResolveName(m_Host));
+    NPT_Result result = tcp_socket.Connect(NPT_SocketAddress(ip_address, m_Port), 
+                                           NPT_LOG_TCP_HANDLER_DEFAULT_CONNECT_TIMEOUT);
+    if (NPT_FAILED(result)) {
+        return result;
+    }
+
+    /* get the stream */
+    return tcp_socket.GetOutputStream(m_Stream);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_LogTcpHandler::Log
++---------------------------------------------------------------------*/
+void
+NPT_LogTcpHandler::Log(const NPT_LogRecord& record)
+{
+    /* ensure we're connected */
+    if (m_Stream.IsNull()) {
+        if (NPT_FAILED(Connect())) return;
+    }
+
+    /* format the record */
+    NPT_String msg;
+    const char* level_name = NPT_Log::GetLogLevelName(record.m_Level);
+    NPT_String  level_string;
+
+    /* format and emit the record */
+    if (level_name[0] == '\0') {
+        level_string = NPT_String::FromIntegerU(record.m_Level);
+        level_name = level_string;
+    }
+    msg.Reserve(2048);
+    msg += "Logger: ";
+    msg += record.m_LoggerName;
+    msg += "\r\nLevel: ";
+    msg += level_name;
+    msg += "\r\nSource-File: ";
+    msg += record.m_SourceFile;
+    msg += "\r\nSource-Line: ";
+    msg += NPT_String::FromIntegerU(record.m_SourceLine);
+    msg += "\r\nTimeStamp: ";
+    msg += NPT_String::FromIntegerU(record.m_TimeStamp.m_Seconds);
+    msg += ":";
+    msg += NPT_String::FromIntegerU(record.m_TimeStamp.m_NanoSeconds/1000000L);
+    msg += "\r\nContent-Length: ";
+    msg += NPT_String::FromIntegerU(NPT_StringLength(record.m_Message));
+    msg += "\r\n\r\n";
+    msg += record.m_Message;
+
+    /* emit the formatted record */
+    if (NPT_FAILED(m_Stream->WriteString(msg))) {
+        m_Stream = NULL;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptLogging.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,472 @@
+/*****************************************************************
+|
+|   Neptune - Logging Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+/** @file
+* Header file for logging
+*/
+
+#ifndef _NPT_LOGGING_H_
+#define _NPT_LOGGING_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptDebug.h"
+#include "NptTypes.h"
+#include "NptTime.h"
+#include "NptStrings.h"
+#include "NptList.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+class NPT_LogRecord {
+public:
+    const char*   m_LoggerName;
+    int           m_Level;
+    const char*   m_Message;
+    NPT_TimeStamp m_TimeStamp;
+    const char*   m_SourceFile;
+    unsigned int  m_SourceLine;
+    const char*   m_SourceFunction;
+};
+
+class NPT_LogHandler {
+public:
+    // class methods
+    static NPT_Result Create(const char*      logger_name,
+                             const char*      handler_name,
+                             NPT_LogHandler*& handler);
+
+    // methods
+    virtual void Log(const NPT_LogRecord& record) = 0;
+    virtual ~NPT_LogHandler() {}
+};
+
+class NPT_Logger {
+public:
+    // methods
+    NPT_Logger(const char* name);
+    ~NPT_Logger();
+    void Log(int          level, 
+             const char*  source_file,
+             unsigned int source_line,
+             const char*  source_function,
+             const char*  msg, 
+                          ...);
+
+    NPT_Result AddHandler(NPT_LogHandler* handler);
+    NPT_Result SetParent(NPT_Logger* parent);
+    int        GetLevel() const { return m_Level; }
+
+private:
+    // members
+    NPT_String                m_Name;
+    int                       m_Level;
+    bool                      m_LevelIsInherited;
+    bool                      m_ForwardToParent;
+    NPT_Logger*               m_Parent;
+    NPT_List<NPT_LogHandler*> m_Handlers;
+
+    // friends
+    friend class NPT_LogManager;
+};
+
+typedef struct {
+    NPT_Logger* logger;
+    const char* name;
+} NPT_LoggerReference;
+
+class NPT_Log {
+public:
+    // class methods
+    static int         GetLogLevel(const char* name);
+    static const char* GetLogLevelName(int level);
+    static const char* GetLogLevelAnsiColor(int level);
+    static void        FormatRecordToStream(const NPT_LogRecord& record,
+                                            NPT_OutputStream&    stream,
+                                            bool                 use_colors,
+                                            NPT_Flags            format_filter);
+};
+
+class NPT_LogConfigEntry {
+public:
+    NPT_LogConfigEntry(const char* key, const char* value) :
+      m_Key(key), m_Value(value) {}
+    NPT_String m_Key;
+    NPT_String m_Value;
+};
+
+class NPT_LogManager {
+public:
+    // class methods
+    static void EnableLogging(bool value);
+    static void SetConfig(const char* config);
+    static bool ConfigValueIsBooleanTrue(NPT_String& value);
+    static bool ConfigValueIsBooleanFalse(NPT_String& value);
+    static NPT_Logger* GetLogger(const char* name);
+
+    // methods
+    NPT_LogManager();
+    ~NPT_LogManager();
+    NPT_String* GetConfigValue(const char* prefix, const char* suffix);
+    NPT_Result  Configure();
+
+private:
+    // methods
+    NPT_Result  SetConfigValue(const char* key, const char* value);
+    NPT_Result  ParseConfig(const char* config, NPT_Size config_size);
+    NPT_Result  ParseConfigSource(NPT_String& source);
+    NPT_Result  ParseConfigFile(const char* filename);
+    bool        HaveLoggerConfig(const char* name);
+    NPT_Logger* FindLogger(const char* name);
+    NPT_Result  ConfigureLogger(NPT_Logger* logger);
+
+    // members
+    bool                         m_Configured;
+    bool                         m_Configuring;
+    NPT_List<NPT_LogConfigEntry> m_Config;
+    NPT_List<NPT_Logger*>        m_Loggers;
+    NPT_Logger*                  m_Root;
+};
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define NPT_LOG_LEVEL_FATAL   700
+#define NPT_LOG_LEVEL_SEVERE  600 
+#define NPT_LOG_LEVEL_WARNING 500
+#define NPT_LOG_LEVEL_INFO    400
+#define NPT_LOG_LEVEL_FINE    300
+#define NPT_LOG_LEVEL_FINER   200
+#define NPT_LOG_LEVEL_FINEST  100 
+
+#define NPT_LOG_LEVEL_OFF     32767
+#define NPT_LOG_LEVEL_ALL     0
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#define NPT_LOG_GET_LOGGER(_logger)                                   \
+    if ((_logger).logger == NULL) {                                   \
+        (_logger).logger = NPT_LogManager::GetLogger((_logger).name); \
+    }
+
+#if defined(NPT_CONFIG_ENABLE_LOGGING)
+
+#define NPT_DEFINE_LOGGER(_logger, _name) static NPT_LoggerReference _logger = { NULL, (_name) };
+
+#define NPT_LOG_X(_logger, _level, _argsx)                              \
+do {                                                                    \
+    NPT_LOG_GET_LOGGER((_logger))                                       \
+    if ((_logger).logger && (_level) >= (_logger).logger->GetLevel()) { \
+        (_logger).logger->Log _argsx;                                   \
+    }                                                                   \
+} while(0)
+
+#define NPT_CHECK_LL(_logger, _level, _result) do {                                    \
+    NPT_Result _x = (_result);                                                         \
+    if (_x != NPT_SUCCESS) {                                                           \
+        NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"NPT_CHECK failed, result=%d [%s]", _x, NPT_ResultText(_x))); \
+        return _x;                                                                     \
+    }                                                                                  \
+} while(0)
+
+#define NPT_CHECK_LABEL_LL(_logger, _level, _result, _label) do {                      \
+    NPT_Result _x = (_result);                                                         \
+    if (_x != NPT_SUCCESS) {                                                           \
+        NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"NPT_CHECK failed, result=%d [%s]", _x, NPT_ResultText(_x))); \
+        goto _label;                                                                   \
+    }                                                                                  \
+} while(0)
+#define NPT_CHECK_POINTER_LL(_logger, _level, _p) do {                                 \
+    if ((_p) == NULL) {                                                                  \
+        NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"@@@ NULL pointer parameter"));                     \
+        return NPT_ERROR_INVALID_PARAMETERS;                                                     \
+    }                                                                                  \
+} while(0)
+#define NPT_CHECK_POINTER_LABEL_LL(_logger, _level, _p, _label) do {                   \
+    if ((_p) == NULL) {                                                                  \
+        NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"@@@ NULL pointer parameter"));                     \
+        goto _label;                                                                   \
+    }                                                                                  \
+} while(0)
+
+#else /* NPT_CONFIG_ENABLE_LOGGING */
+
+#define NPT_DEFINE_LOGGER(_logger, _name)
+#define NPT_LOG_X(_logger, _level, _argsx)
+#define NPT_CHECK_LL(_logger, _level, _result) NPT_CHECK(_result)
+#define NPT_CHECK_LABEL_LL(_logger, _level, _result, _label) NPT_CHECK_LABEL((_result), _label)
+#define NPT_CHECK_POINTER_LL(_logger, _level, _p) NPT_CHECK_POINTER((_p))
+#define NPT_CHECK_POINTER_LABEL_LL(_logger, _level, _p, _label) NPT_CHECK_POINTER_LABEL((_p), _label)
+
+#endif /* NPT_CONFIG_ENABLE_LOGGING */
+
+#define NPT_SET_LOCAL_LOGGER(_name) NPT_DEFINE_LOGGER(_NPT_LocalLogger, (_name))
+#define NPT_CHECK_L(_level, _result) NPT_CHECK_LL(_NPT_LocalLogger, (_level), (_result))
+#define NPT_CHECK_LABEL_L(_level, _result, _label) NPT_CHECK_LABEL_LL(_NPT_LocalLogger, (_level), NULL, (_result), _label)
+
+/* NOTE: the following are machine-generated, do not edit */
+#define NPT_LOG_LL(_logger,_level,_msg) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg)))
+#define NPT_LOG(_level,_msg) NPT_LOG_LL((_NPT_LocalLogger),(_level),(_msg))
+#define NPT_LOG_L(_logger,_level,_msg) NPT_LOG_LL((_logger),(_level),(_msg))
+#define NPT_LOG_LL1(_logger,_level,_msg,_arg1) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1)))
+#define NPT_LOG_1(_level,_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),(_level),(_msg),(_arg1))
+#define NPT_LOG_L1(_logger,_level,_msg,_arg1) NPT_LOG_LL1((_logger),(_level),(_msg),(_arg1))
+#define NPT_LOG_LL2(_logger,_level,_msg,_arg1,_arg2) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2)))
+#define NPT_LOG_2(_level,_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2))
+#define NPT_LOG_L2(_logger,_level,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),(_level),(_msg),(_arg1),(_arg2))
+#define NPT_LOG_LL3(_logger,_level,_msg,_arg1,_arg2,_arg3) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3)))
+#define NPT_LOG_3(_level,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_L3(_logger,_level,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_LL4(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4)))
+#define NPT_LOG_4(_level,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_L4(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_LL5(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5)))
+#define NPT_LOG_5(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_L5(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_LL6(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6)))
+#define NPT_LOG_6(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_L6(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_LL7(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7)))
+#define NPT_LOG_7(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_L7(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_LL8(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8)))
+#define NPT_LOG_8(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_L8(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_LL9(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9)))
+#define NPT_LOG_9(_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_L9(_logger,_level,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),(_level),(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+
+#define NPT_LOG_FATAL(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg))
+#define NPT_LOG_FATAL_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FATAL,(_msg))
+#define NPT_LOG_FATAL_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1))
+#define NPT_LOG_FATAL_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1))
+#define NPT_LOG_FATAL_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FATAL_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FATAL_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FATAL_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FATAL_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FATAL_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FATAL_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FATAL_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FATAL_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FATAL_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FATAL_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FATAL_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FATAL_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FATAL_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FATAL_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FATAL_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FATAL,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_SEVERE(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg))
+#define NPT_LOG_SEVERE_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_SEVERE,(_msg))
+#define NPT_LOG_SEVERE_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1))
+#define NPT_LOG_SEVERE_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1))
+#define NPT_LOG_SEVERE_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_SEVERE_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_SEVERE_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_SEVERE_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_SEVERE_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_SEVERE_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_SEVERE_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_SEVERE_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_SEVERE_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_SEVERE_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_SEVERE_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_SEVERE_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_SEVERE_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_SEVERE_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_SEVERE_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_SEVERE_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_SEVERE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_WARNING(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg))
+#define NPT_LOG_WARNING_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_WARNING,(_msg))
+#define NPT_LOG_WARNING_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1))
+#define NPT_LOG_WARNING_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1))
+#define NPT_LOG_WARNING_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_WARNING_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_WARNING_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_WARNING_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_WARNING_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_WARNING_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_WARNING_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_WARNING_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_WARNING_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_WARNING_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_WARNING_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_WARNING_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_WARNING_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_WARNING_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_WARNING_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_WARNING_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_WARNING,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_INFO(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg))
+#define NPT_LOG_INFO_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_INFO,(_msg))
+#define NPT_LOG_INFO_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1))
+#define NPT_LOG_INFO_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1))
+#define NPT_LOG_INFO_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_INFO_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_INFO_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_INFO_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_INFO_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_INFO_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_INFO_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_INFO_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_INFO_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_INFO_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_INFO_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_INFO_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_INFO_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_INFO_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_INFO_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_INFO_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_INFO,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINE(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg))
+#define NPT_LOG_FINE_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FINE,(_msg))
+#define NPT_LOG_FINE_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1))
+#define NPT_LOG_FINE_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1))
+#define NPT_LOG_FINE_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINE_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINE_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINE_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINE_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINE_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINE_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINE_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINE_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINE_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINE_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINE_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINE_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINE_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINE_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINE_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FINE,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINER(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg))
+#define NPT_LOG_FINER_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FINER,(_msg))
+#define NPT_LOG_FINER_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1))
+#define NPT_LOG_FINER_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1))
+#define NPT_LOG_FINER_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINER_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINER_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINER_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINER_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINER_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINER_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINER_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINER_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINER_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINER_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINER_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINER_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINER_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINER_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINER_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FINER,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINEST(_msg) NPT_LOG_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg))
+#define NPT_LOG_FINEST_L(_logger,_msg) NPT_LOG_LL((_logger),NPT_LOG_LEVEL_FINEST,(_msg))
+#define NPT_LOG_FINEST_1(_msg,_arg1) NPT_LOG_LL1((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1))
+#define NPT_LOG_FINEST_L1(_logger,_msg,_arg1) NPT_LOG_LL1((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1))
+#define NPT_LOG_FINEST_2(_msg,_arg1,_arg2) NPT_LOG_LL2((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINEST_L2(_logger,_msg,_arg1,_arg2) NPT_LOG_LL2((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2))
+#define NPT_LOG_FINEST_3(_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINEST_L3(_logger,_msg,_arg1,_arg2,_arg3) NPT_LOG_LL3((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3))
+#define NPT_LOG_FINEST_4(_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINEST_L4(_logger,_msg,_arg1,_arg2,_arg3,_arg4) NPT_LOG_LL4((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4))
+#define NPT_LOG_FINEST_5(_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINEST_L5(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5) NPT_LOG_LL5((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5))
+#define NPT_LOG_FINEST_6(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINEST_L6(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6) NPT_LOG_LL6((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6))
+#define NPT_LOG_FINEST_7(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINEST_L7(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7) NPT_LOG_LL7((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7))
+#define NPT_LOG_FINEST_8(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINEST_L8(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8) NPT_LOG_LL8((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8))
+#define NPT_LOG_FINEST_9(_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+#define NPT_LOG_FINEST_L9(_logger,_msg,_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9) NPT_LOG_LL9((_logger),NPT_LOG_LEVEL_FINEST,(_msg),(_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6),(_arg7),(_arg8),(_arg9))
+
+#define NPT_CHECK_FATAL(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_result))
+#define NPT_CHECK_FATAL_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FATAL,(_result))
+#define NPT_CHECK_SEVERE(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_result))
+#define NPT_CHECK_SEVERE_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_SEVERE,(_result))
+#define NPT_CHECK_WARNING(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_result))
+#define NPT_CHECK_WARNING_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_WARNING,(_result))
+#define NPT_CHECK_INFO(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_result))
+#define NPT_CHECK_INFO_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_INFO,(_result))
+#define NPT_CHECK_FINE(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_result))
+#define NPT_CHECK_FINE_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FINE,(_result))
+#define NPT_CHECK_FINER(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_result))
+#define NPT_CHECK_FINER_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FINER,(_result))
+#define NPT_CHECK_FINEST(_result) NPT_CHECK_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_result))
+#define NPT_CHECK_FINEST_L(_logger,_result) NPT_CHECK_LL((_logger),NPT_LOG_LEVEL_FINEST,(_result))
+
+#define NPT_CHECK_LABEL_FATAL(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_result),_label)
+#define NPT_CHECK_LABEL_FATAL_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FATAL,(_result),_label)
+#define NPT_CHECK_LABEL_SEVERE(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_result),_label)
+#define NPT_CHECK_LABEL_SEVERE_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_SEVERE,(_result),_label)
+#define NPT_CHECK_LABEL_WARNING(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_result),_label)
+#define NPT_CHECK_LABEL_WARNING_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_WARNING,(_result),_label)
+#define NPT_CHECK_LABEL_INFO(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_result),_label)
+#define NPT_CHECK_LABEL_INFO_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_INFO,(_result),_label)
+#define NPT_CHECK_LABEL_FINE(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_result),_label)
+#define NPT_CHECK_LABEL_FINE_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FINE,(_result),_label)
+#define NPT_CHECK_LABEL_FINER(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_result),_label)
+#define NPT_CHECK_LABEL_FINER_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FINER,(_result),_label)
+#define NPT_CHECK_LABEL_FINEST(_result,_label) NPT_CHECK_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_result),_label)
+#define NPT_CHECK_LABEL_FINEST_L(_logger,_result,_label) NPT_CHECK_LABEL_LL((_logger),NPT_LOG_LEVEL_FINEST,(_result),_label)
+
+#define NPT_CHECK_POINTER_FATAL(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_p))
+#define NPT_CHECK_POINTER_FATAL_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FATAL,(_p))
+#define NPT_CHECK_POINTER_SEVERE(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_p))
+#define NPT_CHECK_POINTER_SEVERE_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_SEVERE,(_p))
+#define NPT_CHECK_POINTER_WARNING(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_p))
+#define NPT_CHECK_POINTER_WARNING_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_WARNING,(_p))
+#define NPT_CHECK_POINTER_INFO(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_p))
+#define NPT_CHECK_POINTER_INFO_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_INFO,(_p))
+#define NPT_CHECK_POINTER_FINE(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_p))
+#define NPT_CHECK_POINTER_FINE_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FINE,(_p))
+#define NPT_CHECK_POINTER_FINER(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_p))
+#define NPT_CHECK_POINTER_FINER_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FINER,(_p))
+#define NPT_CHECK_POINTER_FINEST(_p) NPT_CHECK_POINTER_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_p))
+#define NPT_CHECK_POINTER_FINEST_L(_logger,_p) NPT_CHECK_POINTER_LL(_logger,NPT_LOG_LEVEL_FINEST,(_p))
+
+#define NPT_CHECK_POINTER_LABEL_FATAL(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FATAL,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FATAL_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FATAL,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_SEVERE(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_SEVERE,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_SEVERE_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_SEVERE,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_WARNING(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_WARNING,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_WARNING_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_WARNING,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_INFO(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_INFO,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_INFO_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_INFO,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FINE(_p, _label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINE,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FINE_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FINE,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FINER(_p,_label) NPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINER,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FINER_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FINER,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FINEST(_p,_label) NNPT_CHECK_POINTER_LABEL_LL((_NPT_LocalLogger),NPT_LOG_LEVEL_FINEST,(_p),(_label))
+#define NPT_CHECK_POINTER_LABEL_FINEST_L(_logger,_p,_label) NPT_CHECK_POINTER_LABEL_LL(_logger,NPT_LOG_LEVEL_FINEST,(_p),(_label))
+
+#endif /* _NPT_LOGGING_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptMap.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,330 @@
+/*****************************************************************
+|
+|   Neptune - Maps
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_MAP_H_
+#define _NPT_MAP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptResults.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Map
++---------------------------------------------------------------------*/
+template <typename K, typename V> 
+class NPT_Map 
+{
+public:
+    // types
+    class Entry {
+    public:
+        // constructor
+        Entry(const K& key, const V& value) : m_Key(key), m_Value(value) {}
+        Entry(const K& key) : m_Key(key) {}
+        
+        // accessors
+        const K& GetKey()   const { return m_Key;   }
+        const V& GetValue() const { return m_Value; }
+
+        // operators 
+        bool operator==(const Entry& other) const {
+            return m_Key == other.m_Key && m_Value == other.m_Value;
+        }
+
+    protected:
+        // methods
+        void SetValue(const V& value) { m_Value = value; }
+
+        // members
+        K m_Key;
+        V m_Value;
+
+        // friends
+        friend class NPT_Map<K,V>;
+    };
+
+    class EntryValueDeleter {
+    public:
+        void operator()(Entry* entry) const {
+            delete entry->GetValue();
+        }
+    };
+
+    // constructors
+    NPT_Map<K,V>() {}
+    NPT_Map<K,V>(const NPT_Map<K,V>& copy);
+
+    // destructor
+    ~NPT_Map<K,V>();
+
+    // methods
+    NPT_Result   Put(const K& key, const V& value);
+    NPT_Result   Get(const K& key, V*& value) const;
+    bool         HasKey(const K& key) const { return GetEntry(key) != NULL; }
+    bool         HasValue(const V& value) const;
+    NPT_Result   Erase(const K& key);
+    NPT_Cardinal GetEntryCount() const         { return m_Entries.GetItemCount(); }
+    const NPT_List<Entry*>& GetEntries() const { return m_Entries; }
+    NPT_Result   Clear();
+
+    // operators
+    V&                  operator[](const K& key);
+    const NPT_Map<K,V>& operator=(const NPT_Map<K,V>& copy);
+    bool                operator==(const NPT_Map<K,V>& other) const;
+    bool                operator!=(const NPT_Map<K,V>& other) const;
+
+private:
+    // types
+    typedef typename NPT_List<Entry*>::Iterator ListIterator;
+
+    // methods
+    Entry* GetEntry(const K& key) const;
+
+    // members
+    NPT_List<Entry*> m_Entries;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::NPT_Map<K,V>
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+NPT_Map<K,V>::NPT_Map(const NPT_Map<K,V>& copy)
+{
+    *this = copy;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::~NPT_Map<K,V>
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+NPT_Map<K,V>::~NPT_Map()
+{
+    // call Clear to ensure we delete all entry objects
+    Clear();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::Clear
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+NPT_Result
+NPT_Map<K,V>::Clear()
+{
+    m_Entries.Apply(NPT_ObjectDeleter<Entry>());
+    m_Entries.Clear();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::GetEntry
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+typename NPT_Map<K,V>::Entry*
+NPT_Map<K,V>::GetEntry(const K& key) const
+{
+    typename NPT_List<Entry*>::Iterator entry = m_Entries.GetFirstItem();
+    while (entry) {
+        if ((*entry)->GetKey() == key) {
+            return *entry;
+        }
+        ++entry;
+    }
+
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::Put
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+NPT_Result
+NPT_Map<K,V>::Put(const K& key, const V& value)
+{
+    Entry* entry = GetEntry(key);
+    if (entry == NULL) {
+        // no existing entry for that key, create one
+        m_Entries.Add(new Entry(key, value));
+    } else {
+        // replace the existing entry for that key
+        entry->SetValue(value);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::Get
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+NPT_Result
+NPT_Map<K,V>::Get(const K& key, V*& value) const
+{
+    Entry* entry = GetEntry(key);
+    if (entry == NULL) {
+        // no existing entry for that key
+        value = NULL;
+        return NPT_ERROR_NO_SUCH_ITEM;
+    } else {
+        // found an entry with that key
+        value = &entry->m_Value;
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::HasValue
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+bool
+NPT_Map<K,V>::HasValue(const V& value) const
+{
+    ListIterator entry = m_Entries.GetFirstItem();
+    while (entry) {
+        if (value == (*entry)->m_Value) {
+            return true;
+        }
+        ++entry;
+    }
+
+    return false;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::operator=
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+const NPT_Map<K,V>&
+NPT_Map<K,V>::operator=(const NPT_Map<K,V>& copy)
+{
+    // do nothing if we're assigning to ourselves
+    if (this == &copy) return copy;
+
+    // destroy all entries
+    Clear();
+
+    // copy all entries one by one
+    ListIterator entry = copy.m_Entries.GetFirstItem();
+    while (entry) {
+        m_Entries.Add(new Entry((*entry)->GetKey(), (*entry)->GetValue()));
+        ++entry;
+    }
+
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::Erase
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+NPT_Result
+NPT_Map<K,V>::Erase(const K& key)
+{
+    ListIterator entry = m_Entries.GetFirstItem();
+    while (entry) {
+        if ((*entry)->GetKey() == key) {
+            delete *entry; // do this before removing the entry from the
+                           // list, because Erase() will invalidate the
+                           // iterator item
+            m_Entries.Erase(entry);
+            return NPT_SUCCESS;
+        }
+        ++entry;
+    }
+
+    return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::operator==
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+bool
+NPT_Map<K,V>::operator==(const NPT_Map<K,V>& other) const
+{
+    // quick test
+    if (m_Entries.GetItemCount() != other.m_Entries.GetItemCount()) return false;
+
+    // compare all entries to all other entries
+    ListIterator entry = m_Entries.GetFirstItem();
+    while (entry) {
+        V* value;
+        if (NPT_SUCCEEDED(other.Get((*entry)->m_Key, value))) {
+            // the other map has an entry for this key, check the value
+            if (!(*value == (*entry)->m_Value)) return false;
+        } else {
+            // the other map does not have an entry for this key
+            return false;
+        }
+        ++entry;
+    }
+
+    return true;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::operator!=
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+bool
+NPT_Map<K,V>::operator!=(const NPT_Map<K,V>& other) const
+{
+    return !(*this == other);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Map<K,V>::operator[]
++---------------------------------------------------------------------*/
+template <typename K, typename V>
+inline
+V&
+NPT_Map<K,V>::operator[](const K& key)
+{
+    Entry* entry = GetEntry(key);
+    if (entry == NULL) {
+        // create a new "default" entry for this key
+        entry = new Entry(key);
+        m_Entries.Add(entry);
+    }
+     
+    return entry->m_Value;
+}
+
+#endif // _NPT_MAP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptMessaging.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,49 @@
+/*****************************************************************
+|
+|   Neptune - Messaging System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptMessaging.h"
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+NPT_Message::Type NPT_Message::MessageType = "Generic Message";
+
+/*----------------------------------------------------------------------
+|   NPT_MessageHandler::HandleMessage
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_MessageHandler::HandleMessage(NPT_Message* message)
+{
+    return message->Dispatch(this);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptMessaging.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,173 @@
+/*****************************************************************
+|
+|   Neptune - Messaging System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_MESSAGING_H_
+#define _NPT_MESSAGING_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConstants.h"
+#include "NptTypes.h"
+#include "NptResults.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+|   forward references
++---------------------------------------------------------------------*/
+class NPT_Message;
+
+/*----------------------------------------------------------------------
+|   NPT_MessageHandler
++---------------------------------------------------------------------*/
+class NPT_MessageHandler
+{
+ public:
+    // methods
+    virtual ~NPT_MessageHandler() {}
+
+    // default message handler
+    virtual void OnMessage(NPT_Message*) {}
+
+    // this method is a central point of handling for received messages.
+    // it can be overloaded by subclasses who wish to process all 
+    // incoming messages
+    virtual NPT_Result HandleMessage(NPT_Message* message);
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Messsage
++---------------------------------------------------------------------*/
+class NPT_Message
+{
+ public:
+    // types
+    typedef const char* Type;
+
+    // static members
+    static Type MessageType;
+
+    // methods
+    virtual           ~NPT_Message() {}
+    virtual Type       GetType() { return MessageType; }
+    virtual NPT_Result Dispatch(NPT_MessageHandler* handler) {
+        return DefaultDeliver(handler);
+    }
+    // this method should really be called 'Deliver', but this would
+    // cause a problem when subclasses overload it 
+    virtual NPT_Result DefaultDeliver(NPT_MessageHandler* handler) {
+        handler->OnMessage(this);
+        return NPT_SUCCESS;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TerminateMesssage
++---------------------------------------------------------------------*/
+class NPT_TerminateMessage : public NPT_Message
+{
+ public:
+    // methods
+    NPT_Result Dispatch(NPT_MessageHandler* /*handler*/) {
+        return NPT_ERROR_TERMINATED;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_MessageQueue
++---------------------------------------------------------------------*/
+class NPT_MessageQueue
+{
+ public:
+    // methods
+    virtual           ~NPT_MessageQueue() {}
+    virtual NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+    virtual NPT_Result QueueMessage(NPT_Message*        message, 
+                                    NPT_MessageHandler* handler) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_MessageReceiver
++---------------------------------------------------------------------*/
+class NPT_MessageReceiver
+{
+public:
+    // methods
+    NPT_MessageReceiver() : m_Queue(NULL), m_Handler(NULL) {}
+    NPT_MessageReceiver(NPT_MessageHandler* handler) : 
+        m_Queue(NULL), m_Handler(handler) {}
+    NPT_MessageReceiver(NPT_MessageQueue* queue) : 
+        m_Queue(queue), m_Handler(NULL) {}
+    NPT_MessageReceiver(NPT_MessageHandler* handler, 
+                        NPT_MessageQueue*   queue) : 
+        m_Queue(queue), m_Handler(handler) {}
+    virtual ~NPT_MessageReceiver() {}
+    NPT_Result SetQueue(NPT_MessageQueue* queue) {
+        m_Queue = queue;
+        return NPT_SUCCESS;
+    }
+    NPT_Result SetHandler(NPT_MessageHandler* handler) {
+        m_Handler = handler;
+        return NPT_SUCCESS;
+    }
+    virtual NPT_Result PostMessage(NPT_Message* message) {
+        if (m_Queue) {
+            return m_Queue->QueueMessage(message, m_Handler);
+        } else {
+            return NPT_FAILURE;
+        }
+    }
+
+protected:
+    // members
+    NPT_MessageQueue*   m_Queue;
+    NPT_MessageHandler* m_Handler;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_MessageBroadcaster
++---------------------------------------------------------------------*/
+class NPT_MessageBroadcaster
+{
+public:
+    // methods
+    NPT_MessageBroadcaster(NPT_Message* message) : m_Message(message) {}
+    NPT_Result operator()(NPT_MessageReceiver*& receiver) const {
+        receiver->PostMessage(m_Message);
+        return NPT_SUCCESS;
+    }
+
+private:
+    // members
+    NPT_Message* m_Message;
+};
+
+#endif // _NPT_MESSAGING_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptNetwork.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,247 @@
+/*****************************************************************
+|
+|   Neptune - Network
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptSockets.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::Any
++---------------------------------------------------------------------*/
+const NPT_IpAddress NPT_IpAddress::Any;
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress()
+{
+    m_Address[0] = m_Address[1] = m_Address[2] = m_Address[3] = 0;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::NPT_IpAddress
++---------------------------------------------------------------------*/
+NPT_IpAddress::NPT_IpAddress(unsigned long address)
+{
+    Set(address);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_IpAddress::Parse(const char* name)
+{
+    // check the name
+    if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // clear the address
+    m_Address[0] = m_Address[1] = m_Address[2] = m_Address[3] = 0;
+
+    // parse
+    unsigned int  fragment;
+    bool          fragment_empty = true;
+    unsigned char address[4];
+    unsigned int  accumulator;
+    for (fragment = 0, accumulator = 0; fragment < 4; ++name) {
+        if (*name == '\0' || *name == '.') {
+            // fragment terminator
+            if (fragment_empty) return NPT_ERROR_INVALID_SYNTAX;
+            address[fragment++] = accumulator;
+            if (*name == '\0') break;
+            accumulator = 0;
+            fragment_empty = true;
+        } else if (*name >= '0' && *name <= '9') {
+            // numerical character
+            accumulator = accumulator*10 + (*name - '0');
+            if (accumulator > 255) return NPT_ERROR_INVALID_SYNTAX;
+            fragment_empty = false; 
+        } else {
+            // invalid character
+            return NPT_ERROR_INVALID_SYNTAX;
+        }
+    }
+
+    if (fragment == 4 && *name == '\0' && !fragment_empty) {
+        m_Address[0] = address[0];
+        m_Address[1] = address[1];
+        m_Address[2] = address[2];
+        m_Address[3] = address[3];
+        return NPT_SUCCESS;
+    } else {
+        return NPT_ERROR_INVALID_SYNTAX;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::AsLong
++---------------------------------------------------------------------*/
+unsigned long
+NPT_IpAddress::AsLong() const
+{
+    return 
+        (((unsigned long)m_Address[0])<<24) |
+        (((unsigned long)m_Address[1])<<16) |
+        (((unsigned long)m_Address[2])<< 8) |
+        (((unsigned long)m_Address[3]));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::AsBytes
++---------------------------------------------------------------------*/
+const unsigned char* 
+NPT_IpAddress::AsBytes() const
+{
+    return m_Address;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_IpAddress::ToString() const
+{
+    NPT_String address;
+    address.Reserve(16);
+    address += NPT_String::FromInteger(m_Address[0]);
+    address += '.';
+    address += NPT_String::FromInteger(m_Address[1]);
+    address += '.';
+    address += NPT_String::FromInteger(m_Address[2]);
+    address += '.';
+    address += NPT_String::FromInteger(m_Address[3]);
+
+    return address;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::Set
++---------------------------------------------------------------------*/
+NPT_Result    
+NPT_IpAddress::Set(const unsigned char bytes[4])
+{
+    m_Address[0] = bytes[0];
+    m_Address[1] = bytes[1];
+    m_Address[2] = bytes[2];
+    m_Address[3] = bytes[3];
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::Set
++---------------------------------------------------------------------*/
+NPT_Result    
+NPT_IpAddress::Set(unsigned long address)
+{
+    m_Address[0] = (unsigned char)((address >> 24) & 0xFF);
+    m_Address[1] = (unsigned char)((address >> 16) & 0xFF);
+    m_Address[2] = (unsigned char)((address >>  8) & 0xFF);
+    m_Address[3] = (unsigned char)((address      ) & 0xFF);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MacAddress::NPT_MacAddress
++---------------------------------------------------------------------*/
+NPT_MacAddress::NPT_MacAddress(Type                  type,
+                               const unsigned char*  address, 
+                               unsigned int          length)
+{
+    SetAddress(type, address, length);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MacAddress::SetAddress
++---------------------------------------------------------------------*/
+void
+NPT_MacAddress::SetAddress(Type                 type,
+                           const unsigned char* address, 
+                           unsigned int         length)
+{
+    m_Type = type;
+    if (length > NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH) {
+        length = NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH;
+    }
+    m_Length = length;
+    for (unsigned int i=0; i<length; i++) {
+        m_Address[i] = address[i];
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MacAddress::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_MacAddress::ToString() const
+{
+    NPT_String result;
+ 
+    if (m_Length) {
+        char s[3*NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH];
+        const char hex[17] = "0123456789abcdef";
+        for (unsigned int i=0; i<m_Length; i++) {
+            s[i*3  ] = hex[m_Address[i]>>4];
+            s[i*3+1] = hex[m_Address[i]&0xf];
+            s[i*3+2] = ':';
+        }
+        s[3*m_Length-1] = '\0';
+        result = s;
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterface::NPT_NetworkInterface
++---------------------------------------------------------------------*/ 
+NPT_NetworkInterface::NPT_NetworkInterface(const char*           name,
+                                           const NPT_MacAddress& mac,
+                                           NPT_Flags             flags) :
+    m_Name(name),
+    m_MacAddress(mac),
+    m_Flags(flags)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterface::AddAddress
++---------------------------------------------------------------------*/ 
+NPT_Result
+NPT_NetworkInterface::AddAddress(const NPT_NetworkInterfaceAddress& address)
+{
+    return m_Addresses.Add(address);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptNetwork.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,210 @@
+/*****************************************************************
+|
+|   Neptune - Network
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_NETWORK_H_
+#define _NPT_NETWORK_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH  = 8;
+
+/*----------------------------------------------------------------------
+|   flags
++---------------------------------------------------------------------*/
+#define NPT_NETWORK_INTERFACE_FLAG_LOOPBACK       0x01
+#define NPT_NETWORK_INTERFACE_FLAG_PROMISCUOUS    0x02
+#define NPT_NETWORK_INTERFACE_FLAG_BROADCAST      0x04
+#define NPT_NETWORK_INTERFACE_FLAG_MULTICAST      0x08
+#define NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT 0x10
+
+/*----------------------------------------------------------------------
+|   workarounds
++---------------------------------------------------------------------*/
+#if defined(_WIN32)
+#if defined(SetPort)
+#undef SetPort
+#endif
+#endif
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef unsigned int NPT_IpPort;
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress
++---------------------------------------------------------------------*/
+class NPT_IpAddress
+{
+public:
+    // class members
+    static const NPT_IpAddress Any;
+
+    // constructors and destructor
+    NPT_IpAddress();
+    NPT_IpAddress(unsigned long address);
+
+    // methods
+    NPT_Result       ResolveName(const char* name, 
+                                 NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+    NPT_Result       Parse(const char* name);
+    NPT_Result       Set(unsigned long address);
+    NPT_Result       Set(const unsigned char bytes[4]);
+    const unsigned char* AsBytes() const;
+    unsigned long    AsLong() const;
+    NPT_String       ToString() const;
+    
+private:
+    // members
+    unsigned char m_Address[4];
+};
+
+/*----------------------------------------------------------------------
+|   NPT_MacAddress
++---------------------------------------------------------------------*/
+class NPT_MacAddress
+{
+public:
+    // typedef enum
+    typedef enum {
+        TYPE_UNKNOWN,
+        TYPE_LOOPBACK,
+        TYPE_ETHERNET,
+        TYPE_PPP,
+        TYPE_IEEE_802_11
+    } Type;
+    
+    // constructors and destructor
+    NPT_MacAddress() : m_Type(TYPE_UNKNOWN), m_Length(0) {}
+    NPT_MacAddress(Type           type,
+                   const unsigned char* addr, 
+                   unsigned int   length);
+    
+    // methods
+    void                 SetAddress(Type type, const unsigned char* addr,
+                                    unsigned int length);
+    Type                 GetType() const    { return m_Type; }
+    const unsigned char* GetAddress() const { return m_Address; }
+    unsigned int         GetLength() const  { return m_Length; }
+    NPT_String           ToString() const;
+    
+private:
+    // members
+    Type          m_Type;
+    unsigned char m_Address[NPT_NETWORK_MAX_MAC_ADDRESS_LENGTH];
+    unsigned int  m_Length;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterfaceAddress
++---------------------------------------------------------------------*/
+class NPT_NetworkInterfaceAddress
+{
+public:
+    // constructors and destructor
+    NPT_NetworkInterfaceAddress(const NPT_IpAddress& primary,
+                                const NPT_IpAddress& broadcast,
+                                const NPT_IpAddress& destination,
+                                const NPT_IpAddress& netmask) :
+        m_PrimaryAddress(primary),
+        m_BroadcastAddress(broadcast),
+        m_DestinationAddress(destination),
+        m_NetMask(netmask) {}
+
+    // methods
+    const NPT_IpAddress& GetPrimaryAddress() const {
+        return m_PrimaryAddress;
+    }
+    const NPT_IpAddress& GetBroadcastAddress() const {
+        return m_BroadcastAddress;
+    }
+    const NPT_IpAddress& GetDestinationAddress() const {
+        return m_DestinationAddress;
+    }
+    const NPT_IpAddress& GetNetMask() const {
+        return m_NetMask;
+    }
+    
+private:
+    // members
+    NPT_IpAddress m_PrimaryAddress;
+    NPT_IpAddress m_BroadcastAddress;
+    NPT_IpAddress m_DestinationAddress;
+    NPT_IpAddress m_NetMask;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterface
++---------------------------------------------------------------------*/
+class NPT_NetworkInterface
+{
+public:
+    // class methods
+    static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces);
+
+    // constructors and destructor
+    NPT_NetworkInterface(const char*           name,
+                         const NPT_MacAddress& mac,
+                         NPT_Flags             flags);
+   ~NPT_NetworkInterface() {}
+
+    // methods
+    NPT_Result AddAddress(const NPT_NetworkInterfaceAddress& address);
+    const NPT_String& GetName() const {
+        return m_Name;
+    }
+    const NPT_MacAddress& GetMacAddress() const {
+        return m_MacAddress;
+    }
+    NPT_Flags GetFlags() const { return m_Flags; }
+    const NPT_List<NPT_NetworkInterfaceAddress>& GetAddresses() const {
+        return m_Addresses;
+    }    
+    
+private:
+    // members
+    NPT_String                            m_Name;
+    NPT_MacAddress                        m_MacAddress;
+    NPT_Flags                             m_Flags;
+    NPT_List<NPT_NetworkInterfaceAddress> m_Addresses;
+};
+
+
+#endif // _NPT_NETWORK_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,36 @@
+/*****************************************************************
+|
+|   Neptune - Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptQueue.h"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptQueue.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,96 @@
+/*****************************************************************
+|
+|   Neptune - Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_QUEUE_H_
+#define _NPT_QUEUE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|   NPT_QueueItem
++---------------------------------------------------------------------*/
+class NPT_QueueItem;
+
+/*----------------------------------------------------------------------
+|   NPT_GenericQueue
++---------------------------------------------------------------------*/
+class NPT_GenericQueue
+{
+ public:
+    // class methods
+    static NPT_GenericQueue* CreateInstance(NPT_Cardinal max_items = 0);
+
+    // methods
+    virtual           ~NPT_GenericQueue() {}
+    virtual NPT_Result Push(NPT_QueueItem* item, 
+                           NPT_Timeout     timeout = NPT_TIMEOUT_INFINITE) = 0; 
+    virtual NPT_Result Pop(NPT_QueueItem*& item, 
+                           NPT_Timeout     timeout = NPT_TIMEOUT_INFINITE) = 0;
+    virtual NPT_Result Peek(NPT_QueueItem*& item, 
+                           NPT_Timeout     timeout = NPT_TIMEOUT_INFINITE) = 0;
+ protected:
+    // methods
+    NPT_GenericQueue() {}
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Queue
++---------------------------------------------------------------------*/
+template <class T>
+class NPT_Queue
+{
+ public:
+    // methods
+    NPT_Queue(NPT_Cardinal max_items = 0) :
+        m_Delegate(NPT_GenericQueue::CreateInstance(max_items)) {}
+    virtual ~NPT_Queue<T>() { delete m_Delegate; }
+    virtual NPT_Result Push(T* item, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+        return m_Delegate->Push(reinterpret_cast<NPT_QueueItem*>(item), timeout);
+    }
+    virtual NPT_Result Pop(T*& item, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+        return m_Delegate->Pop(reinterpret_cast<NPT_QueueItem*&>(item), 
+                               timeout);
+    }
+    virtual NPT_Result Peek(T*& item, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+        return m_Delegate->Peek(reinterpret_cast<NPT_QueueItem*&>(item), 
+                                timeout);
+    }
+
+ protected:
+    // members
+    NPT_GenericQueue* m_Delegate;
+};
+
+#endif // _NPT_QUEUE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptReferences.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,146 @@
+/*****************************************************************
+|
+|   Neptune - References
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_REFERENCES_H_
+#define _NPT_REFERENCES_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Reference
++---------------------------------------------------------------------*/
+template <typename T>
+class NPT_Reference
+{
+public:
+    // constructors and destructor
+    NPT_Reference() : m_Object(NULL), m_Counter(NULL) {}
+    explicit NPT_Reference(T* object) : 
+        m_Object(object), m_Counter(object?new NPT_Cardinal(1):NULL) {}
+
+    NPT_Reference(const NPT_Reference<T>& ref) :
+        m_Object(ref.m_Object), m_Counter(ref.m_Counter) {
+        if (m_Counter) ++(*m_Counter);
+    }
+
+    // this methods should be private, but this causes a problem on some
+    // compilers, because we need this function in order to implement
+    // the cast operator operator NPT_Reference<U>() below, which would
+    // have to be marked as a friend, and friend declarations with the 
+    // same class name confuses some compilers
+    NPT_Reference(T* object, NPT_Cardinal* counter) : 
+        m_Object(object), m_Counter(counter) {
+        if (m_Counter) ++(*m_Counter);
+    }
+
+    ~NPT_Reference() {
+        Release();
+    }
+
+    // overloaded operators
+    NPT_Reference<T>& operator=(const NPT_Reference<T>& ref) {
+        if (this != &ref) {
+            Release();
+            m_Object = ref.m_Object;
+            m_Counter = ref.m_Counter;
+            if (m_Counter) ++(*m_Counter);
+        }
+        return *this;
+    }
+    NPT_Reference<T>& operator=(T* object) {
+        Release();
+        m_Object = object;
+        m_Counter = object?new NPT_Cardinal(1):NULL;
+        return *this;
+    }
+    T& operator*() const { return *m_Object; }
+    T* operator->() const { return m_Object; }
+
+    bool operator==(const NPT_Reference<T>& ref) {
+        return m_Object == ref.m_Object;
+    } 
+    bool operator!=(const NPT_Reference<T>& ref) {
+        return m_Object != ref.m_Object;
+    }
+
+    // overloaded cast operators
+    template <typename U> operator NPT_Reference<U>() {
+        return NPT_Reference<U>(m_Object, m_Counter);
+    }
+
+    // methods
+    /**
+     * Returns the naked pointer value.
+     */
+    T* AsPointer() const { return m_Object; }
+    
+    /**
+     * Returns the reference counter value.
+     */
+    NPT_Cardinal GetCounter() const { return *m_Counter; }
+    
+    /**
+     * Returns wether this references a NULL object.
+     */
+    bool IsNull()  const { return m_Object == NULL; }
+    
+    /**
+     * Detach the reference from the shared object.
+     * The reference count is decremented, but the object is not deleted if the
+     * reference count becomes 0.
+     * After the method returns, this reference does not point to any shared object.
+     */
+    void Detach() {
+        if (m_Counter && --(*m_Counter) == 0) {
+            delete m_Counter; 
+        }
+        m_Counter = NULL;
+        m_Object  = NULL;
+    }
+    
+private:
+    // methods
+    void Release() {
+        if (m_Counter && --(*m_Counter) == 0) {
+            delete m_Counter; m_Counter = NULL;
+            delete m_Object;  m_Object  = NULL;
+        }
+    }
+
+    // members
+    T*            m_Object;
+    NPT_Cardinal* m_Counter;
+};
+
+#endif // _NPT_REFERENCES_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptResults.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,116 @@
+
+/*****************************************************************
+|
+|   Neptune - Result Code Map
+|
+|   This file is automatically generated by a script, do not edit!
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   NPT_ResultText
++---------------------------------------------------------------------*/
+const char*
+NPT_ResultText(NPT_Result result)
+{
+    switch (result) {
+        case NPT_SUCCESS: return "SUCCESS";
+        case NPT_FAILURE: return "FAILURE";
+
+        case NPT_ERROR_INVALID_PARAMETERS: return "NPT_ERROR_INVALID_PARAMETERS";
+        case NPT_ERROR_PERMISSION_DENIED: return "NPT_ERROR_PERMISSION_DENIED";
+        case NPT_ERROR_OUT_OF_MEMORY: return "NPT_ERROR_OUT_OF_MEMORY";
+        case NPT_ERROR_NO_SUCH_NAME: return "NPT_ERROR_NO_SUCH_NAME";
+        case NPT_ERROR_NO_SUCH_PROPERTY: return "NPT_ERROR_NO_SUCH_PROPERTY";
+        case NPT_ERROR_NO_SUCH_ITEM: return "NPT_ERROR_NO_SUCH_ITEM";
+        case NPT_ERROR_NO_SUCH_CLASS: return "NPT_ERROR_NO_SUCH_CLASS";
+        case NPT_ERROR_OVERFLOW: return "NPT_ERROR_OVERFLOW";
+        case NPT_ERROR_INTERNAL: return "NPT_ERROR_INTERNAL";
+        case NPT_ERROR_INVALID_STATE: return "NPT_ERROR_INVALID_STATE";
+        case NPT_ERROR_INVALID_FORMAT: return "NPT_ERROR_INVALID_FORMAT";
+        case NPT_ERROR_INVALID_SYNTAX: return "NPT_ERROR_INVALID_SYNTAX";
+        case NPT_ERROR_NOT_IMPLEMENTED: return "NPT_ERROR_NOT_IMPLEMENTED";
+        case NPT_ERROR_NOT_SUPPORTED: return "NPT_ERROR_NOT_SUPPORTED";
+        case NPT_ERROR_TIMEOUT: return "NPT_ERROR_TIMEOUT";
+        case NPT_ERROR_WOULD_BLOCK: return "NPT_ERROR_WOULD_BLOCK";
+        case NPT_ERROR_TERMINATED: return "NPT_ERROR_TERMINATED";
+        case NPT_ERROR_OUT_OF_RANGE: return "NPT_ERROR_OUT_OF_RANGE";
+        case NPT_ERROR_LIST_EMPTY: return "NPT_ERROR_LIST_EMPTY";
+        case NPT_ERROR_LIST_OPERATION_ABORTED: return "NPT_ERROR_LIST_OPERATION_ABORTED";
+        case NPT_ERROR_LIST_OPERATION_CONTINUE: return "NPT_ERROR_LIST_OPERATION_CONTINUE";
+        case NPT_ERROR_NO_SUCH_FILE: return "NPT_ERROR_NO_SUCH_FILE";
+        case NPT_ERROR_FILE_NOT_OPEN: return "NPT_ERROR_FILE_NOT_OPEN";
+        case NPT_ERROR_FILE_BUSY: return "NPT_ERROR_FILE_BUSY";
+        case NPT_ERROR_FILE_ALREADY_OPEN: return "NPT_ERROR_FILE_ALREADY_OPEN";
+        case NPT_ERROR_FILE_NOT_READABLE: return "NPT_ERROR_FILE_NOT_READABLE";
+        case NPT_ERROR_FILE_NOT_WRITABLE: return "NPT_ERROR_FILE_NOT_WRITABLE";
+        case NPT_ERROR_FILE_NOT_DIRECTORY: return "NPT_ERROR_FILE_NOT_DIRECTORY";
+        case NPT_ERROR_FILE_ALREADY_EXISTS: return "NPT_ERROR_FILE_ALREADY_EXISTS";
+        case NPT_ERROR_FILE_NOT_ENOUGH_SPACE: return "NPT_ERROR_FILE_NOT_ENOUGH_SPACE";
+        case NPT_ERROR_DIRECTORY_NOT_EMPTY: return "NPT_ERROR_DIRECTORY_NOT_EMPTY";
+        case NPT_ERROR_READ_FAILED: return "NPT_ERROR_READ_FAILED";
+        case NPT_ERROR_WRITE_FAILED: return "NPT_ERROR_WRITE_FAILED";
+        case NPT_ERROR_EOS: return "NPT_ERROR_EOS";
+        case NPT_ERROR_CONNECTION_RESET: return "NPT_ERROR_CONNECTION_RESET";
+        case NPT_ERROR_CONNECTION_ABORTED: return "NPT_ERROR_CONNECTION_ABORTED";
+        case NPT_ERROR_CONNECTION_REFUSED: return "NPT_ERROR_CONNECTION_REFUSED";
+        case NPT_ERROR_CONNECTION_FAILED: return "NPT_ERROR_CONNECTION_FAILED";
+        case NPT_ERROR_HOST_UNKNOWN: return "NPT_ERROR_HOST_UNKNOWN";
+        case NPT_ERROR_SOCKET_FAILED: return "NPT_ERROR_SOCKET_FAILED";
+        case NPT_ERROR_GETSOCKOPT_FAILED: return "NPT_ERROR_GETSOCKOPT_FAILED";
+        case NPT_ERROR_SETSOCKOPT_FAILED: return "NPT_ERROR_SETSOCKOPT_FAILED";
+        case NPT_ERROR_SOCKET_CONTROL_FAILED: return "NPT_ERROR_SOCKET_CONTROL_FAILED";
+        case NPT_ERROR_BIND_FAILED: return "NPT_ERROR_BIND_FAILED";
+        case NPT_ERROR_LISTEN_FAILED: return "NPT_ERROR_LISTEN_FAILED";
+        case NPT_ERROR_ACCEPT_FAILED: return "NPT_ERROR_ACCEPT_FAILED";
+        case NPT_ERROR_ADDRESS_IN_USE: return "NPT_ERROR_ADDRESS_IN_USE";
+        case NPT_ERROR_NETWORK_DOWN: return "NPT_ERROR_NETWORK_DOWN";
+        case NPT_ERROR_NETWORK_UNREACHABLE: return "NPT_ERROR_NETWORK_UNREACHABLE";
+        case NPT_ERROR_NO_SUCH_INTERFACE: return "NPT_ERROR_NO_SUCH_INTERFACE";
+        case NPT_ERROR_XML_INVALID_NESTING: return "NPT_ERROR_XML_INVALID_NESTING";
+        case NPT_ERROR_XML_TAG_MISMATCH: return "NPT_ERROR_XML_TAG_MISMATCH";
+        case NPT_ERROR_HTTP_INVALID_RESPONSE_LINE: return "NPT_ERROR_HTTP_INVALID_RESPONSE_LINE";
+        case NPT_ERROR_HTTP_INVALID_REQUEST_LINE: return "NPT_ERROR_HTTP_INVALID_REQUEST_LINE";
+        case NPT_ERROR_HTTP_NO_PROXY: return "NPT_ERROR_HTTP_NO_PROXY";
+        case NPT_ERROR_HTTP_INVALID_REQUEST: return "NPT_ERROR_HTTP_INVALID_REQUEST";
+        case NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN: return "NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN";
+        case NPT_ERROR_CALLBACK_NOTHING_PENDING: return "NPT_ERROR_CALLBACK_NOTHING_PENDING";
+        case NPT_ERROR_NO_SUCH_SERIAL_PORT: return "NPT_ERROR_NO_SUCH_SERIAL_PORT";
+        case NPT_ERROR_SERIAL_PORT_NOT_OPEN: return "NPT_ERROR_SERIAL_PORT_NOT_OPEN";
+        case NPT_ERROR_SERIAL_PORT_ALREADY_OPEN: return "NPT_ERROR_SERIAL_PORT_ALREADY_OPEN";
+        case NPT_ERROR_SERIAL_PORT_BUSY: return "NPT_ERROR_SERIAL_PORT_BUSY";
+
+        default: return "UNKNOWN";
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptResults.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,160 @@
+/*****************************************************************
+|
+|   Neptune - Result Codes
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_RESULTS_H_
+#define _NPT_RESULTS_H_
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#if defined(NPT_DEBUG)
+#include "NptDebug.h"
+#define NPT_CHECK(_x)               \
+do {                                \
+    NPT_Result _result = (_x);      \
+    if (_result != NPT_SUCCESS) {   \
+        NPT_Debug("%s(%d): @@@ NPT_CHECK failed, result=%d (%s)\n", __FILE__, __LINE__, _result, NPT_ResultText(_result)); \
+        return _result;             \
+    }                               \
+} while(0)
+#define NPT_CHECK_POINTER(_p)                 \
+do {                                          \
+    if ((_p) == NULL) {                       \
+        NPT_Debug("%s(%d): @@@ NULL pointer parameter\n", __FILE__, __LINE__); \
+        return NPT_ERROR_INVALID_PARAMETERS;  \
+    }                                         \
+} while(0)
+#define NPT_CHECK_LABEL(_x, label)  \
+do {                                \
+    NPT_Result _result = (_x);      \
+    if (_result != NPT_SUCCESS) {   \
+        NPT_Debug("%s(%d): @@@ NPT_CHECK failed, result=%d (%s)\n", __FILE__, __LINE__, _result, NPT_ResultText(_result)); \
+        goto label;                 \
+    }                               \
+} while(0)
+#define NPT_CHECK_POINTER_LABEL(_p, label)   \
+do {                                         \
+    if (_p == NULL) {                        \
+        NPT_Debug("%s(%d): @@@ NULL pointer parameter\n", __FILE__, __LINE__); \
+        goto label;                          \
+    }                                        \
+} while(0)
+#else
+#define NPT_CHECK(_x)               \
+do {                                \
+    NPT_Result _result = (_x);      \
+    if (_result != NPT_SUCCESS) {   \
+        return _result;             \
+    }                               \
+} while(0)
+#define NPT_CHECK_POINTER(_p)                               \
+do {                                                        \
+    if ((_p) == NULL) return NPT_ERROR_INVALID_PARAMETERS;  \
+} while(0)
+#define NPT_CHECK_LABEL(_x, label)  \
+do {                                \
+    NPT_Result _result = (_x);      \
+    if (_result != NPT_SUCCESS) {   \
+        goto label;                 \
+    }                               \
+} while(0)
+#define NPT_CHECK_POINTER_LABEL(_p, label)   \
+do {                                         \
+    if ((_p) == NULL) {                      \
+        goto label;                          \
+    }                                        \
+} while(0)
+#endif
+
+#define NPT_FAILED(result)              ((result) != NPT_SUCCESS)
+#define NPT_SUCCEEDED(result)           ((result) == NPT_SUCCESS)
+
+/*----------------------------------------------------------------------
+|   result codes
++---------------------------------------------------------------------*/
+/** Result indicating that the operation or call succeeded */
+#define NPT_SUCCESS                     0
+
+/** Result indicating an unspecififed failure condition */
+#define NPT_FAILURE                     (-1)
+
+#if !defined(NPT_ERROR_BASE)
+#define NPT_ERROR_BASE -20000
+#endif
+
+// error bases
+const int NPT_ERROR_BASE_GENERAL        = NPT_ERROR_BASE-0;
+const int NPT_ERROR_BASE_LIST           = NPT_ERROR_BASE-100;
+const int NPT_ERROR_BASE_FILE           = NPT_ERROR_BASE-200;
+const int NPT_ERROR_BASE_IO             = NPT_ERROR_BASE-300;
+const int NPT_ERROR_BASE_SOCKET         = NPT_ERROR_BASE-400;
+const int NPT_ERROR_BASE_INTERFACES     = NPT_ERROR_BASE-500;
+const int NPT_ERROR_BASE_XML            = NPT_ERROR_BASE-600;
+const int NPT_ERROR_BASE_UNIX           = NPT_ERROR_BASE-700;
+const int NPT_ERROR_BASE_HTTP           = NPT_ERROR_BASE-800;
+const int NPT_ERROR_BASE_THREADS        = NPT_ERROR_BASE-900;
+const int NPT_ERROR_BASE_SERIAL_PORT    = NPT_ERROR_BASE-1000;
+const int NPT_ERROR_BASE_TLS            = NPT_ERROR_BASE-1100;
+
+// general errors
+const int NPT_ERROR_INVALID_PARAMETERS  = NPT_ERROR_BASE_GENERAL - 0;
+const int NPT_ERROR_PERMISSION_DENIED   = NPT_ERROR_BASE_GENERAL - 1;
+const int NPT_ERROR_OUT_OF_MEMORY       = NPT_ERROR_BASE_GENERAL - 2;
+const int NPT_ERROR_NO_SUCH_NAME        = NPT_ERROR_BASE_GENERAL - 3;
+const int NPT_ERROR_NO_SUCH_PROPERTY    = NPT_ERROR_BASE_GENERAL - 4;
+const int NPT_ERROR_NO_SUCH_ITEM        = NPT_ERROR_BASE_GENERAL - 5;
+const int NPT_ERROR_NO_SUCH_CLASS       = NPT_ERROR_BASE_GENERAL - 6;
+const int NPT_ERROR_OVERFLOW            = NPT_ERROR_BASE_GENERAL - 7;
+const int NPT_ERROR_INTERNAL            = NPT_ERROR_BASE_GENERAL - 8;
+const int NPT_ERROR_INVALID_STATE       = NPT_ERROR_BASE_GENERAL - 9;
+const int NPT_ERROR_INVALID_FORMAT      = NPT_ERROR_BASE_GENERAL - 10;
+const int NPT_ERROR_INVALID_SYNTAX      = NPT_ERROR_BASE_GENERAL - 11;
+const int NPT_ERROR_NOT_IMPLEMENTED     = NPT_ERROR_BASE_GENERAL - 12;
+const int NPT_ERROR_NOT_SUPPORTED       = NPT_ERROR_BASE_GENERAL - 13;
+const int NPT_ERROR_TIMEOUT             = NPT_ERROR_BASE_GENERAL - 14;
+const int NPT_ERROR_WOULD_BLOCK         = NPT_ERROR_BASE_GENERAL - 15;
+const int NPT_ERROR_TERMINATED          = NPT_ERROR_BASE_GENERAL - 16;
+const int NPT_ERROR_OUT_OF_RANGE        = NPT_ERROR_BASE_GENERAL - 17;
+const int NPT_ERROR_OUT_OF_RESOURCES    = NPT_ERROR_BASE_GENERAL - 18;
+
+/* standard error codes                                  */
+/* these are special codes to convey an errno            */
+/* the error code is (SHI_ERROR_BASE_ERRNO - errno)      */
+/* where errno is the positive integer from errno.h      */
+const int NPT_ERROR_BASE_ERRNO          = NPT_ERROR_BASE-2000;
+#define NPT_ERROR_ERRNO(e)              (NPT_ERROR_BASE_ERRNO - (e))
+
+/*----------------------------------------------------------------------
+|   functions
++---------------------------------------------------------------------*/
+const char* NPT_ResultText(int result);
+
+#endif // _NPT_RESULTS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptRingBuffer.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,270 @@
+/*****************************************************************
+|
+|   Neptune - Ring Buffer
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptRingBuffer.h"
+#include "NptResults.h"
+#include "NptUtils.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::NPT_RingBuffer
++---------------------------------------------------------------------*/
+NPT_RingBuffer::NPT_RingBuffer(NPT_Size size) :
+    m_Size(size),
+    m_BufferIsLocal(true),
+    m_Closed(false)
+{
+    m_Data.start = new unsigned char[size];
+    m_Data.end   = m_Data.start + size;
+
+    m_In = m_Out = m_Data.start;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::NPT_RingBuffer
++---------------------------------------------------------------------*/
+NPT_RingBuffer::NPT_RingBuffer(void* buffer, NPT_Size size) :
+    m_Size(size),
+    m_BufferIsLocal(false)
+{
+    m_Data.start = (unsigned char*)buffer;
+    m_Data.end   = m_Data.start + size;
+
+    m_In = m_Out = m_Data.start;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::~NPT_RingBuffer
++---------------------------------------------------------------------*/
+NPT_RingBuffer::~NPT_RingBuffer()
+{
+    if (m_BufferIsLocal) delete[] m_Data.start;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::GetContiguousSpace
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetContiguousSpace() const
+{
+    return 
+        (m_In < m_Out) ?
+        (NPT_Size)(m_Out - m_In - 1) :
+        ((m_Out == m_Data.start) ? 
+         (NPT_Size)(m_Data.end - m_In - 1) : 
+         (NPT_Size)(m_Data.end - m_In));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::GetSpace
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetSpace() const
+{
+    return 
+        (m_In < m_Out) ? 
+        (NPT_Size)(m_Out - m_In - 1) : 
+        (NPT_Size)(m_Data.end - m_In + m_Out - m_Data.start - 1);
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::Write
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Write(const void* buffer, NPT_Size byte_count)
+{
+    if (m_Closed) return NPT_ERROR_WRITE_FAILED;
+
+    if (byte_count == 0) return NPT_SUCCESS;
+    if (m_In < m_Out) {
+        if (buffer) NPT_CopyMemory(m_In, buffer, byte_count);
+        m_In += byte_count;
+        if (m_In == m_Data.end) m_In = m_Data.start;
+    } else {
+        unsigned int chunk = (unsigned int)(m_Data.end - m_In);
+        if (chunk >= byte_count) chunk = byte_count;
+
+        if (buffer) NPT_CopyMemory(m_In, buffer, chunk);
+        m_In += chunk;
+        if (m_In == m_Data.end) m_In = m_Data.start;
+        if (chunk != byte_count) {
+            if (buffer) {
+                NPT_CopyMemory(m_In, 
+                               ((const char*)buffer)+chunk, 
+                               byte_count-chunk);
+            }
+            m_In += byte_count-chunk;
+            if (m_In == m_Data.end) m_In = m_Data.start;
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::GetContiguousAvailable
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetContiguousAvailable() const
+{
+    return 
+        (m_Out <= m_In) ? 
+        (NPT_Size)(m_In-m_Out) :
+        (NPT_Size)(m_Data.end - m_Out);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Size
+NPT_RingBuffer::GetAvailable() const
+{
+    return 
+        (m_Out <= m_In) ? 
+        (NPT_Size)(m_In-m_Out) :
+        (NPT_Size)(m_Data.end - m_Out + m_In - m_Data.start);
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::Read
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Read(void* buffer, NPT_Size byte_count)
+{
+    if (m_Closed) return NPT_ERROR_READ_FAILED;
+
+    if (byte_count == 0) return NPT_SUCCESS;
+    if (m_In > m_Out) {
+        if (buffer) NPT_CopyMemory(buffer, m_Out, byte_count);
+        m_Out += byte_count;
+        if (m_Out == m_Data.end) m_Out = m_Data.start;
+    } else {
+        unsigned int chunk = (unsigned int)(m_Data.end - m_Out);
+        if (chunk >= byte_count) chunk = byte_count;
+
+        if (buffer) NPT_CopyMemory(buffer, m_Out, chunk);
+        m_Out += chunk;
+        if (m_Out == m_Data.end) m_Out = m_Data.start;
+        if (chunk != byte_count) {
+            if (buffer) {
+                NPT_CopyMemory(((char*)buffer)+chunk, m_Out, byte_count-chunk);
+            }
+            m_Out += byte_count-chunk;
+            if (m_Out == m_Data.end) m_Out = m_Data.start;
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::ReadByte
++----------------------------------------------------------------------*/
+unsigned char
+NPT_RingBuffer::ReadByte()
+{
+    unsigned char result = *m_Out++;
+    if (m_Out == m_Data.end) m_Out = m_Data.start;
+    return result;
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::PeekByte
++----------------------------------------------------------------------*/
+unsigned char
+NPT_RingBuffer::PeekByte(NPT_Position offset)
+{
+    unsigned char *where;
+
+    where = m_Out+offset;
+    if (where >= m_Data.end) where -= (m_Data.end - m_Data.start);
+
+    return *where;
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::MoveIn
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::MoveIn(NPT_Position offset)
+{
+    int fold;
+
+    m_In += offset;
+    fold = (int)(m_In - m_Data.end);
+    if (fold >= 0) {
+        m_In = m_Data.start + fold;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::MoveOut
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::MoveOut(NPT_Position offset)
+{
+    int fold;
+
+    m_Out += offset;
+    fold = (int)(m_Out - m_Data.end);
+    if (fold >= 0) {
+        m_Out = m_Data.start + fold;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::Flush
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Flush()
+{
+    m_In = m_Out = m_Data.start;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------+
+|    NPT_RingBuffer::Close
++----------------------------------------------------------------------*/
+NPT_Result
+NPT_RingBuffer::Close()
+{
+    m_Closed = true;
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptRingBuffer.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,84 @@
+/*****************************************************************
+|
+|   Neptune - Ring Buffer
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_RING_BUFFER_H_
+#define _NPT_RING_BUFFER_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptReferences.h"
+
+/*----------------------------------------------------------------------
+|   NPT_RingBuffer
++---------------------------------------------------------------------*/
+class NPT_RingBuffer
+{
+ public:
+    // methods
+                  NPT_RingBuffer(NPT_Size size);
+                  NPT_RingBuffer(void* buffer, NPT_Size size);
+    virtual      ~NPT_RingBuffer();
+    NPT_Size      GetSpace() const;
+    NPT_Size      GetContiguousSpace() const;
+    NPT_Result    Write(const void* buffer, NPT_Size byte_count);
+    NPT_Size      GetAvailable() const;
+    NPT_Size      GetContiguousAvailable() const;
+    NPT_Result    Read(void* buffer, NPT_Size byte_count);
+    unsigned char ReadByte();
+    unsigned char PeekByte(NPT_Position offset);
+    NPT_Result    MoveIn(NPT_Position offset);
+    NPT_Result    MoveOut(NPT_Position offset);
+    NPT_Result    Flush();
+    NPT_Result    Close();
+    bool          IsClosed() { return m_Closed; }
+
+    // accessors
+    unsigned char* GetWritePointer()  { return m_In; }
+    unsigned char* GetReadPointer()   { return m_Out;}
+
+ private:
+    // members
+    struct {
+        unsigned char* start;
+        unsigned char* end;
+    }              m_Data;
+    unsigned char* m_In;
+    unsigned char* m_Out;
+    NPT_Size       m_Size;
+    bool           m_BufferIsLocal;
+    bool           m_Closed;
+};
+
+typedef NPT_Reference<NPT_RingBuffer> NPT_RingBufferReference;
+
+#endif // _NPT_RING_BUFFER_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSelectableMessageQueue.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+|   Neptune - Selectable Message Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SELECTABLE_MESSAGE_QUEUE_H_
+#define _NPT_SELECTABLE_MESSAGE_QUEUE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptMessaging.h"
+#include "NptSimpleMessageQueue.h"
+
+/*----------------------------------------------------------------------
+|   NPT_SelectableMessageQueue
++---------------------------------------------------------------------*/
+class NPT_SelectableMessageQueue : public NPT_SimpleMessageQueue
+{
+public:
+    // methods
+             NPT_SelectableMessageQueue();
+    virtual ~NPT_SelectableMessageQueue();
+    
+    // NPT_MessageQueue methods
+    virtual NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+    virtual NPT_Result QueueMessage(NPT_Message*        message,
+                                    NPT_MessageHandler* handler);
+
+    // methods
+    int  GetEventFd() { return m_Pipe[0]; }
+ 
+private:
+    // methods
+    NPT_Result FlushEvent();
+
+    // members
+    int m_Pipe[2];
+};
+
+
+#endif /* _NPT_SELECTABLE_MESSAGE_QUEUE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSerialPort.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,119 @@
+/*****************************************************************
+|
+|   Neptune - Serial Ports
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SERIAL_PORT_H_
+#define _NPT_SERIAL_PORT_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_NO_SUCH_SERIAL_PORT      = NPT_ERROR_BASE_SERIAL_PORT - 0;
+const int NPT_ERROR_SERIAL_PORT_NOT_OPEN     = NPT_ERROR_BASE_SERIAL_PORT - 1;
+const int NPT_ERROR_SERIAL_PORT_ALREADY_OPEN = NPT_ERROR_BASE_SERIAL_PORT - 2;
+const int NPT_ERROR_SERIAL_PORT_BUSY         = NPT_ERROR_BASE_SERIAL_PORT - 3;
+
+typedef enum {
+    NPT_SERIAL_PORT_PARITY_NONE,
+    NPT_SERIAL_PORT_PARITY_EVEN,
+    NPT_SERIAL_PORT_PARITY_ODD,
+    NPT_SERIAL_PORT_PARITY_MARK
+} NPT_SerialPortParity;
+
+typedef enum {
+    NPT_SERIAL_PORT_STOP_BITS_1,
+    NPT_SERIAL_PORT_STOP_BITS_1_5,
+    NPT_SERIAL_PORT_STOP_BITS_2
+} NPT_SerialPortStopBits;
+
+typedef enum {
+    NPT_SERIAL_PORT_FLOW_CONTROL_NONE,
+    NPT_SERIAL_PORT_FLOW_CONTROL_HARDWARE,
+    NPT_SERIAL_PORT_FLOW_CONTROL_XON_XOFF
+} NPT_SerialPortFlowControl;
+
+/*----------------------------------------------------------------------
+|   NPT_SerialPortInterface
++---------------------------------------------------------------------*/
+class NPT_SerialPortInterface
+{
+public:
+    // constructors and destructor
+    virtual ~NPT_SerialPortInterface() {}
+
+    // methods
+    virtual NPT_Result Open(unsigned int              speed, 
+                            NPT_SerialPortStopBits    stop_bits,
+                            NPT_SerialPortFlowControl flow_control,
+                            NPT_SerialPortParity      parity) = 0;
+    virtual NPT_Result Close() = 0;
+    virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream) = 0;
+    virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_SerialPort
++---------------------------------------------------------------------*/
+class NPT_SerialPort : public NPT_SerialPortInterface
+{
+public:
+    // constructors and destructor
+    NPT_SerialPort(const char* name);
+   ~NPT_SerialPort() { delete m_Delegate; }
+
+    // NPT_SerialPortInterface methods
+    NPT_Result Open(unsigned int              speed, 
+                    NPT_SerialPortStopBits    stop_bits = NPT_SERIAL_PORT_STOP_BITS_1,
+                    NPT_SerialPortFlowControl flow_control = NPT_SERIAL_PORT_FLOW_CONTROL_NONE,
+                    NPT_SerialPortParity      parity = NPT_SERIAL_PORT_PARITY_NONE) {
+        return m_Delegate->Open(speed, stop_bits, flow_control, parity);
+    }
+    NPT_Result Close() {
+        return m_Delegate->Close();
+    }
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream) {
+        return m_Delegate->GetInputStream(stream);
+    }
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) {
+        return m_Delegate->GetOutputStream(stream);
+    }
+
+protected:
+    // members
+    NPT_SerialPortInterface* m_Delegate;
+};
+
+#endif // _NPT_SERIAL_PORT_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSimpleMessageQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,94 @@
+/*****************************************************************
+|
+|   Neptune - Simple Message Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptSimpleMessageQueue.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   NPT_SimpleMessageCapsule
++---------------------------------------------------------------------*/
+struct NPT_SimpleMessageCapsule
+{
+    NPT_SimpleMessageCapsule(NPT_Message* message, 
+                             NPT_MessageHandler* handler) :
+        m_Message(message), m_Handler(handler) {}
+    NPT_Message*        m_Message;
+    NPT_MessageHandler* m_Handler;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_SimpleMessageQueue::NPT_SimpleMessageQueue
++---------------------------------------------------------------------*/
+NPT_SimpleMessageQueue::NPT_SimpleMessageQueue()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SimpleMessageQueue::~NPT_SimpleMessageQueue
++---------------------------------------------------------------------*/
+NPT_SimpleMessageQueue::~NPT_SimpleMessageQueue()
+{
+    // empty the queue
+    // TBD
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SimpleMessageQueue::QueueMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SimpleMessageQueue::QueueMessage(NPT_Message*        message, 
+                                     NPT_MessageHandler* handler)
+{
+    // push the message on the queue, with the handler reference
+    return m_Queue.Push(new NPT_SimpleMessageCapsule(message, handler));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SimpleMessageQueue::PumpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SimpleMessageQueue::PumpMessage(NPT_Timeout timeout /* = NPT_TIMEOUT_INFINITE */)
+{
+    NPT_SimpleMessageCapsule* capsule;
+    NPT_Result result = m_Queue.Pop(capsule, timeout);
+    if (NPT_SUCCEEDED(result) && capsule) {
+        if (capsule->m_Handler && capsule->m_Message) {
+            result = capsule->m_Handler->HandleMessage(capsule->m_Message);
+        }
+        delete capsule->m_Message;
+        delete capsule;
+    } 
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSimpleMessageQueue.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+|   Neptune - Simple Message Queue
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SIMPLE_MESSAGE_QUEUE_H_
+#define _NPT_SIMPLE_MESSAGE_QUEUE_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptThreads.h"
+#include "NptMessaging.h"
+#include "NptQueue.h"
+
+/*----------------------------------------------------------------------
+|   class references
++---------------------------------------------------------------------*/
+struct NPT_SimpleMessageCapsule;
+
+/*----------------------------------------------------------------------
+|   NPT_SimpleMessageQueue
++---------------------------------------------------------------------*/
+class NPT_SimpleMessageQueue : public NPT_MessageQueue
+{
+ public:
+    // members
+    NPT_SimpleMessageQueue();
+    virtual ~NPT_SimpleMessageQueue();
+
+    // NPT_MessageQueue methods
+    virtual NPT_Result QueueMessage(NPT_Message*        message, 
+                                    NPT_MessageHandler* handler);
+    virtual NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+ private:
+    // members
+    NPT_Queue<NPT_SimpleMessageCapsule> m_Queue;
+};
+
+#endif // _NPT_SIMPLE_MESSAGE_QUEUE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSockets.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,59 @@
+/*****************************************************************
+|
+|   Neptune - Sockets
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptSockets.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   NPT_SocketAddress::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_SocketAddress::ToString() const
+{
+    NPT_String s = m_IpAddress.ToString();
+    s += ':';
+    s += NPT_String::FromInteger(m_Port);
+    return s;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SocketAddress::operator==
++---------------------------------------------------------------------*/
+bool
+NPT_SocketAddress::operator==(const NPT_SocketAddress& other) const
+{
+    return (other.GetIpAddress().AsLong() == m_IpAddress.AsLong() && 
+            other.GetPort() == m_Port);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSockets.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,333 @@
+/*****************************************************************
+|
+|   Neptune - Network Sockets
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SOCKETS_H_
+#define _NPT_SOCKETS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStreams.h"
+#include "NptStrings.h"
+#include "NptDataBuffer.h"
+#include "NptNetwork.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_CONNECTION_RESET      = NPT_ERROR_BASE_SOCKET - 0;
+const int NPT_ERROR_CONNECTION_ABORTED    = NPT_ERROR_BASE_SOCKET - 1;
+const int NPT_ERROR_CONNECTION_REFUSED    = NPT_ERROR_BASE_SOCKET - 2;
+const int NPT_ERROR_CONNECTION_FAILED     = NPT_ERROR_BASE_SOCKET - 3;
+const int NPT_ERROR_HOST_UNKNOWN          = NPT_ERROR_BASE_SOCKET - 4;
+const int NPT_ERROR_SOCKET_FAILED         = NPT_ERROR_BASE_SOCKET - 5;
+const int NPT_ERROR_GETSOCKOPT_FAILED     = NPT_ERROR_BASE_SOCKET - 6;
+const int NPT_ERROR_SETSOCKOPT_FAILED     = NPT_ERROR_BASE_SOCKET - 7;
+const int NPT_ERROR_SOCKET_CONTROL_FAILED = NPT_ERROR_BASE_SOCKET - 8;
+const int NPT_ERROR_BIND_FAILED           = NPT_ERROR_BASE_SOCKET - 9;
+const int NPT_ERROR_LISTEN_FAILED         = NPT_ERROR_BASE_SOCKET - 10;
+const int NPT_ERROR_ACCEPT_FAILED         = NPT_ERROR_BASE_SOCKET - 11;
+const int NPT_ERROR_ADDRESS_IN_USE        = NPT_ERROR_BASE_SOCKET - 12;
+const int NPT_ERROR_NETWORK_DOWN          = NPT_ERROR_BASE_SOCKET - 13;
+const int NPT_ERROR_NETWORK_UNREACHABLE   = NPT_ERROR_BASE_SOCKET - 14;
+
+/*----------------------------------------------------------------------
+|   forward references
++---------------------------------------------------------------------*/
+class NPT_Socket;
+
+/*----------------------------------------------------------------------
+|   NPT_SocketAddress
++---------------------------------------------------------------------*/
+class NPT_SocketAddress 
+{
+public:
+    // constructors and destructor
+    NPT_SocketAddress() : m_Port(0) {}
+    NPT_SocketAddress(const NPT_IpAddress& address, NPT_IpPort port) :
+        m_IpAddress(address),
+        m_Port(port) {}
+
+    // methods
+    NPT_Result SetIpAddress(const NPT_IpAddress& address) {
+        m_IpAddress = address;
+        return NPT_SUCCESS;
+    }
+    const NPT_IpAddress& GetIpAddress() const { 
+        return m_IpAddress; 
+    }
+    NPT_Result SetPort(NPT_IpPort port) { 
+        m_Port = port; 
+        return NPT_SUCCESS; 
+    }
+    NPT_IpPort GetPort() const { 
+        return m_Port; 
+    }
+    NPT_String ToString() const;
+
+    // operators
+    bool operator==(const NPT_SocketAddress& other) const;
+
+private:
+    // members
+    NPT_IpAddress m_IpAddress;
+    NPT_IpPort    m_Port;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_SocketInfo
++---------------------------------------------------------------------*/
+typedef struct {
+    NPT_SocketAddress local_address;
+    NPT_SocketAddress remote_address;
+} NPT_SocketInfo;
+
+/*----------------------------------------------------------------------
+|   NPT_SocketInterface
++---------------------------------------------------------------------*/
+class NPT_SocketInterface
+{
+ public:
+    virtual ~NPT_SocketInterface() {}
+
+    // interface methods
+    virtual NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true) = 0;
+    virtual NPT_Result Connect(const NPT_SocketAddress& address, NPT_Timeout timeout) = 0;
+    virtual NPT_Result Disconnect() = 0;
+    virtual NPT_Result WaitForConnection(NPT_Timeout timeout) = 0;
+    virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream) = 0;
+    virtual NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) = 0;
+    virtual NPT_Result GetInfo(NPT_SocketInfo& info) = 0;
+    virtual NPT_Result SetBlockingMode(bool blocking) = 0;
+    virtual NPT_Result SetReadTimeout(NPT_Timeout timeout) = 0;
+    virtual NPT_Result SetWriteTimeout(NPT_Timeout timeout) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_UdpSocketInterface
++---------------------------------------------------------------------*/
+class NPT_UdpSocketInterface
+{
+ public:
+    virtual ~NPT_UdpSocketInterface() {}
+
+    // methods
+    virtual NPT_Result Send(const NPT_DataBuffer&    packet, 
+                            const NPT_SocketAddress* address = NULL) = 0;
+    virtual NPT_Result Receive(NPT_DataBuffer&     packet, 
+                               NPT_SocketAddress*  address = NULL) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_UdpMulticastSocketInterface
++---------------------------------------------------------------------*/
+class NPT_UdpMulticastSocketInterface
+{
+ public:
+    virtual ~NPT_UdpMulticastSocketInterface() {}
+
+    // methods
+    virtual NPT_Result JoinGroup(const NPT_IpAddress& group, 
+                                 const NPT_IpAddress& iface) = 0;
+    virtual NPT_Result LeaveGroup(const NPT_IpAddress& group,
+                                  const NPT_IpAddress& iface) = 0;
+    virtual NPT_Result SetTimeToLive(unsigned char ttl) = 0;
+    virtual NPT_Result SetInterface(const NPT_IpAddress& iface) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TcpServerSocketInterface
++---------------------------------------------------------------------*/
+class NPT_TcpServerSocketInterface
+{
+ public:
+    virtual ~NPT_TcpServerSocketInterface() {}
+
+    // interface methods
+    virtual NPT_Result Listen(unsigned int max_clients) = 0;
+    virtual NPT_Result WaitForNewClient(NPT_Socket*& client, 
+                                        NPT_Timeout  timeout) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Socket
++---------------------------------------------------------------------*/
+class NPT_Socket : public NPT_SocketInterface
+{
+public:
+    // constructor and destructor
+    NPT_Socket(NPT_SocketInterface* delegate) :
+        m_SocketDelegate(delegate) {}
+    virtual ~NPT_Socket();
+
+    // delegate NPT_SocketInterface methods
+    NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true) {             
+        return m_SocketDelegate->Bind(address, reuse_address);                            
+    }                                                               
+    NPT_Result Connect(const NPT_SocketAddress& address,            
+                       NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+       return m_SocketDelegate->Connect(address, timeout);                 
+    }       
+    NPT_Result Disconnect() {
+       return m_SocketDelegate->Disconnect();                 
+    }  
+    NPT_Result WaitForConnection(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
+        return m_SocketDelegate->WaitForConnection(timeout);                 
+    } 
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream) {   
+        return m_SocketDelegate->GetInputStream(stream);                   
+    }                                                               
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) { 
+    return m_SocketDelegate->GetOutputStream(stream);                      
+    }                                                               
+    NPT_Result GetInfo(NPT_SocketInfo& info) {                      
+        return m_SocketDelegate->GetInfo(info);                            
+    }                                                               
+    NPT_Result SetBlockingMode(bool blocking) {                      
+        return m_SocketDelegate->SetBlockingMode(blocking);                            
+    }                                                          
+    NPT_Result SetReadTimeout(NPT_Timeout timeout) {                      
+        return m_SocketDelegate->SetReadTimeout(timeout);                            
+    }                                                          
+    NPT_Result SetWriteTimeout(NPT_Timeout timeout) {                      
+        return m_SocketDelegate->SetWriteTimeout(timeout);                            
+    }                                                          
+
+protected:
+    // constructor
+    NPT_Socket() {}
+
+    // members
+    NPT_SocketInterface* m_SocketDelegate;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_UdpSocket
++---------------------------------------------------------------------*/
+class NPT_UdpSocket : public NPT_Socket,
+                      public NPT_UdpSocketInterface
+{
+ public:
+    // constructor and destructor
+             NPT_UdpSocket();
+    virtual ~NPT_UdpSocket();
+
+    // delegate NPT_UdpSocketInterface methods
+    NPT_Result Send(const NPT_DataBuffer&    packet,           
+                    const NPT_SocketAddress* address = NULL) {
+        return m_UdpSocketDelegate->Send(packet, address);              
+    }                                                         
+    NPT_Result Receive(NPT_DataBuffer&     packet,            
+                       NPT_SocketAddress*  address = NULL) {  
+        return m_UdpSocketDelegate->Receive(packet, address);           
+    }
+
+protected:
+    // constructor
+    NPT_UdpSocket(NPT_UdpSocketInterface* delegate);
+
+    // members
+    NPT_UdpSocketInterface* m_UdpSocketDelegate;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_UdpMulticastSocket
++---------------------------------------------------------------------*/
+class NPT_UdpMulticastSocket : public NPT_UdpSocket, 
+                               public NPT_UdpMulticastSocketInterface
+{
+public:
+    // constructor and destructor
+             NPT_UdpMulticastSocket();
+    virtual ~NPT_UdpMulticastSocket();
+
+    // delegate NPT_UdpMulticastSocketInterface methods
+    NPT_Result JoinGroup(const NPT_IpAddress& group,            
+                         const NPT_IpAddress& iface =           
+                         NPT_IpAddress::Any) {                  
+        return m_UdpMulticastSocketDelegate->JoinGroup(group, iface);
+    }                                                           
+    NPT_Result LeaveGroup(const NPT_IpAddress& group,           
+                          const NPT_IpAddress& iface =          
+                          NPT_IpAddress::Any) {                 
+        return m_UdpMulticastSocketDelegate->LeaveGroup(group, iface);
+    }                                                          
+    NPT_Result SetTimeToLive(unsigned char ttl) {     
+        return m_UdpMulticastSocketDelegate->SetTimeToLive(ttl); 
+    }
+    NPT_Result SetInterface(const NPT_IpAddress& iface) {
+        return m_UdpMulticastSocketDelegate->SetInterface(iface);
+    }
+
+protected:
+    // members
+    NPT_UdpMulticastSocketInterface* m_UdpMulticastSocketDelegate;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TcpClientSocket
++---------------------------------------------------------------------*/
+class NPT_TcpClientSocket : public NPT_Socket
+{
+public:
+    // constructors and destructor
+             NPT_TcpClientSocket();
+    virtual ~NPT_TcpClientSocket();
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TcpServerSocket
++---------------------------------------------------------------------*/
+class NPT_TcpServerSocket : public NPT_Socket,
+                            public NPT_TcpServerSocketInterface
+{
+public:
+    // constructors and destructor
+             NPT_TcpServerSocket();
+    virtual ~NPT_TcpServerSocket();
+
+    // delegate NPT_TcpServerSocketInterface methods
+    NPT_Result Listen(unsigned int max_clients) {   
+        return m_TcpServerSocketDelegate->Listen(max_clients);
+    }
+    NPT_Result WaitForNewClient(NPT_Socket*& client, 
+                                NPT_Timeout  timeout = NPT_TIMEOUT_INFINITE) {
+        return m_TcpServerSocketDelegate->WaitForNewClient(client, timeout);
+    }
+
+protected:
+    // members
+    NPT_TcpServerSocketInterface* m_TcpServerSocketDelegate;
+};
+
+#endif // _NPT_SOCKETS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptStack.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,72 @@
+/*****************************************************************
+|
+|   Neptune - Stack
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+****************************************************************/
+
+#ifndef _NPT_STACK_H_
+#define _NPT_STACK_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptResults.h"
+#include "NptTypes.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Stack
++---------------------------------------------------------------------*/
+template <typename T> 
+class NPT_Stack : public NPT_List<T>
+{
+public:
+    // methods
+    NPT_Result Push(const T& value) {
+        return Add(value);
+    }
+
+    NPT_Result Peek(T& value) {
+        // NOTE: we must use the this-> accessor here because the standard
+        // requires it when the member to look up is in a parent template
+        if (this->m_ItemCount == 0) return NPT_ERROR_NO_SUCH_ITEM;
+        value = this->m_Tail->m_Data;
+        return NPT_SUCCESS;
+    }
+
+    NPT_Result Pop(T& value) {
+        // NOTE: we must use the this-> accessor here because the standard
+        // requires it when the member to look up is in a parent template
+        if (this->m_ItemCount == 0) return NPT_ERROR_NO_SUCH_ITEM;
+        typename NPT_List<T>::Iterator tail = this->GetLastItem();
+        value = *tail;
+        return this->Erase(tail);
+    }
+};
+
+#endif // _NPT_STACK_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptStreams.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,600 @@
+/*****************************************************************
+|
+|   Neptune - Byte Streams
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptStreams.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const NPT_Size      NPT_INPUT_STREAM_LOAD_DEFAULT_READ_CHUNK = 4096;
+const NPT_LargeSize NPT_INPUT_STREAM_LOAD_MAX_SIZE           = 0x100000; // 1GB
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::Load
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::Load(NPT_DataBuffer& buffer, NPT_Size max_read /* = 0 */)
+{
+    NPT_Result    result;
+    NPT_LargeSize total_bytes_read;
+
+    // reset the buffer
+    buffer.SetDataSize(0);
+
+    // check the limits
+    if (max_read > NPT_INPUT_STREAM_LOAD_MAX_SIZE) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // try to get the stream size
+    NPT_LargeSize size;
+    if (NPT_SUCCEEDED(GetSize(size))) { 
+        // make sure we don't read more than max_read
+        if (max_read && max_read < size) size = max_read;
+        if (size > NPT_INPUT_STREAM_LOAD_MAX_SIZE) {
+            return NPT_ERROR_OUT_OF_RANGE;
+        }
+    } else {
+        size = max_read;
+    } 
+        
+    // pre-allocate the buffer
+    if (size) NPT_CHECK(buffer.Reserve((NPT_Size)size));
+
+    // read the data from the file
+    total_bytes_read = 0;
+    do {
+        NPT_LargeSize available = 0;
+        NPT_LargeSize bytes_to_read;
+        NPT_Size      bytes_read;
+        NPT_Byte*     data;
+
+        // check if we know how much data is available
+        result = GetAvailable(available);
+        if (NPT_SUCCEEDED(result) && available) {
+            // we know how much is available
+            bytes_to_read = available;
+        } else {
+            bytes_to_read = NPT_INPUT_STREAM_LOAD_DEFAULT_READ_CHUNK;
+        }
+
+        // make sure we don't read more than what was asked
+        if (size != 0 && total_bytes_read+bytes_to_read>size) {
+            bytes_to_read = size-total_bytes_read;
+        }
+
+        // stop if we've read everything
+        if (bytes_to_read == 0) break;
+
+        // ensure that the buffer has enough space
+        if (total_bytes_read+bytes_to_read > NPT_INPUT_STREAM_LOAD_MAX_SIZE) {
+            buffer.SetBufferSize(0);
+            return NPT_ERROR_OUT_OF_RANGE;
+        }
+        NPT_CHECK(buffer.Reserve((NPT_Size)(total_bytes_read+bytes_to_read)));
+
+        // read the data
+        data = buffer.UseData()+total_bytes_read;
+        result = Read((void*)data, (NPT_Size)bytes_to_read, &bytes_read);
+        if (NPT_SUCCEEDED(result) && bytes_read != 0) {
+            total_bytes_read += bytes_read;
+            buffer.SetDataSize((NPT_Size)total_bytes_read);
+        }
+    } while(NPT_SUCCEEDED(result) && (size==0 || total_bytes_read < size));
+
+    if (result == NPT_ERROR_EOS) {
+        return NPT_SUCCESS;
+    } else {
+        return result;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::ReadFully
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadFully(void* buffer, NPT_Size bytes_to_read)
+{
+    // shortcut
+    if (bytes_to_read == 0) return NPT_SUCCESS;
+
+    // read until failure
+    NPT_Size bytes_read;
+    while (bytes_to_read) {
+        NPT_Result result = Read(buffer, bytes_to_read, &bytes_read);
+        if (NPT_FAILED(result)) return result;
+        if (bytes_read == 0) return NPT_ERROR_INTERNAL;
+        NPT_ASSERT(bytes_read <= bytes_to_read);
+        bytes_to_read -= bytes_read;
+        buffer = (void*)(((NPT_Byte*)buffer)+bytes_read);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::ReadUI64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI64(NPT_UInt64& value)
+{
+    unsigned char buffer[8];
+
+    // read bytes from the stream
+    NPT_Result result;
+    result = ReadFully((void*)buffer, 8);
+    if (NPT_FAILED(result)) {
+        value = 0;
+        return result;
+    }
+
+    // convert bytes to value
+    value = NPT_BytesToInt64Be(buffer);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::ReadUI32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI32(NPT_UInt32& value)
+{
+    unsigned char buffer[4];
+
+    // read bytes from the stream
+    NPT_Result result;
+    result = ReadFully((void*)buffer, 4);
+    if (NPT_FAILED(result)) {
+        value = 0;
+        return result;
+    }
+
+    // convert bytes to value
+    value = NPT_BytesToInt32Be(buffer);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::ReadUI24
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI24(NPT_UInt32& value)
+{
+    unsigned char buffer[3];
+
+    // read bytes from the stream
+    NPT_Result result;
+    result = ReadFully((void*)buffer, 3);
+    if (NPT_FAILED(result)) {
+        value = 0;
+        return result;
+    }
+
+    // convert bytes to value
+    value = NPT_BytesToInt24Be(buffer);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::ReadUI16
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI16(NPT_UInt16& value)
+{
+    unsigned char buffer[2];
+
+    // read bytes from the stream
+    NPT_Result result;
+    result = ReadFully((void*)buffer, 2);
+    if (NPT_FAILED(result)) {
+        value = 0;
+        return result;
+    }
+
+    // convert bytes to value
+    value = NPT_BytesToInt16Be(buffer);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::ReadUI08
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::ReadUI08(NPT_UInt8& value)
+{
+    unsigned char buffer[1];
+
+    // read bytes from the stream
+    NPT_Result result;
+    result = ReadFully((void*)buffer, 1);
+    if (NPT_FAILED(result)) {        
+        value = 0;
+        return result;
+    }
+
+    // convert bytes to value
+    value = buffer[0];
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_InputStream::Skip
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_InputStream::Skip(NPT_Size count)
+{
+    // get the current location
+    NPT_Position position;
+    NPT_CHECK(Tell(position));
+
+    // seek ahead
+    return Seek(position+count);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteFully
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteFully(const void* buffer, NPT_Size bytes_to_write)
+{
+    // shortcut
+    if (bytes_to_write == 0) return NPT_SUCCESS;
+
+    // write until failure
+    NPT_Size bytes_written;
+    while (bytes_to_write) {
+        NPT_Result result = Write(buffer, bytes_to_write, &bytes_written);
+        if (NPT_FAILED(result)) return result;
+        if (bytes_written == 0) return NPT_ERROR_INTERNAL;
+        NPT_ASSERT(bytes_written <= bytes_to_write);
+        bytes_to_write -= bytes_written;
+        buffer = (const void*)(((const NPT_Byte*)buffer)+bytes_written);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteString
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteString(const char* buffer)
+{
+    // shortcut
+    NPT_Size string_length;
+    if (buffer == NULL || (string_length = NPT_StringLength(buffer)) == 0) {
+        return NPT_SUCCESS;
+    }
+
+    // write the string
+    return WriteFully((const void*)buffer, string_length);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteLine
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteLine(const char* buffer)
+{
+    NPT_CHECK(WriteString(buffer));
+    NPT_CHECK(WriteFully((const void*)"\r\n", 2));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteUI64
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI64(NPT_UInt64 value)
+{
+    unsigned char buffer[8];
+
+    // convert value to bytes
+    NPT_BytesFromInt64Be(buffer, value);
+
+    // write bytes to the stream
+    return WriteFully((void*)buffer, 8);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteUI32
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI32(NPT_UInt32 value)
+{
+    unsigned char buffer[4];
+
+    // convert value to bytes
+    NPT_BytesFromInt32Be(buffer, value);
+
+    // write bytes to the stream
+    return WriteFully((void*)buffer, 4);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteUI24
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI24(NPT_UInt32 value)
+{
+    unsigned char buffer[3];
+
+    // convert value to bytes
+    NPT_BytesFromInt24Be(buffer, value);
+
+    // write bytes to the stream
+    return WriteFully((void*)buffer, 3);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteUI16
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI16(NPT_UInt16 value)
+{
+    unsigned char buffer[2];
+
+    // convert value to bytes
+    NPT_BytesFromInt16Be(buffer, value);
+
+    // write bytes to the stream
+    return WriteFully((void*)buffer, 2);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_OutputStream::WriteUI08
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_OutputStream::WriteUI08(NPT_UInt8 value)
+{
+    return WriteFully((void*)&value, 1);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::NPT_MemoryStream
++---------------------------------------------------------------------*/
+NPT_MemoryStream::NPT_MemoryStream(NPT_Size initial_capacity) : 
+    m_Buffer(initial_capacity),
+    m_ReadOffset(0),
+    m_WriteOffset(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::NPT_MemoryStream
++---------------------------------------------------------------------*/
+NPT_MemoryStream::NPT_MemoryStream(const void* data, NPT_Size size) : 
+    m_Buffer(data, size),
+    m_ReadOffset(0),
+    m_WriteOffset(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_MemoryStream::Read(void*     buffer, 
+                       NPT_Size  bytes_to_read, 
+                       NPT_Size* bytes_read)
+{
+    // check for shortcut
+    if (bytes_to_read == 0) {
+        if (bytes_read) *bytes_read = 0;
+        return NPT_SUCCESS;
+    }
+
+    // clip to what's available
+    NPT_Size available = m_Buffer.GetDataSize();
+    if (m_ReadOffset+bytes_to_read > available) {
+        bytes_to_read = available-m_ReadOffset;
+    }
+
+    // copy the data
+    if (bytes_to_read) {
+        NPT_CopyMemory(buffer, (void*)(((char*)m_Buffer.UseData())+m_ReadOffset), bytes_to_read);
+        m_ReadOffset += bytes_to_read;
+    } 
+    if (bytes_read) *bytes_read = bytes_to_read;
+
+    return bytes_to_read?NPT_SUCCESS:NPT_ERROR_EOS; 
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::InputSeek
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_MemoryStream::InputSeek(NPT_Position offset)
+{
+    if (offset > m_Buffer.GetDataSize()) {
+        return NPT_ERROR_OUT_OF_RANGE;
+    } else {
+        m_ReadOffset = (NPT_Size)offset;
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::Write
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_MemoryStream::Write(const void* data, 
+                        NPT_Size    bytes_to_write, 
+                        NPT_Size*   bytes_written)
+{
+    NPT_CHECK(m_Buffer.Reserve(m_WriteOffset+bytes_to_write));
+
+    NPT_CopyMemory(m_Buffer.UseData()+m_WriteOffset, data, bytes_to_write);
+    m_WriteOffset += bytes_to_write;
+    if (m_WriteOffset > m_Buffer.GetDataSize()) {
+        m_Buffer.SetDataSize(m_WriteOffset);
+    }
+    if (bytes_written) *bytes_written = bytes_to_write;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::OutputSeek
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_MemoryStream::OutputSeek(NPT_Position offset)
+{
+    if (offset <= m_Buffer.GetDataSize()) {
+        m_WriteOffset = (NPT_Size)offset;
+        return NPT_SUCCESS;
+    } else {
+        return NPT_ERROR_OUT_OF_RANGE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_MemoryStream::SetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_MemoryStream::SetSize(NPT_Size size)
+{
+    // try to resize the data buffer
+    NPT_CHECK(m_Buffer.SetDataSize(size));
+
+    // adjust the read and write offsets
+    if (m_ReadOffset > size) m_ReadOffset = size;
+    if (m_WriteOffset > size) m_WriteOffset = size;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StreamToStreamCopy
++---------------------------------------------------------------------*/
+const unsigned int NPT_STREAM_COPY_BUFFER_SIZE = 4096; // copy 4k at a time
+NPT_Result 
+NPT_StreamToStreamCopy(NPT_InputStream&  from, 
+                       NPT_OutputStream& to,
+                       NPT_Position      offset /* = 0 */,
+                       NPT_LargeSize     size   /* = 0, 0 means the entire stream */)
+{
+    // seek into the input if required
+    if (offset) {
+        NPT_CHECK(from.Seek(offset));
+    }
+
+    // allocate a buffer for the transfer
+    NPT_LargeSize bytes_transfered = 0;
+    NPT_Byte*     buffer = new NPT_Byte[NPT_STREAM_COPY_BUFFER_SIZE];
+    NPT_Result result = NPT_SUCCESS;
+    if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+
+    // copy until an error occurs or the end of stream is reached
+    for (;;) {
+        // read some data
+        NPT_Size   bytes_to_read = NPT_STREAM_COPY_BUFFER_SIZE;
+        NPT_Size   bytes_read = 0;
+        if (size) {
+            // a max size was specified
+            if (bytes_to_read > (NPT_Size)(size-bytes_transfered)) {
+                bytes_to_read = (NPT_Size)(size-bytes_transfered);
+            }
+        }
+        result = from.Read(buffer, bytes_to_read, &bytes_read);
+        if (NPT_FAILED(result)) {
+            if (result == NPT_ERROR_EOS) result = NPT_SUCCESS;
+            break;
+        }
+        if (bytes_read == 0) continue;
+        
+        // write the data
+        result = to.WriteFully(buffer, bytes_read);
+        if (NPT_FAILED(result)) break;
+
+        // update the counts
+        if (size) {
+            bytes_transfered += bytes_read;
+            if (bytes_transfered >= size) break;
+        }
+    }
+
+    // free the buffer and return
+    delete[] buffer;
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StringOutputStream::NPT_StringOutputStream
++---------------------------------------------------------------------*/
+NPT_StringOutputStream::NPT_StringOutputStream(NPT_Size size) :
+    m_String(new NPT_String),
+    m_StringIsOwned(true)
+{
+    m_String->Reserve(size);
+}
+
+
+/*----------------------------------------------------------------------
+|   NPT_StringOutputStream::NPT_StringOutputStream
++---------------------------------------------------------------------*/
+NPT_StringOutputStream::NPT_StringOutputStream(NPT_String* storage) :
+    m_String(storage),
+    m_StringIsOwned(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StringOutputStream::~NPT_StringOutputStream
++---------------------------------------------------------------------*/
+NPT_StringOutputStream::~NPT_StringOutputStream()
+{
+    if (m_StringIsOwned) delete m_String;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StringOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_StringOutputStream::Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written /* = NULL */)
+{
+     m_String->Append((const char*)buffer, bytes_to_write);
+    if (bytes_written) *bytes_written = bytes_to_write;
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptStreams.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,275 @@
+/*****************************************************************
+|
+|   Neptune - Byte Streams
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_STREAMS_H_
+#define _NPT_STREAMS_H_
+
+/*----------------------------------------------------------------------
+|    includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptReferences.h"
+#include "NptConstants.h"
+#include "NptResults.h"
+#include "NptDataBuffer.h"
+#include "NptStrings.h"
+
+/*----------------------------------------------------------------------
+|    class references
++---------------------------------------------------------------------*/
+class NPT_String;
+
+/*----------------------------------------------------------------------
+|    constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_READ_FAILED  = NPT_ERROR_BASE_IO - 0;
+const int NPT_ERROR_WRITE_FAILED = NPT_ERROR_BASE_IO - 1;
+const int NPT_ERROR_EOS          = NPT_ERROR_BASE_IO - 2;
+
+/*----------------------------------------------------------------------
+|    NPT_InputStream
++---------------------------------------------------------------------*/
+class NPT_InputStream
+{
+ public:
+    // constructor and destructor
+    virtual ~NPT_InputStream() {};
+
+    // methods
+    virtual NPT_Result Load(NPT_DataBuffer& buffer, NPT_Size max_read = 0);
+    virtual NPT_Result Read(void*     buffer, 
+                            NPT_Size  bytes_to_read, 
+                            NPT_Size* bytes_read = NULL) = 0;
+    virtual NPT_Result ReadFully(void*     buffer, 
+                                 NPT_Size  bytes_to_read);
+    virtual NPT_Result Seek(NPT_Position offset) = 0;
+    virtual NPT_Result Skip(NPT_Size offset);
+    virtual NPT_Result Tell(NPT_Position& offset) = 0;
+    virtual NPT_Result GetSize(NPT_LargeSize& size) = 0;
+    virtual NPT_Result GetAvailable(NPT_LargeSize& available) = 0;
+    virtual NPT_Result Close() { return NPT_SUCCESS; }    
+
+    // data access methods
+    NPT_Result ReadUI64(NPT_UInt64& value);
+    NPT_Result ReadUI32(NPT_UInt32& value);
+    NPT_Result ReadUI24(NPT_UInt32& value);
+    NPT_Result ReadUI16(NPT_UInt16& value);
+    NPT_Result ReadUI08(NPT_UInt8&  value);    
+};
+
+typedef NPT_Reference<NPT_InputStream> NPT_InputStreamReference;
+
+/*----------------------------------------------------------------------
+|    NPT_OutputStream
++---------------------------------------------------------------------*/
+class NPT_OutputStream
+{
+public:
+    // constructor and destructor
+    virtual ~NPT_OutputStream() {};
+
+    // methods
+    virtual NPT_Result Write(const void* buffer, 
+                             NPT_Size    bytes_to_write, 
+                             NPT_Size*   bytes_written = NULL) = 0;
+    virtual NPT_Result WriteFully(const void* buffer, 
+                                  NPT_Size    bytes_to_write);
+    virtual NPT_Result WriteString(const char* string_buffer);
+    virtual NPT_Result WriteLine(const char* line_buffer);
+    virtual NPT_Result Seek(NPT_Position offset) = 0;
+    virtual NPT_Result Tell(NPT_Position& offset) = 0;
+    virtual NPT_Result Flush() { return NPT_SUCCESS; }
+    
+    // data access methods
+    NPT_Result WriteUI64(NPT_UInt64 value);
+    NPT_Result WriteUI32(NPT_UInt32 value);
+    NPT_Result WriteUI24(NPT_UInt32 value);
+    NPT_Result WriteUI16(NPT_UInt16 value);
+    NPT_Result WriteUI08(NPT_UInt8  value);    
+};
+
+typedef NPT_Reference<NPT_OutputStream> NPT_OutputStreamReference;
+
+/*----------------------------------------------------------------------
+|    NPT_StreamToStreamCopy
++---------------------------------------------------------------------*/
+NPT_Result NPT_StreamToStreamCopy(NPT_InputStream&  from, 
+                                  NPT_OutputStream& to,
+                                  NPT_Position      offset = 0,
+                                  NPT_LargeSize     size   = 0 /* 0 means the entire stream */);
+
+/*----------------------------------------------------------------------
+|    NPT_DelegatingInputStream
+|
+|    Use this class as a base class if you need to inherit both from
+|    NPT_InputStream and NPT_OutputStream which share the Seek and Tell
+|    method. In this case, you override the  base-specific version of 
+|    those methods, InputSeek, InputTell, instead of the Seek and Tell 
+|    methods.
++---------------------------------------------------------------------*/
+class NPT_DelegatingInputStream : public NPT_InputStream
+{
+public:
+    // NPT_InputStream methods
+    NPT_Result Seek(NPT_Position offset) {
+        return InputSeek(offset);
+    }
+    NPT_Result Tell(NPT_Position& offset) {
+        return InputTell(offset);
+    }
+
+private:
+    // methods
+    virtual NPT_Result InputSeek(NPT_Position  offset) = 0;
+    virtual NPT_Result InputTell(NPT_Position& offset) = 0;
+};
+
+/*----------------------------------------------------------------------
+|    NPT_DelegatingOutputStream
+|
+|    Use this class as a base class if you need to inherit both from
+|    NPT_InputStream and NPT_OutputStream which share the Seek and Tell
+|    method. In this case, you override the  base-specific version of 
+|    those methods, OutputSeek and OutputTell, instead of the Seek and 
+|    Tell methods.
++---------------------------------------------------------------------*/
+class NPT_DelegatingOutputStream : public NPT_OutputStream
+{
+public:
+    // NPT_OutputStream methods
+    NPT_Result Seek(NPT_Position offset) {
+        return OutputSeek(offset);
+    }
+    NPT_Result Tell(NPT_Position& offset) {
+        return OutputTell(offset);
+    }
+
+private:
+    // methods
+    virtual NPT_Result OutputSeek(NPT_Position  offset) = 0;
+    virtual NPT_Result OutputTell(NPT_Position& offset) = 0;
+};
+
+/*----------------------------------------------------------------------
+|    NPT_MemoryStream
++---------------------------------------------------------------------*/
+class NPT_MemoryStream : 
+    public NPT_DelegatingInputStream,
+    public NPT_DelegatingOutputStream
+{
+public:
+    // constructor and destructor
+    NPT_MemoryStream(NPT_Size initial_capacity = 0);
+    NPT_MemoryStream(const void* data, NPT_Size size);
+    virtual ~NPT_MemoryStream() {}
+
+    // accessors
+    const NPT_DataBuffer& GetBuffer() const { return m_Buffer; }
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read = NULL);
+    NPT_Result GetSize(NPT_LargeSize& size)  { 
+        size = m_Buffer.GetDataSize();    
+        return NPT_SUCCESS;
+    }
+    NPT_Result GetAvailable(NPT_LargeSize& available) { 
+        available = (NPT_LargeSize)m_Buffer.GetDataSize()-m_ReadOffset; 
+        return NPT_SUCCESS;
+    }
+
+    // NPT_OutputStream methods
+    NPT_Result Write(const void* buffer, 
+                     NPT_Size    bytes_to_write, 
+                     NPT_Size*   bytes_written = NULL);
+
+    // methods delegated to m_Buffer
+    const NPT_Byte* GetData() const { return m_Buffer.GetData(); }
+    NPT_Byte*       UseData()       { return m_Buffer.UseData(); }
+    NPT_Size        GetDataSize() const   { return m_Buffer.GetDataSize(); }
+    NPT_Size        GetBufferSize() const { return m_Buffer.GetBufferSize();}
+
+    // methods
+    NPT_Result SetSize(NPT_Size size);
+
+private:
+    // NPT_DelegatingInputStream methods
+    NPT_Result InputSeek(NPT_Position offset);
+    NPT_Result InputTell(NPT_Position& offset) { 
+        offset = m_ReadOffset; 
+        return NPT_SUCCESS;
+    }
+
+    // NPT_DelegatingOutputStream methods
+    NPT_Result OutputSeek(NPT_Position offset);
+    NPT_Result OutputTell(NPT_Position& offset) {
+        offset = m_WriteOffset; 
+        return NPT_SUCCESS;
+    }
+
+protected:
+    // members
+    NPT_DataBuffer m_Buffer;
+    NPT_Size       m_ReadOffset;
+    NPT_Size       m_WriteOffset;
+};
+
+typedef NPT_Reference<NPT_MemoryStream> NPT_MemoryStreamReference;
+
+/*----------------------------------------------------------------------
+|   NPT_StringOutputStream
++---------------------------------------------------------------------*/
+class NPT_StringOutputStream : public NPT_OutputStream
+{
+public:
+    // methods
+    NPT_StringOutputStream(NPT_Size size = 4096);
+    NPT_StringOutputStream(NPT_String* storage);
+    virtual ~NPT_StringOutputStream() ;
+
+    const NPT_String& GetString() const { return *m_String; }
+    NPT_Result Reset() { if (m_String) m_String->SetLength(0); return NPT_SUCCESS; }
+
+    // NPT_OutputStream methods
+    NPT_Result Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written = NULL);
+
+    NPT_Result Seek(NPT_Position /*offset*/)  { return NPT_ERROR_NOT_SUPPORTED;   }
+    NPT_Result Tell(NPT_Position& offset) { offset = m_String->GetLength(); return NPT_SUCCESS; }
+
+protected:
+    NPT_String* m_String;
+    bool        m_StringIsOwned;
+};
+
+typedef NPT_Reference<NPT_StringOutputStream> NPT_StringOutputStreamReference;
+
+#endif // _NPT_STREAMS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1056 @@
+/*****************************************************************
+|
+|   Neptune - String Objects
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptStrings.h"
+#include "NptResults.h"
+#include "NptUtils.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define NPT_STRINGS_WHITESPACE_CHARS "\r\n\t "
+
+const unsigned int NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE = 256;
+const unsigned int NPT_STRING_FORMAT_BUFFER_MAX_SIZE     = 0x80000; // 512k
+
+/*----------------------------------------------------------------------
+|   helpers
++---------------------------------------------------------------------*/
+inline char NPT_Uppercase(char x) {
+    return (x >= 'a' && x <= 'z') ? x&0xdf : x;
+}
+
+inline char NPT_Lowercase(char x) {
+    return (x >= 'A' && x <= 'Z') ? x^32 : x;
+}
+               
+/*----------------------------------------------------------------------
+|   NPT_String::EmptyString
++---------------------------------------------------------------------*/
+char NPT_String::EmptyString = '\0';
+
+/*----------------------------------------------------------------------
+|   NPT_String::FromInteger
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::FromInteger(NPT_Int64 value)
+{
+    char str[32];
+    char* c = &str[31];
+    *c-- = '\0';
+
+    // handle the sign
+    bool negative = false;
+    if (value < 0) {
+        negative = true;
+        value = -value;
+    }
+
+    // process the digits
+    do {
+        int digit = (int)(value%10);
+        *c-- = '0'+digit;
+        value /= 10;
+    } while(value);
+
+    if (negative) {
+        *c = '-';
+    } else {
+        ++c;
+    }
+
+    return NPT_String(c);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::FromIntegerU
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::FromIntegerU(NPT_UInt64 value)
+{
+    char str[32];
+    char* c = &str[31];
+    *c = '\0';
+
+    // process the digits
+    do {
+        int digit = (int)(value%10);
+        *--c = '0'+digit;
+        value /= 10;
+    } while(value);
+
+    return NPT_String(c);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Format
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::Format(const char* format, ...)
+{
+    NPT_String result;
+    NPT_Size   buffer_size = NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE; // default value
+    
+    va_list  args;
+    va_start(args, format);
+
+    for(;;) {
+        /* try to format (it might not fit) */
+        result.Reserve(buffer_size);
+        char* buffer = result.UseChars();
+        int f_result = NPT_FormatStringVN(buffer, buffer_size, format, args);
+        if (f_result >= (int)(buffer_size)) f_result = -1;
+        if (f_result >= 0) {
+            result.SetLength(f_result);
+            break;
+        }
+        
+        /* the buffer was too small, try something bigger         */
+        /* (we don't trust the return value of NPT_FormatStringVN */
+        /* for the actual size needed)                            */
+        buffer_size *= 2;
+        if (buffer_size > NPT_STRING_FORMAT_BUFFER_MAX_SIZE) break;
+    }
+
+    va_end(args);
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const char* str)
+{
+    if (str == NULL) {
+        m_Chars = NULL;
+    } else {
+        m_Chars = Buffer::Create(str);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const char* str, NPT_Size length)
+{
+    if (str == NULL || length == 0) {
+        m_Chars = NULL;
+    } else {
+        m_Chars = Buffer::Create(str, length);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const NPT_String& str)
+{
+    if (str.GetLength() == 0) {
+        m_Chars = NULL;
+    } else {
+        m_Chars = Buffer::Create(str.GetChars(), str.GetLength());
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(const char* str,
+                       NPT_Ordinal first, 
+                       NPT_Size    length)
+{
+    // shortcut
+    if (str != NULL && length != 0) {
+        // truncate length      
+        NPT_Size str_length = StringLength(str);
+        if (first < str_length) {
+            if (first+length > str_length) {
+                length = str_length-first;
+            }
+            if (length != 0) {
+                m_Chars = Buffer::Create(str+first, length);
+                return;
+            }
+        }
+    } 
+    m_Chars = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::NPT_String
++---------------------------------------------------------------------*/
+NPT_String::NPT_String(char c, NPT_Cardinal repeat)
+{
+    if (repeat != 0) {
+        m_Chars = Buffer::Create(c, repeat);
+    } else {
+        m_Chars = NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::SetLength
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_String::SetLength(NPT_Size length, bool pad)
+{
+    // special case for 0
+    if (length == 0) {
+        Reset();
+        return NPT_SUCCESS;
+    }
+    
+    // reserve the space
+    Reserve(length);
+
+    // pad with spaces if necessary
+    char* chars = UseChars();
+    if (pad) {
+        unsigned int current_length = GetLength();
+        if (length > current_length) {
+            unsigned int pad_length = length-current_length;
+            NPT_SetMemory(chars+current_length, ' ', pad_length);
+        }
+    }
+    
+    // update the length and terminate the buffer
+    GetBuffer()->SetLength(length);
+    chars[length] = '\0';
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::PrepareToWrite
++---------------------------------------------------------------------*/
+inline char*
+NPT_String::PrepareToWrite(NPT_Size length)
+{
+    NPT_ASSERT(length != 0);
+    if (m_Chars == NULL || GetBuffer()->GetAllocated() < length) {
+        // the buffer is too small, we need to allocate a new one.
+        NPT_Size needed = length;
+        if (m_Chars != NULL) {
+            NPT_Size grow = GetBuffer()->GetAllocated()*2;
+            if (grow > length) needed = grow;
+            delete GetBuffer();
+        }
+        m_Chars = Buffer::Create(needed);
+    }    
+    GetBuffer()->SetLength(length);
+    return m_Chars;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Reserve
++---------------------------------------------------------------------*/
+void
+NPT_String::Reserve(NPT_Size allocate)
+{
+    if (m_Chars == NULL || GetBuffer()->GetAllocated() < allocate) {
+        // the buffer is too small, we need to allocate a new one.
+        NPT_Size needed = allocate;
+        if (m_Chars != NULL) {
+            NPT_Size grow = GetBuffer()->GetAllocated()*2;
+            if (grow > allocate) needed = grow;
+        }
+        NPT_Size length = GetLength();
+        char* copy = Buffer::Create(needed, length);
+        if (m_Chars != NULL) {
+            CopyString(copy, m_Chars);
+            delete GetBuffer();
+        } else {
+            copy[0] = '\0';
+        }
+        m_Chars = copy;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Assign
++---------------------------------------------------------------------*/
+void
+NPT_String::Assign(const char* str, NPT_Size length)
+{
+    if (str == NULL || length == 0) {
+        Reset();
+    } else {
+        PrepareToWrite(length);
+        CopyBuffer(m_Chars, str, length);
+        m_Chars[length] = '\0';
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::operator=
++---------------------------------------------------------------------*/
+NPT_String&
+NPT_String::operator=(const char* str)
+{
+    if (str == NULL) {
+        Reset();
+    } else {
+        NPT_Size length = StringLength(str);
+        if (length == 0) {
+            Reset();
+        } else {
+            CopyString(PrepareToWrite(length), str);
+        }
+    }
+
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::operator=
++---------------------------------------------------------------------*/
+NPT_String&
+NPT_String::operator=(const NPT_String& str)
+{
+    // do nothing if we're assigning to ourselves
+    if (this != &str) {
+        Assign(str.GetChars(), str.GetLength());
+    }
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Append
++---------------------------------------------------------------------*/
+void
+NPT_String::Append(const char* str, NPT_Size length)
+{
+    // shortcut
+    if (str == NULL || length == 0) return;
+
+    // compute the new length
+    NPT_Size old_length = GetLength();
+    NPT_Size new_length = old_length + length;
+
+    // allocate enough space
+    Reserve(new_length);
+    
+    // append the new string at the end of the current one
+    CopyBuffer(m_Chars+old_length, str, length);
+    m_Chars[new_length] = '\0';
+
+    // update the length
+    GetBuffer()->SetLength(new_length);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Compare
++---------------------------------------------------------------------*/
+int 
+NPT_String::Compare(const char *s, bool ignore_case) const
+{
+    return NPT_String::Compare(GetChars(), s, ignore_case);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Compare
++---------------------------------------------------------------------*/
+int 
+NPT_String::Compare(const char *s1, const char *s2, bool ignore_case)
+{
+    const char *r1 = s1;
+    const char *r2 = s2;
+
+    if (ignore_case) {
+        while (NPT_Uppercase(*r1) == NPT_Uppercase(*r2)) {
+            if (*r1++ == '\0') {
+                return 0;
+            } 
+            r2++;
+        }
+        return NPT_Uppercase(*r1) - NPT_Uppercase(*r2);
+    } else {
+        while (*r1 == *r2) {
+            if (*r1++ == '\0') {
+                return 0;
+            } 
+            r2++;
+        }
+        return (*r1 - *r2);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::CompareN
++---------------------------------------------------------------------*/
+int 
+NPT_String::CompareN(const char *s, NPT_Size count, bool ignore_case) const
+{
+    return NPT_String::CompareN(GetChars(), s, count, ignore_case);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::CompareN
++---------------------------------------------------------------------*/
+int 
+NPT_String::CompareN(const char* s1, const char *s2, NPT_Size count, bool ignore_case)
+{
+    const char* me = s1;
+
+    if (ignore_case) {
+        for (unsigned int i=0; i<count; i++) {
+            if (NPT_Uppercase(me[i]) != NPT_Uppercase(s2[i])) {
+                return NPT_Uppercase(me[i]) - NPT_Uppercase(s2[i]);
+            }
+        }
+        return 0;
+    } else {
+        for (unsigned int i=0; i<count; i++) {
+            if (me[i] != s2[i]) {
+                return (me[i] - s2[i]);
+            }
+        }
+        return 0;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Split
++---------------------------------------------------------------------*/
+NPT_List<NPT_String> 
+NPT_String::Split(const char* separator) const
+{
+    NPT_List<NPT_String> result;
+    NPT_Size             separator_length = NPT_StringLength(separator);
+    
+    // sepcial case for empty separators
+    if (separator_length == 0) {
+        result.Add(*this);
+        return result;
+    }
+    
+    int current = 0;  
+    int next;  
+    do {
+        next = Find(separator, current);
+        unsigned int end = (next>=0?next:GetLength());
+        result.Add(SubString(current, end-current));
+        current = next+separator_length;
+    } while (next >= 0);
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::SubString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const
+{
+    if (first >= GetLength()) {
+        first = GetLength();
+        length = 0;
+    } else if (first+length >= GetLength()) {
+        length = GetLength()-first;
+    }
+    return NPT_String(GetChars()+first, length);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StringStartsWith
+|
+|    returns:
+|   1 if str starts with sub,
+|   0 if str is large enough but does not start with sub
+|     -1 if str is too short to start with sub
++---------------------------------------------------------------------*/
+static inline int
+NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case)
+{
+    if (ignore_case) {
+        while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) {
+            if (*str++ == '\0') {
+                return 1;
+            }
+            sub++;
+        }
+    } else {
+        while (*str == *sub) {
+            if (*str++ == '\0') {
+                return 1;
+            }
+            sub++;
+        }
+    }
+    return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::StartsWith
++---------------------------------------------------------------------*/
+bool 
+NPT_String::StartsWith(const char *s, bool ignore_case) const
+{
+    if (s == NULL) return false;
+    return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::EndsWith
++---------------------------------------------------------------------*/
+bool 
+NPT_String::EndsWith(const char *s, bool ignore_case) const
+{
+    if (s == NULL) return false;
+    NPT_Size str_length = NPT_StringLength(s);
+    if (str_length > GetLength()) return false;
+    return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Find
++---------------------------------------------------------------------*/
+int
+NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const
+{
+    // check args
+    if (str == NULL || start >= GetLength()) return -1;
+
+    // skip to start position
+    const char* src = m_Chars + start;
+
+    // look for a substring
+    while (*src) {
+        int cmp = NPT_StringStartsWith(src, str, ignore_case);
+        switch (cmp) {
+            case -1:
+                // ref is too short, abort
+                return -1;
+            case 1:
+                // match
+                return (int)(src-m_Chars);
+        }
+        src++;
+    }
+
+    return -1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Find
++---------------------------------------------------------------------*/
+int
+NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const
+{
+    // check args
+    if (start >= GetLength()) return -1;
+
+    // skip to start position
+    const char* src = m_Chars + start;
+
+    // look for the character
+    if (ignore_case) {
+        while (*src) {
+            if (NPT_Uppercase(*src) == NPT_Uppercase(c)) {
+                return (int)(src-m_Chars);
+            }
+            src++;
+        }
+    } else {
+        while (*src) {
+            if (*src == c) return (int)(src-m_Chars);
+            src++;
+        }
+    }
+
+    return -1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::ReverseFind
++---------------------------------------------------------------------*/
+int
+NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const
+{
+    // check args
+    if (str == NULL || *str == '\0') return -1;
+
+    // look for a substring
+    NPT_Size my_length = GetLength();
+    NPT_Size str_length = NPT_StringLength(str);
+    int i=my_length-start-str_length;
+    const char* src = GetChars();
+    if (i<0) return -1;
+    for (;i>=0; i--) {
+        int cmp = NPT_StringStartsWith(src+i, str, ignore_case);
+        if (cmp == 1) {
+            // match
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::ReverseFind
++---------------------------------------------------------------------*/
+int
+NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const
+{
+    // check args
+    NPT_Size length = GetLength();
+    int i = length-start-1;
+    if (i < 0) return -1;
+
+    // look for the character
+    const char* src = GetChars();
+    if (ignore_case) {
+        for (;i>=0;i--) {
+            if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) {
+                return i;
+            }
+        }
+    } else {
+        for (;i>=0;i--) {
+            if (src[i] == c) return i;
+        }
+    }
+
+    return -1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::MakeLowercase
++---------------------------------------------------------------------*/
+void
+NPT_String::MakeLowercase()
+{
+    // the source is the current buffer
+    const char* src = GetChars();
+
+    // convert all the characters of the existing buffer
+    char* dst = const_cast<char*>(src);
+    while (*dst != '\0') {
+        *dst = NPT_Lowercase(*dst);
+        dst++;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::MakeUppercase
++---------------------------------------------------------------------*/
+void
+NPT_String::MakeUppercase() 
+{
+    // the source is the current buffer
+    const char* src = GetChars();
+
+    // convert all the characters of the existing buffer
+    char* dst = const_cast<char*>(src);
+    while (*dst != '\0') {
+        *dst = NPT_Uppercase(*dst);
+        dst++;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::ToLowercase
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::ToLowercase() const
+{
+    NPT_String result(*this);
+    result.MakeLowercase();
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::ToUppercase
++---------------------------------------------------------------------*/
+NPT_String
+NPT_String::ToUppercase() const
+{
+    NPT_String result(*this);
+    result.MakeUppercase();
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Replace
++---------------------------------------------------------------------*/
+void
+NPT_String::Replace(char a, char b) 
+{
+    // check args
+    if (m_Chars == NULL || a == '\0' || b == '\0') return;
+
+    // we are going to modify the characters
+    char* src = m_Chars;
+
+    // process the buffer in place
+    while (*src) {
+        if (*src == a) *src = b;
+        src++;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Replace
++---------------------------------------------------------------------*/
+void
+NPT_String::Replace(char a, const char* str) 
+{
+    // check args
+    if (m_Chars == NULL || a == '\0' || str == NULL || str[0] == '\0') return;
+
+    // optimization
+    if (NPT_StringLength(str) == 1) return Replace(a, str[0]);
+
+    // we are going to create a new string
+    NPT_String dst;
+    char* src = m_Chars;
+
+    // reserve at least as much as input
+    dst.Reserve(GetLength());
+
+    // process the buffer
+    while (*src) {
+        if (*src == a) {
+            dst += str;
+        } else {
+            dst += *src;
+        }
+        src++;
+    }
+
+    Assign(dst.GetChars(), dst.GetLength());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Insert
++---------------------------------------------------------------------*/
+void
+NPT_String::Insert(const char* str, NPT_Ordinal where)
+{
+    // check args
+    if (str == NULL || where > GetLength()) return;
+
+    // measure the string to insert
+    NPT_Size str_length = StringLength(str);
+    if (str_length == 0) return;
+
+    // compute the size of the new string
+    NPT_Size old_length = GetLength();
+    NPT_Size new_length = str_length + GetLength();
+
+    // prepare to write the new string
+    char* src = m_Chars;
+    char* nst = Buffer::Create(new_length, new_length);
+    char* dst = nst;
+
+    // copy the beginning of the old string
+    if (where > 0) {
+        CopyBuffer(dst, src, where);
+        src += where;
+        dst += where;
+    }
+
+    // copy the inserted string
+    CopyString(dst, str);
+    dst += str_length;
+
+    // copy the end of the old string
+    if (old_length > where) {
+        CopyString(dst, src);
+    }
+
+    // use the new string
+    if (m_Chars) delete GetBuffer();
+    m_Chars = nst;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Erase
++---------------------------------------------------------------------*/
+void
+NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */)
+{
+    // check bounds
+    NPT_Size length = GetLength();
+    if (start+count > length) {
+        if (start >= length) return;
+        count = length-start;
+    }
+    if (count == 0) return;
+
+    CopyString(m_Chars+start, m_Chars+start+count);
+    GetBuffer()->SetLength(length-count);
+}
+
+/*----------------------------------------------------------------------
+|    NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_String::ToInteger(NPT_Int32& value, bool relaxed) const
+{
+    return NPT_ParseInteger32(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+|    NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_String::ToInteger(NPT_UInt32& value, bool relaxed) const
+{
+    return NPT_ParseInteger32U(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+|    NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_String::ToInteger(NPT_Int64& value, bool relaxed) const
+{
+    return NPT_ParseInteger64(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+|    NPT_String::ToInteger
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_String::ToInteger(NPT_UInt64& value, bool relaxed) const
+{
+    return NPT_ParseInteger64U(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+|    NPT_String::ToFloat
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_String::ToFloat(float& value, bool relaxed) const
+{
+    return NPT_ParseFloat(GetChars(), value, relaxed);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::TrimLeft
++---------------------------------------------------------------------*/
+void 
+NPT_String::TrimLeft()
+{
+    TrimLeft(NPT_STRINGS_WHITESPACE_CHARS);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::TrimLeft
++---------------------------------------------------------------------*/
+void 
+NPT_String::TrimLeft(char c)
+{
+    char s[2] = {c, 0};
+    TrimLeft((const char*)s);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::TrimLeft
++---------------------------------------------------------------------*/
+void 
+NPT_String::TrimLeft(const char* chars)
+{
+    if (m_Chars == NULL) return;
+    const char* s = m_Chars;
+    while (char c = *s) {
+        const char* x = chars;
+        while (*x) {
+            if (*x == c) break;
+            x++;
+        }
+        if (*x == 0) break; // not found
+        s++;
+    }
+    if (s == m_Chars) {
+        // nothing was trimmed
+        return;
+    }
+
+    // shift chars to the left
+    char* d = m_Chars;
+    GetBuffer()->SetLength(GetLength()-(s-d));
+    while ((*d++ = *s++)) {};
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::TrimRight
++---------------------------------------------------------------------*/
+void 
+NPT_String::TrimRight()
+{
+    TrimRight(NPT_STRINGS_WHITESPACE_CHARS);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::TrimRight
++---------------------------------------------------------------------*/
+void 
+NPT_String::TrimRight(char c)
+{
+    char s[2] = {c, 0};
+    TrimRight((const char*)s);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::TrimRight
++---------------------------------------------------------------------*/
+void 
+NPT_String::TrimRight(const char* chars)
+{
+    if (m_Chars == NULL || m_Chars[0] == '\0') return;
+    char* tail = m_Chars+GetLength()-1;
+    char* s = tail;
+    while (s != m_Chars-1) {
+        const char* x = chars;
+        while (*x) {
+            if (*x == *s) {
+                *s = '\0';
+                break;
+            }
+            x++;
+        }
+        if (*x == 0) break; // not found
+        s--;
+    }
+    if (s == tail) {
+        // nothing was trimmed
+        return;
+    }
+    GetBuffer()->SetLength(1+(int)(s-m_Chars));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Trim
++---------------------------------------------------------------------*/
+void 
+NPT_String::Trim()
+{
+    TrimLeft();
+    TrimRight();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Trim
++---------------------------------------------------------------------*/
+void 
+NPT_String::Trim(char c)
+{
+    char s[2] = {c, 0};
+    TrimLeft((const char*)s);
+    TrimRight((const char*)s);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::Trim
++---------------------------------------------------------------------*/
+void 
+NPT_String::Trim(const char* chars)
+{
+    TrimLeft(chars);
+    TrimRight(chars);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::operator+(const NPT_String&, const char*)
++---------------------------------------------------------------------*/
+NPT_String 
+operator+(const NPT_String& s1, const char* s2)
+{
+    // shortcut
+    if (s2 == NULL) return NPT_String(s1);
+
+    // measure strings
+    NPT_Size s1_length = s1.GetLength();
+    NPT_Size s2_length = NPT_String::StringLength(s2);
+
+    // allocate space for the new string
+    NPT_String result;
+    char* start = result.PrepareToWrite(s1_length+s2_length);
+
+    // concatenate the two strings into the result
+    NPT_String::CopyBuffer(start, s1, s1_length);
+    NPT_String::CopyString(start+s1_length, s2);
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::operator+(const NPT_String& , const char*)
++---------------------------------------------------------------------*/
+NPT_String 
+operator+(const char* s1, const NPT_String& s2)
+{
+    // shortcut
+    if (s1 == NULL) return NPT_String(s2);
+
+    // measure strings
+    NPT_Size s1_length = NPT_String::StringLength(s1);
+    NPT_Size s2_length = s2.GetLength();
+
+    // allocate space for the new string
+    NPT_String result;
+    char* start = result.PrepareToWrite(s1_length+s2_length);
+
+    // concatenate the two strings into the result
+    NPT_String::CopyBuffer(start, s1, s1_length);
+    NPT_String::CopyString(start+s1_length, s2.GetChars());
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_String::operator+(const NPT_String& , char)
++---------------------------------------------------------------------*/
+NPT_String 
+operator+(const NPT_String& s1, char c)
+{
+    // allocate space for the new string
+    NPT_String result;
+    result.Reserve(s1.GetLength()+1);
+    
+    // append
+    result = s1;
+    result += c;
+
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,334 @@
+/*****************************************************************
+|
+|   Neptune - String Objects
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_STRINGS_H_
+#define _NPT_STRINGS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#if defined(NPT_CONFIG_HAVE_NEW_H)
+#include <new>
+#endif
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptList.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_STRING_SEARCH_FAILED = -1;
+
+/*----------------------------------------------------------------------
+|   NPT_String
++---------------------------------------------------------------------*/
+class NPT_String
+{
+public:
+    // factories
+    static NPT_String FromInteger(NPT_Int64 value);
+    static NPT_String FromIntegerU(NPT_UInt64 value);
+    static NPT_String Format(const char* format, ...);
+    
+    // constructors
+    NPT_String(const NPT_String& str);
+    NPT_String(const char* str);
+    NPT_String(const char* str, NPT_Size length);
+    NPT_String(const char* str, NPT_Ordinal first, NPT_Size length);
+    NPT_String(char c, NPT_Cardinal repeat = 1);
+    NPT_String() : m_Chars(NULL) {}
+   ~NPT_String() { if (m_Chars) delete GetBuffer(); }
+
+    // string info and manipulations
+    bool       IsEmpty() const { return m_Chars == NULL || GetBuffer()->GetLength() == 0; }
+    NPT_Size   GetLength()   const { return m_Chars ? GetBuffer()->GetLength() : 0;    }
+    NPT_Size   GetCapacity() const { return m_Chars ? GetBuffer()->GetAllocated() : 0; }
+    NPT_Result SetLength(NPT_Size length, bool pad = false);
+    void       Assign(const char* chars, NPT_Size size);
+    void       Append(const char* chars, NPT_Size size);
+    void       Append(const char* s) { Append(s, StringLength(s)); }
+    int        Compare(const char* s, bool ignore_case = false) const;
+    static int Compare(const char* s1, const char* s2, bool ignore_case = false);
+    int        CompareN(const char* s, NPT_Size count, bool ignore_case = false) const;
+    static int CompareN(const char* s1, const char* s2, NPT_Size count, bool ignore_case = false);
+
+    // substrings
+    NPT_String SubString(NPT_Ordinal first, NPT_Size length) const;
+    NPT_String SubString(NPT_Ordinal first) const {
+        return SubString(first, GetLength());
+    }
+    NPT_String Left(NPT_Size length) const {
+        return SubString(0, length);
+    }
+    NPT_String Right(NPT_Size length) const {
+        return length >= GetLength() ? 
+               *this : 
+               SubString(GetLength()-length, length);
+    }
+    NPT_List<NPT_String> Split(const char* separator) const;
+    
+    // buffer management
+    void       Reserve(NPT_Size length);
+
+    // conversions
+    NPT_String ToLowercase() const;
+    NPT_String ToUppercase() const;
+    NPT_Result ToInteger(NPT_Int32& value, bool relaxed = true) const;
+    NPT_Result ToInteger(NPT_UInt32& value, bool relaxed = true) const;
+    NPT_Result ToInteger(NPT_Int64& value, bool relaxed = true) const;
+    NPT_Result ToInteger(NPT_UInt64& value, bool relaxed = true) const;
+    NPT_Result ToFloat(float& value, bool relaxed = true) const;
+    
+    // processing
+    void MakeLowercase();
+    void MakeUppercase();
+    void Replace(char a, char b);
+    void Replace(char a, const char* str);
+
+    // search
+    int  Find(char c, NPT_Ordinal start = 0, bool ignore_case = false) const;
+    int  Find(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const;
+    int  ReverseFind(char c, NPT_Ordinal start = 0, bool ignore_case = false) const;
+    int  ReverseFind(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const;
+    bool StartsWith(const char* s, bool ignore_case = false) const;
+    bool EndsWith(const char* s, bool ignore_case = false) const;
+
+    // editing
+    void Insert(const char* s, NPT_Ordinal where = 0);
+    void Erase(NPT_Ordinal start, NPT_Cardinal count = 1);
+    void Replace(NPT_Ordinal start, NPT_Cardinal count, const char* s);
+    void TrimLeft();
+    void TrimLeft(char c);
+    void TrimLeft(const char* chars);
+    void TrimRight();
+    void TrimRight(char c);
+    void TrimRight(const char* chars);
+    void Trim();
+    void Trim(char c);
+    void Trim(const char* chars);
+
+    // type casting
+    operator char*() const        { return m_Chars ? m_Chars: &EmptyString; }
+    operator const char* () const { return m_Chars ? m_Chars: &EmptyString; }
+    const char* GetChars() const  { return m_Chars ? m_Chars: &EmptyString; }
+    char*       UseChars()        { return m_Chars ? m_Chars: &EmptyString; }
+
+    // operator overloading
+    NPT_String& operator=(const char* str);
+    NPT_String& operator=(const NPT_String& str);
+    NPT_String& operator=(char c);
+    const NPT_String& operator+=(const NPT_String& s) {
+        Append(s.GetChars(), s.GetLength());
+        return *this;
+    }
+    const NPT_String& operator+=(const char* s) {
+        Append(s);
+        return *this;
+    }
+    const NPT_String& operator+=(char c) {
+        Append(&c, 1);
+        return *this;
+    }
+    char operator[](int index) const {
+        NPT_ASSERT((unsigned int)index < GetLength());
+        return GetChars()[index];
+    }
+    char& operator[](int index) {
+        NPT_ASSERT((unsigned int)index < GetLength());
+        return UseChars()[index];
+    }
+
+    // friend operators
+    friend NPT_String operator+(const NPT_String& s1, const NPT_String& s2) {
+        return s1+s2.GetChars();
+    }
+    friend NPT_String operator+(const NPT_String& s1, const char* s2);
+    friend NPT_String operator+(const char* s1, const NPT_String& s2);
+    friend NPT_String operator+(const NPT_String& s, char c);
+    friend NPT_String operator+(char c, const NPT_String& s);
+
+protected:
+    // inner classes
+    class Buffer {
+    public:
+        // class methods
+        static Buffer* Allocate(NPT_Size allocated, NPT_Size length) {
+            void* mem = ::operator new(sizeof(Buffer)+allocated+1);
+            return new(mem) Buffer(allocated, length);
+        }
+        static char* Create(NPT_Size allocated, NPT_Size length=0) {
+            Buffer* shared = Allocate(allocated, length);
+            return shared->GetChars();
+        }
+        static char* Create(const char* copy) {
+            NPT_Size length = StringLength(copy);
+            Buffer* shared = Allocate(length, length);
+            CopyString(shared->GetChars(), copy);
+            return shared->GetChars();
+        }
+        static char* Create(const char* copy, NPT_Size length) {
+            Buffer* shared = Allocate(length, length);
+            CopyBuffer(shared->GetChars(), copy, length);
+            shared->GetChars()[length] = '\0';
+            return shared->GetChars();
+        }
+        static char* Create(char c, NPT_Cardinal repeat) {
+            Buffer* shared = Allocate(repeat, repeat);
+            char* s = shared->GetChars();
+            while (repeat--) {
+                *s++ = c;
+            }
+            *s = '\0';
+            return shared->GetChars();
+        }
+
+        // methods
+        char* GetChars() { 
+            // return a pointer to the first char
+            return reinterpret_cast<char*>(this+1); 
+        }
+        NPT_Size GetLength() const      { return m_Length; }
+        void SetLength(NPT_Size length) { m_Length = length; }
+        NPT_Size GetAllocated() const   { return m_Allocated; }
+
+    private:
+        // methods
+        Buffer(NPT_Size allocated, NPT_Size length = 0) : 
+            m_Length(length),
+            m_Allocated(allocated) {}
+
+        // members
+        NPT_Cardinal m_Length;
+        NPT_Cardinal m_Allocated;
+        // the actual string data follows
+
+    };
+    
+    // members
+    char* m_Chars;
+
+private:
+    // friends
+    friend class Buffer;
+
+    // static members
+    static char EmptyString;
+
+    // methods
+    Buffer* GetBuffer() const { 
+        return reinterpret_cast<Buffer*>(m_Chars)-1;
+    }
+    void Reset() { 
+        if (m_Chars != NULL) {
+            delete GetBuffer(); 
+            m_Chars = NULL;
+        }
+    }
+    char* PrepareToWrite(NPT_Size length);
+    void PrepareToAppend(NPT_Size length, NPT_Size allocate);
+
+    // static methods
+    static void CopyString(char* dst, const char* src) {
+        while ((*dst++ = *src++)){}
+    }
+    
+    static void CopyBuffer(char* dst, const char* src, NPT_Size size) {
+        while (size--) *dst++ = *src++;
+    }
+    
+    static NPT_Size StringLength(const char* str) {
+        NPT_Size length = 0;
+        while (*str++) length++;
+        return length;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   external operators
++---------------------------------------------------------------------*/
+inline bool operator==(const NPT_String& s1, const NPT_String& s2) { 
+    return s1.Compare(s2) == 0; 
+}
+inline bool operator==(const NPT_String& s1, const char* s2) {
+    return s1.Compare(s2) == 0; 
+}
+inline bool operator==(const char* s1, const NPT_String& s2) {
+    return s2.Compare(s1) == 0; 
+}
+inline bool operator!=(const NPT_String& s1, const NPT_String& s2) {
+    return s1.Compare(s2) != 0; 
+}
+inline bool operator!=(const NPT_String& s1, const char* s2) {
+    return s1.Compare(s2) != 0; 
+}
+inline bool operator!=(const char* s1, const NPT_String& s2) {
+    return s2.Compare(s1) != 0; 
+}
+inline bool operator<(const NPT_String& s1, const NPT_String& s2) {
+    return s1.Compare(s2) < 0; 
+}
+inline bool operator<(const NPT_String& s1, const char* s2) {
+    return s1.Compare(s2) < 0; 
+}
+inline bool operator<(const char* s1, const NPT_String& s2) {
+    return s2.Compare(s1) > 0; 
+}
+inline bool operator>(const NPT_String& s1, const NPT_String& s2) {
+    return s1.Compare(s2) > 0; 
+}
+inline bool operator>(const NPT_String& s1, const char* s2) {
+    return s1.Compare(s2) > 0; 
+}
+inline bool operator>(const char* s1, const NPT_String& s2) {
+    return s2.Compare(s1) < 0; 
+}
+inline bool operator<=(const NPT_String& s1, const NPT_String& s2) {
+    return s1.Compare(s2) <= 0; 
+}
+inline bool operator<=(const NPT_String& s1, const char* s2) {
+    return s1.Compare(s2) <= 0; 
+}
+inline bool operator<=(const char* s1, const NPT_String& s2) {
+    return s2.Compare(s1) >= 0; 
+}
+inline bool operator>=(const NPT_String& s1, const NPT_String& s2) {
+    return s1.Compare(s2) >= 0; 
+}
+inline bool operator>=(const NPT_String& s1, const char* s2) {
+    return s1.Compare(s2) >= 0; 
+}
+inline bool operator>=(const char* s1, const NPT_String& s2) {
+    return s2.Compare(s1) <= 0; 
+}
+
+#endif // _NPT_STRINGS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSystem.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,37 @@
+/*****************************************************************
+|
+|   Neptune - System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptSystem.h"
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptSystem.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,60 @@
+/*****************************************************************
+|
+|   Neptune - System
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_SYSTEM_H_
+#define _NPT_SYSTEM_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptTime.h"
+
+/*----------------------------------------------------------------------
+|   NPT_System
++---------------------------------------------------------------------*/
+class NPT_System
+{
+public:
+    // methods
+    static NPT_Result GetProcessId(NPT_UInt32& id);
+    static NPT_Result GetCurrentTimeStamp(NPT_TimeStamp& now);
+    static NPT_Result Sleep(const NPT_TimeInterval& duration);
+    static NPT_Result SleepUntil(const NPT_TimeStamp& when);
+    static NPT_Result SetRandomSeed(unsigned int seed);
+    static NPT_UInt32 GetRandomInteger();
+    
+protected:
+    // constructor
+    NPT_System() {}
+};
+
+#endif // _NPT_SYSTEM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptThreads.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,156 @@
+/*****************************************************************
+|
+|   Neptune - Threads
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot
++---------------------------------------------------------------------*/
+NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot() :
+    m_CallbackArgs(NULL),
+    m_Shutdown(false),
+    m_NotificationHelper(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackSlot::Shutdown
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ThreadCallbackSlot::Shutdown()
+{
+    // protect against concurrent access
+    //FIXME: This will not work if another Thread has called ReceiveCallback with a timeout
+    NPT_AutoLock lock(m_ReadLock);
+
+    // signal we are shut down
+    m_Shutdown = true;
+
+    // clear up any pending callbacks
+    m_Pending.SetValue(0);
+    m_Ack.SetValue(1);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackSlot::SetNotificationHelper
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ThreadCallbackSlot::SetNotificationHelper(NotificationHelper* helper)
+{
+    m_NotificationHelper = helper;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackSlot::ReceiveCallback
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ThreadCallbackSlot::ReceiveCallback(NPT_ThreadCallbackReceiver& receiver,
+                                        NPT_Timeout                 timeout)
+{
+    // protect against concurrent access
+    //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - read locking, timeout=%d\n", timeout);
+    NPT_AutoLock lock(m_ReadLock);
+
+    if (timeout) {
+        // wait until there is a pending callback
+        //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - waiting...\n");
+        NPT_Result result = m_Pending.WaitUntilEquals(1, timeout);
+        if (NPT_FAILED(result)) return result; // don't log here because the result
+                                               // could be NPT_ERROR_TIMEOUT which
+                                               // is an expected normal case.
+        //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - got it\n");
+    } else {
+        // see if something is pending
+        if (m_Pending.GetValue() == 0) {
+            //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - nothing pending\n");
+            return NPT_ERROR_CALLBACK_NOTHING_PENDING;
+        }
+    }
+
+    // check if we have been shutdown
+    if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;
+
+    // process the callback
+    //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - calling back\n");
+    receiver.OnCallback(const_cast<void*>(m_CallbackArgs));
+
+    // signal that we've processed the callback
+    m_Pending.SetValue(0);
+    m_Ack.SetValue(1);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackSlot::SendCallback
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ThreadCallbackSlot::SendCallback(void* args)
+{
+    // protect against concurrent access
+    //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - write locking\n");
+    NPT_AutoLock lock(m_WriteLock);
+
+    // there should be nothing pending
+#if defined(NPT_DEBUG)
+    NPT_ASSERT(m_Pending.GetValue() == 0);
+#endif
+
+    // check if we have been shutdown
+    if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;
+
+    // put the callback args
+    m_CallbackArgs = args;
+    //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - signalling\n");
+    m_Pending.SetValue(1);
+    
+    // call the helper before we wait
+    if (m_NotificationHelper) {
+        m_NotificationHelper->Notify();
+    }
+
+    // wait until the callback has been process, or we've been shutdown
+    //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - waiting...\n");
+    m_Ack.WaitUntilEquals(1);
+    //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - got it\n");
+
+    // done
+    m_Ack.SetValue(0);
+    m_CallbackArgs = NULL;
+
+    return m_Shutdown?NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN:NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptThreads.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,281 @@
+/*****************************************************************
+|
+|   Neptune - Threads
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_THREADS_H_
+#define _NPT_THREADS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptInterfaces.h"
+
+/*----------------------------------------------------------------------
+|   error codes
++---------------------------------------------------------------------*/
+const int NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN = NPT_ERROR_BASE_THREADS-0;
+const int NPT_ERROR_CALLBACK_NOTHING_PENDING  = NPT_ERROR_BASE_THREADS-1;
+
+/*----------------------------------------------------------------------
+|   NPT_MutexInterface
++---------------------------------------------------------------------*/
+class NPT_MutexInterface
+{
+ public:
+    // methods
+    virtual           ~NPT_MutexInterface() {}
+    virtual NPT_Result Lock()   = 0;
+    virtual NPT_Result Unlock() = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Mutex
++---------------------------------------------------------------------*/
+class NPT_Mutex : public NPT_MutexInterface
+{
+ public:
+    // methods
+               NPT_Mutex();
+              ~NPT_Mutex() { delete m_Delegate; }
+    NPT_Result Lock()   { return m_Delegate->Lock();   }
+    NPT_Result Unlock() { return m_Delegate->Unlock(); }
+
+ private:
+    // members
+    NPT_MutexInterface* m_Delegate;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_AutoLock
++---------------------------------------------------------------------*/
+class NPT_AutoLock
+{
+ public:
+    // methods
+     NPT_AutoLock(NPT_Mutex &mutex) : m_Mutex(mutex)   {
+        m_Mutex.Lock();
+    }
+    ~NPT_AutoLock() {
+        m_Mutex.Unlock(); 
+    }
+        
+ private:
+    // members
+    NPT_Mutex& m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Lock
++---------------------------------------------------------------------*/
+template <typename T> 
+class NPT_Lock : public T,
+                 public NPT_Mutex
+{
+};
+
+/*----------------------------------------------------------------------
+|   NPT_SharedVariableInterface
++---------------------------------------------------------------------*/
+class NPT_SharedVariableInterface
+{
+ public:
+    // methods
+    virtual           ~NPT_SharedVariableInterface() {}
+    virtual void       SetValue(int value)= 0;
+    virtual int        GetValue()         = 0;
+    virtual NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+    virtual NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_SharedVariable
++---------------------------------------------------------------------*/
+class NPT_SharedVariable : public NPT_SharedVariableInterface
+{
+ public:
+    // methods
+               NPT_SharedVariable(int value = 0);
+              ~NPT_SharedVariable() { delete m_Delegate; }
+    void SetValue(int value) { 
+        m_Delegate->SetValue(value); 
+    }
+    int GetValue() { 
+        return m_Delegate->GetValue(); 
+    }
+    NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) { 
+        return m_Delegate->WaitUntilEquals(value, timeout); 
+    }
+    NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) { 
+        return m_Delegate->WaitWhileEquals(value, timeout); 
+    }
+
+ private:
+    // members
+    NPT_SharedVariableInterface* m_Delegate;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_AtomicVariableInterface
++---------------------------------------------------------------------*/
+class NPT_AtomicVariableInterface
+{
+ public:
+    // methods
+    virtual      ~NPT_AtomicVariableInterface() {}
+    virtual  int  Increment() = 0;
+    virtual  int  Decrement() = 0;
+    virtual  int  GetValue()  = 0;
+    virtual  void SetValue(int value)  = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_AtomicVariable
++---------------------------------------------------------------------*/
+class NPT_AtomicVariable : public NPT_AtomicVariableInterface
+{
+ public:
+    // methods
+         NPT_AtomicVariable(int value = 0);
+        ~NPT_AtomicVariable() { delete m_Delegate;             }
+    int  Increment()          { return m_Delegate->Increment();}
+    int  Decrement()          { return m_Delegate->Decrement();}
+    void SetValue(int value)  { m_Delegate->SetValue(value);   }
+    int  GetValue()           { return m_Delegate->GetValue(); }
+
+ private:
+    // members
+    NPT_AtomicVariableInterface* m_Delegate;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Runnable
++---------------------------------------------------------------------*/
+class NPT_Runnable
+{
+public:
+    virtual ~NPT_Runnable() {}  
+    virtual void Run() = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadInterface
++---------------------------------------------------------------------*/
+class NPT_ThreadInterface: public NPT_Runnable, public NPT_Interruptible
+{
+ public:
+    // methods
+    virtual           ~NPT_ThreadInterface() {}
+    virtual NPT_Result Start() = 0;
+    virtual NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE)  = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Thread
++---------------------------------------------------------------------*/
+class NPT_Thread : public NPT_ThreadInterface
+{
+ public:
+    // types
+    typedef unsigned long ThreadId;
+
+    // class methods
+    static ThreadId GetCurrentThreadId();
+
+    // methods
+    explicit NPT_Thread(bool detached = false);
+    explicit NPT_Thread(NPT_Runnable& target, bool detached = false);
+   ~NPT_Thread() { delete m_Delegate; }
+
+    // NPT_ThreadInterface methods
+    NPT_Result Start() { 
+        return m_Delegate->Start(); 
+    } 
+    NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE)  { 
+        return m_Delegate->Wait(timeout);  
+    }
+
+    // NPT_Runnable methods
+    virtual void Run() {}
+
+    // NPT_Interruptible methods
+    virtual NPT_Result Interrupt() { return m_Delegate->Interrupt(); }
+
+ private:
+    // members
+    NPT_ThreadInterface* m_Delegate;
+};
+
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackReceiver
++---------------------------------------------------------------------*/
+class NPT_ThreadCallbackReceiver
+{
+public:
+    virtual ~NPT_ThreadCallbackReceiver() {}
+    virtual void OnCallback(void* args) = 0;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ThreadCallbackSlot
++---------------------------------------------------------------------*/
+class NPT_ThreadCallbackSlot
+{
+public:
+    // types
+    class NotificationHelper {
+    public:
+        virtual ~NotificationHelper() {};
+        virtual void Notify(void) = 0;
+    };
+
+    // constructor
+    NPT_ThreadCallbackSlot();
+
+    // methods
+    NPT_Result ReceiveCallback(NPT_ThreadCallbackReceiver& receiver, NPT_Timeout timeout = 0);
+    NPT_Result SendCallback(void* args);
+    NPT_Result SetNotificationHelper(NotificationHelper* helper);
+    NPT_Result Shutdown();
+
+protected:
+    // members
+    volatile void*      m_CallbackArgs;
+    volatile bool       m_Shutdown;
+    NPT_SharedVariable  m_Pending;
+    NPT_SharedVariable  m_Ack;
+    NPT_Mutex           m_ReadLock;
+    NPT_Mutex           m_WriteLock;
+    NotificationHelper* m_NotificationHelper;
+};
+
+#endif // _NPT_THREADS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptTime.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,189 @@
+/*****************************************************************
+|
+|   Neptune - Time
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTime.h"
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::NPT_TimeStamp
++---------------------------------------------------------------------*/
+NPT_TimeStamp::NPT_TimeStamp(float seconds)
+{
+    m_Seconds     = (long)seconds;
+    m_NanoSeconds = (long)(1E9f*(seconds - (float)m_Seconds));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator float
++---------------------------------------------------------------------*/
+NPT_TimeStamp::operator float() const
+{       
+    return ((float)m_Seconds) + ((float)m_NanoSeconds)/1E9f;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator+=
++---------------------------------------------------------------------*/
+NPT_TimeStamp&
+NPT_TimeStamp::operator+=(const NPT_TimeStamp& t)
+{
+    m_Seconds += t.m_Seconds;
+    m_NanoSeconds += t.m_NanoSeconds;
+    if (m_NanoSeconds <= -1000000000) {
+        m_Seconds--;
+        m_NanoSeconds += 1000000000;
+    } else if (m_NanoSeconds >= 1000000000) {
+        m_Seconds++;
+        m_NanoSeconds -= 1000000000;
+    }
+    if (m_NanoSeconds < 0 && m_Seconds > 0) {
+        m_Seconds--;
+        m_NanoSeconds += 1000000000;
+    }
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator-=
++---------------------------------------------------------------------*/
+NPT_TimeStamp&
+NPT_TimeStamp::operator-=(const NPT_TimeStamp& t)
+{
+    m_Seconds -= t.m_Seconds;
+    m_NanoSeconds -= t.m_NanoSeconds;
+    if (m_NanoSeconds <= -1000000000) {
+        m_Seconds--;
+        m_NanoSeconds += 1000000000;
+    } else if (m_NanoSeconds >= 1000000000) {
+        m_Seconds++;
+        m_NanoSeconds -= 1000000000;
+    }
+    if (m_NanoSeconds < 0 && m_Seconds > 0) {
+        m_Seconds--;
+        m_NanoSeconds += 1000000000;
+    }
+    return *this;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator==
++---------------------------------------------------------------------*/
+bool
+NPT_TimeStamp::operator==(const NPT_TimeStamp& t) const
+{
+    return 
+        m_Seconds     == t.m_Seconds && 
+        m_NanoSeconds == t.m_NanoSeconds;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator!=
++---------------------------------------------------------------------*/
+bool
+NPT_TimeStamp::operator!=(const NPT_TimeStamp& t) const
+{
+    return 
+        m_Seconds     != t.m_Seconds || 
+        m_NanoSeconds != t.m_NanoSeconds;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator>
++---------------------------------------------------------------------*/
+bool
+NPT_TimeStamp::operator>(const NPT_TimeStamp& t) const
+{
+    return 
+        m_Seconds   > t.m_Seconds || 
+        (m_Seconds == t.m_Seconds && m_NanoSeconds > t.m_NanoSeconds);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator<
++---------------------------------------------------------------------*/
+bool
+NPT_TimeStamp::operator<(const NPT_TimeStamp& t) const
+{
+    return 
+        m_Seconds   < t.m_Seconds || 
+        (m_Seconds == t.m_Seconds && m_NanoSeconds < t.m_NanoSeconds);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator>=
++---------------------------------------------------------------------*/
+bool
+NPT_TimeStamp::operator>=(const NPT_TimeStamp& t) const
+{
+    return *this > t || *this == t;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator<=
++---------------------------------------------------------------------*/
+bool
+NPT_TimeStamp::operator<=(const NPT_TimeStamp& t) const
+{
+    return *this < t || *this == t;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator+
++---------------------------------------------------------------------*/
+NPT_TimeStamp
+operator+(const NPT_TimeStamp& timestamp, long seconds)
+{
+    // shortcut
+    if (seconds == 0) return NPT_TimeStamp(timestamp);
+
+    NPT_TimeStamp result = timestamp;
+    result.m_Seconds += seconds;
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp::operator-
++---------------------------------------------------------------------*/
+NPT_TimeStamp
+operator-(const NPT_TimeStamp& timestamp, long seconds)
+{
+    // shortcut
+    if (seconds == 0) return NPT_TimeStamp(timestamp);
+
+    NPT_TimeStamp result = timestamp;
+    result.m_Seconds -= seconds;
+
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptTime.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,96 @@
+/*****************************************************************
+|
+|   Neptune - Time
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_TIME_H_
+#define _NPT_TIME_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   NPT_TimeStamp
++---------------------------------------------------------------------*/
+class NPT_TimeStamp
+{
+ public:
+    // methods
+    NPT_TimeStamp(unsigned long seconds = 0, unsigned long nano_seconds = 0) :
+        m_Seconds(seconds), m_NanoSeconds(nano_seconds) {}
+    NPT_TimeStamp(float seconds);
+    operator float() const;
+    NPT_TimeStamp& operator+=(const NPT_TimeStamp& time_stamp);
+    NPT_TimeStamp& operator-=(const NPT_TimeStamp& time_stamp);
+    bool operator==(const NPT_TimeStamp& time_stamp) const;
+    bool operator!=(const NPT_TimeStamp& time_stamp) const;
+    bool operator>(const NPT_TimeStamp& time_stamp) const;
+    bool operator<(const NPT_TimeStamp& time_stamp) const;
+    bool operator>=(const NPT_TimeStamp& time_stamp) const;
+    bool operator<=(const NPT_TimeStamp& time_stamp) const;
+
+    // friend operators
+    friend NPT_TimeStamp operator+(const NPT_TimeStamp& timestamp, long seconds);
+    friend NPT_TimeStamp operator-(const NPT_TimeStamp& timestamp, long seconds);
+
+    // members
+    long m_Seconds;
+    long m_NanoSeconds;
+};
+
+/*----------------------------------------------------------------------
+|   operator+
++---------------------------------------------------------------------*/
+inline 
+NPT_TimeStamp 
+operator+(const NPT_TimeStamp& t1, const NPT_TimeStamp& t2) 
+{
+    NPT_TimeStamp t = t1;
+    return t += t2;
+}
+
+/*----------------------------------------------------------------------
+|   operator-
++---------------------------------------------------------------------*/
+inline 
+NPT_TimeStamp 
+operator-(const NPT_TimeStamp& t1, const NPT_TimeStamp& t2) 
+{
+    NPT_TimeStamp t = t1;
+    return t -= t2;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TimeInterval
++---------------------------------------------------------------------*/
+typedef NPT_TimeStamp NPT_TimeInterval;
+
+#endif // _NPT_TIME_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptTls.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,492 @@
+/*****************************************************************
+|
+|   Neptune - TLS/SSL Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#if defined(NPT_CONFIG_ENABLE_TLS)
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTls.h"
+#include "NptLogging.h"
+#include "NptUtils.h"
+#include "NptSockets.h"
+
+#include "ssl.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+//NPT_SET_LOCAL_LOGGER("neptune.tls")
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_TLS_CONTEXT_DEFAULT_SESSION_CACHE = 16;
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef NPT_Reference<NPT_TlsSessionImpl> NPT_TlsSessionImplReference;
+
+/*----------------------------------------------------------------------
+|   NPT_Tls_MapResult
++---------------------------------------------------------------------*/
+static NPT_Result
+NPT_Tls_MapResult(int err)
+{
+    switch (err) {
+        case SSL_ERROR_CONN_LOST:         return NPT_ERROR_CONNECTION_ABORTED;
+        case SSL_ERROR_TIMEOUT:           return NPT_ERROR_TIMEOUT;
+        case SSL_ERROR_EOS:               return NPT_ERROR_EOS;
+        case SSL_ERROR_NOT_SUPPORTED:     return NPT_ERROR_NOT_SUPPORTED;
+        case SSL_ERROR_INVALID_HANDSHAKE: return NPT_ERROR_TLS_INVALID_HANDSHAKE;
+        case SSL_ERROR_INVALID_PROT_MSG:  return NPT_ERROR_TLS_INVALID_PROTOCOL_MESSAGE;
+        case SSL_ERROR_INVALID_HMAC:      return NPT_ERROR_TLS_INVALID_HMAC;
+        case SSL_ERROR_INVALID_VERSION:   return NPT_ERROR_TLS_INVALID_VERSION;
+        case SSL_ERROR_INVALID_SESSION:   return NPT_ERROR_TLS_INVALID_SESSION;
+        case SSL_ERROR_NO_CIPHER:         return NPT_ERROR_TLS_NO_CIPHER;
+        case SSL_ERROR_BAD_CERTIFICATE:   return NPT_ERROR_TLS_BAD_CERTIFICATE;
+        case SSL_ERROR_INVALID_KEY:       return NPT_ERROR_INVALID_KEY;
+        case 0:                           return NPT_SUCCESS;
+        default:                          return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsContextImpl
++---------------------------------------------------------------------*/
+class NPT_TlsContextImpl {
+public:
+    NPT_TlsContextImpl() :
+        m_SSL_CTX(ssl_ctx_new(SSL_SERVER_VERIFY_LATER, NPT_TLS_CONTEXT_DEFAULT_SESSION_CACHE)) {};
+    ~NPT_TlsContextImpl() { ssl_ctx_free(m_SSL_CTX); }
+    
+   NPT_Result LoadKey(NPT_TlsKeyFormat     key_format, 
+                      const unsigned char* key_data,
+                      NPT_Size             key_data_size,
+                      const char*          password);
+    
+    SSL_CTX* m_SSL_CTX;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TlsContextImpl::LoadKey
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsContextImpl::LoadKey(NPT_TlsKeyFormat     key_format, 
+                            const unsigned char* key_data,
+                            NPT_Size             key_data_size,
+                            const char*          password)
+{
+    int object_type;
+    switch (key_format) {
+        case NPT_TLS_KEY_FORMAT_RSA_PRIVATE: object_type = SSL_OBJ_RSA_KEY; break;
+        case NPT_TLS_KEY_FORMAT_PKCS8:       object_type = SSL_OBJ_PKCS8;   break;
+        case NPT_TLS_KEY_FORMAT_PKCS12:      object_type = SSL_OBJ_PKCS12;  break;
+        default: return NPT_ERROR_INVALID_PARAMETERS;
+    }
+    
+    int result = ssl_obj_memory_load(m_SSL_CTX, object_type, key_data, key_data_size, password);
+    return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsStreamAdapter
++---------------------------------------------------------------------*/
+struct NPT_TlsStreamAdapter
+{
+    static int Read(SSL_SOCKET* _self, void* buffer, unsigned int size) {
+        NPT_TlsStreamAdapter* self = (NPT_TlsStreamAdapter*)_self;
+        NPT_Size bytes_read = 0;
+        NPT_Result result = self->m_Input->Read(buffer, size, &bytes_read);
+        if (NPT_FAILED(result)) {
+            switch (result) {
+                case NPT_ERROR_EOS:     return SSL_ERROR_EOS;
+                case NPT_ERROR_TIMEOUT: return SSL_ERROR_TIMEOUT;
+                default:                return SSL_ERROR_CONN_LOST;
+            }
+        }
+        return bytes_read;
+    }
+
+    static int Write(SSL_SOCKET* _self, const void* buffer, unsigned int size) {
+        NPT_TlsStreamAdapter* self = (NPT_TlsStreamAdapter*)_self;
+        NPT_Size bytes_written = 0;
+        NPT_Result result = self->m_Output->Write(buffer, size, &bytes_written);
+        if (NPT_FAILED(result)) {
+            switch (result) {
+                case NPT_ERROR_EOS:     return SSL_ERROR_EOS;
+                case NPT_ERROR_TIMEOUT: return SSL_ERROR_TIMEOUT;
+                default:                return SSL_ERROR_CONN_LOST;
+            }
+        }
+        return bytes_written;
+    }
+    
+    NPT_TlsStreamAdapter(NPT_InputStreamReference  input, 
+                         NPT_OutputStreamReference output) :
+        m_Input(input), m_Output(output) {
+        m_Base.Read  = Read;
+        m_Base.Write = Write;
+    }
+    
+    SSL_SOCKET                m_Base;
+    NPT_InputStreamReference  m_Input;
+    NPT_OutputStreamReference m_Output;
+};
+
+
+/*----------------------------------------------------------------------
+|   NPT_TlsSessionImpl
++---------------------------------------------------------------------*/
+class NPT_TlsSessionImpl {
+public:
+    NPT_TlsSessionImpl(SSL_CTX*                   context,
+                       NPT_InputStreamReference&  input,
+                       NPT_OutputStreamReference& output) :
+        m_SSL_CTX(context),
+        m_SSL(NULL),
+        m_StreamAdapter(input, output) {}
+    ~NPT_TlsSessionImpl() { ssl_free(m_SSL); }
+    
+    // methods
+    NPT_Result Handshake();
+    NPT_Result GetSessionId(NPT_DataBuffer& session_id);
+    NPT_UInt32 GetCipherSuiteId();
+    NPT_Result GetPeerCertificateInfo(NPT_TlsCertificateInfo& cert_info);
+    
+    // members
+    SSL_CTX*             m_SSL_CTX;
+    SSL*                 m_SSL;
+    NPT_TlsStreamAdapter m_StreamAdapter;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TlsSessionImpl::Handshake
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::Handshake()
+{
+    if (m_SSL == NULL) {
+        // we have not performed the handshake yet 
+        m_SSL = ssl_client_new(m_SSL_CTX, &m_StreamAdapter.m_Base, NULL, 0);
+    }
+    
+    int result = ssl_handshake_status(m_SSL);
+    return NPT_Tls_MapResult(result);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsSessionImpl::GetSessionId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::GetSessionId(NPT_DataBuffer& session_id)
+{
+    if (m_SSL == NULL) {
+        // no handshake done
+        session_id.SetDataSize(0);
+        return NPT_ERROR_INVALID_STATE;
+    }
+    
+    // return the session id
+    session_id.SetData(ssl_get_session_id(m_SSL),
+                       ssl_get_session_id_size(m_SSL));
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsSessionImpl::GetCipherSuiteId
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_TlsSessionImpl::GetCipherSuiteId()
+{
+    if (m_SSL == NULL) {
+        // no handshake done
+        return 0;
+    }
+    
+    return ssl_get_cipher_id(m_SSL);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsSessionImpl::GetPeerCertificateInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsSessionImpl::GetPeerCertificateInfo(NPT_TlsCertificateInfo& cert_info)
+{
+    cert_info.subject.common_name         = ssl_get_cert_dn(m_SSL, SSL_X509_CERT_COMMON_NAME);
+    cert_info.subject.organization        = ssl_get_cert_dn(m_SSL, SSL_X509_CERT_ORGANIZATION);
+    cert_info.subject.organizational_name = ssl_get_cert_dn(m_SSL, SSL_X509_CERT_ORGANIZATIONAL_NAME);
+    cert_info.issuer.common_name          = ssl_get_cert_dn(m_SSL, SSL_X509_CA_CERT_COMMON_NAME);
+    cert_info.issuer.organization         = ssl_get_cert_dn(m_SSL, SSL_X509_CA_CERT_ORGANIZATION);
+    cert_info.issuer.organizational_name  = ssl_get_cert_dn(m_SSL, SSL_X509_CA_CERT_ORGANIZATIONAL_NAME);
+    
+    ssl_get_cert_fingerprints(m_SSL, cert_info.fingerprint.md5, cert_info.fingerprint.sha1);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsInputStream
++---------------------------------------------------------------------*/
+class NPT_TlsInputStream : public NPT_InputStream {
+public:
+    NPT_TlsInputStream(NPT_TlsSessionImplReference& session) :
+        m_Session(session),
+        m_Position(0),
+        m_RecordCacheData(NULL),
+        m_RecordCacheSize(0) {}
+    
+    // NPT_InputStream methods
+    virtual NPT_Result Read(void*     buffer, 
+                            NPT_Size  bytes_to_read, 
+                            NPT_Size* bytes_read = NULL);
+    virtual NPT_Result Seek(NPT_Position)           { return NPT_ERROR_NOT_SUPPORTED; }
+    virtual NPT_Result Tell(NPT_Position& offset)   { offset = m_Position; return NPT_SUCCESS; }
+    virtual NPT_Result GetSize(NPT_LargeSize& size) { size=0; return NPT_ERROR_NOT_SUPPORTED; }
+    virtual NPT_Result GetAvailable(NPT_LargeSize& available);
+
+private:
+    NPT_TlsSessionImplReference m_Session;
+    NPT_Position                m_Position;
+    uint8_t*                    m_RecordCacheData;
+    NPT_Size                    m_RecordCacheSize;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TlsInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsInputStream::Read(void*     buffer, 
+                         NPT_Size  bytes_to_read, 
+                         NPT_Size* bytes_read)
+{
+    // setup default values
+    if (bytes_read) *bytes_read = 0;
+    
+    // quick check for edge case
+    if (bytes_to_read == 0) return NPT_SUCCESS;
+    
+    // read a new record if we don't have one cached
+    if (m_RecordCacheData == NULL) {
+        int ssl_result;
+        do {
+            ssl_result = ssl_read(m_Session->m_SSL, &m_RecordCacheData);
+        } while (ssl_result == 0);
+        if (ssl_result < 0) {
+            return NPT_Tls_MapResult(ssl_result);
+        } 
+        m_RecordCacheSize = ssl_result;
+    }
+    
+    // we now have data in cache
+    if (bytes_to_read > m_RecordCacheSize) {
+        // read at most what's in the cache
+        bytes_to_read = m_RecordCacheSize;
+    }
+    NPT_CopyMemory(buffer, m_RecordCacheData, bytes_to_read);
+    if (bytes_read) *bytes_read = bytes_to_read;
+
+    // update the record cache
+    m_RecordCacheSize -= bytes_to_read;
+    if (m_RecordCacheSize == 0) {
+        // nothing left in the cache
+        m_RecordCacheData = NULL;
+    } else {
+        // move the cache pointer
+        m_RecordCacheData += bytes_to_read;
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsInputStream::GetAvailable(NPT_LargeSize& /*available*/)
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsOutputStream
++---------------------------------------------------------------------*/
+class NPT_TlsOutputStream : public NPT_OutputStream {
+public:
+    NPT_TlsOutputStream(NPT_TlsSessionImplReference& session) :
+        m_Session(session),
+        m_Position(0) {}
+    
+    // NPT_OutputStream methods
+    virtual NPT_Result Write(const void* buffer, 
+                             NPT_Size    bytes_to_write, 
+                             NPT_Size*   bytes_written = NULL);
+    virtual NPT_Result Seek(NPT_Position) { return NPT_ERROR_NOT_SUPPORTED; }
+    virtual NPT_Result Tell(NPT_Position& offset) { offset = m_Position; return NPT_SUCCESS; }
+
+private:
+    NPT_TlsSessionImplReference m_Session;
+    NPT_Position                m_Position;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TlsOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsOutputStream::Write(const void* buffer, 
+                           NPT_Size    bytes_to_write, 
+                           NPT_Size*   bytes_written)
+{
+    // setup default values
+    if (bytes_written) *bytes_written = 0;
+    
+    // quick check for edge case 
+    if (bytes_to_write == 0) return NPT_SUCCESS;
+    
+    // write some data
+    int ssl_result;
+    do {
+        ssl_result = ssl_write(m_Session->m_SSL, (const uint8_t*)buffer, bytes_to_write);
+    } while (ssl_result == 0);
+    if (ssl_result < 0) {
+        return NPT_Tls_MapResult(ssl_result);
+    }
+    m_Position += ssl_result;
+    if (bytes_written) *bytes_written = (NPT_Size)ssl_result;
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsContext::NPT_TlsContext
++---------------------------------------------------------------------*/
+NPT_TlsContext::NPT_TlsContext() :
+    m_Impl(new NPT_TlsContextImpl())
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsContext::~NPT_TlsContext
++---------------------------------------------------------------------*/
+NPT_TlsContext::~NPT_TlsContext()
+{
+    delete m_Impl;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsContext::LoadKey
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsContext::LoadKey(NPT_TlsKeyFormat     key_format, 
+                        const unsigned char* key_data,
+                        NPT_Size             key_data_size,
+                        const char*          password)
+{
+    return m_Impl->LoadKey(key_format, key_data, key_data_size, password);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::NPT_TlsClientSession
++---------------------------------------------------------------------*/
+NPT_TlsClientSession::NPT_TlsClientSession(NPT_TlsContextReference&   context,
+                                           NPT_InputStreamReference&  input,
+                                           NPT_OutputStreamReference& output) :
+    m_Context(context),
+    m_Impl(new NPT_TlsSessionImpl(context->m_Impl->m_SSL_CTX, input, output))
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::~NPT_TlsClientSession
++---------------------------------------------------------------------*/
+NPT_TlsClientSession::~NPT_TlsClientSession()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::Handshake
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsClientSession::Handshake()
+{
+    return m_Impl->Handshake();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::GetSessionId
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsClientSession::GetSessionId(NPT_DataBuffer& session_id)
+{
+    return m_Impl->GetSessionId(session_id);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::GetCipherSuiteId
++---------------------------------------------------------------------*/
+NPT_UInt32
+NPT_TlsClientSession::GetCipherSuiteId()
+{
+    return m_Impl->GetCipherSuiteId();
+}
+              
+/*----------------------------------------------------------------------
+|   NPT_TlsSession::GetPeerCertificateInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_TlsClientSession::GetPeerCertificateInfo(NPT_TlsCertificateInfo& cert_info)
+{
+    return m_Impl->GetPeerCertificateInfo(cert_info);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsClientSession::GetInputStream(NPT_InputStreamReference& stream)
+{
+    stream = new NPT_TlsInputStream(m_Impl);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_TlsClientSession::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+    stream = new NPT_TlsOutputStream(m_Impl);
+    return NPT_SUCCESS;
+}
+
+#endif // NPT_CONFIG_ENABLE_TLS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptTls.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,161 @@
+/*****************************************************************
+|
+|   Neptune - TLS/SSL Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_TLS_H_
+#define _NPT_TLS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   error codes
++---------------------------------------------------------------------*/
+const NPT_Result NPT_ERROR_INVALID_PASSWORD             = (NPT_ERROR_BASE_TLS-1);
+const NPT_Result NPT_ERROR_TLS_INVALID_HANDSHAKE        = (NPT_ERROR_BASE_TLS-2);
+const NPT_Result NPT_ERROR_TLS_INVALID_PROTOCOL_MESSAGE = (NPT_ERROR_BASE_TLS-3);
+const NPT_Result NPT_ERROR_TLS_INVALID_HMAC             = (NPT_ERROR_BASE_TLS-4);
+const NPT_Result NPT_ERROR_TLS_INVALID_VERSION          = (NPT_ERROR_BASE_TLS-5);
+const NPT_Result NPT_ERROR_TLS_INVALID_SESSION          = (NPT_ERROR_BASE_TLS-6);
+const NPT_Result NPT_ERROR_TLS_NO_CIPHER                = (NPT_ERROR_BASE_TLS-7);
+const NPT_Result NPT_ERROR_TLS_BAD_CERTIFICATE          = (NPT_ERROR_BASE_TLS-8);
+const NPT_Result NPT_ERROR_INVALID_KEY                  = (NPT_ERROR_BASE_TLS-9);
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_TLS_NULL_WITH_NULL_NULL      = 0x00;
+const unsigned int NPT_TLS_RSA_WITH_RC4_128_MD5     = 0x04;
+const unsigned int NPT_TLS_RSA_WITH_RC4_128_SHA     = 0x05;
+const unsigned int NPT_TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F;
+const unsigned int NPT_TLS_RSA_WITH_AES_256_CBC_SHA = 0x35;
+
+/*----------------------------------------------------------------------
+|   class references
++---------------------------------------------------------------------*/
+class NPT_TlsContextImpl;
+class NPT_TlsSessionImpl;
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef enum {
+    NPT_TLS_KEY_FORMAT_RSA_PRIVATE,
+    NPT_TLS_KEY_FORMAT_PKCS8,
+    NPT_TLS_KEY_FORMAT_PKCS12
+} NPT_TlsKeyFormat;
+
+/*----------------------------------------------------------------------
+|   NPT_TlsContext
++---------------------------------------------------------------------*/
+class NPT_TlsContext
+{
+public:
+    NPT_TlsContext();
+   ~NPT_TlsContext();
+   
+   // methods
+   NPT_Result LoadKey(NPT_TlsKeyFormat     key_format, 
+                      const unsigned char* key_data,
+                      NPT_Size             key_data_size,
+                      const char*          password);
+                   
+      
+protected:
+    NPT_TlsContextImpl* m_Impl;
+    
+    // friends
+    friend class NPT_TlsClientSession;
+    friend class NPT_TlsServerSession;
+};
+
+typedef NPT_Reference<NPT_TlsContext> NPT_TlsContextReference;
+
+/*----------------------------------------------------------------------
+|   NPT_TlsCertificateInfo
++---------------------------------------------------------------------*/
+struct NPT_TlsCertificateInfo
+{
+    struct {
+        NPT_String common_name;
+        NPT_String organization;
+        NPT_String organizational_name;
+    } subject;
+    struct {
+        NPT_String common_name;
+        NPT_String organization;
+        NPT_String organizational_name;
+    } issuer;
+    struct {
+        unsigned char sha1[20];
+        unsigned char md5[16];
+    } fingerprint;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TlsClientSession
++---------------------------------------------------------------------*/
+class NPT_TlsClientSession
+{
+public:
+    NPT_TlsClientSession(NPT_TlsContextReference&   context,
+                         NPT_InputStreamReference&  input,
+                         NPT_OutputStreamReference& output);
+   ~NPT_TlsClientSession();
+    NPT_Result Handshake();
+    NPT_Result GetSessionId(NPT_DataBuffer& session_id);
+    NPT_UInt32 GetCipherSuiteId();
+    NPT_Result GetPeerCertificateInfo(NPT_TlsCertificateInfo& info);
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+    
+protected:
+    NPT_TlsContextReference           m_Context;
+    NPT_Reference<NPT_TlsSessionImpl> m_Impl;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_TlsServerSession
++---------------------------------------------------------------------*/
+class NPT_TlsServerSession
+{
+public:
+    NPT_TlsServerSession(NPT_TlsContext&           context,
+                         NPT_InputStreamReference  input,
+                         NPT_OutputStreamReference output);
+
+protected:
+    NPT_TlsSessionImpl* m_Impl;
+};
+
+#endif // _NPT_TLS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptTypes.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,145 @@
+/*****************************************************************
+|
+|   Neptune - Types
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_TYPES_H_
+#define _NPT_TYPES_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+/*----------------------------------------------------------------------
+|   sized types (this assumes that ints are 32 bits)
++---------------------------------------------------------------------*/
+typedef NPT_CONFIG_INT64_TYPE          NPT_Int64;
+typedef unsigned NPT_CONFIG_INT64_TYPE NPT_UInt64;
+typedef unsigned int                   NPT_UInt32;
+typedef int                            NPT_Int32;
+typedef unsigned short                 NPT_UInt16;
+typedef short                          NPT_Int16;
+typedef unsigned char                  NPT_UInt8;
+typedef char                           NPT_Int8;
+typedef float                          NPT_Float;
+
+/*----------------------------------------------------------------------
+|   named types       
++---------------------------------------------------------------------*/
+typedef int           NPT_Result;
+typedef unsigned int  NPT_Cardinal;
+typedef unsigned int  NPT_Ordinal;
+typedef unsigned long NPT_Size;
+typedef NPT_UInt64    NPT_LargeSize;
+typedef signed   long NPT_Offset;
+typedef NPT_UInt64    NPT_Position;
+typedef long          NPT_Timeout;
+typedef void          NPT_Interface;
+typedef unsigned char NPT_Byte;
+typedef unsigned int  NPT_Flags;
+typedef void*         NPT_Any;
+typedef const void*   NPT_AnyConst;
+
+/*----------------------------------------------------------------------
+|   limits       
++---------------------------------------------------------------------*/
+#if !defined(NPT_INT_MIN)
+#if defined(NPT_CONFIG_HAVE_INT_MIN)
+#define NPT_INT_MIN INT_MIN
+#endif
+#endif
+
+#if !defined(NPT_INT_MAX)
+#if defined(NPT_CONFIG_HAVE_INT_MAX)
+#define NPT_INT_MAX INT_MAX
+#endif
+#endif
+
+#if !defined(NPT_UINT_MAX)
+#if defined(NPT_CONFIG_HAVE_UINT_MAX)
+#define NPT_UINT_MAX UINT_MAX
+#endif
+#endif
+
+#if !defined(NPT_LONG_MIN)
+#if defined(NPT_CONFIG_HAVE_LONG_MIN)
+#define NPT_LONG_MIN LONG_MIN
+#endif
+#endif
+
+#if !defined(NPT_LONG_MAX)
+#if defined(NPT_CONFIG_HAVE_LONG_MAX)
+#define NPT_LONG_MAX LONG_MAX
+#endif
+#endif
+
+#if !defined(NPT_ULONG_MAX)
+#if defined(NPT_CONFIG_HAVE_ULONG_MAX)
+#define NPT_ULONG_MAX ULONG_MAX
+#endif
+#endif
+
+#if !defined(NPT_INT32_MAX)
+#define NPT_INT32_MAX 0x7FFFFFFF
+#endif
+
+#if !defined(NPT_INT32_MIN)
+#define NPT_INT32_MIN (-NPT_INT32_MAX - 1) 
+#endif
+
+#if !defined(NPT_UINT32_MAX)
+#define NPT_UINT32_MAX 0xFFFFFFFF
+#endif
+
+#if !defined(NPT_INT64_MAX)
+#if defined(NPT_CONFIG_HAVE_LLONG_MAX)
+#define NPT_INT64_MAX LLONG_MAX
+#else
+#define NPT_INT64_MAX 0x7FFFFFFFFFFFFFFFLL
+#endif
+#endif
+
+#if !defined(NPT_INT64_MIN)
+#if defined(NPT_CONFIG_HAVE_LLONG_MIN)
+#define NPT_INT64_MIN LLONG_MIN
+#else
+#define NPT_INT64_MIN (-NPT_INT64_MAX - 1LL) 
+#endif
+#endif
+
+#if !defined(NPT_UINT64_MAX)
+#if defined(NPT_CONFIG_HAVE_ULLONG_MAX)
+#define NPT_UINT64_MAX ULLONG_MAX
+#else
+#define NPT_UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
+#endif
+#endif
+
+#endif // _NPT_TYPES_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptUri.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,736 @@
+/*****************************************************************
+|
+|   Neptune - URI
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ***************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptUri.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::ParseScheme
++---------------------------------------------------------------------*/
+NPT_Uri::SchemeId
+NPT_Uri::ParseScheme(const NPT_String& scheme)
+{
+    if (scheme == "http") {
+        return SCHEME_ID_HTTP;
+    } else {
+        return SCHEME_ID_UNKNOWN;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::SetScheme
++---------------------------------------------------------------------*/
+void
+NPT_Uri::SetScheme(const char* scheme)
+{
+    m_Scheme = scheme;
+    m_Scheme.MakeLowercase();
+    m_SchemeId = ParseScheme(m_Scheme);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::SetSchemeFromUri
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Uri::SetSchemeFromUri(const char* uri)
+{
+    const char* start = uri;
+    char c;
+    while ((c =*uri++)) {
+        if (c == ':') {
+            m_Scheme.Assign(start, (NPT_Size)(uri-start-1));
+            m_Scheme.MakeLowercase();
+            m_SchemeId = ParseScheme(m_Scheme);
+            return NPT_SUCCESS;
+        } else if ((c >= 'a' && c <= 'z') ||
+                   (c >= 'A' && c <= 'Z') ||
+                   (c >= '0' && c <= '9') ||
+                   (c == '+')             ||
+                   (c == '.')             ||
+                   (c == '-')) {
+            continue;
+        } else {
+            break;
+        }
+    }
+    return NPT_ERROR_INVALID_SYNTAX;
+}
+
+/*----------------------------------------------------------------------
+Appendix A.  Collected ABNF for URI
+
+   URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+   hier-part     = "//" authority path-abempty
+                 / path-absolute
+                 / path-rootless
+                 / path-empty
+
+   URI-reference = URI / relative-ref
+
+   absolute-URI  = scheme ":" hier-part [ "?" query ]
+
+   relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
+
+   relative-part = "//" authority path-abempty
+                 / path-absolute
+                 / path-noscheme
+                 / path-empty
+
+   scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+   authority     = [ userinfo "@" ] host [ ":" port ]
+   userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
+   host          = IP-literal / IPv4address / reg-name
+   port          = *DIGIT
+
+   IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
+
+   IPvFuture     = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+   IPv6address   =                            6( h16 ":" ) ls32
+                 /                       "::" 5( h16 ":" ) ls32
+                 / [               h16 ] "::" 4( h16 ":" ) ls32
+                 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+                 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+                 / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+                 / [ *4( h16 ":" ) h16 ] "::"              ls32
+                 / [ *5( h16 ":" ) h16 ] "::"              h16
+                 / [ *6( h16 ":" ) h16 ] "::"
+
+   h16           = 1*4HEXDIG
+   ls32          = ( h16 ":" h16 ) / IPv4address
+   IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
+   dec-octet     = DIGIT                 ; 0-9
+                 / %x31-39 DIGIT         ; 10-99
+                 / "1" 2DIGIT            ; 100-199
+                 / "2" %x30-34 DIGIT     ; 200-249
+                 / "25" %x30-35          ; 250-255
+
+   reg-name      = *( unreserved / pct-encoded / sub-delims )
+
+   path          = path-abempty    ; begins with "/" or is empty
+                 / path-absolute   ; begins with "/" but not "//"
+                 / path-noscheme   ; begins with a non-colon segment
+                 / path-rootless   ; begins with a segment
+                 / path-empty      ; zero characters
+
+   path-abempty  = *( "/" segment )
+   path-absolute = "/" [ segment-nz *( "/" segment ) ]
+   path-noscheme = segment-nz-nc *( "/" segment )
+   path-rootless = segment-nz *( "/" segment )
+   path-empty    = 0<pchar>
+
+   segment       = *pchar
+   segment-nz    = 1*pchar
+   segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+                 ; non-zero-length segment without any colon ":"
+
+   pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+   query         = *( pchar / "/" / "?" )
+
+   fragment      = *( pchar / "/" / "?" )
+
+   pct-encoded   = "%" HEXDIG HEXDIG
+
+   unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+   reserved      = gen-delims / sub-delims
+   gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+   sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+                 / "*" / "+" / "," / ";" / "="
+
+---------------------------------------------------------------------*/
+                 
+#define NPT_URI_ALWAYS_ENCODE " !\"<>\\^`{|}"
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::PathCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::PathCharsToEncode = NPT_URI_ALWAYS_ENCODE "?#[]";
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::QueryCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::QueryCharsToEncode = NPT_URI_ALWAYS_ENCODE "#[]";
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::FragmentCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::FragmentCharsToEncode = NPT_URI_ALWAYS_ENCODE "[]";
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::UnsafeCharsToEncode
++---------------------------------------------------------------------*/
+const char* const
+NPT_Uri::UnsafeCharsToEncode = NPT_URI_ALWAYS_ENCODE; // and ' ?
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::PercentEncode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Uri::PercentEncode(const char* str, const char* chars, bool encode_percents)
+{
+    NPT_String encoded;
+
+    // check args
+    if (str == NULL) return encoded;
+
+    // reserve at least the size of the current uri
+    encoded.Reserve(NPT_StringLength(str));
+
+    // process each character
+    char escaped[3];
+    escaped[0] = '%';
+    while (unsigned char c = *str++) {
+        bool encode = false;
+        if (encode_percents && c == '%') {
+            encode = true;
+        } else if (c < ' ' || c > '~') {
+            encode = true;
+        } else {
+            const char* match = chars;
+            while (*match) {
+                if (c == *match) {
+                    encode = true;
+                    break;
+                }
+                ++match;
+            }
+        }
+        if (encode) {
+            // encode
+            NPT_ByteToHex(c, &escaped[1]);
+            encoded.Append(escaped, 3);
+        } else {
+            // no encoding required
+            encoded += c;
+        }
+    }
+    
+    return encoded;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Uri::PercentDecode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Uri::PercentDecode(const char* str)
+{
+    NPT_String decoded;
+
+    // check args
+    if (str == NULL) return decoded;
+
+    // reserve at least the size of the current uri
+    decoded.Reserve(NPT_StringLength(str));
+
+    // process each character
+    while (unsigned char c = *str++) {
+        if (c == '%') {
+            // needs to be unescaped
+            unsigned char unescaped;
+            if (NPT_SUCCEEDED(NPT_HexToByte(str, unescaped))) {
+                decoded += unescaped;
+                str += 2;
+            } else {
+                // not a valid escape sequence, just keep the %
+                decoded += c;
+            }
+        } else {
+            // no unescaping required
+            decoded += c;
+        }
+    }
+
+    return decoded;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::NPT_UrlQuery
++---------------------------------------------------------------------*/ 
+NPT_UrlQuery::NPT_UrlQuery(const char* query)
+{
+    Parse(query);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::UrlEncode
++---------------------------------------------------------------------*/ 
+NPT_String
+NPT_UrlQuery::UrlEncode(const char* str, bool encode_percents)
+{
+    NPT_String encoded = NPT_Uri::PercentEncode(
+        str, 
+        ";/?:@&=+$,"    /* reserved as defined in RFC 2396 */
+        "\"#<>\\^`{|}", /* other unsafe chars              */
+        encode_percents);
+    encoded.Replace(' ','+');
+    
+    return encoded;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::UrlDecode
++---------------------------------------------------------------------*/
+NPT_String
+NPT_UrlQuery::UrlDecode(const char* str)
+{
+    NPT_String decoded = NPT_Uri::PercentDecode(str);
+    decoded.Replace('+', ' ');
+    return decoded;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::ToString
++---------------------------------------------------------------------*/
+NPT_String 
+NPT_UrlQuery::ToString()
+{
+    NPT_String encoded;
+    bool       separator = false;
+    for (NPT_List<Field>::Iterator it = m_Fields.GetFirstItem();
+         it;
+         ++it) {
+         Field& field = *it;
+         if (separator) encoded += "&";
+         separator = true;
+         encoded += UrlEncode(field.m_Name, false);
+         encoded += "=";
+         encoded += UrlEncode(field.m_Value, false);
+    }
+
+    return encoded;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::Parse
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_UrlQuery::Parse(const char* query)
+{
+    const char* cursor = query;
+    NPT_String  name;
+    NPT_String  value;
+    bool        in_name = true;
+    do {
+        if (*cursor == '\0' || *cursor == '&') {
+            if (!name.IsEmpty() && !value.IsEmpty()) {
+                AddField(UrlDecode(name), UrlDecode(value));   
+            }
+            name.SetLength(0);
+            value.SetLength(0);
+            in_name = true;
+        } else if (*cursor == '=' && in_name) {
+            in_name = false;
+        } else {
+            if (in_name) {
+                name += *cursor;
+            } else {
+                value += *cursor;
+            }
+        }
+    } while (*cursor++);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::AddField
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_UrlQuery::AddField(const char* name, const char* value)
+{
+    return m_Fields.Add(Field(name, value));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery::GetField
++---------------------------------------------------------------------*/
+const char* 
+NPT_UrlQuery::GetField(const char* name)
+{
+    for (NPT_List<Field>::Iterator it = m_Fields.GetFirstItem();
+         it;
+         ++it) {
+         Field& field = *it;
+         if (field.m_Name == name) return field.m_Value;
+    }
+
+    // field not found
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef enum {
+    NPT_URL_PARSER_STATE_START,
+    NPT_URL_PARSER_STATE_SCHEME,
+    NPT_URL_PARSER_STATE_LEADING_SLASH,
+    NPT_URL_PARSER_STATE_HOST,
+    NPT_URL_PARSER_STATE_PORT,
+    NPT_URL_PARSER_STATE_PATH,
+    NPT_URL_PARSER_STATE_QUERY
+} NPT_UrlParserState;
+
+/*----------------------------------------------------------------------
+|   NPT_Url::NPT_Url
++---------------------------------------------------------------------*/
+NPT_Url::NPT_Url() : 
+    m_Port(NPT_URL_INVALID_PORT),
+    m_Path("/"),
+    m_HasQuery(false),
+    m_HasFragment(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::NPT_Url
++---------------------------------------------------------------------*/
+NPT_Url::NPT_Url(const char* url, SchemeId expected_scheme, NPT_UInt16 default_port) : 
+    m_Port(NPT_URL_INVALID_PORT),
+    m_HasQuery(false),
+    m_HasFragment(false)
+{
+    // check parameters
+    if (url == NULL) return;
+
+    // set the uri scheme
+    if (NPT_FAILED(SetSchemeFromUri(url))) {
+        return;
+    }
+    if (expected_scheme != SCHEME_ID_UNKNOWN) {
+        // check that we got the expected scheme
+        if (m_SchemeId != expected_scheme) return;
+    }
+    url += m_Scheme.GetLength()+1;
+
+    // intialize the parser
+    NPT_UrlParserState state = NPT_URL_PARSER_STATE_START;
+    const char* mark = url;
+
+    // parse the URL
+    char c;
+    do  {
+        c = *url++;
+        switch (state) {
+          case NPT_URL_PARSER_STATE_START:
+            if (c == '/') {
+                state = NPT_URL_PARSER_STATE_LEADING_SLASH;
+            } else {
+                return;
+            }
+            break;
+
+          case NPT_URL_PARSER_STATE_LEADING_SLASH:
+            if (c == '/') {
+                state = NPT_URL_PARSER_STATE_HOST;
+                mark = url;
+            } else {
+                return;
+            }
+            break;
+
+          case NPT_URL_PARSER_STATE_HOST:
+            if (c == ':' || c == '/' || c == '\0') {
+                m_Host.Assign(mark, (NPT_Size)(url-1-mark));
+                if (c == ':') {
+                    mark = url;
+                    state = NPT_URL_PARSER_STATE_PORT;
+                } else {
+                    mark = url-1;
+                    m_Port = default_port;
+                    state = NPT_URL_PARSER_STATE_PATH;
+                }
+            }
+            break;
+
+          case NPT_URL_PARSER_STATE_PORT:
+            if (c >= '0' && c <= '9') {
+                unsigned int val = m_Port*10+(c-'0');
+                if (val > 65535) {
+                    m_Port = NPT_URL_INVALID_PORT;
+                    return;
+                }
+                m_Port = val;
+            } else if (c == '/' || c == '\0') {
+                mark = url-1;
+                state = NPT_URL_PARSER_STATE_PATH;
+            } else {
+                // invalid character
+                m_Port = NPT_URL_INVALID_PORT;
+                return;
+            }
+            break;
+
+          case NPT_URL_PARSER_STATE_PATH:
+            if (*mark) {
+                SetPathPlus(mark);
+                return;
+            }
+            break;
+
+          default:
+            break;
+        }
+    } while (c);
+
+    // if we get here, the path is implicit
+    m_Path = "/";
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::NPT_Url
++---------------------------------------------------------------------*/
+NPT_Url::NPT_Url(const char* scheme,
+                 const char* host, 
+                 NPT_UInt16  port, 
+                 const char* path,
+                 const char* query,
+                 const char* fragment) :
+    m_Host(host),
+    m_Port(port),
+    m_Path(path),
+    m_HasQuery(query != NULL),
+    m_Query(query),
+    m_HasFragment(fragment != NULL),
+    m_Fragment(fragment)
+{
+    SetScheme(scheme);
+}    
+
+/*----------------------------------------------------------------------
+|   NPT_Url::IsValid
++---------------------------------------------------------------------*/
+bool
+NPT_Url::IsValid() const
+{
+    return m_Port != NPT_URL_INVALID_PORT && !m_Host.IsEmpty();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::SetHost
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Url::SetHost(const char* host)
+{
+    const char* port = host;
+    while (*port && *port != ':') port++;
+    if (*port) {
+        m_Host.Assign(host, (NPT_Size)(port-host));
+        NPT_UInt32 port_number;
+        if (NPT_SUCCEEDED(NPT_ParseInteger32U(port+1, port_number, false))) {
+            m_Port = (short)port_number;
+        }
+    } else {
+        m_Host = host;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::SetHost
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Url::SetPort(NPT_UInt16 port)
+{
+    m_Port = port;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::SetPath
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Url::SetPath(const char* path)
+{
+    m_Path = path;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::SetPathPlus
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Url::SetPathPlus(const char* path_plus)
+{
+    // check parameters
+    if (path_plus == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // reset any existing values
+    m_Path.SetLength(0);
+    m_Query.SetLength(0);
+    m_Fragment.SetLength(0);
+    m_HasQuery = false;
+    m_HasFragment = false;
+
+    // intialize the parser
+    NPT_UrlParserState state = NPT_URL_PARSER_STATE_PATH;
+    const char* mark = path_plus;
+
+    // parse the path+
+    char c;
+    do  {
+        c = *path_plus++;
+        switch (state) {
+          case NPT_URL_PARSER_STATE_PATH:
+            if (c == '\0' || c == '?' || c == '#') {
+                if (path_plus-1 > mark) {
+                    m_Path.Append(mark, (NPT_Size)(path_plus-1-mark));
+                    m_Path = PercentDecode(m_Path);
+                }
+                if (c == '?') {
+                    m_HasQuery = true;
+                    state = NPT_URL_PARSER_STATE_QUERY;
+                    mark = path_plus;
+                } else if (c == '#') {
+                    m_HasFragment = true;
+                    m_Fragment = path_plus;
+                    m_Fragment = PercentDecode(m_Fragment);
+                    return NPT_SUCCESS;
+                }
+            }
+            break;
+
+          case NPT_URL_PARSER_STATE_QUERY:
+            if (c == '\0' || c == '#') {
+                m_Query.Assign(mark, (NPT_Size)(path_plus-1-mark));
+                // do not decode query so it can be parsed properly by NPT_UrlQuery
+                if (c == '#') {
+                    m_HasFragment = true;
+                    m_Fragment = path_plus;
+                    m_Fragment = PercentDecode(m_Fragment);
+                }
+                return NPT_SUCCESS;
+            }
+            break;
+
+          default: 
+            break;
+        }
+    } while (c);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::SetQuery
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Url::SetQuery(const char* query)
+{
+    m_Query = query;
+    m_HasQuery = query!=NULL && NPT_StringLength(query)>0;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::SetFragment
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Url::SetFragment(const char* fragment)
+{
+    m_Fragment = fragment;
+    m_HasFragment = fragment!=NULL;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::ToRequestString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Url::ToRequestString(bool with_fragment) const
+{
+    NPT_String result;
+    NPT_Size   length = m_Path.GetLength()+1;
+    if (m_HasQuery)    length += 1+m_Query.GetLength();
+    if (with_fragment) length += 1+m_Fragment.GetLength();
+    result.Reserve(length);
+
+    if (m_Path.IsEmpty()) {
+        result += "/";
+    } else {
+        result += PercentEncode(m_Path, PathCharsToEncode, false);
+    }
+    if (m_HasQuery) {
+        result += "?";
+        result += PercentEncode(m_Query, QueryCharsToEncode, false);
+    }
+    if (with_fragment && m_HasFragment) {
+        result += "#";
+        result += PercentEncode(m_Fragment, FragmentCharsToEncode, false);
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::ToStringWithDefaultPort
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Url::ToStringWithDefaultPort(NPT_UInt16 default_port, bool with_fragment) const
+{
+    NPT_String result;
+    NPT_String request = ToRequestString(with_fragment);
+    NPT_Size   length = m_Scheme.GetLength()+3+m_Host.GetLength()+6+request.GetLength();
+
+    result.Reserve(length);
+    result += m_Scheme;
+    result += "://";
+    result += m_Host;
+    if (m_Port != default_port) {
+        NPT_String port = NPT_String::FromInteger(m_Port);
+        result += ":";
+        result += port;
+    }
+    result += request;
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Url::ToString
++---------------------------------------------------------------------*/
+NPT_String
+NPT_Url::ToString(bool with_fragment) const
+{
+    return ToStringWithDefaultPort(0, with_fragment);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptUri.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,169 @@
+/*****************************************************************
+|
+|   Neptune - URI
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_URI_H_
+#define _NPT_URI_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptStrings.h"
+#include "NptList.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const NPT_UInt16 NPT_URL_INVALID_PORT = 0;
+
+/*----------------------------------------------------------------------
+|   NPT_Uri
++---------------------------------------------------------------------*/
+class NPT_Uri {
+public:
+    // types
+    typedef enum {
+        SCHEME_ID_UNKNOWN,
+        SCHEME_ID_HTTP
+    } SchemeId;
+
+    // constants. use as a parameter to Encode()
+    static const char* const PathCharsToEncode;
+    static const char* const QueryCharsToEncode;
+    static const char* const FragmentCharsToEncode;
+    static const char* const UnsafeCharsToEncode;
+
+    // class methods
+    static NPT_String PercentEncode(const char* str, const char* chars, bool encode_percents=true);
+    static NPT_String PercentDecode(const char* str);
+    static SchemeId   ParseScheme(const NPT_String& scheme);
+
+    // methods
+    NPT_Uri() : m_SchemeId(SCHEME_ID_UNKNOWN) {}
+    virtual ~NPT_Uri() {}
+    const NPT_String& GetScheme() const {
+        return m_Scheme;
+    }
+    void SetScheme(const char* scheme);
+    NPT_Result SetSchemeFromUri(const char* uri);
+    SchemeId GetSchemeId() const {
+        return m_SchemeId;
+    }
+
+protected:
+    // members
+    NPT_String m_Scheme;
+    SchemeId   m_SchemeId;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_UrlQuery
++---------------------------------------------------------------------*/
+class NPT_UrlQuery
+{
+public:
+    // class methods
+    static NPT_String UrlEncode(const char* str, bool encode_percents=true);
+    static NPT_String UrlDecode(const char* str);
+    
+    // types
+    struct Field {
+        Field(const char* name, const char* value) :
+            m_Name(name), m_Value(value) {}
+        NPT_String m_Name;
+        NPT_String m_Value;
+    };
+
+    // constructor
+    NPT_UrlQuery() {}
+    NPT_UrlQuery(const char* query);
+
+    // accessors
+    NPT_List<Field>& GetFields() { return m_Fields; }
+
+    // methods
+    NPT_Result  Parse(const char* query);
+    NPT_Result  AddField(const char* name, const char* value);
+    const char* GetField(const char* name);
+    NPT_String  ToString();
+
+private:
+    // members
+    NPT_List<Field> m_Fields;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Url
++---------------------------------------------------------------------*/
+class NPT_Url : public NPT_Uri {
+public:
+    // constructors and destructor
+    NPT_Url();
+    NPT_Url(const char* url, 
+            SchemeId    expected_scheme = SCHEME_ID_UNKNOWN, 
+            NPT_UInt16  default_port = NPT_URL_INVALID_PORT);
+    NPT_Url(const char* scheme,
+            const char* host, 
+            NPT_UInt16  port, 
+            const char* path,
+            const char* query = NULL,
+            const char* fragment = NULL);
+
+    // methods
+    const NPT_String&  GetHost() const     { return m_Host;     }
+    NPT_UInt16         GetPort() const     { return m_Port;     }
+    const NPT_String&  GetPath() const     { return m_Path;     }
+    const NPT_String&  GetQuery() const    { return m_Query;    }
+    const NPT_String&  GetFragment() const { return m_Fragment; }
+    virtual bool       IsValid() const;
+    bool               HasQuery()    const { return m_HasQuery;    } 
+    bool               HasFragment() const { return m_HasFragment; }
+    NPT_Result         SetHost(const char*  host);
+    NPT_Result         SetPort(NPT_UInt16 port);
+    NPT_Result         SetPath(const char* path);
+    NPT_Result         SetPathPlus(const char* path_plus);
+    NPT_Result         SetQuery(const char* query);
+    NPT_Result         SetFragment(const char* fragment);
+    virtual NPT_String ToRequestString(bool with_fragment = false) const;
+    virtual NPT_String ToStringWithDefaultPort(NPT_UInt16 default_port, bool with_fragment = true) const;
+    virtual NPT_String ToString(bool with_fragment = true) const;
+
+protected:
+    // members
+    NPT_String m_Host;
+    NPT_UInt16 m_Port;
+    NPT_String m_Path;
+    bool       m_HasQuery;
+    NPT_String m_Query;
+    bool       m_HasFragment;
+    NPT_String m_Fragment;
+};
+
+#endif // _NPT_URI_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptUtils.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,745 @@
+/*****************************************************************
+|
+|   Neptune - Utils
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <math.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptDebug.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+#if defined(NPT_CONFIG_HAVE_LIMITS_H)
+#include <limits.h>
+#endif
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_FORMAT_LOCAL_BUFFER_SIZE = 1024;
+const unsigned int NPT_FORMAT_BUFFER_INCREMENT  = 4096;
+const unsigned int NPT_FORMAT_BUFFER_MAX_SIZE   = 65536;
+
+/*----------------------------------------------------------------------
+|   NPT_BytesToInt64Be
++---------------------------------------------------------------------*/
+NPT_UInt64 
+NPT_BytesToInt64Be(const unsigned char* bytes)
+{
+    return 
+        ( ((NPT_UInt64)bytes[0])<<56 ) |
+        ( ((NPT_UInt64)bytes[1])<<48 ) |
+        ( ((NPT_UInt64)bytes[2])<<40 ) |
+        ( ((NPT_UInt64)bytes[3])<<32 ) |
+        ( ((NPT_UInt64)bytes[4])<<24 ) |
+        ( ((NPT_UInt64)bytes[5])<<16 ) |
+        ( ((NPT_UInt64)bytes[6])<<8  ) |
+        ( ((NPT_UInt64)bytes[7])     );    
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BytesToInt32Be
++---------------------------------------------------------------------*/
+NPT_UInt32 
+NPT_BytesToInt32Be(const unsigned char* bytes)
+{
+    return 
+        ( ((NPT_UInt32)bytes[0])<<24 ) |
+        ( ((NPT_UInt32)bytes[1])<<16 ) |
+        ( ((NPT_UInt32)bytes[2])<<8  ) |
+        ( ((NPT_UInt32)bytes[3])     );    
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BytesToInt24Be
++---------------------------------------------------------------------*/
+NPT_UInt32 
+NPT_BytesToInt24Be(const unsigned char* bytes)
+{
+    return 
+        ( ((NPT_UInt32)bytes[0])<<16 ) |
+        ( ((NPT_UInt32)bytes[1])<<8  ) |
+        ( ((NPT_UInt32)bytes[2])     );    
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BytesToInt16Be
++---------------------------------------------------------------------*/
+NPT_UInt16
+NPT_BytesToInt16Be(const unsigned char* bytes)
+{
+    return 
+        ( ((NPT_UInt16)bytes[0])<<8  ) |
+        ( ((NPT_UInt16)bytes[1])     );    
+}
+
+/*----------------------------------------------------------------------
+|    NPT_BytesFromInt64Be
++---------------------------------------------------------------------*/
+void 
+NPT_BytesFromInt64Be(unsigned char* buffer, NPT_UInt64 value)
+{
+    buffer[0] = (unsigned char)(value>>56) & 0xFF;
+    buffer[1] = (unsigned char)(value>>48) & 0xFF;
+    buffer[2] = (unsigned char)(value>>40) & 0xFF;
+    buffer[3] = (unsigned char)(value>>32) & 0xFF;
+    buffer[4] = (unsigned char)(value>>24) & 0xFF;
+    buffer[5] = (unsigned char)(value>>16) & 0xFF;
+    buffer[6] = (unsigned char)(value>> 8) & 0xFF;
+    buffer[7] = (unsigned char)(value    ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_BytesFromInt32Be
++---------------------------------------------------------------------*/
+void 
+NPT_BytesFromInt32Be(unsigned char* buffer, NPT_UInt32 value)
+{
+    buffer[0] = (unsigned char)(value>>24) & 0xFF;
+    buffer[1] = (unsigned char)(value>>16) & 0xFF;
+    buffer[2] = (unsigned char)(value>> 8) & 0xFF;
+    buffer[3] = (unsigned char)(value    ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_BytesFromInt24Be
++---------------------------------------------------------------------*/
+void 
+NPT_BytesFromInt24Be(unsigned char* buffer, NPT_UInt32 value)
+{
+    buffer[0] = (unsigned char)(value>>16) & 0xFF;
+    buffer[1] = (unsigned char)(value>> 8) & 0xFF;
+    buffer[2] = (unsigned char)(value    ) & 0xFF;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_BytesFromInt16Be
++---------------------------------------------------------------------*/
+void 
+NPT_BytesFromInt16Be(unsigned char* buffer, NPT_UInt16 value)
+{
+    buffer[0] = (unsigned char)((value>> 8) & 0xFF);
+    buffer[1] = (unsigned char)((value    ) & 0xFF);
+}
+
+#if !defined(NPT_CONFIG_HAVE_SNPRINTF)
+/*----------------------------------------------------------------------
+|   NPT_FormatString
++---------------------------------------------------------------------*/
+int 
+NPT_FormatString(char* /*str*/, NPT_Size /*size*/, const char* /*format*/, ...)
+{
+    NPT_ASSERT(0); // not implemented yet
+    return 0;
+}
+#endif // NPT_CONFIG_HAVE_SNPRINTF
+
+/*----------------------------------------------------------------------
+|   NPT_NibbleToHex
++---------------------------------------------------------------------*/
+static char NPT_NibbleToHex(unsigned int nibble, bool uppercase = true)
+{
+    NPT_ASSERT(nibble < 16);
+    if (uppercase) {
+        return (nibble < 10) ? ('0' + nibble) : ('A' + (nibble-10));
+    } else {
+        return (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
+    }
+    return (nibble < 10) ? ('0' + nibble) : ('A' + (nibble-10));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HexToNibble
++---------------------------------------------------------------------*/
+static int NPT_HexToNibble(char hex)
+{
+    if (hex >= 'a' && hex <= 'f') {
+        return ((hex - 'a') + 10);
+    } else if (hex >= 'A' && hex <= 'F') {
+        return ((hex - 'A') + 10);
+    } else if (hex >= '0' && hex <= '9') {
+        return (hex - '0');
+    } else {
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ByteToHex
++---------------------------------------------------------------------*/
+void
+NPT_ByteToHex(NPT_Byte b, char* buffer, bool uppercase)
+{
+    buffer[0] = NPT_NibbleToHex((b>>4) & 0x0F, uppercase);
+    buffer[1] = NPT_NibbleToHex(b      & 0x0F, uppercase);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HexToByte
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_HexToByte(const char* buffer, NPT_Byte& b)
+{
+    int nibble_0 = NPT_HexToNibble(buffer[0]);
+    if (nibble_0 < 0) return NPT_ERROR_INVALID_SYNTAX;
+    
+    int nibble_1 = NPT_HexToNibble(buffer[1]);
+    if (nibble_1 < 0) return NPT_ERROR_INVALID_SYNTAX;
+
+    b = (nibble_0 << 4) | nibble_1;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_HexString
++---------------------------------------------------------------------*/
+NPT_String 
+NPT_HexString(const unsigned char* data,
+              NPT_Size             data_size,
+              const char*          separator,
+              bool                 uppercase)
+{
+    NPT_String result;
+    
+    // quick check 
+    if (data == NULL || data_size == 0) return result;
+        
+    // set the result size
+    NPT_Size separator_length = separator?NPT_StringLength(separator):0;
+    result.SetLength(data_size*2+(data_size-1)*separator_length);
+    
+    // build the string
+    const unsigned char* src = data;
+    char* dst = result.UseChars();
+    while (data_size--) {
+        NPT_ByteToHex(*src++, dst, uppercase);
+        dst += 2;
+        if (data_size) {
+            NPT_CopyMemory(dst, separator, separator_length);
+            dst += separator_length;
+        }
+    }
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_ParseFloat
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseFloat(const char* str, float& result, bool relaxed)
+{
+    // safe default value 
+    result = 0.0f;
+
+    // check params
+    if (str == NULL || *str == '\0') {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // ignore leading whitespace
+    if (relaxed) {
+        while (*str == ' ' || *str == '\t') {
+            str++;
+        }
+    }
+    if (*str == '\0') {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // check for sign
+    bool  negative = false;
+    if (*str == '-') {
+        // negative number
+        negative = true; 
+        str++;
+    } else if (*str == '+') {
+        // skip the + sign
+        str++;
+    }
+
+    // parse the digits
+    bool  after_radix = false;
+    bool  empty = true;
+    float value = 0.0f;
+    float decimal = 10.0f;
+    char  c;
+    while ((c = *str++)) {
+        if (c == '.') {
+            if (after_radix || (*str < '0' || *str > '9')) {
+                return NPT_ERROR_INVALID_PARAMETERS;
+            } else {
+                after_radix = true;
+            }
+        } else if (c >= '0' && c <= '9') {
+            empty = false;
+            if (after_radix) {
+                value += (float)(c-'0')/decimal;
+                decimal *= 10.0f;
+            } else {
+                value = 10.0f*value + (float)(c-'0');
+            }
+        } else if (c == 'e' || c == 'E') {
+            // exponent
+            if (*str == '+' || *str == '-' || (*str >= '0' && *str <= '9')) {
+                int exponent = 0;
+                if (NPT_SUCCEEDED(NPT_ParseInteger(str, exponent, relaxed))) {
+                    value *= (float)pow(10.0f, (float)exponent);
+                    break;
+                } else {
+                    return NPT_ERROR_INVALID_PARAMETERS;
+                }
+            } else {
+                return NPT_ERROR_INVALID_PARAMETERS;
+            }
+        } else {
+            if (relaxed) {
+                break;
+            } else {
+                return NPT_ERROR_INVALID_PARAMETERS;
+            }
+        } 
+    }
+
+    // check that the value was non empty
+    if (empty) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // return the result
+    result = negative ? -value : value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_ParseInteger64
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseInteger64(const char* str, NPT_Int64& result, bool relaxed, NPT_Cardinal* chars_used)
+{
+    // safe default value
+    result = 0;
+    if (chars_used) *chars_used = 0;
+
+    if (str == NULL) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // ignore leading whitespace
+    if (relaxed) {
+        while (*str == ' ' || *str == '\t') {
+            str++;
+            if (chars_used) (*chars_used)++;
+        }
+    }
+    if (*str == '\0') {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // check for sign
+    bool negative = false;
+    if (*str == '-') {
+        // negative number
+        negative = true; 
+        str++;
+        if (chars_used) (*chars_used)++;
+    } else if (*str == '+') {
+        // skip the + sign
+        str++;
+        if (chars_used) (*chars_used)++;
+    }
+
+    // check for overflows
+    NPT_Int64 max = NPT_INT64_MAX/10;
+
+    // adjust the max for overflows when the value is negative
+    if (negative && ((NPT_INT64_MAX%10) == 9)) ++max;
+
+    // parse the digits
+    bool      empty = true;
+    NPT_Int64 value = 0;
+    char c;
+    while ((c = *str++)) {
+        if (c >= '0' && c <= '9') {
+            if (value < 0 || value > max) return NPT_ERROR_OVERFLOW;
+            value = 10*value + (c-'0');
+            if (value < 0 && (!negative || value != NPT_INT64_MIN)) return NPT_ERROR_OVERFLOW;
+            empty = false;
+            if (chars_used) (*chars_used)++;
+        } else {
+            if (relaxed) {
+                break;
+            } else {
+                return NPT_ERROR_INVALID_PARAMETERS;
+            }
+        } 
+    }
+
+    // check that the value was non empty
+    if (empty) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // return the result
+    result = negative ? -value : value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_ParseInteger64U
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseInteger64U(const char* str, NPT_UInt64& result, bool relaxed, NPT_Cardinal* chars_used)
+{
+    // safe default value
+    result = 0;
+    if (chars_used) *chars_used = 0;
+
+    if (str == NULL) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // ignore leading whitespace
+    if (relaxed) {
+        while (*str == ' ' || *str == '\t') {
+            str++;
+            if (chars_used) (*chars_used)++;
+        }
+    }
+    if (*str == '\0') {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // parse the digits
+    bool       empty = true;
+    NPT_UInt64 value = 0;
+    char c;
+    while ((c = *str++)) {
+        if (c >= '0' && c <= '9') {
+            NPT_UInt64 new_value;
+            if (value > NPT_UINT64_MAX/10)  return NPT_ERROR_OVERFLOW;
+            new_value = 10*value + (c-'0');
+            if (new_value < value) return NPT_ERROR_OVERFLOW;
+            value = new_value;
+            empty = false;
+            if (chars_used) (*chars_used)++;
+        } else {
+            if (relaxed) {
+                break;
+            } else {
+                return NPT_ERROR_INVALID_PARAMETERS;
+            }
+        } 
+    }
+
+    // check that the value was non empty
+    if (empty) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // return the result
+    result = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_ParseInteger32
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseInteger32(const char* str, NPT_Int32& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+    NPT_Int64 value_64;
+    NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+    value = 0;
+    if (NPT_SUCCEEDED(result)) {
+        if (value_64 < NPT_INT32_MIN || value_64 > NPT_INT32_MAX) {
+            return NPT_ERROR_OVERFLOW;
+        }
+        value = (NPT_Int32)value_64;
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|     NPT_ParseInteger32U
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseInteger32U(const char* str, NPT_UInt32& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+    NPT_UInt64 value_64;
+    NPT_Result result = NPT_ParseInteger64U(str, value_64, relaxed, chars_used);
+    value = 0;
+    if (NPT_SUCCEEDED(result)) {
+        if (value_64 > (NPT_UInt64)NPT_UINT32_MAX) return NPT_ERROR_OVERFLOW;
+        value = (NPT_UInt32)value_64;
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_ParseInteger
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseInteger(const char* str, int& value, bool relaxed, NPT_Cardinal* chars_used)
+{
+    NPT_Int64 value_64;
+    NPT_Result result = NPT_ParseInteger64(str, value_64, relaxed, chars_used);
+    value = 0;
+    if (NPT_SUCCEEDED(result)) {
+        if (value_64 < NPT_INT_MIN || value_64 > NPT_INT_MAX) {
+            return NPT_ERROR_OVERFLOW;
+        }
+        value = (int)value_64;
+    }
+    return result;
+}
+
+
+#if !defined(NPT_CONFIG_HAVE_STRCPY)
+/*----------------------------------------------------------------------
+|    NPT_CopyString
++---------------------------------------------------------------------*/
+void
+NPT_CopyString(char* dst, const char* src)
+{
+    while(*dst++ = *src++);
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_FormatOutput
++---------------------------------------------------------------------*/
+void
+NPT_FormatOutput(void        (*function)(void* parameter, const char* message),
+                 void*       function_parameter,
+                 const char* format, 
+                 va_list     args)
+{
+    char         local_buffer[NPT_FORMAT_LOCAL_BUFFER_SIZE];
+    unsigned int buffer_size = NPT_FORMAT_LOCAL_BUFFER_SIZE;
+    char*        buffer = local_buffer;
+
+    for(;;) {
+        int result;
+
+        /* try to format the message (it might not fit) */
+        result = NPT_FormatStringVN(buffer, buffer_size-1, format, args);
+        buffer[buffer_size-1] = 0; /* force a NULL termination */
+        if (result >= 0) break;
+
+        /* the buffer was too small, try something bigger */
+        buffer_size = (buffer_size+NPT_FORMAT_BUFFER_INCREMENT)*2;
+        if (buffer_size > NPT_FORMAT_BUFFER_MAX_SIZE) break;
+        if (buffer != local_buffer) delete[] buffer;
+        buffer = new char[buffer_size];
+        if (buffer == NULL) return;
+    }
+
+    (*function)(function_parameter, buffer);
+    if (buffer != local_buffer) delete[] buffer;
+}
+
+/*----------------------------------------------------------------------
+|   local types
++---------------------------------------------------------------------*/
+typedef enum {
+    NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME,
+    NPT_MIME_PARAMETER_PARSER_STATE_IN_NAME,
+    NPT_MIME_PARAMETER_PARSER_STATE_NEED_EQUALS,
+    NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE,
+    NPT_MIME_PARAMETER_PARSER_STATE_IN_VALUE,
+    NPT_MIME_PARAMETER_PARSER_STATE_IN_QUOTED_VALUE,
+    NPT_MIME_PARAMETER_PARSER_STATE_NEED_SEPARATOR
+} NPT_MimeParameterParserState;
+
+/*----------------------------------------------------------------------
+|   NPT_ParseMimeParameters
+|
+|     From RFC 822 and RFC 2045
+|
+|                                                 ; (  Octal, Decimal.)
+|     CHAR        =  <any ASCII character>        ; (  0-177,  0.-127.)
+|     ALPHA       =  <any ASCII alphabetic character>
+|                                                 ; (101-132, 65.- 90.)
+|                                                 ; (141-172, 97.-122.)
+|     DIGIT       =  <any ASCII decimal digit>    ; ( 60- 71, 48.- 57.)
+|     CTL         =  <any ASCII control           ; (  0- 37,  0.- 31.)
+|                     character and DEL>          ; (    177,     127.)
+|     CR          =  <ASCII CR, carriage return>  ; (     15,      13.)
+|     LF          =  <ASCII LF, linefeed>         ; (     12,      10.)
+|     SPACE       =  <ASCII SP, space>            ; (     40,      32.)
+|     HTAB        =  <ASCII HT, horizontal-tab>   ; (     11,       9.)
+|     <">         =  <ASCII quote mark>           ; (     42,      34.)
+|     CRLF        =  CR LF
+|
+|     LWSP-char   =  SPACE / HTAB                 ; semantics = SPACE
+|
+|     linear-white-space =  1*([CRLF] LWSP-char)  ; semantics = SPACE
+|                                                 ; CRLF => folding
+|
+|     parameter := attribute "=" value
+|
+|     attribute := token
+|                  ; Matching of attributes
+|                  ; is ALWAYS case-insensitive.
+|
+|     value := token / quoted-string
+|
+|     token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, or tspecials>
+|
+|     tspecials :=  "(" / ")" / "<" / ">" / "@" /
+|                   "," / ";" / ":" / "\" / <">
+|                   "/" / "[" / "]" / "?" / "="
+|
+|     quoted-string = <"> *(qtext/quoted-pair) <">; Regular qtext or
+|                                                 ;   quoted chars.
+|
+|     qtext       =  <any CHAR excepting <">,     ; => may be folded
+|                     "\" & CR, and including
+|                     linear-white-space>
+|
+|     quoted-pair =  "\" CHAR                     ; may quote any char
+|
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseMimeParameters(const char*                      encoded,
+                        NPT_Map<NPT_String, NPT_String>& parameters)
+{
+    // check parameters
+    if (encoded == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    
+    // reserve some space 
+    NPT_String param_name;
+    NPT_String param_value;
+    param_name.Reserve(64);
+    param_value.Reserve(64);
+
+    NPT_MimeParameterParserState state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME;
+    bool quoted_char = false;
+    for (;;) {
+        char c = *encoded++;
+        if (!quoted_char && (c == 0x0A || c == 0x0D)) continue; // ignore EOL chars
+        switch (state) {
+            case NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME:
+                if (c == '\0') break; // END
+                if (c == ' ' || c == '\t') continue; // ignore leading whitespace
+                if (c <  ' ') return NPT_ERROR_INVALID_SYNTAX; // CTLs are invalid
+                param_name += c; // we're not strict: accept all other chars
+                state = NPT_MIME_PARAMETER_PARSER_STATE_IN_NAME;
+                break;
+                
+            case NPT_MIME_PARAMETER_PARSER_STATE_IN_NAME:
+                if (c <  ' ') return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+                if (c == ' ') {
+                    state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_EQUALS;
+                } else if (c == '=') {
+                    state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE;
+                } else {
+                    param_name += c; // we're not strict: accept all other chars
+                }
+                break;
+                
+            case NPT_MIME_PARAMETER_PARSER_STATE_NEED_EQUALS:
+                if (c <  ' ') return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+                if (c == ' ' || c == '\t') continue; // ignore leading whitespace
+                if (c != '=') return NPT_ERROR_INVALID_SYNTAX;
+                state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE;
+                break;
+
+            case NPT_MIME_PARAMETER_PARSER_STATE_NEED_VALUE:
+                if (c <  ' ') return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+                if (c == ' ' || c == '\t') continue; // ignore leading whitespace
+                if (c == '"') {
+                    state = NPT_MIME_PARAMETER_PARSER_STATE_IN_QUOTED_VALUE;
+                } else {
+                    param_value += c; // we're not strict: accept all other chars
+                    state = NPT_MIME_PARAMETER_PARSER_STATE_IN_VALUE;
+                }
+                break;
+                
+            case NPT_MIME_PARAMETER_PARSER_STATE_IN_QUOTED_VALUE:
+                if (quoted_char) {
+                    quoted_char = false;
+                    if (c == '\0') return NPT_ERROR_INVALID_SYNTAX;
+                    param_value += c; // accept all chars
+                    break;
+                } else if (c == '\\') {
+                    quoted_char = true;
+                    break;
+                } else if (c == '"') {
+                    // add the parameter to the map
+                    param_name.TrimRight();
+                    param_value.TrimRight();
+                    parameters[param_name] = param_value;
+                    param_name.SetLength(0);
+                    param_value.SetLength(0);
+                    state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_SEPARATOR;
+                } else if (c <  ' ') {
+                    return NPT_ERROR_INVALID_SYNTAX; // END or CTLs are invalid
+                } else {
+                    param_value += c; // we're not strict: accept all other chars
+                }
+                break;
+                
+            case NPT_MIME_PARAMETER_PARSER_STATE_IN_VALUE:
+                if (c == '\0' || c == ';') {
+                    // add the parameter to the map
+                    param_name.TrimRight();
+                    param_value.TrimRight();
+                    parameters[param_name] = param_value;
+                    param_name.SetLength(0);
+                    param_value.SetLength(0);
+                    state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME;
+                } else if (c < ' ') {
+                    // CTLs are invalid
+                    return NPT_ERROR_INVALID_SYNTAX;
+                } else {
+                    param_value += c; // we're not strict: accept all other chars
+                }
+                break;
+
+            case NPT_MIME_PARAMETER_PARSER_STATE_NEED_SEPARATOR:
+                if (c == '\0') break;
+                if (c <  ' ') return NPT_ERROR_INVALID_SYNTAX; // CTLs are invalid
+                if (c == ' ' || c == '\t') continue; // ignore whitespace
+                if (c != ';') return NPT_ERROR_INVALID_SYNTAX;
+                state = NPT_MIME_PARAMETER_PARSER_STATE_NEED_NAME;
+                break;
+        }
+        if (c == '\0') break; // end of buffer
+    }
+    
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptUtils.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,208 @@
+/*****************************************************************
+|
+|   Neptune Utils
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_UTILS_H_
+#define _NPT_UTILS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptStrings.h"
+#include "NptMap.h"
+
+#if defined (NPT_CONFIG_HAVE_STDIO_H)
+#include <stdio.h>
+#endif
+
+#if defined (NPT_CONFIG_HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STDARG_H)
+#include <stdarg.h>
+#endif
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#define NPT_ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
+
+/*----------------------------------------------------------------------
+|   byte I/O
++---------------------------------------------------------------------*/
+extern void NPT_BytesFromInt64Be(unsigned char* buffer, NPT_UInt64 value);
+extern void NPT_BytesFromInt32Be(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt24Be(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt16Be(unsigned char* buffer, NPT_UInt16 value);
+extern NPT_UInt64 NPT_BytesToInt64Be(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt32Be(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt24Be(const unsigned char* buffer);
+extern NPT_UInt16 NPT_BytesToInt16Be(const unsigned char* buffer);
+
+extern void NPT_BytesFromInt64Le(unsigned char* buffer, NPT_UInt64 value);
+extern void NPT_BytesFromInt32Le(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt24Le(unsigned char* buffer, NPT_UInt32 value);
+extern void NPT_BytesFromInt16Le(unsigned char* buffer, NPT_UInt16 value);
+extern NPT_UInt64 NPT_BytesToInt64Le(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt32Le(const unsigned char* buffer);
+extern NPT_UInt32 NPT_BytesToInt24Le(const unsigned char* buffer);
+extern NPT_UInt16 NPT_BytesToInt16Le(const unsigned char* buffer);
+
+/*----------------------------------------------------------------------
+|    conversion utilities
++---------------------------------------------------------------------*/
+extern NPT_Result 
+NPT_ParseFloat(const char* str, float& result, bool relaxed = true);
+
+extern NPT_Result 
+NPT_ParseInteger(const char* str, int& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result 
+NPT_ParseInteger32(const char* str, NPT_Int32& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result 
+NPT_ParseInteger32U(const char* str, NPT_UInt32& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result 
+NPT_ParseInteger64(const char* str, NPT_Int64& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+extern NPT_Result 
+NPT_ParseInteger64U(const char* str, NPT_UInt64& result, bool relaxed = true, NPT_Cardinal* chars_used = 0);
+
+/*----------------------------------------------------------------------
+|    formatting
++---------------------------------------------------------------------*/
+void
+NPT_FormatOutput(void        (*function)(void* parameter, const char* message),
+                 void*       function_parameter,
+                 const char* format, 
+                 va_list     args);
+
+void NPT_ByteToHex(NPT_Byte b, char* buffer, bool uppercase=false);
+NPT_Result NPT_HexToByte(const char* buffer, NPT_Byte& b);
+NPT_String NPT_HexString(const unsigned char* data, 
+                         NPT_Size             data_size,
+                         const char*          separator = NULL,
+                         bool                 uppercase=false);
+
+/*----------------------------------------------------------------------
+|    parsing
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ParseMimeParameters(const char*                      encoded,
+                        NPT_Map<NPT_String, NPT_String>& parameters);
+
+/*----------------------------------------------------------------------
+|    environment variables
++---------------------------------------------------------------------*/
+NPT_Result NPT_GetEnvironment(const char* name, NPT_String& value);
+
+/*----------------------------------------------------------------------
+|   string utils
++---------------------------------------------------------------------*/
+#if defined (NPT_CONFIG_HAVE_STDIO_H)
+#include <stdio.h>
+#endif
+
+#if defined (NPT_CONFIG_HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#if defined (NPT_CONFIG_HAVE_SNPRINTF)
+#define NPT_FormatString NPT_snprintf
+#else
+int NPT_FormatString(char* str, NPT_Size size, const char* format, ...);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_VSNPRINTF)
+#define NPT_FormatStringVN(s,c,f,a) NPT_vsnprintf(s,c,f,a)
+#else
+extern int NPT_FormatStringVN(char *buffer, size_t count, const char *format, va_list argptr);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_MEMCPY)
+#define NPT_CopyMemory memcpy
+#else
+extern void NPT_CopyMemory(void* dest, void* src, NPT_Size size);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRCMP)
+#define NPT_StringsEqual(s1, s2) (strcmp((s1), (s2)) == 0)
+#else
+extern int NPT_StringsEqual(const char* s1, const char* s2);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRNCMP)
+#define NPT_StringsEqualN(s1, s2, n) (strncmp((s1), (s2), (n)) == 0)
+#else
+extern int NPT_StringsEqualN(const char* s1, const char* s2, unsigned long size);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRLEN)
+#define NPT_StringLength(s) (NPT_Size)(strlen(s))
+#else
+extern unsigned long NPT_StringLength(const char* s);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_STRCPY)
+#define NPT_CopyString(dst, src) ((void)NPT_strcpy((dst), (src)))
+#else
+extern void NPT_CopyString(char* dst, const char* src);
+#endif
+
+/**
+ * Copy up to n characters from src to dst.
+ * The destination buffer will be null-terminated, so it must
+ * have enough space for n+1 characters (n from the source plus
+ * the null terminator).
+ */
+#if defined(NPT_CONFIG_HAVE_STRNCPY)
+#define NPT_CopyStringN(dst, src, n) \
+do { ((void)NPT_strncpy((dst), (src), n)); (dst)[(n)] = '\0'; } while(0)
+#else
+extern int NPT_CopyStringN(char* dst, const char* src, unsigned long n);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_MEMSET)
+#define NPT_SetMemory memset
+#else
+extern void NPT_SetMemory(void* dest, int c, NPT_Size size);
+#endif
+
+#if defined(NPT_CONFIG_HAVE_MEMCMP)
+#define NPT_MemoryEqual(s1, s2, n) (memcmp((s1), (s2), (n)) == 0) 
+#else 
+extern int NPT_MemoryEqual(const void* s1, const void* s2, unsigned long n); 
+#endif
+
+#endif // _NPT_UTILS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptVersion.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,41 @@
+/*****************************************************************
+|
+|   Neptune - Version Info
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_VERSION_H_
+#define _NPT_VERSION_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#define NPT_NEPTUNE_VERSION        0x01000100
+#define NPT_NEPTUNE_VERSION_STRING "1.0.1"
+
+#endif // _NPT_VERSION_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptXml.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,2510 @@
+/*****************************************************************
+|
+|   Neptune - Xml Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptXml.h"
+#include "NptUtils.h"
+#include "NptMap.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   local compilation flags
++---------------------------------------------------------------------*/
+//#define NPT_XML_PARSER_DEBUG
+#ifdef NPT_XML_PARSER_DEBUG
+#define NPT_XML_Debug_0(s) NPT_Debug(s)
+#define NPT_XML_Debug_1(s,x0) NPT_Debug(s,x0)
+#define NPT_XML_Debug_2(s,x0,x1) NPT_Debug(s,x0,x1)
+#define NPT_XML_Debug_3(s,x0,x1,x2) NPT_Debug(s,x0,x1,x2)
+#define NPT_XML_Debug_4(s,x0,x1,x2,x3) NPT_Debug(s,x0,x1,x2,x3)
+#else
+#define NPT_XML_Debug_0(s)
+#define NPT_XML_Debug_1(s,x0)
+#define NPT_XML_Debug_2(s,x0,x1)
+#define NPT_XML_Debug_3(s,x0,x1,x2)
+#define NPT_XML_Debug_4(s,x0,x1,x2,x3)
+#endif
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+static const NPT_String 
+NPT_XmlNamespaceUri_Xml("http://www.w3.org/XML/1998/namespace");
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAttributeFinder
++---------------------------------------------------------------------*/
+class NPT_XmlAttributeFinder
+{
+public:
+    // if 'namespc' is NULL, we're looking for ANY namespace
+    // if 'namespc' is '\0', we're looking for NO namespace
+    // if 'namespc' is non-empty, look for that SPECIFIC namespace
+    NPT_XmlAttributeFinder(const NPT_XmlElementNode& element, 
+                           const char*               name, 
+                           const char*               namespc) : 
+      m_Element(element), m_Name(name), m_Namespace(namespc) {}
+
+    bool operator()(const NPT_XmlAttribute* const & attribute) const {
+        if (attribute->m_Name == m_Name) {
+            if (m_Namespace) {
+                const NPT_String& prefix = attribute->GetPrefix();
+                if (m_Namespace[0] == '\0') {
+                    // match if the attribute has NO namespace
+                    return prefix.IsEmpty();
+                } else {
+                    // match if the attribute has the SPECIFIC namespace
+                    // we're looking for
+                    if (prefix.IsEmpty()) {
+                        // attributes without a prefix don't have a namespace
+                        return false;
+                    } else {
+                        const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
+                        return namespc && *namespc == m_Namespace;
+                    }
+                }
+            } else {
+                // ANY namespace will match
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+private:
+    const NPT_XmlElementNode& m_Element;
+    const char*               m_Name;
+    const char*               m_Namespace;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAttributeFinderWithPrefix
++---------------------------------------------------------------------*/
+class NPT_XmlAttributeFinderWithPrefix
+{
+public:
+    NPT_XmlAttributeFinderWithPrefix(const char* prefix, const char* name) : 
+      m_Prefix(prefix?prefix:""), m_Name(name) {}
+
+    bool operator()(const NPT_XmlAttribute* const & attribute) const {
+        return attribute->m_Prefix == m_Prefix && attribute->m_Name == m_Name;
+    }
+
+private:
+    const char* m_Prefix;
+    const char* m_Name;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlTagFinder
++---------------------------------------------------------------------*/
+class NPT_XmlTagFinder
+{
+public:
+    // if 'namespc' is NULL, we're looking for ANY namespace
+    // if 'namespc' is '\0', we're looking for NO namespace
+    // if 'namespc' is non-empty, look for that SPECIFIC namespace
+    NPT_XmlTagFinder(const char* tag, const char* namespc) : 
+      m_Tag(tag), m_Namespace(namespc) {}
+
+    bool operator()(const NPT_XmlNode* const & node) const {
+        const NPT_XmlElementNode* element = node->AsElementNode();
+        if (element && element->m_Tag == m_Tag) {
+            if (m_Namespace) {
+                // look for a SPECIFIC namespace or NO namespace
+                const NPT_String* namespc = element->GetNamespace();
+                if (namespc) {
+                    // the element has a namespace, match if it is equal to
+                    // what we're looking for
+                    return *namespc == m_Namespace;
+                } else {
+                    // the element does not have a namespace, match if we're
+                    // looking for NO namespace
+                    return m_Namespace[0] == '\0';
+                }
+            } else {
+                // ANY namespace will match
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+private:
+    const char* m_Tag;
+    const char* m_Namespace;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlTextFinder
++---------------------------------------------------------------------*/
+class NPT_XmlTextFinder
+{
+public:
+    bool operator()(const NPT_XmlNode* const & node) const {
+        return node->AsTextNode() != NULL;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceCollapser
++---------------------------------------------------------------------*/
+class NPT_XmlNamespaceCollapser
+{
+public:
+    NPT_XmlNamespaceCollapser(NPT_XmlElementNode* element) : 
+      m_Root(element) {}
+
+    void operator()(NPT_XmlNode*& node) const {
+        NPT_XmlElementNode* element = node->AsElementNode();
+        if (element == NULL) return;
+
+        // collapse the namespace for this element
+        CollapseNamespace(element, element->GetPrefix());
+
+        // collapse the namespaces for the attributes
+        NPT_List<NPT_XmlAttribute*>::Iterator item = element->GetAttributes().GetFirstItem();
+        while (item) {
+            NPT_XmlAttribute* attribute = *item;
+            CollapseNamespace(element, attribute->GetPrefix());
+            ++item;
+        }
+
+        // recurse to the children
+        element->GetChildren().Apply(*this);
+    }
+
+private:
+    // methods
+    void CollapseNamespace(NPT_XmlElementNode* element, const NPT_String& prefix) const;
+
+    // members
+    NPT_XmlElementNode* m_Root;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceCollapser::CollapseNamespace
++---------------------------------------------------------------------*/
+void
+NPT_XmlNamespaceCollapser::CollapseNamespace(NPT_XmlElementNode* element, 
+                                             const NPT_String&   prefix) const
+{
+    if (m_Root->m_NamespaceMap == NULL ||
+        (m_Root->m_NamespaceMap->GetNamespaceUri(prefix) == NULL && prefix != "xml")) {
+        // the root element does not have that prefix in the map
+        const NPT_String* uri = element->GetNamespaceUri(prefix);
+        if (uri) m_Root->SetNamespaceUri(prefix, uri->GetChars());
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAttribute::NPT_XmlAttribute
++---------------------------------------------------------------------*/
+NPT_XmlAttribute::NPT_XmlAttribute(const char* name, const char* value) :
+    m_Value(value)
+{
+    const char* cursor = name;
+    while (char c = *cursor++) {
+        if (c == ':') {
+            unsigned int prefix_length = (unsigned int)(cursor-name)-1;
+            m_Prefix.Assign(name, prefix_length);
+            name = cursor;
+            break;
+        }
+    }
+    m_Name = name;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::NPT_XmlElementNode
++---------------------------------------------------------------------*/
+NPT_XmlElementNode::NPT_XmlElementNode(const char* prefix, const char* tag) :
+    NPT_XmlNode(ELEMENT),
+    m_Prefix(prefix),
+    m_Tag(tag),
+    m_NamespaceMap(NULL),
+    m_NamespaceParent(NULL)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::NPT_XmlElementNode
++---------------------------------------------------------------------*/
+NPT_XmlElementNode::NPT_XmlElementNode(const char* tag) :
+    NPT_XmlNode(ELEMENT),
+    m_NamespaceMap(NULL),
+    m_NamespaceParent(NULL)
+{
+    const char* cursor = tag;
+    while (char c = *cursor++) {
+        if (c == ':') {
+            unsigned int prefix_length = (unsigned int)(cursor-tag)-1;
+            m_Prefix.Assign(tag, prefix_length);
+            tag = cursor;
+            break;
+        }
+    }
+    m_Tag = tag;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::~NPT_XmlElementNode
++---------------------------------------------------------------------*/
+NPT_XmlElementNode::~NPT_XmlElementNode()
+{
+    m_Children.Apply(NPT_ObjectDeleter<NPT_XmlNode>());
+    m_Attributes.Apply(NPT_ObjectDeleter<NPT_XmlAttribute>());
+    delete m_NamespaceMap;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::SetParent
++---------------------------------------------------------------------*/
+void
+NPT_XmlElementNode::SetParent(NPT_XmlNode* parent)
+{
+    // update our parent
+    m_Parent = parent;
+
+    // update out namespace linkage
+    NPT_XmlElementNode* parent_element =
+        parent?parent->AsElementNode():NULL;
+    NPT_XmlElementNode* namespace_parent;
+    if (parent_element) {
+        namespace_parent = 
+            parent_element->m_NamespaceMap ? 
+            parent_element:
+            parent_element->m_NamespaceParent;
+    } else {
+        namespace_parent = NULL;
+    }
+    if (namespace_parent != m_NamespaceParent) {
+        m_NamespaceParent = namespace_parent;
+        RelinkNamespaceMaps();
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::AddChild
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::AddChild(NPT_XmlNode* child)
+{
+    if (child == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    child->SetParent(this);
+    return m_Children.Add(child);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::GetChild
++---------------------------------------------------------------------*/
+NPT_XmlElementNode*
+NPT_XmlElementNode::GetChild(const char* tag, const char* namespc, NPT_Ordinal n) const
+{
+    // remap the requested namespace to match the semantics of the finder
+    // and allow for "" to also mean NO namespace
+    if (namespc == NULL || namespc[0] == '\0') {
+        namespc = ""; // for the finder, empty string means NO namespace
+    } else if (namespc[0] == '*' && namespc[1] == '\0') {
+        namespc = NULL; // for the finder, NULL means ANY namespace
+    }
+
+    // find the child
+    NPT_List<NPT_XmlNode*>::Iterator item;
+    item = m_Children.Find(NPT_XmlTagFinder(tag, namespc), n);
+    return item?(*item)->AsElementNode():NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::AddAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::AddAttribute(const char* name, 
+                                 const char* value)
+{
+    if (name == NULL || value == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    return m_Attributes.Add(new NPT_XmlAttribute(name, value));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::SetAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::SetAttribute(const char* prefix,
+                                 const char* name, 
+                                 const char* value)
+{
+    if (name == NULL || value == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+    /* see if this attribute is already set */
+    NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+    attribute = m_Attributes.Find(NPT_XmlAttributeFinderWithPrefix(prefix, name));
+    if (attribute) {
+        // an attribute with this name and prefix already exists, 
+        // change its value
+        (*attribute)->SetValue(value); 
+        return NPT_SUCCESS;
+    }
+    return m_Attributes.Add(new NPT_XmlAttribute(prefix, name, value));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::SetAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::SetAttribute(const char* name, const char* value)
+{
+    return SetAttribute(NULL, name, value);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::GetAttribute
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetAttribute(const char* name, const char* namespc) const
+{
+    // remap the requested namespace to match the semantics of the finder
+    // and allow for "" to also mean NO namespace
+    if (namespc == NULL || namespc[0] == '\0') {
+        namespc = ""; // for the finder, empty string means NO namespace
+    } else if (namespc[0] == '*' && namespc[1] == '\0') {
+        namespc = NULL; // for the finder, NULL means ANY namespace
+    }
+
+    // find the attribute
+    NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+    attribute = m_Attributes.Find(NPT_XmlAttributeFinder(*this, name, namespc));
+    if (attribute) { 
+        return &(*attribute)->GetValue();
+    } else {
+        return NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::AddText
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::AddText(const char* text)
+{
+    return AddChild(new NPT_XmlTextNode(NPT_XmlTextNode::CHARACTER_DATA, text));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::GetText
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetText(NPT_Ordinal n) const
+{
+    NPT_List<NPT_XmlNode*>::Iterator node;
+    node = m_Children.Find(NPT_XmlTextFinder(), n);
+    return node?&(*node)->AsTextNode()->GetString():NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::MakeStandalone
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::MakeStandalone()
+{
+    NPT_XmlNamespaceCollapser collapser(this);
+    NPT_XmlNode* node_pointer = this;
+    collapser(node_pointer);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::RelinkNamespaceMaps
++---------------------------------------------------------------------*/
+void
+NPT_XmlElementNode::RelinkNamespaceMaps()
+{
+    // update our children so that they can inherit the right
+    // namespace map
+    NPT_List<NPT_XmlNode*>::Iterator item = m_Children.GetFirstItem();
+    while (item) {
+        NPT_XmlElementNode* element = (*item)->AsElementNode();
+        if (element) {
+            if (m_NamespaceMap) {
+                // we have a map, so our children point to us
+                element->SetNamespaceParent(this);
+            } else {
+                // we don't have a map, so our children point to
+                // where we also point
+                element->SetNamespaceParent(m_NamespaceParent);
+            }
+        }
+        ++item;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::SetNamespaceParent
++---------------------------------------------------------------------*/
+void
+NPT_XmlElementNode::SetNamespaceParent(NPT_XmlElementNode* parent)
+{
+    m_NamespaceParent = parent;
+    RelinkNamespaceMaps();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::SetNamespaceUri
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlElementNode::SetNamespaceUri(const char* prefix, const char* uri)
+{
+    // ensure that we have a namespace map
+    if (m_NamespaceMap == NULL) {
+        m_NamespaceMap = new NPT_XmlNamespaceMap();
+        RelinkNamespaceMaps();
+    }
+
+    return m_NamespaceMap->SetNamespaceUri(prefix, uri);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::GetNamespaceUri
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetNamespaceUri(const char* prefix) const
+{
+    if (m_NamespaceMap) {
+        // look in our namespace map first
+        const NPT_String* namespc = m_NamespaceMap->GetNamespaceUri(prefix);
+        if (namespc) {
+            if (namespc->IsEmpty()) {
+                return NULL;
+            } else {
+                return namespc;
+            }
+        }
+    } 
+
+    // look into our parent's namespace map
+    if (m_NamespaceParent) {
+        return m_NamespaceParent->GetNamespaceUri(prefix);
+    } else {
+        // check if this is a well-known namespace
+        if (prefix[0] == 'x' && 
+            prefix[1] == 'm' && 
+            prefix[2] == 'l' && 
+            prefix[3] == '\0') {
+            return &NPT_XmlNamespaceUri_Xml;
+        }
+
+        // not found
+        return NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::GetNamespace
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetNamespace() const
+{
+    return GetNamespaceUri(m_Prefix);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode::GetNamespacePrefix
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlElementNode::GetNamespacePrefix(const char* uri) const
+{
+    NPT_XmlNamespaceMap* namespace_map = 
+        m_NamespaceMap? 
+        m_NamespaceMap:
+        (m_NamespaceParent?
+         m_NamespaceParent->m_NamespaceMap:
+         NULL);
+
+    if (namespace_map) {
+        return namespace_map->GetNamespacePrefix(uri);
+    } else {
+        return NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlTextNode::NPT_XmlTextNode
++---------------------------------------------------------------------*/
+NPT_XmlTextNode::NPT_XmlTextNode(TokenType token_type, const char* text) :
+    NPT_XmlNode(TEXT),
+    m_TokenType(token_type),
+    m_Text(text)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator
++---------------------------------------------------------------------*/
+class NPT_XmlAccumulator {
+public:
+             NPT_XmlAccumulator();
+            ~NPT_XmlAccumulator();
+    void     Append(char c);
+    void     Append(const char* s);
+    void     AppendUTF8(unsigned int c);
+    void     Reset() { m_Valid = 0; }
+    const char*          GetString();
+    NPT_Size             GetSize() const   { return m_Valid;  }
+    const unsigned char* GetBuffer() const { return m_Buffer; }
+
+private:
+    // methods
+    void Allocate(NPT_Size size);
+
+    // members
+    unsigned char* m_Buffer;
+    NPT_Size       m_Allocated;
+    NPT_Size       m_Valid;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::NPT_XmlAccumulator
++---------------------------------------------------------------------*/
+NPT_XmlAccumulator::NPT_XmlAccumulator() :
+    m_Buffer(NULL),
+    m_Allocated(0),
+    m_Valid(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::~NPT_XmlAccumulator
++---------------------------------------------------------------------*/
+NPT_XmlAccumulator::~NPT_XmlAccumulator()
+{
+    delete[] m_Buffer;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::Allocate
++---------------------------------------------------------------------*/
+void
+NPT_XmlAccumulator::Allocate(NPT_Size size)
+{
+    // check if we have enough
+    if (m_Allocated >= size) return;
+
+    // compute new size
+    do {
+        m_Allocated = m_Allocated ? m_Allocated * 2 : 32;
+    } while (m_Allocated < size);
+
+    // reallocate
+    unsigned char* new_buffer = new unsigned char[m_Allocated];
+    NPT_CopyMemory(new_buffer, m_Buffer, m_Valid);
+    delete[] m_Buffer;
+    m_Buffer = new_buffer;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::Append
++---------------------------------------------------------------------*/
+inline void
+NPT_XmlAccumulator::Append(char c)
+{
+    NPT_Size needed = m_Valid+1;
+    if (needed > m_Allocated) Allocate(needed);
+    m_Buffer[m_Valid++] = c;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::Append
++---------------------------------------------------------------------*/
+void
+NPT_XmlAccumulator::Append(const char* s)
+{
+    char c;
+    while ((c = *s++)) Append(c);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::AppendUTF8
++---------------------------------------------------------------------*/
+inline void
+NPT_XmlAccumulator::AppendUTF8(unsigned int c)
+{
+    NPT_Size needed = m_Valid+4; // allocate 4 more chars
+    if (needed > m_Allocated) Allocate(needed);
+
+    if (c <= 0x7F) {
+        // 000000–00007F -> 1 char = 0xxxxxxx
+        m_Buffer[m_Valid++] = (char)c;
+    } else if (c <= 0x7FF) {
+        // 000080–0007FF -> 2 chars = 110zzzzx 10xxxxxx
+        m_Buffer[m_Valid++] = 0xC0|(c>>6  );
+        m_Buffer[m_Valid++] = 0x80|(c&0x3F);
+    } else if (c <= 0xFFFF) {
+        // 000800–00FFFF -> 3 chars = 1110zzzz 10zxxxxx 10xxxxxx
+        m_Buffer[m_Valid++] = 0xE0| (c>>12      );
+        m_Buffer[m_Valid++] = 0x80|((c&0xFC0)>>6);
+        m_Buffer[m_Valid++] = 0x80| (c&0x3F     );
+    } else if (c <= 0x10FFFF) {
+        // 010000–10FFFF -> 4 chars = 11110zzz 10zzxxxx 10xxxxxx 10xxxxxx
+        m_Buffer[m_Valid++] = 0xF0| (c>>18         );
+        m_Buffer[m_Valid++] = 0x80|((c&0x3F000)>>12);
+        m_Buffer[m_Valid++] = 0x80|((c&0xFC0  )>> 6);
+        m_Buffer[m_Valid++] = 0x80| (c&0x3F        );
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAccumulator::GetString
++---------------------------------------------------------------------*/
+inline const char*
+NPT_XmlAccumulator::GetString()
+{
+    // ensure that the buffer is NULL terminated 
+    Allocate(m_Valid+1);
+    m_Buffer[m_Valid] = '\0';
+    return (const char*)m_Buffer;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceMap::~NPT_XmlNamespaceMap
++---------------------------------------------------------------------*/
+NPT_XmlNamespaceMap::~NPT_XmlNamespaceMap()
+{
+    m_Entries.Apply(NPT_ObjectDeleter<Entry>());
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceMap::SetNamespaceUri
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlNamespaceMap::SetNamespaceUri(const char* prefix, const char* uri)
+{
+    NPT_List<Entry*>::Iterator item = m_Entries.GetFirstItem();
+    while (item) {
+        if ((*item)->m_Prefix == prefix) {
+            // the prefix is already in the map, update the value
+            (*item)->m_Uri = uri;
+            return NPT_SUCCESS;
+        }
+        ++item;
+    }
+
+    // the prefix is not in the map, add it
+    return m_Entries.Add(new Entry(prefix, uri));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceMap::GetNamespaceUri
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlNamespaceMap::GetNamespaceUri(const char* prefix)
+{
+    NPT_List<Entry*>::Iterator item = m_Entries.GetFirstItem();
+    while (item) {
+        if ((*item)->m_Prefix == prefix) {
+            // match
+            return &(*item)->m_Uri;
+        }
+        ++item;
+    }
+
+    // the prefix is not in the map
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceMap::GetNamespacePrefix
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlNamespaceMap::GetNamespacePrefix(const char* uri)
+{
+    NPT_List<Entry*>::Iterator item = m_Entries.GetFirstItem();
+    while (item) {
+        if ((*item)->m_Uri == uri) {
+            // match
+            return &(*item)->m_Prefix;
+        }
+        ++item;
+    }
+
+    // the uri is not in the map
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   character map
+|
+| flags:
+| 1  --> any char
+| 2  --> whitespace
+| 4  --> name
+| 8  --> content
+| 16 --> value
++---------------------------------------------------------------------*/
+#define NPT_XML_USE_CHAR_MAP
+#if defined(NPT_XML_USE_CHAR_MAP)
+// NOTE: this table is generated by the ruby script 'XmlCharMap.rb'
+static const unsigned char NPT_XmlCharMap[256] = {
+                   0, //   0 0x00 
+                   0, //   1 0x01 
+                   0, //   2 0x02 
+                   0, //   3 0x03 
+                   0, //   4 0x04 
+                   0, //   5 0x05 
+                   0, //   6 0x06 
+                   0, //   7 0x07 
+                   0, //   8 0x08 
+            1|2|8|16, //   9 0x09 
+            1|2|8|16, //  10 0x0a 
+                   0, //  11 0x0b 
+                   0, //  12 0x0c 
+            1|2|8|16, //  13 0x0d 
+                   0, //  14 0x0e 
+                   0, //  15 0x0f 
+                   0, //  16 0x10 
+                   0, //  17 0x11 
+                   0, //  18 0x12 
+                   0, //  19 0x13 
+                   0, //  20 0x14 
+                   0, //  21 0x15 
+                   0, //  22 0x16 
+                   0, //  23 0x17 
+                   0, //  24 0x18 
+                   0, //  25 0x19 
+                   0, //  26 0x1a 
+                   0, //  27 0x1b 
+                   0, //  28 0x1c 
+                   0, //  29 0x1d 
+                   0, //  30 0x1e 
+                   0, //  31 0x1f 
+            1|2|8|16, //  32 0x20 ' '
+              1|8|16, //  33 0x21 '!'
+              1|8|16, //  34 0x22 '"'
+              1|8|16, //  35 0x23 '#'
+              1|8|16, //  36 0x24 '$'
+              1|8|16, //  37 0x25 '%'
+                   1, //  38 0x26 '&'
+              1|8|16, //  39 0x27 '''
+              1|8|16, //  40 0x28 '('
+              1|8|16, //  41 0x29 ')'
+              1|8|16, //  42 0x2a '*'
+              1|8|16, //  43 0x2b '+'
+              1|8|16, //  44 0x2c ','
+            1|4|8|16, //  45 0x2d '-'
+            1|4|8|16, //  46 0x2e '.'
+              1|8|16, //  47 0x2f '/'
+            1|4|8|16, //  48 0x30 '0'
+            1|4|8|16, //  49 0x31 '1'
+            1|4|8|16, //  50 0x32 '2'
+            1|4|8|16, //  51 0x33 '3'
+            1|4|8|16, //  52 0x34 '4'
+            1|4|8|16, //  53 0x35 '5'
+            1|4|8|16, //  54 0x36 '6'
+            1|4|8|16, //  55 0x37 '7'
+            1|4|8|16, //  56 0x38 '8'
+            1|4|8|16, //  57 0x39 '9'
+            1|4|8|16, //  58 0x3a ':'
+              1|8|16, //  59 0x3b ';'
+                   1, //  60 0x3c '<'
+              1|8|16, //  61 0x3d '='
+              1|8|16, //  62 0x3e '>'
+              1|8|16, //  63 0x3f '?'
+              1|8|16, //  64 0x40 '@'
+            1|4|8|16, //  65 0x41 'A'
+            1|4|8|16, //  66 0x42 'B'
+            1|4|8|16, //  67 0x43 'C'
+            1|4|8|16, //  68 0x44 'D'
+            1|4|8|16, //  69 0x45 'E'
+            1|4|8|16, //  70 0x46 'F'
+            1|4|8|16, //  71 0x47 'G'
+            1|4|8|16, //  72 0x48 'H'
+            1|4|8|16, //  73 0x49 'I'
+            1|4|8|16, //  74 0x4a 'J'
+            1|4|8|16, //  75 0x4b 'K'
+            1|4|8|16, //  76 0x4c 'L'
+            1|4|8|16, //  77 0x4d 'M'
+            1|4|8|16, //  78 0x4e 'N'
+            1|4|8|16, //  79 0x4f 'O'
+            1|4|8|16, //  80 0x50 'P'
+            1|4|8|16, //  81 0x51 'Q'
+            1|4|8|16, //  82 0x52 'R'
+            1|4|8|16, //  83 0x53 'S'
+            1|4|8|16, //  84 0x54 'T'
+            1|4|8|16, //  85 0x55 'U'
+            1|4|8|16, //  86 0x56 'V'
+            1|4|8|16, //  87 0x57 'W'
+            1|4|8|16, //  88 0x58 'X'
+            1|4|8|16, //  89 0x59 'Y'
+            1|4|8|16, //  90 0x5a 'Z'
+              1|8|16, //  91 0x5b '['
+              1|8|16, //  92 0x5c '\'
+              1|8|16, //  93 0x5d ']'
+              1|8|16, //  94 0x5e '^'
+            1|4|8|16, //  95 0x5f '_'
+              1|8|16, //  96 0x60 '`'
+            1|4|8|16, //  97 0x61 'a'
+            1|4|8|16, //  98 0x62 'b'
+            1|4|8|16, //  99 0x63 'c'
+            1|4|8|16, // 100 0x64 'd'
+            1|4|8|16, // 101 0x65 'e'
+            1|4|8|16, // 102 0x66 'f'
+            1|4|8|16, // 103 0x67 'g'
+            1|4|8|16, // 104 0x68 'h'
+            1|4|8|16, // 105 0x69 'i'
+            1|4|8|16, // 106 0x6a 'j'
+            1|4|8|16, // 107 0x6b 'k'
+            1|4|8|16, // 108 0x6c 'l'
+            1|4|8|16, // 109 0x6d 'm'
+            1|4|8|16, // 110 0x6e 'n'
+            1|4|8|16, // 111 0x6f 'o'
+            1|4|8|16, // 112 0x70 'p'
+            1|4|8|16, // 113 0x71 'q'
+            1|4|8|16, // 114 0x72 'r'
+            1|4|8|16, // 115 0x73 's'
+            1|4|8|16, // 116 0x74 't'
+            1|4|8|16, // 117 0x75 'u'
+            1|4|8|16, // 118 0x76 'v'
+            1|4|8|16, // 119 0x77 'w'
+            1|4|8|16, // 120 0x78 'x'
+            1|4|8|16, // 121 0x79 'y'
+            1|4|8|16, // 122 0x7a 'z'
+              1|8|16, // 123 0x7b '{'
+              1|8|16, // 124 0x7c '|'
+              1|8|16, // 125 0x7d '}'
+              1|8|16, // 126 0x7e '~'
+              1|8|16, // 127 0x7f 
+              1|8|16, // 128 0x80 
+              1|8|16, // 129 0x81 
+              1|8|16, // 130 0x82 
+              1|8|16, // 131 0x83 
+              1|8|16, // 132 0x84 
+              1|8|16, // 133 0x85 
+              1|8|16, // 134 0x86 
+              1|8|16, // 135 0x87 
+              1|8|16, // 136 0x88 
+              1|8|16, // 137 0x89 
+              1|8|16, // 138 0x8a 
+              1|8|16, // 139 0x8b 
+              1|8|16, // 140 0x8c 
+              1|8|16, // 141 0x8d 
+              1|8|16, // 142 0x8e 
+              1|8|16, // 143 0x8f 
+              1|8|16, // 144 0x90 
+              1|8|16, // 145 0x91 
+              1|8|16, // 146 0x92 
+              1|8|16, // 147 0x93 
+              1|8|16, // 148 0x94 
+              1|8|16, // 149 0x95 
+              1|8|16, // 150 0x96 
+              1|8|16, // 151 0x97 
+              1|8|16, // 152 0x98 
+              1|8|16, // 153 0x99 
+              1|8|16, // 154 0x9a 
+              1|8|16, // 155 0x9b 
+              1|8|16, // 156 0x9c 
+              1|8|16, // 157 0x9d 
+              1|8|16, // 158 0x9e 
+              1|8|16, // 159 0x9f 
+              1|8|16, // 160 0xa0 
+              1|8|16, // 161 0xa1 
+              1|8|16, // 162 0xa2 
+              1|8|16, // 163 0xa3 
+              1|8|16, // 164 0xa4 
+              1|8|16, // 165 0xa5 
+              1|8|16, // 166 0xa6 
+              1|8|16, // 167 0xa7 
+              1|8|16, // 168 0xa8 
+              1|8|16, // 169 0xa9 
+              1|8|16, // 170 0xaa 
+              1|8|16, // 171 0xab 
+              1|8|16, // 172 0xac 
+              1|8|16, // 173 0xad 
+              1|8|16, // 174 0xae 
+              1|8|16, // 175 0xaf 
+              1|8|16, // 176 0xb0 
+              1|8|16, // 177 0xb1 
+              1|8|16, // 178 0xb2 
+              1|8|16, // 179 0xb3 
+              1|8|16, // 180 0xb4 
+              1|8|16, // 181 0xb5 
+              1|8|16, // 182 0xb6 
+              1|8|16, // 183 0xb7 
+              1|8|16, // 184 0xb8 
+              1|8|16, // 185 0xb9 
+              1|8|16, // 186 0xba 
+              1|8|16, // 187 0xbb 
+              1|8|16, // 188 0xbc 
+              1|8|16, // 189 0xbd 
+              1|8|16, // 190 0xbe 
+              1|8|16, // 191 0xbf 
+            1|4|8|16, // 192 0xc0 
+            1|4|8|16, // 193 0xc1 
+            1|4|8|16, // 194 0xc2 
+            1|4|8|16, // 195 0xc3 
+            1|4|8|16, // 196 0xc4 
+            1|4|8|16, // 197 0xc5 
+            1|4|8|16, // 198 0xc6 
+            1|4|8|16, // 199 0xc7 
+            1|4|8|16, // 200 0xc8 
+            1|4|8|16, // 201 0xc9 
+            1|4|8|16, // 202 0xca 
+            1|4|8|16, // 203 0xcb 
+            1|4|8|16, // 204 0xcc 
+            1|4|8|16, // 205 0xcd 
+            1|4|8|16, // 206 0xce 
+            1|4|8|16, // 207 0xcf 
+            1|4|8|16, // 208 0xd0 
+            1|4|8|16, // 209 0xd1 
+            1|4|8|16, // 210 0xd2 
+            1|4|8|16, // 211 0xd3 
+            1|4|8|16, // 212 0xd4 
+            1|4|8|16, // 213 0xd5 
+            1|4|8|16, // 214 0xd6 
+              1|8|16, // 215 0xd7 
+            1|4|8|16, // 216 0xd8 
+            1|4|8|16, // 217 0xd9 
+            1|4|8|16, // 218 0xda 
+            1|4|8|16, // 219 0xdb 
+            1|4|8|16, // 220 0xdc 
+            1|4|8|16, // 221 0xdd 
+            1|4|8|16, // 222 0xde 
+            1|4|8|16, // 223 0xdf 
+            1|4|8|16, // 224 0xe0 
+            1|4|8|16, // 225 0xe1 
+            1|4|8|16, // 226 0xe2 
+            1|4|8|16, // 227 0xe3 
+            1|4|8|16, // 228 0xe4 
+            1|4|8|16, // 229 0xe5 
+            1|4|8|16, // 230 0xe6 
+            1|4|8|16, // 231 0xe7 
+            1|4|8|16, // 232 0xe8 
+            1|4|8|16, // 233 0xe9 
+            1|4|8|16, // 234 0xea 
+            1|4|8|16, // 235 0xeb 
+            1|4|8|16, // 236 0xec 
+            1|4|8|16, // 237 0xed 
+            1|4|8|16, // 238 0xee 
+            1|4|8|16, // 239 0xef 
+            1|4|8|16, // 240 0xf0 
+            1|4|8|16, // 241 0xf1 
+            1|4|8|16, // 242 0xf2 
+            1|4|8|16, // 243 0xf3 
+            1|4|8|16, // 244 0xf4 
+            1|4|8|16, // 245 0xf5 
+            1|4|8|16, // 246 0xf6 
+              1|8|16, // 247 0xf7 
+            1|4|8|16, // 248 0xf8 
+            1|4|8|16, // 249 0xf9 
+            1|4|8|16, // 250 0xfa 
+            1|4|8|16, // 251 0xfb 
+            1|4|8|16, // 252 0xfc 
+            1|4|8|16, // 253 0xfd 
+            1|4|8|16, // 254 0xfe 
+            1|4|8|16  // 255 0xff 
+};
+#endif // defined(NPT_XML_USE_CHAR_MAP)
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#if defined (NPT_XML_USE_CHAR_MAP)
+#define NPT_XML_CHAR_IS_ANY_CHAR(c)        (NPT_XmlCharMap[c] & 1)
+#define NPT_XML_CHAR_IS_WHITESPACE(c)      (NPT_XmlCharMap[c] & 2)
+#define NPT_XML_CHAR_IS_NAME_CHAR(c)       (NPT_XmlCharMap[c] & 4)
+#define NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c) (NPT_XML_CHAR_IS_NAME_CHAR((c)) || ((c) == '#'))
+#define NPT_XML_CHAR_IS_CONTENT_CHAR(c)    (NPT_XmlCharMap[c] & 8)
+#define NPT_XML_CHAR_IS_VALUE_CHAR(c)      (NPT_XmlCharMap[c] & 16)
+#else
+#define NPT_XML_CHAR_IS_WHITESPACE(c) \
+((c) == ' ' || (c) == '\t' || (c) == 0x0D || (c) == 0x0A)
+
+#define NPT_XML_CHAR_IS_ANY_CHAR(c) \
+(NPT_XML_CHAR_IS_WHITESPACE((c)) || ((c) >= 0x20))
+
+#define NPT_XML_CHAR_IS_DIGIT(c) \
+((c) >= '0' && (c) <= '9')
+
+#define NPT_XML_CHAR_IS_LETTER(c) \
+(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') || ((c) >= 0xC0 && (c) <= 0xD6) || ((c) >= 0xD8 && (c) <= 0xF6) || ((c) >= 0xF8))
+
+#define NPT_XML_CHAR_IS_NAME_CHAR(c) \
+(NPT_XML_CHAR_IS_DIGIT((c)) || NPT_XML_CHAR_IS_LETTER((c)) || (c) == '.' || (c) == '-' || (c) == '_' || (c) == ':')
+
+#define NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c) \
+(NPT_XML_CHAR_IS_NAME_CHAR((c)) || ((c) == '#'))
+
+#define NPT_XML_CHAR_IS_CONTENT_CHAR(c) \
+(NPT_XML_CHAR_IS_ANY_CHAR((c)) && ((c) != '&') && ((c) != '<'))
+
+#define NPT_XML_CHAR_IS_VALUE_CHAR(c) \
+(NPT_XML_CHAR_IS_ANY_CHAR((c)) && ((c) != '&') && ((c) != '<'))
+
+#endif // defined(NPT_XML_USE_CHAR_MAP)
+
+/*----------------------------------------------------------------------
+|   NPT_XmlStringIsWhitespace
++---------------------------------------------------------------------*/
+static bool
+NPT_XmlStringIsWhitespace(const char* s, NPT_Size size)
+{
+    for (NPT_Size x=0; x<size; x++) {
+        if (!NPT_XML_CHAR_IS_WHITESPACE((int)s[x])) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlProcessor class
++---------------------------------------------------------------------*/
+class NPT_XmlProcessor {
+public:
+    // constructor and destructor
+   NPT_XmlProcessor(NPT_XmlParser* parser);
+
+    // methods
+    NPT_Result ProcessBuffer(const char* buffer, NPT_Size size);
+    
+private:
+    // types
+    typedef enum {
+        CONTEXT_NONE,
+        CONTEXT_OPEN_TAG,
+        CONTEXT_CLOSE_TAG,
+        CONTEXT_ATTRIBUTE,
+        CONTEXT_VALUE_SINGLE_QUOTE,
+        CONTEXT_VALUE_DOUBLE_QUOTE
+    } Context;
+
+    typedef enum {
+        STATE_IN_WHITESPACE,
+        STATE_IN_NAME,
+        STATE_IN_NAME_SPECIAL,
+        STATE_IN_VALUE_START,
+        STATE_IN_VALUE,
+        STATE_IN_TAG_START,
+        STATE_IN_EMPTY_TAG_END,
+        STATE_IN_CONTENT,
+        STATE_IN_PROCESSING_INSTRUCTION_START,
+        STATE_IN_PROCESSING_INSTRUCTION,
+        STATE_IN_PROCESSING_INSTRUCTION_END,
+        STATE_IN_COMMENT,
+        STATE_IN_COMMENT_END_1,
+        STATE_IN_COMMENT_END_2,
+        STATE_IN_DTD,
+        STATE_IN_DTD_MARKUP_DECL,
+        STATE_IN_DTD_MARKUP_DECL_END,
+        STATE_IN_CDATA,
+        STATE_IN_CDATA_END_1,
+        STATE_IN_CDATA_END_2,
+        STATE_IN_SPECIAL,
+        STATE_IN_ENTITY_REF
+    } State;
+
+    // members
+    NPT_XmlParser*     m_Parser;
+    State              m_State;
+    Context            m_Context;
+    bool               m_SkipNewline;
+    NPT_XmlAccumulator m_Name;
+    NPT_XmlAccumulator m_Value;
+    NPT_XmlAccumulator m_Text;
+    NPT_XmlAccumulator m_Entity;
+
+    // methods
+#ifdef NPT_XML_PARSER_DEBUG
+    const char* StateName(State state) {
+        switch (state) {
+          case STATE_IN_WHITESPACE: return "IN_WHITESPACE";
+          case STATE_IN_NAME: return "IN_NAME";
+          case STATE_IN_NAME_SPECIAL: return "IN_NAME_SPECIAL";
+          case STATE_IN_VALUE_START: return "IN_VALUE_START";
+          case STATE_IN_VALUE: return "IN_VALUE";
+          case STATE_IN_TAG_START: return "IN_TAG_START";
+          case STATE_IN_EMPTY_TAG_END: return "IN_EMPTY_TAG_END";
+          case STATE_IN_CONTENT: return "IN_CONTENT";
+          case STATE_IN_PROCESSING_INSTRUCTION_START: return "IN_PROCESSING_INSTRUCTION_START";
+          case STATE_IN_PROCESSING_INSTRUCTION: return "IN_PROCESSING_INSTRUCTION";
+          case STATE_IN_PROCESSING_INSTRUCTION_END: return "IN_PROCESSING_INSTRUCTION_END";
+          case STATE_IN_COMMENT: return "IN_COMMENT";
+          case STATE_IN_COMMENT_END_1: return "IN_COMMENT_END_1";
+          case STATE_IN_COMMENT_END_2: return "IN_COMMENT_END_2";
+          case STATE_IN_DTD: return "IN_DTD";
+          case STATE_IN_DTD_MARKUP_DECL: return "IN_DTD_MARKUP_DECL";
+          case STATE_IN_DTD_MARKUP_DECL_END: return "IN_DTD_MARKUP_DECL_END";
+          case STATE_IN_CDATA: return "IN_CDATA";
+          case STATE_IN_CDATA_END_1: return "IN_CDATA_END_1";
+          case STATE_IN_CDATA_END_2: return "IN_CDATA_END_2";
+          case STATE_IN_SPECIAL: return "IN_SPECIAL";
+          case STATE_IN_ENTITY_REF: return "IN_ENTITY_REF";
+        }
+        return "UNKNOWN";
+    }
+
+    const char* ContextName(Context context) {
+        switch (context) {
+          case CONTEXT_NONE: return "NONE";
+          case CONTEXT_OPEN_TAG: return "OPEN_TAG";
+          case CONTEXT_CLOSE_TAG: return "CLOSE_TAG";
+          case CONTEXT_ATTRIBUTE: return "ATTRIBUTE";
+          case CONTEXT_VALUE_SINGLE_QUOTE: return "VALUE_SINGLE_QUOTE";
+          case CONTEXT_VALUE_DOUBLE_QUOTE: return "VALUE_DOUBLE_QUOTE";
+        }
+        return "UNKNOWN";
+    }
+#endif /* NPT_XML_PARSER_DEBUG */
+
+    inline void SetState(State state) {
+        NPT_XML_Debug_3("\nstate transition: %s to %s [ctx=%s]\n", 
+                        StateName(m_State), 
+                        StateName(state),
+                        ContextName(m_Context));
+        m_State = state;
+    }
+
+    inline void SetState(State state, Context context) {
+        NPT_XML_Debug_4("\nstate transition: %s [ctx=%s] to %s [ctx=%s]\n", 
+                        StateName(m_State), 
+                        ContextName(m_Context),
+                        StateName(state), 
+                        ContextName(context));
+        m_State = state;
+        m_Context = context;
+    }
+
+    NPT_Result ResolveEntity(NPT_XmlAccumulator& source,
+                             NPT_XmlAccumulator& destination);
+    NPT_Result FlushPendingText();
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlProcessor::NPT_XmlProcessor
++---------------------------------------------------------------------*/
+NPT_XmlProcessor::NPT_XmlProcessor(NPT_XmlParser* parser) :
+    m_Parser(parser),
+    m_State(STATE_IN_WHITESPACE),
+    m_Context(CONTEXT_NONE),
+    m_SkipNewline(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlProcessor::ResolveEntity
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlProcessor::ResolveEntity(NPT_XmlAccumulator& source,
+                                NPT_XmlAccumulator& destination)
+{
+    const char* entity = (const char*)source.GetString();
+    
+    if (NPT_StringsEqual(entity, "lt")) {
+        destination.Append('<');
+    } else if (NPT_StringsEqual(entity, "gt")) {
+        destination.Append('>');
+    } else if (NPT_StringsEqual(entity, "amp")) {
+        destination.Append('&');
+    } else if (NPT_StringsEqual(entity, "quot")) {
+        destination.Append('"');
+    } else if (NPT_StringsEqual(entity, "apos")) {
+        destination.Append('\'');
+    } else if (entity[0] == '#') {
+        int i=1;
+        int base = 10;
+        if (entity[1] == 'x') {
+            i++;
+            base = 16;
+        }
+        int parsed = 0;
+        while (char c = entity[i++]) {
+            int digit = -1;
+            if (c>='0' && c<='9') {
+                digit = c-'0';
+            } else if (base == 16) {
+                if (c >= 'a' && c <= 'f') {
+                    digit = 10+c-'a';
+                } else if (c >= 'A' && c <= 'F') {
+                    digit = 10+c-'A';
+                }
+            }
+            if (digit == -1) {
+                // invalid char, leave the entity unparsed
+                destination.Append(source.GetString());
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            parsed = base*parsed+digit;
+        }
+        destination.AppendUTF8(parsed);
+    } else {
+        // unknown entity, leave as-is
+        destination.Append(source.GetString());
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlProcessor::FlushPendingText
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlProcessor::FlushPendingText()
+{
+    if (m_Text.GetSize() > 0) {
+        NPT_CHECK(m_Parser->OnCharacterData(m_Text.GetString(),
+                                            m_Text.GetSize()));
+        m_Text.Reset();
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlProcessor::ProcessBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlProcessor::ProcessBuffer(const char* buffer, NPT_Size size)
+{
+    unsigned char c;
+
+    while (size-- && (c = *buffer++)) {
+        NPT_XML_Debug_1("[%c]", (c == '\n' || c == '\r') ? '#' : c);
+
+        // normalize line ends
+        if (m_SkipNewline) {
+            m_SkipNewline = false;
+            if (c == '\n') continue;
+        }
+        if (c == '\r') {
+            m_SkipNewline = true;
+            c = '\n';
+        }
+
+        // process the character
+        switch (m_State) {
+          case STATE_IN_WHITESPACE:
+            if (NPT_XML_CHAR_IS_WHITESPACE(c)) break;
+            switch (m_Context) {
+              case CONTEXT_NONE:
+                if (c == '<') {
+                    SetState(STATE_IN_TAG_START);
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+                
+              case CONTEXT_ATTRIBUTE:
+                if (c == '/') {
+                    SetState(STATE_IN_EMPTY_TAG_END, CONTEXT_NONE);
+                } else if (c == '>') {
+                    SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+                } else if (NPT_XML_CHAR_IS_NAME_CHAR(c)) {
+                    m_Name.Reset();
+                    m_Name.Append(c);
+                    SetState(STATE_IN_NAME);
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+
+              case CONTEXT_CLOSE_TAG:
+                if (c == '>') {
+                    NPT_CHECK(FlushPendingText());
+                    NPT_CHECK(m_Parser->OnEndElement(m_Name.GetString()));
+                    SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+
+              default:
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_NAME:
+            if (NPT_XML_CHAR_IS_NAME_CHAR(c)) {
+                m_Name.Append(c);
+                break;
+            }
+            switch (m_Context) {
+              case CONTEXT_ATTRIBUTE:
+                if (c == '=') {
+                    m_Value.Reset();
+                    SetState(STATE_IN_VALUE_START);
+                } else if (!NPT_XML_CHAR_IS_WHITESPACE(c)) {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+
+              case CONTEXT_OPEN_TAG:
+                if (c == '>' || c == '/' || NPT_XML_CHAR_IS_WHITESPACE(c)) {
+                    NPT_CHECK(FlushPendingText());
+                    NPT_CHECK(m_Parser->OnStartElement(m_Name.GetString()));
+                    m_Name.Reset();
+                    if (c == '>') {
+                        SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+                    } else if (c == '/') {
+                        SetState(STATE_IN_EMPTY_TAG_END);
+                    } else {
+                        SetState(STATE_IN_WHITESPACE, CONTEXT_ATTRIBUTE);
+                    }
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+
+              case CONTEXT_CLOSE_TAG:
+                if (c == '>') {
+                    NPT_CHECK(FlushPendingText());
+                    NPT_CHECK(m_Parser->OnEndElement(m_Name.GetString()));
+                    SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+                } else if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+                    SetState(STATE_IN_WHITESPACE);
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+
+              default:
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_NAME_SPECIAL:
+            if (NPT_XML_CHAR_IS_NAME_CHAR(c) || (c == '[')) {
+                m_Name.Append(c);
+
+                const unsigned char* nb = m_Name.GetBuffer();
+                if (m_Name.GetSize() == 2) {
+                    if (nb[0] == '-' &&
+                        nb[1] == '-') {
+                        m_Name.Reset();
+                        SetState(STATE_IN_COMMENT, CONTEXT_NONE);
+                        break;
+                    }
+                } else if (m_Name.GetSize() == 7) {
+                    if (nb[0] == '[' &&
+                        nb[1] == 'C' &&
+                        nb[2] == 'D' &&
+                        nb[3] == 'A' &&
+                        nb[4] == 'T' &&
+                        nb[5] == 'A' &&
+                        nb[6] == '[') {
+                        m_Name.Reset();
+                        SetState(STATE_IN_CDATA, CONTEXT_NONE);
+                        break;
+                    }
+                }
+                break;
+            }
+            if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+                const char* special = m_Name.GetString();
+                if (special && NPT_StringsEqual(special, "DOCTYPE")) {
+                    SetState(STATE_IN_DTD, CONTEXT_NONE);
+                } else {
+                    SetState(STATE_IN_SPECIAL, CONTEXT_NONE);
+                }
+                m_Name.Reset();
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_VALUE_START:
+            if (NPT_XML_CHAR_IS_WHITESPACE(c)) break;
+            if (c == '"') {
+                m_Value.Reset();
+                SetState(STATE_IN_VALUE, CONTEXT_VALUE_DOUBLE_QUOTE);
+            } else if (c == '\'') {
+                m_Value.Reset();
+                SetState(STATE_IN_VALUE, CONTEXT_VALUE_SINGLE_QUOTE);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_VALUE:
+            if ((c == '"'  && m_Context == CONTEXT_VALUE_DOUBLE_QUOTE) || 
+                (c == '\'' && m_Context == CONTEXT_VALUE_SINGLE_QUOTE)) {
+                NPT_CHECK(m_Parser->OnElementAttribute(m_Name.GetString(),
+                                                       m_Value.GetString()));
+                SetState(STATE_IN_WHITESPACE, CONTEXT_ATTRIBUTE);
+            } else if (c == '&') {
+                m_Entity.Reset();
+                SetState(STATE_IN_ENTITY_REF);
+            } else if (NPT_XML_CHAR_IS_WHITESPACE(c)) {
+                m_Value.Append(' ');
+            } else if (NPT_XML_CHAR_IS_VALUE_CHAR(c)) {
+                m_Value.Append(c);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_TAG_START:
+            m_Name.Reset();
+            if (c == '!') {
+                SetState(STATE_IN_NAME_SPECIAL, CONTEXT_NONE);
+            } else if (c == '?') {
+                SetState(STATE_IN_PROCESSING_INSTRUCTION, CONTEXT_NONE);
+            } else if (c == '/') {
+                SetState(STATE_IN_NAME, CONTEXT_CLOSE_TAG);
+            } else if (NPT_XML_CHAR_IS_NAME_CHAR(c)) {
+                m_Name.Append(c);
+                SetState(STATE_IN_NAME, CONTEXT_OPEN_TAG);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_EMPTY_TAG_END:
+            if (c == '>') {
+                NPT_CHECK(FlushPendingText());
+                NPT_CHECK(m_Parser->OnEndElement(NULL));
+                SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_ENTITY_REF:
+            switch (m_Context) {
+              case CONTEXT_VALUE_SINGLE_QUOTE:
+              case CONTEXT_VALUE_DOUBLE_QUOTE:
+                if (c == ';') {
+                    NPT_CHECK(ResolveEntity(m_Entity, m_Value));
+                    SetState(STATE_IN_VALUE);
+                } else if (NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c)) {
+                    m_Entity.Append(c);
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+
+              case CONTEXT_NONE:
+                if (c == ';') {
+                    NPT_CHECK(ResolveEntity(m_Entity, m_Text));
+                    SetState(STATE_IN_CONTENT);
+                } else if (NPT_XML_CHAR_IS_ENTITY_REF_CHAR(c)) {
+                    m_Entity.Append(c);
+                } else {
+                    return NPT_ERROR_INVALID_SYNTAX;
+                }
+                break;
+                
+              default:
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_COMMENT:
+            if (c == '-') {
+                SetState(STATE_IN_COMMENT_END_1);
+            } else if (!NPT_XML_CHAR_IS_ANY_CHAR(c)) {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_COMMENT_END_1:
+            if (c == '-') {
+                SetState(STATE_IN_COMMENT_END_2);
+            } else if (NPT_XML_CHAR_IS_ANY_CHAR(c)) {
+                SetState(STATE_IN_COMMENT);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_COMMENT_END_2:
+            if (c == '>') {
+                SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_CONTENT:
+            if (c == '<') {
+                SetState(STATE_IN_TAG_START, CONTEXT_NONE);
+            } else if (c == '&') {
+                m_Entity.Reset();
+                SetState(STATE_IN_ENTITY_REF);
+            } else {
+                m_Text.Append(c);
+            }
+            break;
+
+          case STATE_IN_PROCESSING_INSTRUCTION_START:
+            break;
+
+          case STATE_IN_PROCESSING_INSTRUCTION_END:
+            if (c == '>') {
+                SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+            } else {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_PROCESSING_INSTRUCTION:
+            if (c == '?') {
+                SetState(STATE_IN_PROCESSING_INSTRUCTION_END);
+            }
+            break;
+
+          case STATE_IN_DTD:
+            if (NPT_XML_CHAR_IS_WHITESPACE(c)) break;
+            if (c == '[') {
+                SetState(STATE_IN_DTD_MARKUP_DECL);
+            } else if (c == '>') {
+                SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+            }
+            break;
+
+          case STATE_IN_DTD_MARKUP_DECL:
+            if (c == ']') {
+                SetState(STATE_IN_DTD_MARKUP_DECL_END);
+            }
+            break;
+
+          case STATE_IN_DTD_MARKUP_DECL_END:
+            if (c == '>') {
+                SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+            } else if (!NPT_XML_CHAR_IS_WHITESPACE(c)) {
+                return NPT_ERROR_INVALID_SYNTAX;
+            }
+            break;
+
+          case STATE_IN_CDATA:
+            if (c == ']') {
+                SetState(STATE_IN_CDATA_END_1);
+            } else  {
+                m_Text.Append(c);
+            }
+            break;
+
+          case STATE_IN_CDATA_END_1:
+            if (c == ']') {
+                SetState(STATE_IN_CDATA_END_2);
+            } else {
+                m_Text.Append(']');
+                m_Text.Append(c);
+                SetState(STATE_IN_CDATA);
+            }
+            break;
+
+          case STATE_IN_CDATA_END_2:
+            if (c == '>') {
+                SetState(STATE_IN_CONTENT, CONTEXT_NONE);
+            } else {
+                m_Text.Append("]]");
+                m_Text.Append(c);
+                SetState(STATE_IN_CDATA);
+            }
+            break;
+
+          case STATE_IN_SPECIAL:
+            if (c == '>') {
+                SetState(STATE_IN_WHITESPACE, CONTEXT_NONE);
+            }
+            break;
+        }
+    }
+
+    return NPT_SUCCESS;
+}       
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::NPT_XmlParser
++---------------------------------------------------------------------*/
+NPT_XmlParser::NPT_XmlParser(bool keep_whitespace /* = false */) :
+    m_Tree(NULL),
+    m_CurrentElement(NULL),
+    m_KeepWhitespace(keep_whitespace)
+{
+    m_Processor = new NPT_XmlProcessor(this);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::~NPT_XmlParser
++---------------------------------------------------------------------*/
+NPT_XmlParser::~NPT_XmlParser()
+{
+    delete m_Processor;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(NPT_InputStream& stream, 
+                     NPT_Size&        size,
+                     NPT_XmlNode*&    node,
+                     bool             incremental /* = false */)
+{       
+    NPT_Result result;
+
+    // reset the tree unless we're in incremental mode
+    if (!incremental) m_Tree = NULL;
+
+    // provide a default return node in case of error
+    node = m_Tree;
+
+    // use a  buffer on the stack
+    char buffer[256];
+
+    // read a buffer and parse it until the end of the stream
+    NPT_Size max_bytes_to_read = size;
+    size = 0;
+    do {
+        NPT_Size bytes_read;
+        NPT_Size bytes_to_read = sizeof(buffer);
+        if (max_bytes_to_read != 0 && 
+            size+bytes_to_read > max_bytes_to_read) {
+            bytes_to_read = max_bytes_to_read-size;
+        }
+        result = stream.Read(buffer, sizeof(buffer), &bytes_read);
+        if (NPT_SUCCEEDED(result)) {
+            // update the counter
+            size += bytes_read;
+
+            // parse the buffer
+            NPT_CHECK(m_Processor->ProcessBuffer(buffer, bytes_read));
+        } else {
+            if (result == NPT_ERROR_WOULD_BLOCK && incremental) break;
+            if (result != NPT_ERROR_EOS) return result;
+        }
+    } while(NPT_SUCCEEDED(result) && 
+            (max_bytes_to_read == 0 || size < max_bytes_to_read));
+
+    // return a tree if we have one 
+    node = m_Tree;
+
+    if (incremental) {
+        return result;
+    } else {
+        return m_Tree?NPT_SUCCESS:NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(NPT_InputStream& stream, 
+                     NPT_XmlNode*&    node,
+                     bool             incremental /* = false */)
+{
+    NPT_Size max_read = 0; // no limit
+    return Parse(stream, max_read, node, incremental);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(const char*   xml, 
+                     NPT_XmlNode*& node, 
+                     bool          incremental /* = false */)
+{       
+    NPT_Size size = NPT_StringLength(xml);
+
+    return Parse(xml, size, node, incremental);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::Parse
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::Parse(const char*   xml, 
+                     NPT_Size      size, 
+                     NPT_XmlNode*& node,
+                     bool          incremental /* = false */)
+{ 
+    // reset the tree unless we're in incremental mode
+    if (!incremental) m_Tree = NULL;
+
+    // provide a default return node in case of error
+    node = m_Tree;
+
+    // parse the buffer
+    NPT_CHECK(m_Processor->ProcessBuffer(xml, size));
+
+    // return a tree if we have one 
+    node = m_Tree;
+
+    if (incremental) {
+        return NPT_SUCCESS;
+    } else {
+        return m_Tree?NPT_SUCCESS:NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::OnStartElement
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlParser::OnStartElement(const char* name)
+{
+    NPT_XML_Debug_1("\nNPT_XmlParser::OnStartElement: %s\n", name);
+
+    // create new node
+    NPT_XmlElementNode* node = new NPT_XmlElementNode(name);
+
+    // add node to tree
+    if (m_CurrentElement) {
+        // add the new node
+        m_CurrentElement->AddChild(node);
+    }
+    m_CurrentElement = node;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::OnElementAttribute
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlParser::OnElementAttribute(const char* name, const char* value)
+{
+    NPT_XML_Debug_2("\nNPT_XmlParser::OnElementAttribute: name=%s, value='%s'\n", 
+                    name, value);
+
+    if (m_CurrentElement == NULL) {
+        return NPT_ERROR_INVALID_SYNTAX;
+    }
+                              
+    // check if this is a namespace attribute
+    if (name[0] == 'x' && 
+        name[1] == 'm' && 
+        name[2] == 'l' && 
+        name[3] == 'n' &&
+        name[4] == 's' &&
+        (name[5] == '\0' || name[5] == ':')) {
+        // namespace definition
+        m_CurrentElement->SetNamespaceUri((name[5] == ':')?name+6:"", value);
+    } else {
+        m_CurrentElement->AddAttribute(name, value);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::OnEndElement
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlParser::OnEndElement(const char* name)
+{
+    NPT_XML_Debug_1("\nNPT_XmlParser::OnEndElement: %s\n", name ? name : "NULL");
+
+    if (m_CurrentElement == NULL) return NPT_ERROR_XML_TAG_MISMATCH;
+
+    // check that the name matches (if there is a name)
+    if (name) {
+        const char*  prefix = name;
+        unsigned int prefix_length = 0;
+        const char*  tag    = name;
+        const char*  cursor = name;
+        while (char c = *cursor++) {
+            if (c == ':') {
+                prefix_length = (unsigned int)(cursor-name)-1;
+                tag = cursor;
+            }
+        }
+        // check that the name and prefix length match
+        if (m_CurrentElement->GetTag() != tag ||
+            m_CurrentElement->GetPrefix().GetLength() != prefix_length) {
+            return NPT_ERROR_XML_TAG_MISMATCH;
+        }
+
+        // check the prefix
+        const char* current_prefix = m_CurrentElement->GetPrefix().GetChars();
+        for (unsigned int i=0; i<prefix_length; i++) {
+            if (current_prefix[i] != prefix[i]) {
+                return NPT_ERROR_XML_TAG_MISMATCH;
+            }
+        }
+    }
+
+    // pop up the stack
+    NPT_XmlNode* parent = m_CurrentElement->GetParent();
+    if (parent == NULL) {
+        m_Tree = m_CurrentElement;
+    }
+    m_CurrentElement = parent ? parent->AsElementNode() : NULL;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser::OnCharacterData
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlParser::OnCharacterData(const char* data, unsigned long size)
+{ 
+    NPT_XML_Debug_1("\nNPT_XmlParser::OnCharacterData: %s\n", data);
+    
+    // check that we have a current element
+    if (m_CurrentElement == NULL) {
+        // we do not allow non-whitespace outside an element content
+        if (!NPT_XmlStringIsWhitespace(data, size)) {
+            return NPT_ERROR_XML_INVALID_NESTING;
+        }
+
+        // ignore whitespace
+        return NPT_SUCCESS;
+    }
+
+    // ignore whitespace if applicable
+    if (m_KeepWhitespace || !NPT_XmlStringIsWhitespace(data, size)) {
+        // add the text to the current element
+        m_CurrentElement->AddText(data);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAttributeWriter
++---------------------------------------------------------------------*/
+class NPT_XmlAttributeWriter
+{
+public:
+    NPT_XmlAttributeWriter(NPT_XmlSerializer& serializer) : m_Serializer(serializer) {}
+    void operator()(NPT_XmlAttribute*& attribute) const {
+        m_Serializer.Attribute(attribute->GetPrefix(),
+                               attribute->GetName(),
+                               attribute->GetValue());
+    }
+
+private:
+    // members
+    NPT_XmlSerializer& m_Serializer;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeWriter
++---------------------------------------------------------------------*/
+class NPT_XmlNodeWriter
+{
+public:
+    NPT_XmlNodeWriter(NPT_XmlSerializer& serializer) : 
+        m_Serializer(serializer), m_AttributeWriter(serializer) {
+        m_Serializer.StartDocument();
+    }
+    void operator()(NPT_XmlNode*& node) const {
+        if (NPT_XmlElementNode* element = node->AsElementNode()) {
+            const NPT_String& prefix = element->GetPrefix();
+            const NPT_String& tag    = element->GetTag();
+            m_Serializer.StartElement(prefix, tag);
+            element->GetAttributes().Apply(m_AttributeWriter);
+
+            // emit namespace attributes
+            if (element->m_NamespaceMap) {
+                NPT_List<NPT_XmlNamespaceMap::Entry*>::Iterator item = 
+                    element->m_NamespaceMap->m_Entries.GetFirstItem();
+                while (item) {
+                    if ((*item)->m_Prefix.IsEmpty()) {
+                        // default namespace
+                        m_Serializer.Attribute(NULL, "xmlns", (*item)->m_Uri);
+                    } else {
+                        // namespace with prefix
+                        m_Serializer.Attribute("xmlns", (*item)->m_Prefix, (*item)->m_Uri);
+                    }
+                    ++item;
+                }
+            }
+
+            element->GetChildren().Apply(*this);
+            m_Serializer.EndElement(prefix, tag);
+        } else if (NPT_XmlTextNode* text = node->AsTextNode()) {
+            m_Serializer.Text(text->GetString());
+        }
+    }
+
+private:
+    // members
+    NPT_XmlSerializer&     m_Serializer;
+    NPT_XmlAttributeWriter m_AttributeWriter;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter
++---------------------------------------------------------------------*/
+class NPT_XmlNodeCanonicalWriter
+{
+public:
+    // types
+    struct MapChainLink {
+        MapChainLink(MapChainLink* parent) : m_Parent(parent) {}
+        MapChainLink*                   m_Parent;
+        NPT_Map<NPT_String, NPT_String> m_RenderedNamespaces;
+    };
+
+    // constructor
+    NPT_XmlNodeCanonicalWriter(NPT_XmlSerializer& serializer, 
+                               MapChainLink*      map_chain = NULL) : 
+        m_MapChain(map_chain),
+        m_Serializer(serializer) {
+        m_Serializer.StartDocument();
+    }
+    void operator()(NPT_XmlNode*& node) const;
+
+private:
+    // types
+    struct SortedAttributeList {
+        // types
+        struct Entry {
+            const NPT_String*       m_NamespaceUri;
+            const NPT_XmlAttribute* m_Attribute;
+        };
+
+        // methods
+        void Add(const NPT_String* namespace_uri, 
+                 const NPT_XmlAttribute* attribute);
+        void Emit(NPT_XmlSerializer& serializer);
+
+        // members
+        NPT_List<Entry> m_Entries;
+    };
+
+    struct SortedNamespaceList {
+        // types
+        struct Entry {
+            const NPT_String* m_NamespacePrefix;
+            const NPT_String* m_NamespaceUri;
+        };
+
+        // methods
+        void Add(const NPT_String* prefix, const NPT_String* uri);
+        void Emit(NPT_XmlSerializer& serializer);
+
+        // members
+        NPT_List<Entry> m_Entries;
+    };
+
+    // methods
+    const NPT_String* GetNamespaceRenderedForPrefix(const NPT_String& prefix) const;
+
+    // members
+    MapChainLink*      m_MapChain;
+    NPT_XmlSerializer& m_Serializer;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter::SortedAttributeList::Add
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedAttributeList::Add(
+    const NPT_String*       namespace_uri,
+    const NPT_XmlAttribute* attribute)
+{
+    // transform empty strings into NULL pointers
+    if (namespace_uri && namespace_uri->IsEmpty()) namespace_uri = NULL;
+
+    // find the namespace insertion position
+    NPT_List<Entry>::Iterator entry = m_Entries.GetFirstItem();
+    for (; entry; ++entry) {
+        // decide if we insert now or move on
+        const NPT_String* other_namespace_uri = entry->m_NamespaceUri;
+        if (namespace_uri &&
+            (other_namespace_uri == NULL || *namespace_uri > *other_namespace_uri)) {
+            // this namespace uri is greater than the other, skip
+            continue;
+        } else if ((namespace_uri == NULL && other_namespace_uri == NULL) ||
+                   (namespace_uri && other_namespace_uri && 
+                   *namespace_uri == *other_namespace_uri)) {
+            // namespace uris match, compare the names
+            const NPT_XmlAttribute* other_attribute = entry->m_Attribute;
+            if (attribute->GetName() > other_attribute->GetName()) continue;
+        }
+        break;
+    }
+    
+    Entry new_entry = {namespace_uri, attribute};
+    m_Entries.Insert(entry, new_entry);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter::SortedAttributeList::Emit
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedAttributeList::Emit(NPT_XmlSerializer& serializer)
+{
+    for (NPT_List<Entry>::Iterator i = m_Entries.GetFirstItem(); i; ++i) {
+        serializer.Attribute(i->m_Attribute->GetPrefix(),
+                             i->m_Attribute->GetName(),
+                             i->m_Attribute->GetValue());
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Add
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Add(const NPT_String* prefix,
+                                                     const NPT_String* uri)
+{
+    // find the namespace insertion position
+    NPT_List<Entry>::Iterator entry = m_Entries.GetFirstItem();
+    if (prefix && !prefix->IsEmpty()) {
+        for (; entry; ++entry) {
+            // decide if we insert now or move on
+            if (entry->m_NamespacePrefix && *prefix <= *entry->m_NamespacePrefix) {
+                break;
+            }
+        }
+    } else {
+        prefix = NULL;
+    }
+
+    Entry new_entry = {prefix, uri};
+    m_Entries.Insert(entry, new_entry);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Emit
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::SortedNamespaceList::Emit(NPT_XmlSerializer& serializer)
+{
+    for (NPT_List<Entry>::Iterator i = m_Entries.GetFirstItem(); i; ++i) {
+        const NPT_String* key   = i->m_NamespacePrefix;
+        const NPT_String* value = i->m_NamespaceUri;
+        if (key == NULL) {
+            serializer.Attribute(NULL, "xmlns", *value);
+        } else if (*key != "xml" || *value != NPT_XmlNamespaceUri_Xml) {
+            serializer.Attribute("xmlns", *key, *value);
+        }
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter::GetNamespaceRenderedForPrefix
++---------------------------------------------------------------------*/
+const NPT_String*
+NPT_XmlNodeCanonicalWriter::GetNamespaceRenderedForPrefix(const NPT_String& prefix) const
+{
+    for (MapChainLink* link = m_MapChain;
+         link;
+         link = link->m_Parent) {
+        NPT_String* uri;
+        if (NPT_SUCCEEDED(link->m_RenderedNamespaces.Get(prefix, uri))) {
+            return uri;
+        }
+    }
+
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNodeCanonicalWriter::operator()
++---------------------------------------------------------------------*/
+void
+NPT_XmlNodeCanonicalWriter::operator()(NPT_XmlNode*& node) const
+{
+    MapChainLink map_link(m_MapChain);
+
+    if (NPT_XmlElementNode* element = node->AsElementNode()) {
+        const NPT_String& prefix = element->GetPrefix();
+        const NPT_String& tag    = element->GetTag();
+
+        // process namespaces
+        const NPT_String* namespace_uri = element->GetNamespace();
+        const NPT_String* rendered = GetNamespaceRenderedForPrefix(prefix);
+        if (namespace_uri && namespace_uri->IsEmpty()) namespace_uri = NULL;
+        if (prefix.IsEmpty()) {
+            // default namespace
+            if (rendered == NULL) {
+                // default namespace not rendered
+                if (namespace_uri) {
+                    map_link.m_RenderedNamespaces.Put("", *namespace_uri);
+                }
+            } else {
+                // default namespace already rendered
+                const char* compare;
+                if (namespace_uri) {
+                    compare = namespace_uri->GetChars();
+                } else {
+                    compare = "";
+                }
+                if (*rendered != compare) {
+                    // the rendered default namespace had a different uri
+                    map_link.m_RenderedNamespaces.Put("", compare);
+                } 
+            }
+        } else {
+            // explicit namespace
+            // NOTE: namespace_uri should not be an empty string, but we test just
+            // in case the XML document is not compliant
+            if (namespace_uri && (rendered == NULL || *rendered != *namespace_uri)) {
+                // namespace prefix not rendered or rendered with a different value
+                map_link.m_RenderedNamespaces.Put(prefix, *namespace_uri);
+            }
+        }
+
+        // process attributes
+        SortedAttributeList prefixed_attributes;
+        SortedAttributeList naked_attributes;
+        for (NPT_List<NPT_XmlAttribute*>::Iterator attribute = element->GetAttributes().GetFirstItem();
+             attribute;
+             ++attribute) {
+             const NPT_String& a_prefix = (*attribute)->GetPrefix();
+             if (a_prefix.IsEmpty()) {
+                 // naked attribute
+                 naked_attributes.Add(NULL, *attribute);
+             } else {
+                // decide if we need to render this namespace declaration
+                namespace_uri = element->GetNamespaceUri(a_prefix);
+                if (namespace_uri) {
+                    rendered = GetNamespaceRenderedForPrefix(a_prefix);;
+                    if (rendered == NULL || *rendered != *namespace_uri) {
+                        // namespace not rendered or rendered with a different value
+                        map_link.m_RenderedNamespaces.Put(a_prefix, *namespace_uri);
+                    }
+                    prefixed_attributes.Add(namespace_uri, *attribute);
+                }
+             }
+        }
+
+        // start of element
+        m_Serializer.StartElement(prefix, tag);
+                    
+        // namespace declarations
+        if (map_link.m_RenderedNamespaces.GetEntryCount()) {
+            SortedNamespaceList namespaces;
+            NPT_List<NPT_Map<NPT_String, NPT_String>::Entry*>::Iterator entry = 
+                map_link.m_RenderedNamespaces.GetEntries().GetFirstItem();
+            while (entry) {
+                const NPT_String& key   = (*entry)->GetKey();
+                const NPT_String& value = (*entry)->GetValue();
+                namespaces.Add(&key, &value);
+                ++entry;
+            }
+            namespaces.Emit(m_Serializer);
+        }
+
+        // attributes
+        naked_attributes.Emit(m_Serializer);
+        prefixed_attributes.Emit(m_Serializer);
+
+        // children
+        MapChainLink* chain;
+        if (map_link.m_RenderedNamespaces.GetEntryCount()) {
+            chain = &map_link;
+        } else {
+            chain = m_MapChain;
+        }
+        element->GetChildren().Apply(NPT_XmlNodeCanonicalWriter(m_Serializer, chain));
+
+        // end of element
+        m_Serializer.EndElement(prefix, tag);
+    } else if (NPT_XmlTextNode* text = node->AsTextNode()) {
+        m_Serializer.Text(text->GetString());
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::NPT_XmlSerializer
++---------------------------------------------------------------------*/
+NPT_XmlSerializer::NPT_XmlSerializer(NPT_OutputStream* output,
+                                     NPT_Cardinal      indentation,
+                                     bool              shrink_empty_elements) :
+    m_Output(output),
+    m_ElementPending(false),
+    m_Depth(0),
+    m_Indentation(indentation),
+    m_ElementHasText(false),
+    m_ShrinkEmptyElements(shrink_empty_elements)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::~NPT_XmlSerializer
++---------------------------------------------------------------------*/
+NPT_XmlSerializer::~NPT_XmlSerializer()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::StartDocument
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlSerializer::StartDocument()
+{
+    // this is required for some parsers
+    return m_Output->WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::EndDocument
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_XmlSerializer::EndDocument()
+{
+    return m_ElementPending?NPT_ERROR_INVALID_STATE:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::EscapeChar
++---------------------------------------------------------------------*/
+void  
+NPT_XmlSerializer::EscapeChar(unsigned char c, char* text)
+{
+    *text++ = '&';
+    *text++ = '#';
+    *text++ = 'x';
+    int c0 = c>>4;
+    int c1 = c&0xF;
+    if (c0) {
+        *text++ = c0 >= 10 ? 'A'+(c0-10) : '0'+c0;
+    }
+    *text++ = c1 >= 10 ? 'A'+(c1-10) : '0'+c1;
+    *text++ = ';';
+    *text   = '\0';
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::ProcessPending
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::ProcessPending()
+{
+    if (!m_ElementPending) return NPT_SUCCESS;
+    m_ElementPending = false;
+    return m_Output->Write(">", 1);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::OutputEscapedString
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::OutputEscapedString(const char* text, bool attribute)
+{
+    const char* start = text;
+    char escaped[7];
+    while (char c = *text) {
+        const char* insert = NULL;
+        switch (c) {
+            case '\r': {
+                EscapeChar(c, escaped);
+                insert = escaped;
+                break;
+            }
+            case '\n':
+            case '\t':
+                if (attribute) {
+                    EscapeChar(c, escaped);
+                    insert = escaped;
+                }
+                break;
+
+            case '&' : insert = "&amp;"; break;
+            case '<' : insert = "&lt;";  break;
+            case '>' : if (!attribute) insert = "&gt;";  break;
+            case '"' : if (attribute) insert = "&quot;"; break;
+            default : 
+                break;
+        }
+        if (insert) {
+            // output pending chars
+            if (start != text) m_Output->Write(start, (NPT_Size)(text-start));
+            m_Output->WriteString(insert);
+            start = ++text;
+        } else {
+            ++text;
+        }
+    }
+    if (start != text) {
+        m_Output->Write(start, (NPT_Size)(text-start));
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::OutputIndentation
++---------------------------------------------------------------------*/
+void
+NPT_XmlSerializer::OutputIndentation(bool start)
+{
+    if (m_Depth || !start) m_Output->Write("\n", 1);
+
+    // ensure we have enough chars in the prefix string
+    unsigned int prefix_length = m_Indentation*m_Depth;
+    if (m_IndentationPrefix.GetLength() < prefix_length) {
+        unsigned int needed = prefix_length-m_IndentationPrefix.GetLength();
+        for (unsigned int i=0; i<needed; i+=16) {
+            m_IndentationPrefix.Append("                ", 16);
+        }
+    }
+
+    // print the indentation prefix
+    m_Output->Write(m_IndentationPrefix.GetChars(), prefix_length);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::StartElement
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::StartElement(const char* prefix, const char* name)
+{
+    ProcessPending();
+    if (m_Indentation) OutputIndentation(true);
+    m_ElementPending = true;
+    m_ElementHasText = false;
+    m_Depth++;
+    m_Output->Write("<", 1);
+    if (prefix && prefix[0]) {
+        m_Output->WriteString(prefix);
+        m_Output->Write(":", 1);
+    }
+    return m_Output->WriteString(name);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::EndElement
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::EndElement(const char* prefix, const char* name)
+{
+    m_Depth--;
+
+    if (m_ElementPending) {
+        // this element has no children
+        m_ElementPending = false;
+        if (m_ShrinkEmptyElements) {
+            return m_Output->Write("/>", 2);
+        } else {
+            m_Output->Write(">",1);
+        }
+    } 
+
+    if (m_Indentation && !m_ElementHasText) OutputIndentation(false);
+    m_ElementHasText = false;
+    m_Output->Write("</", 2);
+    if (prefix && prefix[0]) {
+        m_Output->WriteString(prefix);
+        m_Output->Write(":", 1);
+    }
+    m_Output->WriteString(name);
+    return m_Output->Write(">", 1);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::Attribute
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::Attribute(const char* prefix, const char* name, const char* value)
+{
+    m_Output->Write(" ", 1);
+    if (prefix && prefix[0]) {
+        m_Output->WriteString(prefix);
+        m_Output->Write(":", 1);
+    }
+    m_Output->WriteString(name);
+    m_Output->Write("=\"", 2);
+    OutputEscapedString(value, true);
+    return m_Output->Write("\"", 1);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::Text
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::Text(const char* text)
+{
+    ProcessPending();
+    m_ElementHasText = true;
+    return OutputEscapedString(text, false);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::CdataSection
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::CdataSection(const char* data)
+{
+    ProcessPending();
+    m_ElementHasText = true;
+    m_Output->Write("<![CDATA[", 9);
+    m_Output->WriteString(data);
+    return m_Output->Write("]]>", 3);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer::Comment
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_XmlSerializer::Comment(const char* comment)
+{
+    ProcessPending();
+    m_Output->Write("<!--", 4);
+    m_Output->WriteString(comment);
+    return m_Output->Write("-->", 3);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlWriter::Serialize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlWriter::Serialize(NPT_XmlNode& node, NPT_OutputStream& output)
+{
+    NPT_XmlSerializer serializer(&output, m_Indentation);
+    NPT_XmlNodeWriter node_writer(serializer);
+    NPT_XmlNode* node_pointer = &node;
+    node_writer(node_pointer);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_XmlCanonicalizer::Serialize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XmlCanonicalizer::Serialize(NPT_XmlNode& node, NPT_OutputStream& output)
+{
+    // create a serializer with no indentation and no shrinking of empty elements
+    NPT_XmlSerializer serializer(&output, 0, false);
+
+    // serialize the node
+    NPT_XmlNodeCanonicalWriter node_writer(serializer);
+    NPT_XmlNode* node_pointer = &node;
+    node_writer(node_pointer);
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptXml.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,379 @@
+/*****************************************************************
+|
+|   Neptune - Xml Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_XML_H_
+#define _NPT_XML_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptList.h"
+#include "NptStrings.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_ERROR_XML_INVALID_NESTING = NPT_ERROR_BASE_XML - 0;
+const int NPT_ERROR_XML_TAG_MISMATCH    = NPT_ERROR_BASE_XML - 1;
+
+#define NPT_XML_ANY_NAMESPACE "*"
+#define NPT_XML_NO_NAMESPACE  NULL
+
+/*----------------------------------------------------------------------
+|   forward declarations
++---------------------------------------------------------------------*/
+class NPT_XmlProcessor;
+
+/*----------------------------------------------------------------------
+|   NPT_XmlAttribute
++---------------------------------------------------------------------*/
+class NPT_XmlAttribute
+{
+ public:
+    // methods
+    NPT_XmlAttribute(const char* name, const char* value);
+    NPT_XmlAttribute(const char* prefix, const char* name, const char* value) :
+        m_Prefix(prefix), m_Name(name), m_Value(value) {}
+    const NPT_String& GetPrefix() const { return m_Prefix; }
+    const NPT_String& GetName()   const { return m_Name;   }
+    const NPT_String& GetValue()  const { return m_Value;  }
+    void              SetValue(const char* value) { m_Value = value; }
+
+ private:
+    // members
+    NPT_String m_Prefix;
+    NPT_String m_Name;
+    NPT_String m_Value;
+
+    NPT_XmlAttribute(const NPT_XmlAttribute& attribute) :
+        m_Prefix(attribute.m_Prefix), 
+        m_Name(attribute.m_Name), 
+        m_Value(attribute.m_Value) {}
+    NPT_XmlAttribute& operator=(const NPT_XmlAttribute& a);
+
+    // friends
+    friend class NPT_XmlAttributeFinder;
+    friend class NPT_XmlAttributeFinderWithPrefix;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNamespaceMap
++---------------------------------------------------------------------*/
+class NPT_XmlNamespaceMap
+{
+public:
+    // destructor
+    ~NPT_XmlNamespaceMap();
+
+    // methods   
+    NPT_Result        SetNamespaceUri(const char* prefix, const char* uri);
+    const NPT_String* GetNamespaceUri(const char* prefix);
+    const NPT_String* GetNamespacePrefix(const char* uri);
+
+private:
+    // types
+    class Entry {
+    public:
+        // constructor
+        Entry(const char* prefix, const char* uri) : 
+            m_Prefix(prefix), m_Uri(uri) {}
+
+        // members
+        NPT_String m_Prefix;
+        NPT_String m_Uri;
+    };
+
+    // members
+    NPT_List<Entry*> m_Entries;
+
+    // friends
+    friend class NPT_XmlWriter;
+    friend class NPT_XmlNodeWriter;
+    friend class NPT_XmlNodeCanonicalWriter;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlNode
++---------------------------------------------------------------------*/
+class NPT_XmlElementNode;
+class NPT_XmlTextNode;
+class NPT_XmlNode
+{
+ public:
+    // types
+    typedef enum {
+        DOCUMENT,
+        ELEMENT,
+        TEXT
+    } Type;
+
+    // methods
+    NPT_XmlNode(Type type) : m_Type(type), m_Parent(NULL) {}
+    virtual     ~NPT_XmlNode() {}
+    Type         GetType() const { return m_Type; }
+    NPT_XmlNode* GetParent() const { return m_Parent; }
+
+    // type casting
+    virtual NPT_XmlElementNode*       AsElementNode()       { return NULL; }
+    virtual const NPT_XmlElementNode* AsElementNode() const { return NULL; }
+    virtual NPT_XmlTextNode*          AsTextNode()          { return NULL; }
+    virtual const NPT_XmlTextNode*    AsTextNode() const    { return NULL; }
+
+ protected:
+    // methods
+    virtual void SetParent(NPT_XmlNode* parent) { m_Parent = parent; }
+
+    // members  
+    Type         m_Type;
+    NPT_XmlNode* m_Parent;
+
+    // friends
+    friend class NPT_XmlNodeFinder;
+    friend class NPT_XmlSerializer;
+    friend class NPT_XmlWriter;
+    friend class NPT_XmlElementNode; // to allow access to SetParent()
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlElementNode
++---------------------------------------------------------------------*/
+class NPT_XmlElementNode : public NPT_XmlNode
+{
+ public:
+    // methods
+                            NPT_XmlElementNode(const char* tag);
+                            NPT_XmlElementNode(const char* prefix, const char* tag);
+    virtual                ~NPT_XmlElementNode();
+    NPT_List<NPT_XmlNode*>& GetChildren() { return m_Children; }
+    const NPT_List<NPT_XmlNode*>& 
+                            GetChildren() const { return m_Children; }
+    NPT_XmlElementNode*     GetChild(const char* tag, 
+                                     const char* namespc = NPT_XML_NO_NAMESPACE,
+                                     NPT_Ordinal n=0) const;
+    NPT_Result              AddChild(NPT_XmlNode* child);
+    NPT_Result              SetAttribute(const char* prefix,
+                                         const char* name, 
+                                         const char* value);
+    NPT_Result              SetAttribute(const char* name, 
+                                         const char* value);
+    NPT_Result              AddText(const char* text); 
+    NPT_List<NPT_XmlAttribute*>& 
+                            GetAttributes() { return m_Attributes; }
+    const NPT_List<NPT_XmlAttribute*>&
+                            GetAttributes() const { return m_Attributes; }
+    const NPT_String*       GetAttribute(const char* name,
+                                         const char* namespc = NPT_XML_NO_NAMESPACE) const;
+    const NPT_String&       GetPrefix() const { return m_Prefix; }
+    const NPT_String&       GetTag()    const { return m_Tag;    }
+    const NPT_String*       GetText(NPT_Ordinal n=0) const;
+
+    // bring all the namespace definitions used in this element of one of its descendants
+    // into the namespace map of this element so that it may be serialized as a
+    // standalone element without any prefixes with undefined namespace uris
+    NPT_Result              MakeStandalone();
+
+    // namespace methods   
+    const NPT_String* GetNamespace() const;
+    NPT_Result        SetNamespaceUri(const char* prefix, const char* uri);
+    const NPT_String* GetNamespaceUri(const char* prefix) const;
+    const NPT_String* GetNamespacePrefix(const char* uri) const;
+
+    // type casting
+    NPT_XmlElementNode*       AsElementNode()       { return this; }
+    const NPT_XmlElementNode* AsElementNode() const { return this; }
+
+protected:
+    // methods
+    void SetParent(NPT_XmlNode* parent);
+    void SetNamespaceParent(NPT_XmlElementNode* parent);
+    void RelinkNamespaceMaps();
+
+    NPT_Result AddAttribute(const char* name, const char* value);
+
+    // members  
+    NPT_String                  m_Prefix;
+    NPT_String                  m_Tag;
+    NPT_List<NPT_XmlNode*>      m_Children;
+    NPT_List<NPT_XmlAttribute*> m_Attributes;
+    NPT_XmlNamespaceMap*        m_NamespaceMap;
+    NPT_XmlElementNode*         m_NamespaceParent;
+
+    // friends
+    friend class NPT_XmlTagFinder;
+    friend class NPT_XmlSerializer;
+    friend class NPT_XmlWriter;
+    friend class NPT_XmlNodeWriter;
+    friend class NPT_XmlNodeCanonicalWriter;
+    friend class NPT_XmlParser;
+    friend class NPT_XmlProcessor;
+    friend class NPT_XmlNamespaceCollapser;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlTextNode
++---------------------------------------------------------------------*/
+class NPT_XmlTextNode : public NPT_XmlNode
+{
+ public:
+    // types
+    typedef enum {
+        CHARACTER_DATA,
+        IGNORABLE_WHITESPACE,
+        CDATA_SECTION,
+        ENTITY_REFERENCE,
+        COMMENT
+    } TokenType;
+
+    // constructor
+    NPT_XmlTextNode(TokenType token_type, const char* text);
+
+    // methods
+    const NPT_String& GetString() const { return m_Text; }
+
+    // type casting
+    NPT_XmlTextNode*       AsTextNode()       { return this; }
+    const NPT_XmlTextNode* AsTextNode() const { return this; }
+
+ private:
+    // members  
+    TokenType  m_TokenType;
+    NPT_String m_Text;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlParser
++---------------------------------------------------------------------*/
+class NPT_XmlParser
+{
+ public:
+    // methods
+             NPT_XmlParser(bool keep_whitespace = true);
+    virtual ~NPT_XmlParser();
+    virtual  NPT_Result Parse(const char*   xml, 
+                              NPT_XmlNode*& tree,
+                              bool          incremental=false);
+    virtual  NPT_Result Parse(const char*   xml, 
+                              NPT_Size      size,
+                              NPT_XmlNode*& tree,
+                              bool          incremental=false);
+    virtual  NPT_Result Parse(NPT_InputStream& stream, 
+                              NPT_XmlNode*&    tree,
+                              bool             incremental=false);
+    virtual  NPT_Result Parse(NPT_InputStream& stream, 
+                              NPT_Size&        size,
+                              NPT_XmlNode*&    tree,
+                              bool             incremental=false);
+    
+ protected:
+    // NPT_XmlHandler methods
+    NPT_Result OnStartElement(const char* name);
+    NPT_Result OnElementAttribute(const char* name, const char* value);
+    NPT_Result OnEndElement(const char* name);
+    NPT_Result OnCharacterData(const char* data, unsigned long size);
+    void       RemoveIgnorableWhitespace();
+
+    // members
+    NPT_XmlProcessor*   m_Processor;
+    NPT_XmlElementNode* m_Tree;
+    NPT_XmlElementNode* m_CurrentElement;
+    bool                m_KeepWhitespace;
+
+    // friends
+    friend class NPT_XmlProcessor;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlSerializer
++---------------------------------------------------------------------*/
+class NPT_XmlSerializer
+{
+public:
+    // methods
+                       NPT_XmlSerializer(NPT_OutputStream* output,
+                                         NPT_Cardinal      indentation = 0,
+                                         bool              shrink_empty_elements = true);
+    virtual           ~NPT_XmlSerializer();
+    virtual NPT_Result StartDocument();
+    virtual NPT_Result EndDocument();
+    virtual NPT_Result StartElement(const char* prefix, const char* name);
+    virtual NPT_Result EndElement(const char* prefix, const char* name);
+    virtual NPT_Result Attribute(const char* prefix, const char* name, const char* value);
+    virtual NPT_Result Text(const char* text);
+    virtual NPT_Result CdataSection(const char* data);
+    virtual NPT_Result Comment(const char* comment);
+
+protected:
+    // methods
+    void       EscapeChar(unsigned char c, char* text);
+    NPT_Result ProcessPending();
+    NPT_Result OutputEscapedString(const char* text, bool attribute);
+    void       OutputIndentation(bool start);
+
+    // members
+    NPT_OutputStream* m_Output;
+    bool              m_ElementPending;
+    NPT_Cardinal      m_Depth;
+    NPT_Cardinal      m_Indentation;
+    NPT_String        m_IndentationPrefix;
+    bool              m_ElementHasText;
+    bool              m_ShrinkEmptyElements;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlWriter
++---------------------------------------------------------------------*/
+class NPT_XmlWriter
+{
+public:
+    // constructor
+    explicit NPT_XmlWriter(NPT_Cardinal indentation = 0) : m_Indentation(indentation) {}
+
+    // methods
+    NPT_Result Serialize(NPT_XmlNode& node, NPT_OutputStream& stream);
+
+private:
+    // members
+    NPT_Cardinal m_Indentation;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_XmlCanonicalizer
++---------------------------------------------------------------------*/
+class NPT_XmlCanonicalizer
+{
+public:
+    // methods
+    NPT_Result Serialize(NPT_XmlNode& node, NPT_OutputStream& stream);
+};
+
+#endif // _NPT_XML_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptZip.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,496 @@
+/*****************************************************************
+|
+|   Neptune - Zip Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#if defined(NPT_CONFIG_ENABLE_ZIP)
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptZip.h"
+#include "NptLogging.h"
+#include "NptUtils.h"
+
+#include "zlib.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.zip")
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const unsigned int NPT_ZIP_DEFAULT_BUFFER_SIZE = 4096;
+
+/*----------------------------------------------------------------------
+|   NPT_Zip::MapError
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Zip::MapError(int err)
+{
+    switch (err) {
+        case Z_OK:            return NPT_SUCCESS;           
+        case Z_STREAM_END:    return NPT_ERROR_EOS;
+        case Z_DATA_ERROR:
+        case Z_STREAM_ERROR:  return NPT_ERROR_INVALID_FORMAT;
+        case Z_MEM_ERROR:     return NPT_ERROR_OUT_OF_MEMORY;
+        case Z_VERSION_ERROR: return NPT_ERROR_INTERNAL;
+        case Z_NEED_DICT:     return NPT_ERROR_NOT_SUPPORTED;
+        default:              return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflateState
++---------------------------------------------------------------------*/
+class NPT_ZipInflateState {
+public:
+    NPT_ZipInflateState();
+   ~NPT_ZipInflateState();
+    z_stream m_Stream;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflateState::NPT_ZipInflateState
++---------------------------------------------------------------------*/
+NPT_ZipInflateState::NPT_ZipInflateState()
+{
+    // initialize the state
+    NPT_SetMemory(&m_Stream, 0, sizeof(m_Stream));
+
+    // initialize the decompressor
+    inflateInit2(&m_Stream, 15+32); // 15 = default window bits, +32 = automatic header
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflateState::~NPT_ZipInflateState
++---------------------------------------------------------------------*/
+NPT_ZipInflateState::~NPT_ZipInflateState()
+{
+    inflateEnd(&m_Stream);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflateState
++---------------------------------------------------------------------*/
+class NPT_ZipDeflateState {
+public:
+    NPT_ZipDeflateState(int             compression_level,
+                        NPT_Zip::Format format);
+   ~NPT_ZipDeflateState();
+    z_stream m_Stream;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflateState::NPT_ZipDeflateState
++---------------------------------------------------------------------*/
+NPT_ZipDeflateState::NPT_ZipDeflateState(int             compression_level,
+                                         NPT_Zip::Format format)
+{
+    // check parameters
+    if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
+        compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
+        compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT;
+    }
+
+    // initialize the state
+    NPT_SetMemory(&m_Stream, 0, sizeof(m_Stream));
+
+    // initialize the compressor
+    deflateInit2(&m_Stream, 
+                compression_level,
+                Z_DEFLATED,
+                15 + (format == NPT_Zip::GZIP ? 16 : 0),
+                8,
+                Z_DEFAULT_STRATEGY);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflateState::~NPT_ZipDeflateState
++---------------------------------------------------------------------*/
+NPT_ZipDeflateState::~NPT_ZipDeflateState()
+{
+    deflateEnd(&m_Stream);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::NPT_ZipInflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipInflatingInputStream::NPT_ZipInflatingInputStream(NPT_InputStreamReference& source) :
+    m_Source(source),
+    m_Position(0),
+    m_State(new NPT_ZipInflateState()),
+    m_Buffer(NPT_ZIP_DEFAULT_BUFFER_SIZE)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::~NPT_ZipInflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipInflatingInputStream::~NPT_ZipInflatingInputStream()
+{
+    delete m_State;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipInflatingInputStream::Read(void*     buffer, 
+                                  NPT_Size  bytes_to_read, 
+                                  NPT_Size* bytes_read)
+{
+    // check state and parameters
+    if (m_State == NULL) return NPT_ERROR_INVALID_STATE;
+    if (buffer == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    if (bytes_to_read == 0) return NPT_SUCCESS;
+    
+    // default values
+    if (bytes_read) *bytes_read = 0;
+    
+    // setup the output buffer
+    m_State->m_Stream.next_out  = (Bytef*)buffer;
+    m_State->m_Stream.avail_out = (uInt)bytes_to_read;
+    
+    while (m_State->m_Stream.avail_out) {
+        // decompress what we can
+        int err = inflate(&m_State->m_Stream, Z_NO_FLUSH);
+        
+        if (err == Z_STREAM_END) {
+            // we decompressed everything
+            break;
+        } else if (err == Z_OK) {
+            // we got something
+            continue;
+        } else if (err == Z_BUF_ERROR) {
+            // we need more input data
+            NPT_Size   input_bytes_read = 0;
+            NPT_Result result = m_Source->Read(m_Buffer.UseData(), m_Buffer.GetBufferSize(), &input_bytes_read);
+            if (NPT_FAILED(result)) return result;
+
+            // setup the input buffer
+            m_Buffer.SetDataSize(input_bytes_read);
+            m_State->m_Stream.next_in = m_Buffer.UseData();
+            m_State->m_Stream.avail_in = m_Buffer.GetDataSize();
+        
+        } else {
+            return NPT_Zip::MapError(err);
+        }
+    }
+    
+    // report how much we could decompress
+    NPT_Size progress = bytes_to_read - m_State->m_Stream.avail_out;
+    if (bytes_read) {
+        *bytes_read = progress;
+    }
+    m_Position += progress;
+    
+    return progress == 0 ? NPT_ERROR_EOS:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipInflatingInputStream::Seek(NPT_Position /* offset */)
+{
+    // we can't seek
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipInflatingInputStream::Tell(NPT_Position& offset)
+{
+    offset = m_Position;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipInflatingInputStream::GetSize(NPT_LargeSize& size)
+{
+    // the size is not predictable
+    size = 0;
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipInflatingInputStream::GetAvailable(NPT_LargeSize& available)
+{
+    // we don't know
+    available = 0;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipDeflatingInputStream::NPT_ZipDeflatingInputStream(
+    NPT_InputStreamReference& source,
+    int                       compression_level,
+    NPT_Zip::Format           format) :
+    m_Source(source),
+    m_Position(0),
+    m_Eos(false),
+    m_State(new NPT_ZipDeflateState(compression_level, format)),
+    m_Buffer(NPT_ZIP_DEFAULT_BUFFER_SIZE)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::~NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+NPT_ZipDeflatingInputStream::~NPT_ZipDeflatingInputStream()
+{
+    delete m_State;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipDeflatingInputStream::Read(void*     buffer, 
+                                  NPT_Size  bytes_to_read, 
+                                  NPT_Size* bytes_read)
+{
+    // check state and parameters
+    if (m_State == NULL) return NPT_ERROR_INVALID_STATE;
+    if (buffer == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    if (bytes_to_read == 0) return NPT_SUCCESS;
+    
+    // default values
+    if (bytes_read) *bytes_read = 0;
+    
+    // setup the output buffer
+    m_State->m_Stream.next_out  = (Bytef*)buffer;
+    m_State->m_Stream.avail_out = (uInt)bytes_to_read;
+    
+    while (m_State->m_Stream.avail_out) {
+        // compress what we can
+        int err = deflate(&m_State->m_Stream, m_Eos?Z_FINISH:Z_NO_FLUSH);
+        
+        if (err == Z_STREAM_END) {
+            // we compressed everything
+            break;
+        } else if (err == Z_OK) {
+            // we got something
+            continue;
+        } else if (err == Z_BUF_ERROR) {
+            // we need more input data
+            NPT_Size   input_bytes_read = 0;
+            NPT_Result result = m_Source->Read(m_Buffer.UseData(), m_Buffer.GetBufferSize(), &input_bytes_read);
+            if (result == NPT_ERROR_EOS) {
+                m_Eos = true;
+            } else {
+                if (NPT_FAILED(result)) return result;
+            }
+            
+            // setup the input buffer
+            m_Buffer.SetDataSize(input_bytes_read);
+            m_State->m_Stream.next_in = m_Buffer.UseData();
+            m_State->m_Stream.avail_in = m_Buffer.GetDataSize();
+        
+        } else {
+            return NPT_Zip::MapError(err);
+        }
+    }
+    
+    // report how much we could compress
+    NPT_Size progress = bytes_to_read - m_State->m_Stream.avail_out;
+    if (bytes_read) {
+        *bytes_read = progress;
+    }
+    m_Position += progress;
+    
+    return progress == 0 ? NPT_ERROR_EOS:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipDeflatingInputStream::Seek(NPT_Position /* offset */)
+{
+    // we can't seek
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipDeflatingInputStream::Tell(NPT_Position& offset)
+{
+    offset = m_Position;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipDeflatingInputStream::GetSize(NPT_LargeSize& size)
+{
+    // the size is not predictable
+    size = 0;
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_ZipDeflatingInputStream::GetAvailable(NPT_LargeSize& available)
+{
+    // we don't know
+    available = 0;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Zip::Deflate
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Zip::Deflate(const NPT_DataBuffer& in,
+                 NPT_DataBuffer&       out,
+                 int                   compression_level,
+                 Format                format /* = ZLIB */)
+{
+    // default return state
+    out.SetDataSize(0);
+    
+    // check parameters
+    if (compression_level < NPT_ZIP_COMPRESSION_LEVEL_DEFAULT ||
+        compression_level > NPT_ZIP_COMPRESSION_LEVEL_MAX) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+                
+    // setup the stream
+    z_stream stream;
+    NPT_SetMemory(&stream, 0, sizeof(stream));
+    stream.next_in   = (Bytef*)in.GetData();
+    stream.avail_in  = (uInt)in.GetDataSize();
+    
+    // setup the memory functions
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    // initialize the compressor
+    int err = deflateInit2(&stream, 
+                           compression_level,
+                           Z_DEFLATED,
+                           15 + (format == GZIP ? 16 : 0),
+                           8,
+                           Z_DEFAULT_STRATEGY);
+    if (err != Z_OK) return MapError(err);
+
+    // reserve an output buffer known to be large enough
+    out.Reserve(deflateBound(&stream, stream.avail_in) + (format==GZIP?10:0));
+    stream.next_out  = out.UseData();
+    stream.avail_out = out.GetBufferSize();
+
+    // decompress
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return MapError(err);
+    }
+    
+    // update the output size
+    out.SetDataSize(stream.total_out);
+
+    // cleanup
+    err = deflateEnd(&stream);
+    return MapError(err);
+}
+                              
+/*----------------------------------------------------------------------
+|   NPT_Zip::Inflate
++---------------------------------------------------------------------*/                              
+NPT_Result 
+NPT_Zip::Inflate(const NPT_DataBuffer& in,
+                 NPT_DataBuffer&       out)
+{
+    // assume an output buffer twice the size of the input plus a bit
+    NPT_CHECK_WARNING(out.Reserve(32+2*in.GetDataSize()));
+    
+    // setup the stream
+    z_stream stream;
+    stream.next_in   = (Bytef*)in.GetData();
+    stream.avail_in  = (uInt)in.GetDataSize();
+    stream.next_out  = out.UseData();
+    stream.avail_out = (uInt)out.GetBufferSize();
+
+    // setup the memory functions
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    // initialize the decompressor
+    int err = inflateInit2(&stream, 15+32); // 15 = default window bits, +32 = automatic header
+    if (err != Z_OK) return MapError(err);
+    
+    // decompress until the end
+    do {
+        err = inflate(&stream, Z_SYNC_FLUSH);
+        if (err == Z_STREAM_END || err == Z_OK || err == Z_BUF_ERROR) {
+            out.SetDataSize(stream.total_out);
+            if ((err == Z_OK && stream.avail_out == 0) || err == Z_BUF_ERROR) {
+                // grow the output buffer
+                out.Reserve(out.GetBufferSize()*2);
+                stream.next_out = out.UseData()+stream.total_out;
+                stream.avail_out = out.GetBufferSize()-stream.total_out;
+            }
+        }
+    } while (err == Z_OK);
+    
+    // check for errors
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        return MapError(err);
+    }
+    
+    // cleanup
+    err = inflateEnd(&stream);
+    return MapError(err);
+}
+
+#endif // NPT_CONFIG_ENABLE_ZIP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptZip.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,144 @@
+/*****************************************************************
+|
+|   Neptune - Zip Support
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _NPT_ZIP_H_
+#define _NPT_ZIP_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptStreams.h"
+
+/*----------------------------------------------------------------------
+|   class references
++---------------------------------------------------------------------*/
+class NPT_ZipInflateState;
+class NPT_ZipDeflateState;
+
+/*----------------------------------------------------------------------
+|   NPT_Zip
++---------------------------------------------------------------------*/
+const int NPT_ZIP_COMPRESSION_LEVEL_DEFAULT = -1;
+const int NPT_ZIP_COMPRESSION_LEVEL_MIN     = 0;
+const int NPT_ZIP_COMPRESSION_LEVEL_MAX     = 9;
+const int NPT_ZIP_COMPRESSION_LEVEL_NONE    = 0;
+class NPT_Zip 
+{
+public:
+    // class methods
+    static NPT_Result MapError(int err);
+
+    /** 
+     * Compressed data format
+     */
+    typedef enum {
+        ZLIB,
+        GZIP
+    } Format;
+        
+    /**
+     * Deflate (i.e compress) a buffer
+     */
+    static NPT_Result Deflate(const NPT_DataBuffer& in,
+                              NPT_DataBuffer&       out,
+                              int                   compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT,
+                              Format                format = ZLIB);
+                              
+    /**
+     * Inflate (i.e decompress) a buffer
+     */
+    static NPT_Result Inflate(const NPT_DataBuffer& in,
+                              NPT_DataBuffer&       out);                       
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingInputStream
++---------------------------------------------------------------------*/
+class NPT_ZipInflatingInputStream : public NPT_InputStream 
+{
+public:
+    NPT_ZipInflatingInputStream(NPT_InputStreamReference& source);
+   ~NPT_ZipInflatingInputStream();
+   
+    // NPT_InputStream methods
+    virtual NPT_Result Read(void*     buffer, 
+                            NPT_Size  bytes_to_read, 
+                            NPT_Size* bytes_read = NULL);
+    virtual NPT_Result Seek(NPT_Position offset);
+    virtual NPT_Result Tell(NPT_Position& offset);
+    virtual NPT_Result GetSize(NPT_LargeSize& size);
+    virtual NPT_Result GetAvailable(NPT_LargeSize& available);
+
+private:
+    NPT_InputStreamReference m_Source;
+    NPT_Position             m_Position;
+    NPT_ZipInflateState*     m_State;
+    NPT_DataBuffer           m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ZipInflatingOutputStream
++---------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+class NPT_ZipDeflatingInputStream : public NPT_InputStream 
+{
+public:
+    NPT_ZipDeflatingInputStream(NPT_InputStreamReference& source,
+                                int                       compression_level = NPT_ZIP_COMPRESSION_LEVEL_DEFAULT,
+                                NPT_Zip::Format           format = NPT_Zip::ZLIB);
+   ~NPT_ZipDeflatingInputStream();
+   
+    // NPT_InputStream methods
+    virtual NPT_Result Read(void*     buffer, 
+                            NPT_Size  bytes_to_read, 
+                            NPT_Size* bytes_read = NULL);
+    virtual NPT_Result Seek(NPT_Position offset);
+    virtual NPT_Result Tell(NPT_Position& offset);
+    virtual NPT_Result GetSize(NPT_LargeSize& size);
+    virtual NPT_Result GetAvailable(NPT_LargeSize& available);
+
+private:
+    NPT_InputStreamReference m_Source;
+    NPT_Position             m_Position;
+    bool                     m_Eos;
+    NPT_ZipDeflateState*     m_State;
+    NPT_DataBuffer           m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_ZipDeflatingInputStream
++---------------------------------------------------------------------*/
+
+#endif // _NPT_ZIP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Bsd/NptBsdNetwork.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,240 @@
+/*****************************************************************
+|
+|      Neptune - Network :: BSD Implementation
+|
+|      (c) 2001-2005 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+//#include <net/if_arp.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptStreams.h"
+#include "NptThreads.h"
+#include "NptNetwork.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|       platform adaptation
++---------------------------------------------------------------------*/
+#if !defined(IFHWADDRLEN)
+#define IFHWADDRLEN 6 // default to 48 bits
+#endif
+#if !defined(ARPHRD_ETHER)
+#define ARPHRD_ETHER 1
+#endif
+
+/*----------------------------------------------------------------------
+|       NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
+{
+    int net = socket(AF_INET, SOCK_DGRAM, 0);
+    
+    // Try to get the config until we have enough memory for it
+    // According to "Unix Network Programming", some implementations
+    // do not return an error when the supplied buffer is too small
+    // so we need to try, increasing the buffer size every time, 
+    // until we get the same size twice. We cannot assume success when
+    // the returned size is smaller than the supplied buffer, because
+    // some implementations can return less that the buffer size if
+    // another structure does not fit.
+    unsigned int buffer_size = 4096; // initial guess
+    unsigned int last_size = 0;
+    struct ifconf config;
+    unsigned char* buffer;
+    for (;buffer_size < 16384;) {
+        buffer = new unsigned char[buffer_size];
+        config.ifc_len = buffer_size;
+        config.ifc_buf = (char*)buffer;
+        if (ioctl(net, SIOCGIFCONF, &config) < 0) {
+            if (errno != EINVAL || last_size != 0) {
+                return NPT_ERROR_BASE_UNIX-errno;
+            }
+        } else {
+            if ((unsigned int)config.ifc_len == last_size) {
+                // same size, we can use the buffer
+                break;
+            }
+            // different size, we need to reallocate
+            last_size = config.ifc_len;
+        } 
+        
+        // supply 256 more bytes more next time around
+        buffer_size += 256;
+        delete[] buffer;
+    }
+    
+    unsigned char *entries;
+    for (entries = buffer; entries < buffer+config.ifc_len;) {
+        struct ifreq* entry = (struct ifreq*)entries;
+        // get the size of the addresses
+        unsigned int address_length;
+#if defined(NPT_CONFIG_HAVE_SOCKADDR_SA_LEN)
+        address_length = sizeof(struct sockaddr) > entry->ifr_addr.sa_len ?
+            sizeof(sockaddr) : entry->ifr_addr.sa_len;
+#else
+        switch (entry->ifr_addr.sa_family) {
+#if defined(AF_INET6)
+            case AF_INET6:
+                address_length = sizeof(struct sockaddr_in6);
+                break;
+#endif // defined(AF_INET6)
+                
+            default:
+                address_length = sizeof(struct sockaddr);
+                break;
+        }
+#endif
+                
+        // point to the next entry
+        entries += address_length + sizeof(entry->ifr_name);
+        
+        // ignore anything except AF_INET addresses
+        if (entry->ifr_addr.sa_family != AF_INET) {
+            continue;
+        }
+        
+        // get detailed info about the interface
+        NPT_Flags flags = 0;
+#if defined(SIOCGIFFLAGS)
+        struct ifreq query = *entry;
+        if (ioctl(net, SIOCGIFFLAGS, &query) < 0) continue;
+        
+        // process the flags
+        if ((query.ifr_flags & IFF_UP) == 0) {
+            // the interface is not up, ignore it
+            continue;
+        }
+        if (query.ifr_flags & IFF_BROADCAST) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST;
+        }
+        if (query.ifr_flags & IFF_LOOPBACK) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK;
+        }
+#if defined(IFF_POINTOPOINT)
+        if (query.ifr_flags & IFF_POINTOPOINT) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT;
+        }
+#endif // defined(IFF_POINTOPOINT)
+        if (query.ifr_flags & IFF_PROMISC) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_PROMISCUOUS;
+        }
+        if (query.ifr_flags & IFF_MULTICAST) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
+        }
+#endif // defined(SIOCGIFFLAGS)
+  
+        // get the mac address        
+        NPT_MacAddress mac;
+#if defined(SIOCGIFHWADDR)
+        if (ioctl(net, SIOCGIFHWADDR, &query) == 0) {
+            NPT_MacAddress::Type mac_addr_type;
+            unsigned int         mac_addr_length = IFHWADDRLEN;
+            switch (query.ifr_addr.sa_family) {
+#if defined(ARPHRD_ETHER)
+                case ARPHRD_ETHER:
+                    mac_addr_type = NPT_MacAddress::TYPE_ETHERNET;
+                    break;
+#endif
+
+#if defined(ARPHRD_LOOPBACK)
+                case ARPHRD_LOOPBACK:
+                    mac_addr_type = NPT_MacAddress::TYPE_LOOPBACK;
+                    length = 0;
+                    break;
+#endif
+                          
+#if defined(ARPHRD_PPP)
+                case ARPHRD_PPP:
+                    mac_addr_type = NPT_MacAddress::TYPE_PPP;
+                    mac_addr_length = 0;
+                    break;
+#endif
+                    
+#if defined(ARPHRD_IEEE80211)
+                case ARPHRD_IEEE80211:
+                    mac_addr_type = NPT_MacAddress::TYPE_IEEE_802_11;
+                    break;
+#endif
+                                   
+                default:
+                    mac_addr_type = NPT_MacAddress::TYPE_UNKNOWN;
+                    mac_addr_length = sizeof(query.ifr_addr.sa_data);
+                    break;
+            }
+                
+            mac.SetAddress(mac_addr_type, (const unsigned char*)query.ifr_addr.sa_data, mac_addr_length);
+        }
+#endif
+
+        // create an interface object
+        NPT_NetworkInterface* interface = new NPT_NetworkInterface(entry->ifr_name, mac, flags);
+
+        // primary address
+        NPT_IpAddress primary_address(ntohl(((struct sockaddr_in*)&entry->ifr_addr)->sin_addr.s_addr));
+
+        // broadcast address
+        NPT_IpAddress broadcast_address;
+#if defined(SIOCGIFBRDADDR)
+        if (flags & NPT_NETWORK_INTERFACE_FLAG_BROADCAST) {
+            if (ioctl(net, SIOCGIFBRDADDR, &query) == 0) {
+                broadcast_address.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr));
+            }
+        }
+#endif
+
+        // point to point address
+        NPT_IpAddress destination_address;
+#if defined(SIOCGIFDSTADDR)
+        if (flags & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT) {
+            if (ioctl(net, SIOCGIFDSTADDR, &query) == 0) {
+                destination_address.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr));
+            }
+        }
+#endif
+
+        // netmask
+        NPT_IpAddress netmask(0xFFFFFFFF);
+#if defined(SIOCGIFNETMASK)
+        if (ioctl(net, SIOCGIFNETMASK, &query) == 0) {
+            netmask.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr));
+        }
+#endif
+
+        // create the interface object
+        NPT_NetworkInterfaceAddress iface_address(
+            primary_address,
+            broadcast_address,
+            destination_address,
+            netmask);
+        interface->AddAddress(iface_address);  
+         
+        // add the interface to the list
+        interfaces.Add(interface);   
+    }
+
+    // free resources
+    delete[] buffer;
+    close(net);
+    
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Bsd/NptBsdSockets.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1987 @@
+/*****************************************************************
+|
+|   Neptune - Sockets :: BSD/Winsock Implementation
+|
+|   (c) 2001-2008 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(__SYMBIAN32__)
+
+// Win32 includes
+#if !defined(__WIN32__) 
+#define __WIN32__
+#endif
+#endif
+#if defined(__WIN32__) && !defined(_XBOX)
+#define STRICT
+#define NPT_WIN32_USE_WINSOCK2
+#ifdef NPT_WIN32_USE_WINSOCK2
+/* it is important to include this in this order, because winsock.h and ws2tcpip.h */
+/* have different definitions for the same preprocessor symbols, such as IP_ADD_MEMBERSHIP */
+#include <winsock2.h>
+#include <ws2tcpip.h> 
+#else
+#include <winsock.h>
+#endif
+#include <windows.h>
+
+// XBox
+#elif defined(_XBOX)
+#include <xtl.h>
+#include <winsockx.h>
+
+#elif defined(__TCS__)
+
+// Trimedia includes
+#include <sockets.h>
+
+#elif defined(__PSP__)
+
+// PSP includes
+#include <psptypes.h>
+#include <kernel.h>
+#include <pspnet.h>
+#include <pspnet_error.h>
+#include <pspnet_inet.h>
+#include <pspnet_resolver.h>
+#include <pspnet_apctl.h>
+#include <pspnet_ap_dialog_dummy.h>
+#include <errno.h>
+#include <wlan.h>
+#include <pspnet/sys/socket.h>
+#include <pspnet/sys/select.h>
+#include <pspnet/netinet/in.h>
+
+#elif defined(__PPU__)
+
+// PS3 includes
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <netex/net.h>
+#include <netex/errno.h>
+
+#else
+
+// default includes
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#if !defined(__SYMBIAN32__)
+#include <netinet/tcp.h>
+#endif
+#include <netdb.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+
+#endif 
+
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptStreams.h"
+#include "NptThreads.h"
+#include "NptSockets.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+const int NPT_TCP_SERVER_SOCKET_DEFAULT_LISTEN_COUNT = 20;
+
+/*----------------------------------------------------------------------
+|   WinSock adaptation layer
++---------------------------------------------------------------------*/
+#if defined(__WIN32__) || defined(_XBOX)
+#if defined(_XBOX)
+#include "NptXboxNetwork.h"
+#define SO_ERROR    0x1007          /* unsupported */
+#else
+#include "NptWin32Network.h"
+#endif
+// force a reference to the initializer so that the linker does not optimize it out
+static NPT_WinsockSystem& WinsockInitializer = NPT_WinsockSystem::Initializer; 
+
+#if defined(SetPort)
+#undef SetPort
+#endif
+
+#define EWOULDBLOCK  WSAEWOULDBLOCK
+#define EINPROGRESS  WSAEINPROGRESS
+#define ECONNREFUSED WSAECONNREFUSED
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET   WSAECONNRESET
+#define ETIMEDOUT    WSAETIMEDOUT
+#define ENETRESET    WSAENETRESET
+#define EADDRINUSE   WSAEADDRINUSE
+#define ENETDOWN     WSAENETDOWN
+#define ENETUNREACH  WSAENETUNREACH
+#if !defined(EAGAIN)
+#define EAGAIN       WSAEWOULDBLOCK 
+#endif
+
+#if !defined(__MINGW32__)
+typedef int         ssize_t;
+#endif
+typedef int         socklen_t;
+typedef char*       SocketBuffer;
+typedef const char* SocketConstBuffer;
+typedef char*       SocketOption;
+typedef SOCKET      SocketFd;
+
+#define GetSocketError()                 WSAGetLastError()
+#define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s) == INVALID_SOCKET)
+#define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e) == SOCKET_ERROR)
+#define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e) == SOCKET_ERROR)
+
+/*----------------------------------------------------------------------
+|   Trimedia adaptation layer
++---------------------------------------------------------------------*/
+#elif defined(__TCS__)  // trimedia PSOS w/ Target TCP
+typedef void*       SocketBuffer;
+typedef const void* SocketConstBuffer;
+typedef void*       SocketOption;
+typedef int         SocketFd;
+
+#define GetSocketError()                 errno
+#define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s)  < 0)
+#define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e)  < 0)
+#define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e)  < 0)
+
+/*----------------------------------------------------------------------
+|   PSP adaptation layer
++---------------------------------------------------------------------*/
+#elif defined(__PSP__)
+typedef SceNetInetSocklen_t socklen_t;
+#define timeval SceNetInetTimeval
+#define inet_addr sceNetInetInetAddr
+#define select sceNetInetSelect
+#define socket sceNetInetSocket
+#define connect sceNetInetConnect
+#define bind sceNetInetBind
+#define accept sceNetInetAccept
+#define getpeername sceNetInetGetpeername
+#define getsockopt sceNetInetGetsockopt
+#define setsockopt sceNetInetSetsockopt
+#define listen sceNetInetListen
+#define getsockname sceNetInetGetsockname
+#define sockaddr SceNetInetSockaddr
+#define sockaddr_in SceNetInetSockaddrIn
+#define in_addr SceNetInetInAddr
+#define send  sceNetInetSend
+#define sendto sceNetInetSendto
+#define recv  sceNetInetRecv
+#define recvfrom sceNetInetRecvfrom
+#define closesocket sceNetInetClose
+#define htonl sceNetHtonl
+#define htons sceNetHtons
+#define ntohl sceNetNtohl
+#define ntohs sceNetNtohs
+#define SOL_SOCKET SCE_NET_INET_SOL_SOCKET
+#define AF_INET SCE_NET_INET_AF_INET
+#define SOCK_STREAM SCE_NET_INET_SOCK_STREAM
+#define SOCK_DGRAM SCE_NET_INET_SOCK_DGRAM
+#define SO_BROADCAST SCE_NET_INET_SO_BROADCAST
+#define SO_ERROR SCE_NET_INET_SO_ERROR
+#define IPPROTO_IP SCE_NET_INET_IPPROTO_IP
+#define IP_ADD_MEMBERSHIP SCE_NET_INET_IP_ADD_MEMBERSHIP
+#define IP_MULTICAST_IF SCE_NET_INET_IP_MULTICAST_IF
+#define IP_MULTICAST_TTL SCE_NET_INET_IP_MULTICAST_TTL
+#define SO_REUSEADDR SCE_NET_INET_SO_REUSEADDR
+#define INADDR_ANY SCE_NET_INET_INADDR_ANY
+#define ip_mreq SceNetInetIpMreq
+#ifdef fd_set
+#undef fd_set
+#endif
+#define fd_set SceNetInetFdSet
+#ifdef FD_ZERO
+#undef FD_ZERO
+#endif
+#define FD_ZERO SceNetInetFD_ZERO
+#ifdef FD_SET
+#undef FD_SET
+#endif
+#define FD_SET SceNetInetFD_SET
+#ifdef FD_CLR
+#undef FD_CLR
+#endif
+#define FD_CLR SceNetInetFD_CLR
+#ifdef FD_ISSET
+#undef FD_ISSET
+#endif
+#define FD_ISSET SceNetInetFD_ISSET
+
+#define RESOLVER_TIMEOUT (5 * 1000 * 1000)
+#define RESOLVER_RETRY    5
+
+typedef void*       SocketBuffer;
+typedef const void* SocketConstBuffer;
+typedef void*       SocketOption;
+typedef int         SocketFd;
+
+#define GetSocketError()                 sceNetInetGetErrno()
+#define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s) < 0)
+#define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e) < 0)
+#define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e) < 0)
+
+/*----------------------------------------------------------------------
+|   PS3 adaptation layer
++---------------------------------------------------------------------*/
+#elif defined(__PPU__)
+#undef EWOULDBLOCK    
+#undef ECONNREFUSED  
+#undef ECONNABORTED  
+#undef ECONNRESET    
+#undef ETIMEDOUT     
+#undef ENETRESET     
+#undef EADDRINUSE    
+#undef ENETDOWN      
+#undef ENETUNREACH   
+#undef EAGAIN        
+#undef EINTR     
+#undef EINPROGRESS
+
+#define EWOULDBLOCK   SYS_NET_EWOULDBLOCK 
+#define ECONNREFUSED  SYS_NET_ECONNREFUSED
+#define ECONNABORTED  SYS_NET_ECONNABORTED
+#define ECONNRESET    SYS_NET_ECONNRESET
+#define ETIMEDOUT     SYS_NET_ETIMEDOUT
+#define ENETRESET     SYS_NET_ENETRESET
+#define EADDRINUSE    SYS_NET_EADDRINUSE
+#define ENETDOWN      SYS_NET_ENETDOWN
+#define ENETUNREACH   SYS_NET_ENETUNREACH
+#define EAGAIN        SYS_NET_EAGAIN
+#define EINTR         SYS_NET_EINTR
+#define EINPROGRESS   SYS_NET_EINPROGRESS
+
+typedef void*        SocketBuffer;
+typedef const void*  SocketConstBuffer;
+typedef void*        SocketOption;
+typedef int          SocketFd;
+
+#define closesocket  socketclose
+#define select       socketselect
+
+#define GetSocketError()                 sys_net_errno
+#define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s) < 0)
+#define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e) < 0)
+#define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e) < 0)
+
+// network initializer 
+static struct NPT_Ps3NetworkInitializer {
+    NPT_Ps3NetworkInitializer() {
+        sys_net_initialize_network();
+    }
+    ~NPT_Ps3NetworkInitializer() {
+        sys_net_finalize_network();
+    }
+} Ps3NetworkInitializer;
+
+/*----------------------------------------------------------------------
+|   Default adaptation layer
++---------------------------------------------------------------------*/
+#else  
+typedef void*       SocketBuffer;
+typedef const void* SocketConstBuffer;
+typedef void*       SocketOption;
+typedef int         SocketFd;
+
+#define closesocket  close
+#define ioctlsocket  ioctl
+
+#define GetSocketError()                 errno
+#define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s)  < 0)
+#define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e)  < 0)
+#define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e)  < 0)
+
+#endif
+
+/*----------------------------------------------------------------------
+|   SocketAddressToInetAddress
++---------------------------------------------------------------------*/
+static void
+SocketAddressToInetAddress(const NPT_SocketAddress& socket_address, 
+                           struct sockaddr_in*      inet_address)
+{
+    // initialize the structure
+    for (int i=0; i<8; i++) inet_address->sin_zero[i]=0;
+
+    // setup the structure
+    inet_address->sin_family = AF_INET;
+    inet_address->sin_port = htons(socket_address.GetPort());
+    inet_address->sin_addr.s_addr = htonl(socket_address.GetIpAddress().AsLong());
+}
+
+/*----------------------------------------------------------------------
+|   InetAddressToSocketAddress
++---------------------------------------------------------------------*/
+static void
+InetAddressToSocketAddress(const struct sockaddr_in* inet_address,
+                           NPT_SocketAddress&        socket_address)
+{
+    // read the fields
+    socket_address.SetPort(ntohs(inet_address->sin_port));
+    socket_address.SetIpAddress(NPT_IpAddress(ntohl(inet_address->sin_addr.s_addr)));
+}
+
+/*----------------------------------------------------------------------
+|   MapErrorCode
++---------------------------------------------------------------------*/
+static NPT_Result 
+MapErrorCode(int error)
+{
+    switch (error) {
+        case ECONNRESET:
+        case ENETRESET:
+            return NPT_ERROR_CONNECTION_RESET;
+
+        case ECONNABORTED:
+            return NPT_ERROR_CONNECTION_ABORTED;
+
+        case ECONNREFUSED:
+            return NPT_ERROR_CONNECTION_REFUSED;
+
+        case ETIMEDOUT:
+            return NPT_ERROR_TIMEOUT;
+
+        case EADDRINUSE:
+            return NPT_ERROR_ADDRESS_IN_USE;
+
+        case ENETDOWN:
+            return NPT_ERROR_NETWORK_DOWN;
+
+        case ENETUNREACH:
+            return NPT_ERROR_NETWORK_UNREACHABLE;
+
+        case EINPROGRESS:
+        case EAGAIN:
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+        case EWOULDBLOCK:
+#endif
+            return NPT_ERROR_WOULD_BLOCK;
+
+        default:
+            return NPT_FAILURE;
+    }
+}
+
+#if defined(_XBOX)
+
+struct hostent {
+    char    * h_name;           /* official name of host */
+    char    * * h_aliases;      /* alias list */
+    short   h_addrtype;         /* host address type */
+    short   h_length;           /* length of address */
+    char    * * h_addr_list;    /* list of addresses */
+#define h_addr  h_addr_list[0]  /* address, for backward compat */
+};
+
+typedef struct {
+    struct hostent server;
+    char name[128];
+    char addr[16];
+    char* addr_list[4];
+} HostEnt;
+
+/*----------------------------------------------------------------------
+|   gethostbyname
++---------------------------------------------------------------------*/
+static struct hostent* 
+gethostbyname(const char* name)
+{
+    struct hostent* host = NULL;
+    HostEnt*        host_entry = new HostEnt;
+    WSAEVENT        hEvent = WSACreateEvent();
+    XNDNS*          pDns = NULL;
+
+    INT err = XNetDnsLookup(name, hEvent, &pDns);
+    WaitForSingleObject(hEvent, INFINITE);
+    if (pDns) {
+        if (pDns->iStatus == 0) {
+            strcpy(host_entry->name, name);
+            host_entry->addr_list[0] = host_entry->addr;
+            memcpy(host_entry->addr, &(pDns->aina[0].s_addr), 4);
+            host_entry->server.h_name = host_entry->name;
+            host_entry->server.h_aliases = 0;
+            host_entry->server.h_addrtype = AF_INET;
+            host_entry->server.h_length = 4;
+            host_entry->server.h_addr_list = new char*[4];
+
+            host_entry->server.h_addr_list[0] = host_entry->addr_list[0];
+            host_entry->server.h_addr_list[1] = 0;
+
+            host = (struct hostent*)host_entry;
+        }
+        XNetDnsRelease(pDns);
+    }
+    WSACloseEvent(hEvent);
+    return host;
+};
+
+#endif // _XBOX
+
+/*----------------------------------------------------------------------
+|   NPT_IpAddress::ResolveName
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_IpAddress::ResolveName(const char* name, NPT_Timeout)
+{
+    // check parameters
+    if (name == NULL || name[0] == '\0') return NPT_ERROR_HOST_UNKNOWN;
+
+    // handle numerical addrs
+    NPT_IpAddress numerical_address;
+    if (NPT_SUCCEEDED(numerical_address.Parse(name))) {
+        /* the name is a numerical IP addr */
+        return Set(numerical_address.AsLong());
+    }
+
+#if defined(__TCS__)
+    Set(getHostByName(name));
+#elif defined(__PSP__)
+    int rid;
+    char buf[1024];
+    int buflen = sizeof(buf);
+
+    int ret = sceNetResolverCreate(&rid, buf, buflen);
+    if(ret < 0){
+        return NPT_FAILURE;
+    }
+    ret = sceNetResolverStartNtoA(rid, name, &address->sin_addr,
+        RESOLVER_TIMEOUT, RESOLVER_RETRY);
+    if(ret < 0){
+        return NPT_ERROR_HOST_UNKNOWN;
+    }
+    sceNetResolverDelete(rid);
+#else
+    // do a name lookup
+    struct hostent *host_entry = gethostbyname(name);
+    if (host_entry == NULL ||
+        host_entry->h_addrtype != AF_INET) {
+        return NPT_ERROR_HOST_UNKNOWN;
+    }
+    NPT_CopyMemory(m_Address, host_entry->h_addr, 4);
+
+#if defined(_XBOX)
+    delete host_entry;   
+#endif
+
+#endif
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd
++---------------------------------------------------------------------*/
+class NPT_BsdSocketFd
+{
+public:
+    // constructors and destructor
+    NPT_BsdSocketFd(SocketFd fd) : 
+      m_SocketFd(fd), 
+      m_Blocking(true),
+      m_ReadTimeout(NPT_TIMEOUT_INFINITE), 
+      m_WriteTimeout(NPT_TIMEOUT_INFINITE),
+      m_Position(0) {
+#if !defined(__WIN32__) && !defined(_XBOX)
+        pipe(m_AbortPipe);
+#endif
+    }
+    ~NPT_BsdSocketFd() {
+#if !defined(__WIN32__) && !defined(_XBOX)
+        close(m_AbortPipe[0]);
+        close(m_AbortPipe[1]);
+        closesocket(m_SocketFd);
+#else
+        Disconnect();
+#endif
+    }
+
+    // methods
+    NPT_Result SetBlockingMode(bool blocking);
+    NPT_Result WaitUntilReadable();
+    NPT_Result WaitUntilWriteable();
+    void Disconnect() {
+        if (!m_SocketFd) return;
+
+#if !defined(__WIN32__) && !defined(_XBOX)
+        write(m_AbortPipe[1], "\0", 1);
+#else
+        // no pipe on win32, but closing the socket will
+        // unblock the socket
+        SocketFd socketFd = m_SocketFd;
+        m_SocketFd = 0;
+        if (socketFd) {
+            closesocket(socketFd);
+        }
+#endif
+    }
+
+    // members
+    SocketFd     m_SocketFd;
+    bool         m_Blocking;
+    NPT_Timeout  m_ReadTimeout;
+    NPT_Timeout  m_WriteTimeout;
+    NPT_Position m_Position;
+
+private:
+    // methods
+    friend class NPT_BsdTcpServerSocket;
+    NPT_Result WaitForCondition(bool readable, bool writeable, NPT_Timeout timeout);
+    
+public:
+    // members
+#if !defined(__WIN32__) && !defined(_XBOX)
+    int m_AbortPipe[2]; /* an array to store the file descriptors of the abort pipe. */
+#endif
+};
+
+typedef NPT_Reference<NPT_BsdSocketFd> NPT_BsdSocketFdReference;
+
+#if defined(__WIN32__) || defined(__TCS__) || defined(_XBOX)
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd::SetBlockingMode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketFd::SetBlockingMode(bool blocking)
+{
+    unsigned long args = blocking?0:1;
+    if (ioctlsocket(m_SocketFd, FIONBIO, &args)) {
+        return NPT_ERROR_SOCKET_CONTROL_FAILED;
+    }
+    m_Blocking = blocking;
+    return NPT_SUCCESS;
+}
+#elif defined(__PSP__) || defined(__PPU__)
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd::SetBlockingMode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketFd::SetBlockingMode(bool blocking)
+{
+    int args = blocking?0:1;
+    if (setsockopt(m_SocketFd, SOL_SOCKET, SO_NBIO, &args, sizeof(args))) {
+        return NPT_ERROR_SOCKET_CONTROL_FAILED;
+    }
+    m_Blocking = blocking;
+    return NPT_SUCCESS;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd::SetBlockingMode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketFd::SetBlockingMode(bool blocking)
+{
+    int flags = fcntl(m_SocketFd, F_GETFL, 0);
+    if (blocking) {
+        flags &= ~O_NONBLOCK;
+    } else {
+        flags |= O_NONBLOCK;
+    }
+    if (fcntl(m_SocketFd, F_SETFL, flags)) {
+        return NPT_ERROR_SOCKET_CONTROL_FAILED;
+    }
+    m_Blocking = blocking;
+    return NPT_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd::WaitUntilReadable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketFd::WaitUntilReadable()
+{
+    return WaitForCondition(true, false, m_ReadTimeout);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd::WaitUntilWriteable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketFd::WaitUntilWriteable()
+{
+    return WaitForCondition(false, true, m_WriteTimeout);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketFd::WaitForCondition
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketFd::WaitForCondition(bool        wait_for_readable, 
+                                  bool        wait_for_writeable, 
+                                  NPT_Timeout timeout)
+{
+    // wait for incoming connection
+    NPT_Result result = NPT_SUCCESS;
+    fd_set read_set;
+    fd_set write_set;
+    fd_set except_set;
+    FD_ZERO(&read_set);
+    if (wait_for_readable) FD_SET(m_SocketFd, &read_set);
+    FD_ZERO(&write_set);
+    if (wait_for_writeable) FD_SET(m_SocketFd, &write_set);
+    FD_ZERO(&except_set);
+    FD_SET(m_SocketFd, &except_set);
+
+    struct timeval timeout_value;
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        timeout_value.tv_sec = timeout/1000;
+        timeout_value.tv_usec = 1000*(timeout-1000*(timeout/1000));
+    };
+    
+    int nfds = (int)m_SocketFd+1;
+
+#if !defined(__WIN32__) && !defined(_XBOX)
+    FD_SET(m_AbortPipe[0], &read_set);
+    nfds = (m_AbortPipe[0]>(int)m_SocketFd?m_AbortPipe[0]:(int)m_SocketFd)+1;
+#endif
+
+    int io_result = select(nfds, 
+                           &read_set, &write_set, &except_set, 
+                           timeout == NPT_TIMEOUT_INFINITE ? 
+                           NULL : &timeout_value);
+
+    if (io_result == 0) {
+        if (timeout == 0) {
+            // non-blocking call
+            result = NPT_ERROR_WOULD_BLOCK;
+        } else {
+            // timeout
+            result = NPT_ERROR_TIMEOUT;
+        }
+    } else if (NPT_BSD_SOCKET_SELECT_FAILED(io_result)) {
+        result = MapErrorCode(GetSocketError());
+    } else if ((wait_for_readable  && FD_ISSET(m_SocketFd, &read_set)) ||
+               (wait_for_writeable && FD_ISSET(m_SocketFd, &write_set))) {
+        result = NPT_SUCCESS;
+    } else if (FD_ISSET(m_SocketFd, &except_set)) {
+        result = MapErrorCode(GetSocketError());
+#if !defined(__WIN32__) && !defined(_XBOX)
+    } else if (FD_ISSET(m_AbortPipe[0], &read_set)) {
+        result = NPT_ERROR_CONNECTION_ABORTED;
+#endif
+    } else {
+        // should not happen
+        result = (m_SocketFd == 0)?NPT_ERROR_EOS:NPT_ERROR_INTERNAL;
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketStream
++---------------------------------------------------------------------*/
+class NPT_BsdSocketStream
+{
+ public:
+    // methods
+    NPT_BsdSocketStream(NPT_BsdSocketFdReference& socket_fd) :
+       m_SocketFdReference(socket_fd) {}
+
+    // NPT_InputStream and NPT_OutputStream methods
+    NPT_Result Seek(NPT_Position) { return NPT_ERROR_NOT_SUPPORTED; }
+    NPT_Result Tell(NPT_Position& where) {
+        where = 0;
+        return NPT_SUCCESS;
+    }
+
+ protected:
+    // destructor
+     virtual ~NPT_BsdSocketStream() {}
+
+    // members
+    NPT_BsdSocketFdReference m_SocketFdReference;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketInputStream
++---------------------------------------------------------------------*/
+class NPT_BsdSocketInputStream : public NPT_InputStream,
+                                 private NPT_BsdSocketStream
+{
+public:
+    // constructors and destructor
+    NPT_BsdSocketInputStream(NPT_BsdSocketFdReference& socket_fd) :
+      NPT_BsdSocketStream(socket_fd) {}
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read);
+    NPT_Result Seek(NPT_Position offset) { 
+        return NPT_BsdSocketStream::Seek(offset); }
+    NPT_Result Tell(NPT_Position& where) {
+        return NPT_BsdSocketStream::Tell(where);
+    }
+    NPT_Result GetSize(NPT_LargeSize& size);
+    NPT_Result GetAvailable(NPT_LargeSize& available);
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketInputStream::Read(void*     buffer, 
+                               NPT_Size  bytes_to_read, 
+                               NPT_Size* bytes_read)
+{
+    // if we're blocking, wait until the socket is readable
+    if (m_SocketFdReference->m_Blocking && 
+        m_SocketFdReference->m_ReadTimeout != NPT_TIMEOUT_INFINITE) {
+        NPT_Result result = m_SocketFdReference->WaitUntilReadable();
+        if (result != NPT_SUCCESS) return result;
+    }
+
+    // read from the socket
+    ssize_t nb_read = recv(m_SocketFdReference->m_SocketFd, 
+                           (SocketBuffer)buffer, 
+                           bytes_to_read, 0);
+    if (nb_read > 0) {
+        if (bytes_read) *bytes_read = nb_read;
+        m_SocketFdReference->m_Position += nb_read;
+        return NPT_SUCCESS;
+    } else {
+        if (bytes_read) *bytes_read = 0;
+        if (nb_read == 0) {
+            return NPT_ERROR_EOS;
+        } else {
+            return MapErrorCode(GetSocketError());
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketInputStream::GetSize(NPT_LargeSize& size)
+{
+    // generic socket streams have no size
+    size = 0;
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+#if defined(__PPU__)
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketInputStream::GetAvailable(NPT_LargeSize&)
+{
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketInputStream::GetAvailable(NPT_LargeSize& available)
+{
+    unsigned long ready = 0;
+    int io_result = ioctlsocket(m_SocketFdReference->m_SocketFd, FIONREAD, &ready); 
+    if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
+        available = 0;
+        return NPT_ERROR_SOCKET_CONTROL_FAILED;
+    } else {
+        available = ready;
+        return NPT_SUCCESS;
+    }
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketOutputStream
++---------------------------------------------------------------------*/
+class NPT_BsdSocketOutputStream : public NPT_OutputStream,
+                                  private NPT_BsdSocketStream
+{
+public:
+    // constructors and destructor
+    NPT_BsdSocketOutputStream(NPT_BsdSocketFdReference& socket_fd) :
+        NPT_BsdSocketStream(socket_fd) {}
+
+    // NPT_OutputStream methods
+    NPT_Result Write(const void* buffer, 
+                     NPT_Size    bytes_to_write, 
+                     NPT_Size*   bytes_written);
+    NPT_Result Seek(NPT_Position offset) { 
+        return NPT_BsdSocketStream::Seek(offset); }
+    NPT_Result Tell(NPT_Position& where) {
+        return NPT_BsdSocketStream::Tell(where);
+    }
+    NPT_Result Flush();
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketOutputStream::Write(const void*  buffer, 
+                                 NPT_Size     bytes_to_write, 
+                                 NPT_Size*    bytes_written)
+{
+    // if we're blocking, wait until the socket is writeable
+    if (m_SocketFdReference->m_Blocking && 
+        m_SocketFdReference->m_WriteTimeout != NPT_TIMEOUT_INFINITE) {
+        NPT_Result result = m_SocketFdReference->WaitUntilWriteable();
+        if (result != NPT_SUCCESS) return result;
+    }
+
+    int flags = 0;
+
+    // on some BSD implementations, signal we don't want a SIGPIPE
+    // but instead return EPIPE
+#ifdef MSG_NOSIGNAL
+    flags |= MSG_NOSIGNAL;
+#endif
+
+    // write to the socket
+    ssize_t nb_written = send(m_SocketFdReference->m_SocketFd, 
+                              (SocketConstBuffer)buffer, 
+                              bytes_to_write, flags);
+
+    if (nb_written > 0) {
+        if (bytes_written) *bytes_written = nb_written;
+        m_SocketFdReference->m_Position += nb_written;
+        return NPT_SUCCESS;
+    } else {
+        if (bytes_written) *bytes_written = 0;
+        if (nb_written == 0) {
+            return NPT_ERROR_CONNECTION_RESET;
+        } else {
+            return MapErrorCode(GetSocketError());
+        }
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocketOutputStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocketOutputStream::Flush()
+{
+    int       args = 0;
+    socklen_t size = sizeof(args);
+
+    // get the value of the nagle algorithm
+    if (getsockopt(m_SocketFdReference->m_SocketFd, 
+                  IPPROTO_TCP, 
+                  TCP_NODELAY, 
+                  (char*)&args, 
+                  &size)) {
+        return NPT_ERROR_GETSOCKOPT_FAILED;
+    }
+
+    // return now if nagle was already off
+    if (args == 1) return NPT_SUCCESS;
+
+    // disable the nagle algorithm
+    args = 1;
+    if (setsockopt(m_SocketFdReference->m_SocketFd, 
+                   IPPROTO_TCP, 
+                   TCP_NODELAY, 
+                   (const char*)&args, 
+                   sizeof(args))) {
+        return NPT_ERROR_SETSOCKOPT_FAILED;
+    }
+
+    // send an empty buffer to flush
+    char dummy;
+    send(m_SocketFdReference->m_SocketFd, &dummy, 0, 0); 
+
+    // restore the nagle algorithm to its original setting
+    args = 0;
+    if (setsockopt(m_SocketFdReference->m_SocketFd, 
+                   IPPROTO_TCP, 
+                   TCP_NODELAY, 
+                   (const char*)&args, 
+                   sizeof(args))) {
+        return NPT_ERROR_SETSOCKOPT_FAILED;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket
++---------------------------------------------------------------------*/
+class NPT_BsdSocket : public NPT_SocketInterface
+{
+ public:
+    // constructors and destructor
+             NPT_BsdSocket() {}
+             NPT_BsdSocket(SocketFd fd, bool force_blocking=false);
+    virtual ~NPT_BsdSocket();
+
+    // methods
+    NPT_Result RefreshInfo();
+
+    // NPT_SocketInterface methods
+    NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true);
+    NPT_Result Connect(const NPT_SocketAddress& address, NPT_Timeout timeout);
+    NPT_Result Disconnect();
+    NPT_Result WaitForConnection(NPT_Timeout timeout);
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+    NPT_Result GetInfo(NPT_SocketInfo& info);
+    NPT_Result SetBlockingMode(bool blocking);
+    NPT_Result SetReadTimeout(NPT_Timeout timeout);
+    NPT_Result SetWriteTimeout(NPT_Timeout timeout);
+
+ protected:
+    // members
+    NPT_BsdSocketFdReference m_SocketFdReference;
+    NPT_SocketInfo           m_Info;
+    bool                     m_Blocking;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::NPT_BsdSocket
++---------------------------------------------------------------------*/
+NPT_BsdSocket::NPT_BsdSocket(SocketFd fd, bool force_blocking) : 
+    m_SocketFdReference(new NPT_BsdSocketFd(fd)),
+    m_Blocking(true)
+{
+    // disable the SIGPIPE signal
+#if defined(SO_NOSIGPIPE)
+    int option = 1;
+    setsockopt(m_SocketFdReference->m_SocketFd, 
+               SOL_SOCKET, 
+               SO_NOSIGPIPE, 
+               (SocketOption)&option, 
+               sizeof(option));
+#elif defined(SIGPIPE)
+    signal(SIGPIPE, SIG_IGN);
+#endif
+
+    if (force_blocking) m_SocketFdReference->SetBlockingMode(true);
+    RefreshInfo();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::~NPT_BsdSocket
++---------------------------------------------------------------------*/
+NPT_BsdSocket::~NPT_BsdSocket()
+{
+    // release the socket fd reference
+    m_SocketFdReference = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::Bind
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::Bind(const NPT_SocketAddress& address, bool reuse_address)
+{
+    // on non windows, we need to set reuse address no matter what so
+    // that we can bind on the same port when the socket has closed 
+    // but is still in a timed-out mode
+#if !defined(__WIN32__) && !defined(_XBOX)
+    int option_ra = 1;
+    setsockopt(m_SocketFdReference->m_SocketFd,
+               SOL_SOCKET,
+               SO_REUSEADDR,
+               (SocketOption)&option_ra,
+               sizeof(option_ra));
+#endif
+
+    // set socket options
+    if (reuse_address) {
+        int option = 1;
+        // on macosx/linux, we need to use SO_REUSEPORT instead of SO_REUSEADDR
+#if defined(SO_REUSEPORT)
+        setsockopt(m_SocketFdReference->m_SocketFd, 
+                   SOL_SOCKET, 
+                   SO_REUSEPORT, 
+                   (SocketOption)&option, 
+                   sizeof(option));
+#else
+        setsockopt(m_SocketFdReference->m_SocketFd, 
+                   SOL_SOCKET, 
+                   SO_REUSEADDR, 
+                   (SocketOption)&option, 
+                   sizeof(option));
+#endif
+    }
+    
+    // convert the address
+    struct sockaddr_in inet_address;
+    SocketAddressToInetAddress(address, &inet_address);
+
+#ifdef _XBOX
+    if( address.GetIpAddress().AsLong() != NPT_IpAddress::Any.AsLong() ) {
+        //Xbox can't bind to specific address, defaulting to ANY
+        SocketAddressToInetAddress(NPT_SocketAddress(NPT_IpAddress::Any, address.GetPort()), &inet_address);
+    }
+#endif
+
+    // bind the socket
+    if (bind(m_SocketFdReference->m_SocketFd, 
+             (struct sockaddr*)&inet_address, 
+             sizeof(inet_address)) < 0) {
+        return NPT_ERROR_BIND_FAILED;
+    }
+
+    // refresh socket info
+    RefreshInfo();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::Connect
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdSocket::Connect(const NPT_SocketAddress&, NPT_Timeout)
+{
+    // this is unsupported unless overridden in a derived class
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::Disconnect
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdSocket::Disconnect()
+{
+    // check that we have a socket
+    if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
+
+    m_SocketFdReference->Disconnect();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::WaitForConnection
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdSocket::WaitForConnection(NPT_Timeout)
+{
+    // this is unsupported unless overridden in a derived class
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::GetInputStream(NPT_InputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that we have a socket
+    if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
+
+    // create a stream
+    stream = new NPT_BsdSocketInputStream(m_SocketFdReference);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
+
+    // create a stream
+    stream = new NPT_BsdSocketOutputStream(m_SocketFdReference);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::GetInfo(NPT_SocketInfo& info)
+{
+    // return the cached info
+    info = m_Info;
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::RefreshInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::RefreshInfo()
+{
+    // check that we have a socket
+    if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
+
+    // get the local socket addr
+    struct sockaddr_in inet_address;
+    socklen_t          name_length = sizeof(inet_address);
+    if (getsockname(m_SocketFdReference->m_SocketFd, 
+                    (struct sockaddr*)&inet_address, 
+                    &name_length) == 0) {
+        m_Info.local_address.SetIpAddress(ntohl(inet_address.sin_addr.s_addr));
+        m_Info.local_address.SetPort(ntohs(inet_address.sin_port));
+    }   
+
+    // get the peer socket addr
+    if (getpeername(m_SocketFdReference->m_SocketFd,
+                    (struct sockaddr*)&inet_address, 
+                    &name_length) == 0) {
+        m_Info.remote_address.SetIpAddress(ntohl(inet_address.sin_addr.s_addr));
+        m_Info.remote_address.SetPort(ntohs(inet_address.sin_port));
+    }   
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::SetBlockingMode
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::SetBlockingMode(bool blocking)
+{
+    if (m_Blocking != blocking) {
+        m_SocketFdReference->SetBlockingMode(blocking);
+        m_Blocking = blocking;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::SetReadTimeout
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::SetReadTimeout(NPT_Timeout timeout)
+{
+    m_SocketFdReference->m_ReadTimeout = timeout;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdSocket::SetWriteTimeout
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdSocket::SetWriteTimeout(NPT_Timeout timeout)
+{
+    m_SocketFdReference->m_WriteTimeout = timeout;
+    setsockopt(m_SocketFdReference->m_SocketFd,
+               SOL_SOCKET,
+               SO_SNDTIMEO,
+               (SocketOption)&timeout,
+               sizeof(timeout));
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Socket::~NPT_Socket
++---------------------------------------------------------------------*/
+NPT_Socket::~NPT_Socket()
+{
+    delete m_SocketDelegate;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpSocket
++---------------------------------------------------------------------*/
+class NPT_BsdUdpSocket : public    NPT_UdpSocketInterface,
+                         protected NPT_BsdSocket
+                         
+{
+ public:
+    // constructor
+     NPT_BsdUdpSocket();
+    virtual ~NPT_BsdUdpSocket() {}
+
+    // NPT_SocketInterface methods
+    NPT_Result Connect(const NPT_SocketAddress& address,
+                       NPT_Timeout              timeout);
+
+    // NPT_UdpSocketInterface methods
+    NPT_Result Send(const NPT_DataBuffer&    packet, 
+                    const NPT_SocketAddress* address);
+    NPT_Result Receive(NPT_DataBuffer&     packet, 
+                       NPT_SocketAddress*  address);
+
+    // friends
+    friend class NPT_UdpSocket;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpSocket::NPT_BsdUdpSocket
++---------------------------------------------------------------------*/
+NPT_BsdUdpSocket::NPT_BsdUdpSocket() : 
+    NPT_BsdSocket(socket(AF_INET, SOCK_DGRAM, 0))
+{
+    // set default socket options
+    int option = 1;
+    setsockopt(m_SocketFdReference->m_SocketFd, 
+               SOL_SOCKET, 
+               SO_BROADCAST, 
+               (SocketOption)&option, 
+               sizeof(option));
+
+#ifdef _XBOX
+    // set flag on the socket to allow sending of multicast
+    if (!NPT_BSD_SOCKET_IS_INVALID(m_SocketFdReference->m_SocketFd)) {
+        *(DWORD*)((char*)m_SocketFdReference->m_SocketFd+0xc) |= 0x02000000;
+    }
+#endif
+
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpSocket::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpSocket::Connect(const NPT_SocketAddress& address, 
+                          NPT_Timeout /* ignored */)
+{
+    // setup an address structure
+    struct sockaddr_in inet_address;
+    SocketAddressToInetAddress(address, &inet_address);
+
+    // connect so that we can have some addr bound to the socket
+    int io_result = connect(m_SocketFdReference->m_SocketFd, 
+                            (struct sockaddr *)&inet_address, 
+                            sizeof(inet_address));
+    if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) { 
+        return MapErrorCode(GetSocketError());
+    }
+    
+    // refresh socket info
+    RefreshInfo();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpSocket::Send
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdUdpSocket::Send(const NPT_DataBuffer&    packet, 
+                       const NPT_SocketAddress* address) 
+{
+    // get the packet buffer
+    const NPT_Byte* buffer        = packet.GetData();
+    ssize_t         buffer_length = packet.GetDataSize();
+
+    // if we're blocking, wait until the socket is writeable
+    if (m_SocketFdReference->m_Blocking && 
+        m_SocketFdReference->m_WriteTimeout != NPT_TIMEOUT_INFINITE) {
+        NPT_Result result = m_SocketFdReference->WaitUntilWriteable();
+        if (result != NPT_SUCCESS) return result;
+    }
+
+    // send the packet buffer
+    int io_result;
+    if (address) {
+        // send to the specified address
+
+        // setup an address structure
+        struct sockaddr_in inet_address;
+        SocketAddressToInetAddress(*address, &inet_address);
+        io_result = sendto(m_SocketFdReference->m_SocketFd, 
+                           (SocketConstBuffer)buffer, 
+                           buffer_length, 
+                           0, 
+                           (struct sockaddr *)&inet_address, 
+                           sizeof(inet_address));
+    } else {
+        // send to whichever addr the socket is connected
+        io_result = send(m_SocketFdReference->m_SocketFd, 
+                         (SocketConstBuffer)buffer, 
+                         buffer_length,
+                         0);
+    }
+
+    // check result
+    if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
+        return MapErrorCode(GetSocketError());
+    }
+
+    m_SocketFdReference->m_Position += buffer_length;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpSocket::Receive
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdUdpSocket::Receive(NPT_DataBuffer&    packet, 
+                          NPT_SocketAddress* address)
+{
+    // get the packet buffer
+    NPT_Byte* buffer      = packet.UseData();
+    ssize_t   buffer_size = packet.GetBufferSize();
+
+    // check that we have some space to receive
+    if (buffer_size == 0) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // if we're blocking, wait until the socket is readable
+    if (m_SocketFdReference->m_Blocking && 
+        m_SocketFdReference->m_ReadTimeout != NPT_TIMEOUT_INFINITE) {
+        NPT_Result result = m_SocketFdReference->WaitUntilReadable();
+        if (result != NPT_SUCCESS) return result;
+    }
+
+    // receive a packet
+    int io_result;
+    if (address) {
+        struct sockaddr_in inet_address;
+        socklen_t          inet_address_length = sizeof(inet_address);
+        io_result = recvfrom(m_SocketFdReference->m_SocketFd, 
+                             (SocketBuffer)buffer, 
+                             buffer_size, 
+                             0, 
+                             (struct sockaddr *)&inet_address, 
+                             &inet_address_length);
+
+        // convert the address format
+        if (!NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
+            if (inet_address_length == sizeof(inet_address)) {
+                InetAddressToSocketAddress(&inet_address, *address);
+            }
+        }
+    } else {
+        io_result = recv(m_SocketFdReference->m_SocketFd,
+                         (SocketBuffer)buffer,
+                         buffer_size,
+                         0);
+    }
+
+    // check result
+    if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
+        packet.SetDataSize(0);
+        return MapErrorCode(GetSocketError());
+    } 
+
+    packet.SetDataSize(io_result);
+    m_SocketFdReference->m_Position += io_result;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UdpSocket::NPT_UdpSocket
++---------------------------------------------------------------------*/
+NPT_UdpSocket::NPT_UdpSocket()
+{
+    NPT_BsdUdpSocket* delegate = new NPT_BsdUdpSocket();
+    m_SocketDelegate    = delegate;
+    m_UdpSocketDelegate = delegate;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UdpSocket::NPT_UdpSocket
++---------------------------------------------------------------------*/
+NPT_UdpSocket::NPT_UdpSocket(NPT_UdpSocketInterface* delegate) :
+    m_UdpSocketDelegate(delegate)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UdpSocket::~NPT_UdpSocket
++---------------------------------------------------------------------*/
+NPT_UdpSocket::~NPT_UdpSocket()
+{
+    delete m_UdpSocketDelegate;
+
+    // set the delegate pointers to NULL because it is shared by the
+    // base classes, and we only want to delete the object once
+    m_UdpSocketDelegate = NULL;
+    m_SocketDelegate    = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket
++---------------------------------------------------------------------*/
+class NPT_BsdUdpMulticastSocket : public    NPT_UdpMulticastSocketInterface,
+                                  protected NPT_BsdUdpSocket
+                                  
+{
+ public:
+    // methods
+     NPT_BsdUdpMulticastSocket();
+    ~NPT_BsdUdpMulticastSocket();
+
+    // NPT_UdpMulticastSocketInterface methods
+    NPT_Result JoinGroup(const NPT_IpAddress& group,
+                         const NPT_IpAddress& iface);
+    NPT_Result LeaveGroup(const NPT_IpAddress& group,
+                          const NPT_IpAddress& iface);
+    NPT_Result SetTimeToLive(unsigned char ttl);
+    NPT_Result SetInterface(const NPT_IpAddress& iface);
+
+    // friends 
+    friend class NPT_UdpMulticastSocket;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::NPT_BsdUdpMulticastSocket
++---------------------------------------------------------------------*/
+NPT_BsdUdpMulticastSocket::NPT_BsdUdpMulticastSocket()
+{
+#ifndef _XBOX
+        int option = 1;
+        setsockopt(m_SocketFdReference->m_SocketFd, 
+                   IPPROTO_IP, 
+                   IP_MULTICAST_LOOP,
+                   (SocketOption)&option,
+                   sizeof(option));
+#endif
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::~NPT_BsdUdpMulticastSocket
++---------------------------------------------------------------------*/
+NPT_BsdUdpMulticastSocket::~NPT_BsdUdpMulticastSocket()
+{
+}
+
+#if defined(_XBOX)
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::JoinGroup
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::JoinGroup(const NPT_IpAddress& group,
+                                     const NPT_IpAddress& iface)
+{
+    return NPT_SUCCESS;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::JoinGroup
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::JoinGroup(const NPT_IpAddress& group,
+                                     const NPT_IpAddress& iface)
+{
+    struct ip_mreq mreq;
+
+    // set the interface address
+    mreq.imr_interface.s_addr = htonl(iface.AsLong());
+
+    // set the group address
+    mreq.imr_multiaddr.s_addr = htonl(group.AsLong());
+
+    // set socket option
+    int io_result = setsockopt(m_SocketFdReference->m_SocketFd, 
+                               IPPROTO_IP, IP_ADD_MEMBERSHIP, 
+                               (SocketOption)&mreq, sizeof(mreq));
+    if (io_result == 0) {
+        return NPT_SUCCESS;
+    } else {
+        return MapErrorCode(GetSocketError());
+    }
+}
+#endif
+
+#if defined(_XBOX)
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::LeaveGroup
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::LeaveGroup(const NPT_IpAddress& group,
+                                      const NPT_IpAddress& iface)
+{
+    return NPT_SUCCESS;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::LeaveGroup
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::LeaveGroup(const NPT_IpAddress& group,
+                                      const NPT_IpAddress& iface)
+{
+    struct ip_mreq mreq;
+
+    // set the interface address
+    mreq.imr_interface.s_addr = htonl(iface.AsLong());
+
+    // set the group address
+    mreq.imr_multiaddr.s_addr = htonl(group.AsLong());
+
+    // set socket option
+    int io_result = setsockopt(m_SocketFdReference->m_SocketFd, 
+                               IPPROTO_IP, IP_DROP_MEMBERSHIP, 
+                               (SocketOption)&mreq, sizeof(mreq));
+    if (io_result == 0) {
+        return NPT_SUCCESS;
+    } else {
+        return MapErrorCode(GetSocketError());
+    }
+}
+#endif
+
+#if defined(_XBOX)
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::SetInterface
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::SetInterface(const NPT_IpAddress& iface)
+{
+    return NPT_SUCCESS;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::SetInterface
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::SetInterface(const NPT_IpAddress& iface)
+{
+    struct in_addr iface_addr;
+    // set the interface address
+    iface_addr.s_addr = htonl(iface.AsLong());
+
+    // set socket option
+    int io_result = setsockopt(m_SocketFdReference->m_SocketFd, 
+                               IPPROTO_IP, IP_MULTICAST_IF, 
+                               (char*)&iface_addr, sizeof(iface_addr));
+    if (io_result == 0) {
+        return NPT_SUCCESS;
+    } else {
+        return MapErrorCode(GetSocketError());
+    }
+}
+#endif
+
+#if defined(_XBOX)
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::SetTimeToLive
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::SetTimeToLive(unsigned char ttl)
+{
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_BsdUdpMulticastSocket::SetTimeToLive
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdUdpMulticastSocket::SetTimeToLive(unsigned char ttl)
+{
+    unsigned char ttl_opt = ttl;
+
+    // set socket option
+    int io_result = setsockopt(m_SocketFdReference->m_SocketFd, 
+                               IPPROTO_IP, IP_MULTICAST_TTL, 
+                               (SocketOption)&ttl_opt, sizeof(ttl_opt));
+    if (io_result == 0) {
+        return NPT_SUCCESS;
+    } else {
+        return MapErrorCode(GetSocketError());
+    }
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_UdpMulticastSocket::NPT_UdpMulticastSocket
++---------------------------------------------------------------------*/
+NPT_UdpMulticastSocket::NPT_UdpMulticastSocket() :
+    NPT_UdpSocket(NULL)
+{
+    NPT_BsdUdpMulticastSocket* delegate = new NPT_BsdUdpMulticastSocket();
+    m_SocketDelegate             = delegate;
+    m_UdpSocketDelegate          = delegate;
+    m_UdpMulticastSocketDelegate = delegate;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_UdpMulticastSocket::~NPT_UdpMulticastSocket
++---------------------------------------------------------------------*/
+NPT_UdpMulticastSocket::~NPT_UdpMulticastSocket()
+{
+    delete m_UdpMulticastSocketDelegate;
+
+    // set the delegate pointers to NULL because it is shared by the
+    // base classes, and we only want to delete the object once
+    m_SocketDelegate             = NULL;
+    m_UdpSocketDelegate          = NULL;
+    m_UdpMulticastSocketDelegate = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpClientSocket
++---------------------------------------------------------------------*/
+class NPT_BsdTcpClientSocket : protected NPT_BsdSocket
+{
+ public:
+    // methods
+     NPT_BsdTcpClientSocket();
+    ~NPT_BsdTcpClientSocket();
+
+    // NPT_SocketInterface methods
+    NPT_Result Connect(const NPT_SocketAddress& address,
+                       NPT_Timeout              timeout);
+    NPT_Result WaitForConnection(NPT_Timeout timeout);
+
+protected:
+    // methods
+    NPT_Result DoWaitForConnection(NPT_Timeout timeout);
+
+    // friends
+    friend class NPT_TcpClientSocket;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpClientSocket::NPT_BsdTcpClientSocket
++---------------------------------------------------------------------*/
+NPT_BsdTcpClientSocket::NPT_BsdTcpClientSocket() : 
+    NPT_BsdSocket(socket(AF_INET, SOCK_STREAM, 0))
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpClientSocket::~NPT_BsdTcpClientSocket
++---------------------------------------------------------------------*/
+NPT_BsdTcpClientSocket::~NPT_BsdTcpClientSocket()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpClientSocket::Connect
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdTcpClientSocket::Connect(const NPT_SocketAddress& address, 
+                                NPT_Timeout              timeout)
+{
+    bool was_blocking = m_Blocking;
+
+    // set the socket to nonblocking so that we can timeout on connect
+    if (m_Blocking) {
+        NPT_CHECK(m_SocketFdReference->SetBlockingMode(false));
+    }
+
+    // convert the address
+    struct sockaddr_in inet_address;
+    SocketAddressToInetAddress(address, &inet_address);
+
+    // initiate connection
+    int io_result;
+    io_result = connect(m_SocketFdReference->m_SocketFd, 
+                        (struct sockaddr *)&inet_address, 
+                        sizeof(inet_address));
+    if (io_result == 0) {
+        // immediate connection
+
+        // put the fd back in its original blocking mode
+        if (was_blocking) m_SocketFdReference->SetBlockingMode(true);
+
+        // get socket info
+        RefreshInfo();
+
+        return NPT_SUCCESS;
+    }
+
+    NPT_Result result = MapErrorCode(GetSocketError());
+    
+    if (was_blocking) {
+        // put the fd back in its original blocking mode
+        m_SocketFdReference->SetBlockingMode(true);
+
+        // wait for the connection to be done
+        if (result == NPT_ERROR_WOULD_BLOCK) return DoWaitForConnection(timeout);
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpClientSocket::WaitForConnection
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdTcpClientSocket::WaitForConnection(NPT_Timeout timeout)
+{
+    // this function can only be called directly for non-blocking sockets
+    if (m_Blocking) return NPT_ERROR_INVALID_STATE;
+
+    return DoWaitForConnection(timeout);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpClientSocket::DoWaitForConnection
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_BsdTcpClientSocket::DoWaitForConnection(NPT_Timeout timeout)
+{
+    SocketFd   socket_fd = m_SocketFdReference->m_SocketFd;
+    NPT_Result result = NPT_SUCCESS;
+
+    // wait for connection to succeed or fail
+    fd_set read_set;
+    fd_set write_set;
+    fd_set except_set;
+    FD_ZERO(&read_set);
+    FD_SET(socket_fd, &read_set);
+    FD_ZERO(&write_set);
+    FD_SET(socket_fd, &write_set);
+    FD_ZERO(&except_set);
+    FD_SET(socket_fd, &except_set);
+
+    struct timeval timeout_value;
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        timeout_value.tv_sec = timeout/1000;
+        timeout_value.tv_usec = 1000*(timeout-1000*(timeout/1000));
+    };
+    
+    int nfds = (int)socket_fd+1;
+
+#if !defined(__WIN32__) && !defined(_XBOX)
+    FD_SET(m_SocketFdReference->m_AbortPipe[0], &read_set);
+    nfds = (m_SocketFdReference->m_AbortPipe[0]>(int)socket_fd?m_SocketFdReference->m_AbortPipe[0]:(int)socket_fd)+1;
+#endif
+
+    int io_result = select(nfds, 
+                           &read_set, &write_set, &except_set, 
+                           timeout == NPT_TIMEOUT_INFINITE ? 
+                           NULL : &timeout_value);
+
+    if (io_result == 0) {
+        if (timeout == 0) {
+            // non-blocking call
+            return NPT_ERROR_WOULD_BLOCK;
+        } else {
+            // timeout
+            return NPT_ERROR_TIMEOUT;
+        }
+    } else if (NPT_BSD_SOCKET_SELECT_FAILED(io_result)) {
+        return MapErrorCode(GetSocketError());
+    } else if (FD_ISSET(socket_fd, &read_set)   || 
+               FD_ISSET(socket_fd, &write_set)  ||
+               FD_ISSET(socket_fd, &except_set)) {
+#if defined(_XBOX)
+        if (FD_ISSET(socket_fd, &except_set)) return MapErrorCode(GetSocketError());
+#else
+        // get error status from socket
+        // (some systems return the error in errno, others
+        //  return it in the buffer passed to getsockopt)
+        int error = 0;
+        socklen_t length = sizeof(error);
+        io_result = getsockopt(socket_fd, 
+                               SOL_SOCKET, 
+                               SO_ERROR, 
+                               (SocketOption)&error, 
+                               &length);
+        if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
+            return MapErrorCode(GetSocketError());
+        } else if (error) {
+            return MapErrorCode(error);
+        }
+#endif
+#if !defined(__WIN32__) && !defined(_XBOX)
+    } else if (FD_ISSET(m_SocketFdReference->m_AbortPipe[0], &read_set)) {
+        result = NPT_ERROR_CONNECTION_ABORTED;
+#endif
+    } else {
+        // should not happen
+        result = (socket_fd == 0)?NPT_ERROR_EOS:NPT_ERROR_INTERNAL;
+    }
+
+    
+    // get socket info
+    RefreshInfo();
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TcpClientSocket::NPT_TcpClientSocket
++---------------------------------------------------------------------*/
+NPT_TcpClientSocket::NPT_TcpClientSocket() :
+    NPT_Socket(new NPT_BsdTcpClientSocket())
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TcpClientSocket::NPT_TcpClientSocket
++---------------------------------------------------------------------*/
+NPT_TcpClientSocket::~NPT_TcpClientSocket()
+{
+    delete m_SocketDelegate;
+
+    // set the delegate pointer to NULL because it is shared by the
+    // base classes, and we only want to delete the object once
+    m_SocketDelegate = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpServerSocket
++---------------------------------------------------------------------*/
+class NPT_BsdTcpServerSocket : public    NPT_TcpServerSocketInterface,
+                               protected NPT_BsdSocket
+                               
+{
+ public:
+    // methods
+     NPT_BsdTcpServerSocket();
+    ~NPT_BsdTcpServerSocket();
+
+    // NPT_SocketInterface methods
+    NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true) {
+        // inherit
+        return NPT_BsdSocket::Bind(address, reuse_address);
+    }
+    NPT_Result Connect(const NPT_SocketAddress& address,
+                       NPT_Timeout              timeout) {
+        // inherit
+        return NPT_BsdSocket::Connect(address, timeout);
+    }
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream) {
+        // no stream
+        stream = NULL;
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) {
+        // no stream
+        stream = NULL;
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+    NPT_Result GetInfo(NPT_SocketInfo& info) {
+        // inherit
+        return NPT_BsdSocket::GetInfo(info);
+    }
+
+    // NPT_TcpServerSocket methods
+    NPT_Result Listen(unsigned int max_clients);
+    NPT_Result WaitForNewClient(NPT_Socket*& client, NPT_Timeout timeout);
+
+protected:
+    // members
+    unsigned int m_ListenMax;
+
+    // friends
+    friend class NPT_TcpServerSocket;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpServerSocket::NPT_BsdTcpServerSocket
++---------------------------------------------------------------------*/
+NPT_BsdTcpServerSocket::NPT_BsdTcpServerSocket() : 
+    NPT_BsdSocket(socket(AF_INET, SOCK_STREAM, 0)),
+    m_ListenMax(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpServerSocket::~NPT_BsdTcpServerSocket
++---------------------------------------------------------------------*/
+NPT_BsdTcpServerSocket::~NPT_BsdTcpServerSocket()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpServerSocket::Listen
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdTcpServerSocket::Listen(unsigned int max_clients)
+{
+    // listen for connections
+    if (listen(m_SocketFdReference->m_SocketFd, max_clients) < 0) {
+        m_ListenMax = 0;
+        return NPT_ERROR_LISTEN_FAILED;
+    }   
+    m_ListenMax = max_clients;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_BsdTcpServerSocket::WaitForNewClient
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_BsdTcpServerSocket::WaitForNewClient(NPT_Socket*& client, 
+                                         NPT_Timeout  timeout)
+{
+    // default value
+    client = NULL;
+
+    // check that we are listening for clients
+    if (m_ListenMax == 0) {
+        Listen(NPT_TCP_SERVER_SOCKET_DEFAULT_LISTEN_COUNT);
+    }
+
+    // set the socket to nonblocking so that we can timeout on accept
+    bool was_blocking = m_Blocking;
+    if (m_Blocking) {
+        NPT_CHECK(m_SocketFdReference->SetBlockingMode(false));
+    }
+
+    NPT_Result result = m_SocketFdReference->WaitForCondition(true, true, timeout);
+    if (result != NPT_SUCCESS) return result;
+
+    struct sockaddr_in inet_address;
+    socklen_t          namelen = sizeof(inet_address);
+    SocketFd socket_fd = accept(m_SocketFdReference->m_SocketFd, (struct sockaddr*)&inet_address, &namelen); 
+    if (NPT_BSD_SOCKET_IS_INVALID(socket_fd)) {
+        result = MapErrorCode(GetSocketError());
+    } else {
+        client = new NPT_Socket(new NPT_BsdSocket(socket_fd, m_Blocking));
+    }
+
+    if (was_blocking) {
+        // put the fd back in its original blocking mode
+        m_SocketFdReference->SetBlockingMode(true);
+    }
+
+    // done
+    return result;    
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TcpServerSocket::NPT_TcpServerSocket
++---------------------------------------------------------------------*/
+NPT_TcpServerSocket::NPT_TcpServerSocket()
+{
+    NPT_BsdTcpServerSocket* delegate = new NPT_BsdTcpServerSocket();
+    m_SocketDelegate          = delegate;
+    m_TcpServerSocketDelegate = delegate;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_TcpServerSocket::NPT_TcpServerSocket
++---------------------------------------------------------------------*/
+NPT_TcpServerSocket::~NPT_TcpServerSocket()
+{
+    delete m_TcpServerSocketDelegate;
+
+    // set the delegate pointers to NULL because it is shared by the
+    // base classes, and we only want to delete the object once
+    m_SocketDelegate          = NULL;
+    m_TcpServerSocketDelegate = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Cocoa/NptCocoaMessageQueue.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,39 @@
+/*****************************************************************
+|
+|      Neptune - Cocoa Message Queue
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+#ifndef _NPT_COCOA_MESSAGE_QUEUE_
+#define _NPT_COCOA_MESSAGE_QUEUE_
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptStrings.h"
+#include "NptMessaging.h"
+#include "NptSimpleMessageQueue.h"
+
+/*----------------------------------------------------------------------
+|       NPT_CocoaMessageQueue
++---------------------------------------------------------------------*/
+class NPT_CocoaMessageQueue : public NPT_MessageQueue
+{
+public:
+    NPT_CocoaMessageQueue();
+    ~NPT_CocoaMessageQueue();
+
+    // NPT_MessageQueue methods
+    virtual NPT_Result QueueMessage(NPT_Message*        message,
+                                    NPT_MessageHandler* handler);
+    virtual NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+    // methods
+    NPT_Result HandleMessage(NPT_Message* message, NPT_MessageHandler* handler);
+};
+
+#endif /* _NPT_COCOA_MESSAGE_QUEUE_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Cocoa/NptCocoaMessageQueue.mm	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,98 @@
+/*****************************************************************
+|
+|      Neptune - Cocoa Message Queue
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptCocoaMessageQueue.h"
+#include <Cocoa/Cocoa.h>
+
+/*----------------------------------------------------------------------
+|   NPT_CocoaMessageWrapper
++---------------------------------------------------------------------*/
+@interface NPT_CocoaMessageCapsule : NSObject
+{
+    NPT_Message*        message;
+    NPT_MessageHandler* handler;
+}
+-(id)   initWithMessage: (NPT_Message*) message andHandler: (NPT_MessageHandler*) handler;
+-(void) handle;
+@end
+
+@implementation NPT_CocoaMessageCapsule
+-(id) initWithMessage: (NPT_Message*) aMessage andHandler: (NPT_MessageHandler*) aHandler
+{
+    if ((self = [super init])) {
+        message = aMessage;
+        handler = aHandler;
+    }
+    return self;
+}
+
+-(void) dealloc
+{
+    [super dealloc];
+    delete message;
+}
+
+-(void) handle 
+{
+    if (handler && message) {
+        handler->HandleMessage(message);
+    }
+}
+@end
+
+/*----------------------------------------------------------------------
+|   NPT_CocoaMessageQueue::NPT_CocoaMessageQueue
++---------------------------------------------------------------------*/
+NPT_CocoaMessageQueue::NPT_CocoaMessageQueue()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_CocoaMessageQueue::~NPT_CocoaMessageQueue
++---------------------------------------------------------------------*/
+NPT_CocoaMessageQueue::~NPT_CocoaMessageQueue() 
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_CocoaMessageQueue::PumpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_CocoaMessageQueue::PumpMessage(NPT_Timeout)
+{
+    // you cannot pump messages on this type of queue, since they will
+    // be pumped by the main application message loop 
+    return NPT_ERROR_NOT_SUPPORTED; 
+}
+
+/*----------------------------------------------------------------------
+|   NPT_CocoaMessageQueue::QueueMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_CocoaMessageQueue::QueueMessage(NPT_Message*        message,
+                                    NPT_MessageHandler* handler)
+{
+    // create a capsule to represent the message and handler
+    NPT_CocoaMessageCapsule* capsule = [NPT_CocoaMessageCapsule alloc];
+    [capsule initWithMessage: message andHandler: handler];
+    
+    // trigger the handling of the message on the main thread
+    [capsule performSelectorOnMainThread: @selector(handle)
+                              withObject: nil
+                           waitUntilDone: FALSE];
+     
+    // we no longer hold a reference to the capsule (it will be released
+    // by the receiving thread)
+    [capsule release];
+    
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullHttpProxy.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,23 @@
+/*****************************************************************
+|
+|      Neptune - HTTP Proxy :: Null Implementation
+|
+|      (c) 2001-2007 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptResults.h"
+#include "NptHttp.h"
+
+/*----------------------------------------------------------------------
+|       NPT_HttpProxySelector::GetSystemDefault
++---------------------------------------------------------------------*/
+NPT_HttpProxySelector*
+NPT_HttpProxySelector::GetSystemDefault()
+{
+    return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullNetwork.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,23 @@
+/*****************************************************************
+|
+|      Neptune - Network :: Null Implementation
+|
+|      (c) 2001-2006 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptResults.h"
+#include "NptNetwork.h"
+
+/*----------------------------------------------------------------------
+|       NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& /*interfaces*/)
+{
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,30 @@
+/*****************************************************************
+|
+|      Neptune - Queue :: Null Implementation
+|
+|      (c) 2001-2002 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptQueue.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|       NPT_GenericQueue::CreateInstance
++---------------------------------------------------------------------*/
+NPT_GenericQueue*
+NPT_GenericQueue::CreateInstance(NPT_Cardinal max_items)
+{
+    NPT_ASSERT(0);
+    return NULL;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullSerialPort.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+|   Neptune - Serial Ports :: Null Implementation
+|
+|   (c) 2001-2007 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptUtils.h"
+#include "NptSerialPort.h"
+
+/*----------------------------------------------------------------------
+|   NPT_NullSerialPort
++---------------------------------------------------------------------*/
+class NPT_NullSerialPort: public NPT_SerialPortInterface
+{
+public:
+    // NPT_SerialPortInterface methods
+    NPT_Result Open(unsigned int              speed, 
+                    NPT_SerialPortStopBits    stop_bits = NPT_SERIAL_PORT_STOP_BITS_1,
+                    NPT_SerialPortFlowControl flow_control = NPT_SERIAL_PORT_FLOW_CONTROL_NONE,
+                    NPT_SerialPortParity      parity = NPT_SERIAL_PORT_PARITY_NONE);
+    NPT_Result Close();
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+};
+
+/*----------------------------------------------------------------------
+|   NPT_NullSerialPort::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NullSerialPort::Open(unsigned int              /* speed        */, 
+                         NPT_SerialPortStopBits    /* stop_bits    */,
+                         NPT_SerialPortFlowControl /* flow_control */,
+                         NPT_SerialPortParity      /* parity       */)
+{
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_NullSerialPort::Close
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NullSerialPort::Close()
+{
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_NullSerialPort::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_NullSerialPort::GetInputStream(NPT_InputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_NullSerialPort::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_NullSerialPort::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    return NPT_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SerialPort::NPT_SerialPort
++---------------------------------------------------------------------*/
+NPT_SerialPort::NPT_SerialPort(const char* /* name */)
+{
+    m_Delegate = new NPT_NullSerialPort();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullSystem.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,61 @@
+/*****************************************************************
+|
+|      Neptune - System :: Null Implementation
+|
+|      (c) 2001-2003 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+#include "NptSystem.h"
+#include "NptResults.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|       globals
++---------------------------------------------------------------------*/
+NPT_System System;
+
+/*----------------------------------------------------------------------
+|       NPT_NullSystem
++---------------------------------------------------------------------*/
+class NPT_NullSystem : public NPT_SystemInterface
+{
+public:
+    // methods
+    NPT_NullSystem() {}
+   ~NPT_NullSystem(){}
+    NPT_Result  GetProcessId(NPT_Integer& id) { 
+        id = 0; 
+        return NPT_SUCCESS; 
+    }
+    NPT_Result  GetCurrentTimeStamp(NPT_TimeStamp& now) {
+        now = 0.0f;
+        return NPT_SUCCESS;
+    }
+    NPT_Result  Sleep(const NPT_TimeInterval& /*duration*/) {
+        return NPT_FAILURE;
+    }
+    NPT_Result  SleepUntil(const NPT_TimeStamp& /*when*/) {
+        return NPT_FAILURE;
+    }
+    NPT_Result  SetRandomSeed(unsigned int /*seed*/) {
+        return NPT_SUCCESS;
+    }
+    NPT_Integer GetRandomInteger() {
+        return 0;
+    }
+};
+
+/*----------------------------------------------------------------------
+|       NPT_System::NPT_System
++---------------------------------------------------------------------*/
+NPT_System::NPT_System()
+{
+    m_Delegate = new NPT_NullSystem();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Null/NptNullThreads.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,48 @@
+/*****************************************************************
+|
+|      Neptune - Threads :: Null Implementation
+|
+|      (c) 2001-2002 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptThreads.h"
+
+/*----------------------------------------------------------------------
+|       NPT_NullAtomicVariable
++---------------------------------------------------------------------*/
+class NPT_NullAtomicVariable : public NPT_AtomicVariableInterface
+{
+ public:
+    // methods
+    NPT_NullAtomicVariable(NPT_Integer value) : m_Value(value) {}
+   ~NPT_NullAtomicVariable() {}
+    NPT_Integer Increment() { return ++m_Value; }
+    NPT_Integer Decrement() { return --m_Value; }
+    NPT_Integer GetValue() { return m_Value; }
+    void        SetValue(NPT_Integer value) { m_Value = value; }
+
+ private:
+    // members
+    volatile NPT_Integer m_Value;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_AtomicVariable::NPT_AtomicVariable
++---------------------------------------------------------------------*/
+NPT_AtomicVariable::NPT_AtomicVariable(NPT_Integer value)
+{
+    m_Delegate = new NPT_NullAtomicVariable(value);
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PS3/NptPs3System.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,113 @@
+/*****************************************************************
+|
+|      Neptune - System :: PS3 Implementation
+|
+|      (c) 2001-2006 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/timer.h>
+#include <sys/sys_time.h>
+#include <unistd.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptSystem.h"
+#include "NptResults.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetProcessId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetProcessId(NPT_Integer& id)
+{
+    id = 0;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetCurrentTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetCurrentTimeStamp(NPT_TimeStamp& now)
+{
+    sys_time_sec_t  sec;
+    sys_time_nsec_t nsec;
+
+    int result = sys_time_get_current_time(&sec, &nsec);
+    if (result != CELL_OK){
+        now.m_Seconds     = 0;
+        now.m_NanoSeconds = 0;   
+        return NPT_FAILURE;
+    }
+
+    /* convert format */
+    now.m_Seconds     = sec;
+    now.m_NanoSeconds = nsec;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::Sleep
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::Sleep(const NPT_TimeInterval& duration)
+{
+    unsigned long usecs = 1000000*duration.m_Seconds + duration.m_NanoSeconds/1000;
+    sys_timer_usleep(usecs);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SleepUntil
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::SleepUntil(const NPT_TimeStamp& when)
+{
+    NPT_TimeStamp now;
+    GetCurrentTimeStamp(now);
+    if (when > now) {
+        NPT_TimeInterval duration = when-now;
+        return NPT_System::Sleep(duration);
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SetRandomSeed
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_System::SetRandomSeed(unsigned int seed)
+{
+    srand(seed);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetRandomInteger
++---------------------------------------------------------------------*/
+NPT_Integer 
+NPT_System::GetRandomInteger()
+{
+    static bool seeded = false;
+    if (!seeded) {
+        NPT_TimeStamp now;
+        GetCurrentTimeStamp(now);
+        srand(now.m_NanoSeconds);
+        seeded = true;
+    }
+
+    return rand();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPDirectory.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,199 @@
+/*****************************************************************
+|
+|      Neptune - Directory :: PSP Implementation
+|
+|      Copyright (c) 2004-2008, Plutinosoft, LLC.
+|      Author: Sylvain Rebaud (sylvain@plutinosoft.com)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+
+#include <kernel.h>
+#include <psptypes.h>
+#include <psperror.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptDirectory.h"
+#include "NptDebug.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectoryEntry
++---------------------------------------------------------------------*/
+class NPT_PSPDirectoryEntry : public NPT_DirectoryEntryInterface
+{
+public:
+    // methods
+    NPT_PSPDirectoryEntry(const char* path);
+    virtual ~NPT_PSPDirectoryEntry();
+
+    // NPT_DirectoryInterface methods
+    virtual NPT_Result GetType(NPT_DirectoryEntryType& type);
+    virtual NPT_Result GetSize(NPT_Size& size);
+
+private:
+    // members
+    NPT_StringObject m_Path;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectoryEntry::NPT_PSPDirectoryEntry
++---------------------------------------------------------------------*/
+NPT_PSPDirectoryEntry::NPT_PSPDirectoryEntry(const char* path) :
+    m_Path(path)
+{  
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectoryEntry::~NPT_PSPDirectoryEntry
++---------------------------------------------------------------------*/
+NPT_PSPDirectoryEntry::~NPT_PSPDirectoryEntry()
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectoryEntry::GetType
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPDirectoryEntry::GetType(NPT_DirectoryEntryType& type)
+{
+    //// converts from Utf8 ?
+    //DWORD fa = GetFileAttributes(m_Path);
+    //if (fa == 0xFFFFFFFF) {
+    //    return NPT_FAILURE;
+    //}
+
+    //if ((fa & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+    //    type = NPT_FILE_TYPE;
+    //} else {
+    //    type = NPT_DIRECTORY_TYPE;
+    //}
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectoryEntry::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPDirectoryEntry::GetSize(NPT_Size& size)
+{
+    //WIN32_FIND_DATA filedata;
+
+    //// converts to Utf8?
+    //HANDLE sizeHandle = FindFirstFile(m_Path, &filedata);
+    //if (sizeHandle == INVALID_HANDLE_VALUE) {
+    //    FindClose(sizeHandle);
+    //    return NPT_FAILURE;
+    //}
+
+    //size = filedata.nFileSizeLow;
+    //FindClose(sizeHandle);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_DirectoryEntry::NPT_DirectoryEntry
++---------------------------------------------------------------------*/
+NPT_DirectoryEntry::NPT_DirectoryEntry(const char* path)
+{
+    m_Delegate = new NPT_PSPDirectoryEntry(path);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectory
++---------------------------------------------------------------------*/
+class NPT_PSPDirectory : public NPT_DirectoryInterface
+{
+public:
+    // methods
+    NPT_PSPDirectory(const char* path);
+    virtual ~NPT_PSPDirectory();
+
+    // NPT_DirectoryInterface methods
+    virtual NPT_Result GetNextEntry(NPT_StringObject& name, NPT_Size* size = NULL, NPT_DirectoryEntryType* type = NULL);
+
+private:
+    // members
+    NPT_StringObject m_Path;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectory::NPT_PSPDirectory
++---------------------------------------------------------------------*/
+NPT_PSPDirectory::NPT_PSPDirectory(const char* path) :
+    m_Path(path)
+{
+    if (!m_Path.EndsWith(NPT_WIN32_DIR_DELIMITER_STR)) {
+        if (!m_Path.EndsWith(NPT_UNIX_DIR_DELIMITER_STR)) {
+            m_Path += NPT_UNIX_DIR_DELIMITER_STR;
+        }
+    }
+
+    m_Path += "*.*";    
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectory::~NPT_PSPDirectory
++---------------------------------------------------------------------*/
+NPT_PSPDirectory::~NPT_PSPDirectory()
+{
+    //if (m_SearchHandle != NULL) {
+    //    FindClose(m_SearchHandle);
+    //}
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPDirectory::GetNextEntry
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPDirectory::GetNextEntry(NPT_StringObject& name, NPT_Size* size, NPT_DirectoryEntryType* type)
+{
+    //WIN32_FIND_DATA filedata;
+
+    //if (m_SearchHandle == NULL) {
+    //    m_SearchHandle = FindFirstFile(m_Path, &filedata);
+    //    if (m_SearchHandle == INVALID_HANDLE_VALUE) {
+    //        m_SearchHandle = NULL;
+    //        return NPT_FAILURE;
+    //    }   
+    //} else {
+    //    if (FindNextFile(m_SearchHandle, &filedata) == 0) {
+    //        return NPT_FAILURE;
+    //    }
+    //}
+
+    //// need to convert to Utf8 ?
+    //name = filedata.cFileName;
+
+    //if (size) {
+    //    *size = filedata.nFileSizeLow;
+    //}
+
+    //if (type) {
+    //    *type = (filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? NPT_DIRECTORY_TYPE : NPT_FILE_TYPE;
+    //}
+ 
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Directory::NPT_Directory
++---------------------------------------------------------------------*/
+NPT_Directory::NPT_Directory(const char* path)
+{
+    m_Delegate = new NPT_PSPDirectory(path);
+}
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPFile.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,441 @@
+/*****************************************************************
+|
+|      Neptune - File Byte Stream :: Standard C Implementation
+|
+|      (c) 2001-2003 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include <kernel.h>
+#include <psptypes.h>
+#include <psperror.h>
+#include <mediaman.h>
+#include <umderror.h>
+#include <fatms.h>
+
+#include "NptFile.h"
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileWrapper
++---------------------------------------------------------------------*/
+class NPT_PSPFileWrapper
+{
+public:
+    // constructors and destructor
+    NPT_PSPFileWrapper(SceUID file) : m_File(file) {}
+    ~NPT_PSPFileWrapper() {
+        if (m_File >= 0) {
+            sceIoClose(m_File);
+        }
+    }
+
+    // methods
+    SceUID GetFile() { return m_File; }
+
+private:
+    // members
+    SceUID m_File;
+};
+
+typedef NPT_Reference<NPT_PSPFileWrapper> NPT_PSPFileReference;
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileStream
++---------------------------------------------------------------------*/
+class NPT_PSPFileStream
+{
+public:
+    // constructors and destructor
+    NPT_PSPFileStream(NPT_PSPFileReference file) :
+      m_FileReference(file), m_Position(0) {}
+
+    // NPT_FileInterface methods
+    NPT_Result Seek(NPT_Offset offset);
+    NPT_Result Tell(NPT_Offset& offset);
+
+protected:
+    // constructors and destructors
+    virtual ~NPT_PSPFileStream() {}
+
+    // members
+    NPT_PSPFileReference m_FileReference;
+    SceOff               m_Position;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFileStream::Seek(NPT_Offset offset)
+{
+    SceOff result;
+
+    result = sceIoLseek(m_FileReference->GetFile(), offset, SEEK_SET);
+    if (result >= 0) {
+        m_Position = offset;
+        return NPT_SUCCESS;
+    } else {
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFileStream::Tell(NPT_Offset& offset)
+{
+    offset = m_Position;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileInputStream
++---------------------------------------------------------------------*/
+class NPT_PSPFileInputStream : public NPT_InputStream,
+                               private NPT_PSPFileStream
+                                
+{
+public:
+    // constructors and destructor
+    NPT_PSPFileInputStream(NPT_PSPFileReference& file, NPT_Size size) :
+        NPT_PSPFileStream(file), m_Size(size) {}
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read);
+    NPT_Result Seek(NPT_Offset offset) {
+        return NPT_PSPFileStream::Seek(offset);
+    }
+    NPT_Result Tell(NPT_Offset& offset) {
+        return NPT_PSPFileStream::Tell(offset);
+    }
+    NPT_Result GetSize(NPT_Size& size);
+    NPT_Result GetAvailable(NPT_Size& available);
+
+private:
+    // members
+    NPT_Size m_Size;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFileInputStream::Read(void*     buffer, 
+                             NPT_Size  bytes_to_read, 
+                             NPT_Size* bytes_read)
+{
+    size_t nb_read;
+
+    if (buffer == NULL) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    nb_read = sceIoRead(m_FileReference->GetFile(), (SceChar8*)buffer, bytes_to_read);
+
+    if (nb_read > 0) {
+        if (bytes_read) *bytes_read = (NPT_Size)nb_read;
+        m_Position += nb_read;
+        return NPT_SUCCESS;
+    } else { 
+        if (bytes_read) *bytes_read = 0;
+        return NPT_ERROR_EOS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFileInputStream::GetSize(NPT_Size& size)
+{
+    size = m_Size;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFileInputStream::GetAvailable(NPT_Size& available)
+{
+    long offset = m_Position;
+    if (offset >= 0 && (NPT_Size)offset <= m_Size) {
+        available = m_Size = offset;
+        return NPT_SUCCESS;
+    } else {
+        available = 0;
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileOutputStream
++---------------------------------------------------------------------*/
+class NPT_PSPFileOutputStream : public NPT_OutputStream,
+                                private NPT_PSPFileStream
+{
+public:
+    // constructors and destructor
+    NPT_PSPFileOutputStream(NPT_PSPFileReference& file) :
+        NPT_PSPFileStream(file) {}
+
+    // NPT_InputStream methods
+    NPT_Result Write(const void* buffer, 
+                     NPT_Size    bytes_to_write, 
+                     NPT_Size*   bytes_written);
+    NPT_Result Seek(NPT_Offset offset) {
+        return NPT_PSPFileStream::Seek(offset);
+    }
+    NPT_Result Tell(NPT_Offset& offset) {
+        return NPT_PSPFileStream::Tell(offset);
+    }
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFileOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFileOutputStream::Write(const void* buffer, 
+                               NPT_Size    bytes_to_write, 
+                               NPT_Size*   bytes_written)
+{
+    size_t nb_written;
+
+    nb_written = sceIoWrite(m_FileReference->GetFile(), (SceChar8*)buffer, bytes_to_write);
+
+    if (nb_written > 0) {
+        if (bytes_written) *bytes_written = (NPT_Size)nb_written;
+        m_Position += nb_written;
+        return NPT_SUCCESS;
+    } else {
+        if (bytes_written) *bytes_written = 0;
+        return NPT_ERROR_WRITE_FAILED;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFile
++---------------------------------------------------------------------*/
+class NPT_PSPFile: public NPT_FileInterface
+{
+public:
+    // constructors and destructor
+    NPT_PSPFile(const char* name);
+   ~NPT_PSPFile();
+
+    // NPT_FileInterface methods
+    NPT_Result Open(OpenMode mode);
+    NPT_Result Close();
+    NPT_Result GetSize(NPT_Size& size);
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+
+private:
+    // members
+    NPT_String            m_Name;
+    OpenMode              m_Mode;
+    NPT_PSPFileReference  m_FileReference;
+    NPT_Size              m_Size;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFile::NPT_PSPFile
++---------------------------------------------------------------------*/
+NPT_PSPFile::NPT_PSPFile(const char* name) :
+    m_Name(name),
+    m_Mode(0),
+    m_Size(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFile::~NPT_PSPFile
++---------------------------------------------------------------------*/
+NPT_PSPFile::~NPT_PSPFile()
+{
+    Close();
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPFile::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPFile::Open(NPT_File::OpenMode mode)
+{
+    SceUID file = -1;
+
+    // check if we're already open
+    if (!m_FileReference.IsNull()) {
+        return NPT_ERROR_FILE_ALREADY_OPEN;
+    }
+
+    // store the mode
+    m_Mode = mode;
+
+    // check for special names
+    const char* name = (const char*)m_Name;
+    int flags = 0;
+    SceMode perms = 0; // files opened/created on the PSP require certain permissions
+
+    /* compute mode */
+    if (mode & NPT_FILE_BYTE_STREAM_MODE_WRITE) {
+        perms = 0777; // since we're possibly creating a file, give it full permissions
+        if (mode & NPT_FILE_BYTE_STREAM_MODE_CREATE) {
+            if (mode & NPT_FILE_BYTE_STREAM_MODE_TRUNCATE) {
+                /* write, read, create, truncate */
+                flags = SCE_O_RDWR | SCE_O_CREAT | SCE_O_TRUNC;
+            } else {
+                /* write, read, create */
+                flags = SCE_O_RDWR | SCE_O_CREAT | SCE_O_APPEND;
+            }
+        } else {
+            if (mode & NPT_FILE_BYTE_STREAM_MODE_TRUNCATE) {
+                /* write, read, truncate */
+                flags = SCE_O_RDWR | SCE_O_CREAT | SCE_O_TRUNC;
+            } else {
+                /* write, read */
+                flags = SCE_O_RDWR;
+            }
+        }
+    } else {
+        /* read only */
+        flags = SCE_O_RDONLY;
+    }
+
+    // open the file
+    file = sceIoOpen(name, flags, perms);
+
+    // test the result of the open
+    if (file < 0) {
+        if (file == (SceUID)SCE_ERROR_ERRNO_ENOENT ) {
+            return NPT_ERROR_NO_SUCH_FILE;
+        } else if (file == (SceUID)SCE_ERROR_ERRNO_EACCESS ) {
+            return NPT_ERROR_PERMISSION_DENIED;
+        } else {
+            return NPT_FAILURE;
+        }
+    } else {
+        // get the size
+        SceOff off;
+        off = sceIoLseek(file, 0, SCE_SEEK_END);
+        if (off >= 0) {
+            m_Size = off;
+            sceIoLseek(file, 0, SCE_SEEK_SET);
+        }
+    }
+
+    // create a reference to the FILE object
+    m_FileReference = new NPT_PSPileWrapper(file);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPile::Close
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPile::Close()
+{
+    // release the file reference
+    m_FileReference = NULL;
+
+    // reset the mode
+    m_Mode = 0;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPile::GetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_PSPile::GetSize(NPT_Size& size)
+{
+    // default value
+    size = 0;
+
+    // check that the file is open
+    if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+    // return the size
+    size = m_Size;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPile::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_PSPile::GetInputStream(NPT_InputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+    // check that the mode is compatible
+    if (!(m_Mode & NPT_FILE_OPEN_MODE_READ)) {
+        return NPT_ERROR_FILE_NOT_READABLE;
+    }
+
+    // create a stream
+    stream = new NPT_PSPileInputStream(m_FileReference, m_Size);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPile::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_PSPile::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+    // check that the mode is compatible
+    if (!(m_Mode & NPT_FILE_OPEN_MODE_WRITE)) {
+        return NPT_ERROR_FILE_NOT_WRITABLE;
+    }
+    
+    // create a stream
+    stream = new NPT_PSPileOutputStream(m_FileReference);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_File::NPT_File
++---------------------------------------------------------------------*/
+NPT_File::NPT_File(const char* name)
+{
+    m_Delegate = new NPT_PSPile(name);
+}
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPNetwork.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,71 @@
+/*****************************************************************
+|
+|      Neptune - Network :: PSP Implementation
+|
+|      (c) 2001-2005 Gilles Boccon-Gibod
+|      Author: Sylvain Rebaud (sylvain@plutinosoft.com)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptNetwork.h"
+
+/*----------------------------------------------------------------------
+|       NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
+{
+    union SceNetApctlInfo info;
+    int ret = sceNetApctlGetInfo(SCE_NET_APCTL_INFO_IP_ADDRESS, &info);
+    if (ret < 0) {
+        return NPT_FAILURE;
+    }
+    NPT_IpAddress primary_address;
+    if (NPT_FAILED(primary_address.Parse(info.ip_address))) {
+        return NPT_FAILURE;
+    }
+
+    NPT_IpAddress netmask;
+    if (NPT_FAILED(netmask.Parse(info.netmask))) {
+        return NPT_FAILURE;
+    }
+
+    NPT_IpAddress broadcast_address;
+    NPT_Flags    flags = 0;
+    flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST;
+    flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
+
+    // get mac address
+    SceNetEtherAddr mac_info;
+    ret = sceNetGetLocalEtherAddr(&mac_info);
+    if (ret < 0) {
+        return NPT_FAILURE;
+    }
+    NPT_MacAddress mac(TYPE_IEEE_802_11, mac_info.data, SCE_NET_ETHER_ADDR_LEN);
+
+    // create an interface object
+    char iface_name[5];
+    iface_name[0] = 'i';
+    iface_name[1] = 'f';
+    iface_name[2] = '0';
+    iface_name[3] = '0';
+    iface_name[4] = '\0';
+    NPT_NetworkInterface* iface = new NPT_NetworkInterface(iface_name, mac, flags);
+
+    // set the interface address
+    NPT_NetworkInterfaceAddress iface_address(
+        primary_address,
+        broadcast_address,
+        NPT_IpAddress::Any,
+        netmask);
+    iface->AddAddress(iface_address);  
+
+    // add the interface to the list
+    interfaces.Add(iface);  
+
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,141 @@
+/*****************************************************************
+|
+|      Neptune - Queue :: PSP Implementation
+|
+|      (c) 2001-2002 Gilles Boccon-Gibod
+|      Author: Sylvain Rebaud
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptQueue.h"
+//#include "NptThreads.h"
+#include "NptList.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|       NPT_PSPQueue
++---------------------------------------------------------------------*/
+class NPT_PSPQueue : public NPT_GenericQueue
+{
+public:
+    // methods
+               NPT_PSPQueue(NPT_Cardinal max_items);
+              ~NPT_PSPQueue();
+    NPT_Result Push(NPT_QueueItem* item); 
+    NPT_Result Pop(NPT_QueueItem*& item, NPT_Boolean blocking);
+
+
+private:
+    // members
+    NPT_Cardinal             m_MaxItems;
+    //NPT_Mutex          	 	 m_Mutex;
+    //pthread_cond_t           m_CanPushOrPopCondition;
+    NPT_List<NPT_QueueItem*> m_Items;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPQueue::NPT_PSPQueue
++---------------------------------------------------------------------*/
+NPT_PSPQueue::NPT_PSPQueue(NPT_Cardinal max_items) : 
+    m_MaxItems(max_items)
+{
+    NPT_Debug(":: NPT_PSPQueue::NPT_PSPQueue\n");
+
+    //pthread_cond_init(&m_CanPushOrPopCondition, NULL);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPQueue::~NPT_PSPQueue()
++---------------------------------------------------------------------*/
+NPT_PSPQueue::~NPT_PSPQueue()
+{
+    // destroy resources
+    //pthread_cond_destroy(&m_CanPushOrPopCondition);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPQueue::Push
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPQueue::Push(NPT_QueueItem* item)
+{
+    // lock the mutex that protects the list
+    m_Items.Lock();
+
+    // check that we have not exceeded the max
+    //if (m_MaxItems) {
+    //    while (m_Items.GetItemCount() >= m_MaxItems) {
+    //        // wait until some items have been removed
+    //        //NPT_Debug(":: NPT_PSPQueue::Push - waiting for queue to empty\n");
+    //        pthread_cond_wait(&m_CanPushOrPopCondition, &m_Mutex);
+    //    }
+    //}
+
+    // add the item to the list
+    m_Items.Add(item);
+
+    // if the list was previously empty, signal the condition
+    // to wake up the waiting thread
+    //if (m_Items.GetItemCount() == 1) {    
+    //    pthread_cond_signal(&m_CanPushOrPopCondition);
+    //}
+
+    // unlock the mutex
+    m_Items.Unlock();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPQueue::Pop
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPQueue::Pop(NPT_QueueItem*& item, NPT_Boolean blocking)
+{
+    // lock the mutex that protects the list
+    m_Items.Lock();
+
+    NPT_Result result;
+    //if (blocking) {
+    //    while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) {
+    //        // no item in the list, wait for one
+    //        //NPT_Debug(":: NPT_PSPQueue::Pop - waiting for queue to fill up\n");
+    //        pthread_cond_wait(&m_CanPushOrPopCondition, &m_Mutex);
+    //    }
+    //} else {
+        result = m_Items.PopHead(item);
+    //}
+    
+    // if the list was previously full, signal the condition
+    // to wake up the waiting thread
+    //if (m_MaxItems && (result == NPT_SUCCESS)) {
+    //    if (m_Items.GetItemCount() == m_MaxItems-1) {    
+    //        pthread_cond_signal(&m_CanPushOrPopCondition);
+    //    }
+    //}
+
+    // unlock the mutex
+    m_Items.Unlock();
+ 
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_GenericQueue::CreateInstance
++---------------------------------------------------------------------*/
+NPT_GenericQueue*
+NPT_GenericQueue::CreateInstance(NPT_Cardinal max_items)
+{
+    NPT_Debug(":: NPT_GenericQueue::CreateInstance - queue max_items = %ld\n", 
+           max_items);
+    return new NPT_PSPQueue(max_items);
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPSystem.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,142 @@
+/*****************************************************************
+|
+|      Neptune - System :: Win32 Implementation
+|
+|      (c) 2001-2003 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <psptypes.h>
+#include <kernel.h>
+#include <rtcsvc.h>
+#include <pspnet/sys/time.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptSystem.h"
+#include "NptResults.h"
+#include "NptDebug.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem
++---------------------------------------------------------------------*/
+class NPT_PSPSystem : public NPT_SystemInterface
+{
+public:
+    // methods
+                NPT_PSPSystem();
+               ~NPT_PSPSystem();
+    NPT_Result  GetProcessId(NPT_Integer& id);
+    NPT_Result  GetCurrentTimeStamp(NPT_TimeStamp& now);
+    NPT_Result  Sleep(NPT_UInt32 microseconds);
+    NPT_Result  SetRandomSeed(unsigned int seed);
+    NPT_Integer GetRandomInteger();
+    
+private:
+    bool m_bRandomized;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem::NPT_PSPSystem
++---------------------------------------------------------------------*/
+NPT_PSPSystem::NPT_PSPSystem()
+: m_bRandomized(false)
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem::~NPT_PSPSystem
++---------------------------------------------------------------------*/
+NPT_PSPSystem::~NPT_PSPSystem()
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem::GetProcessId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSystem::GetProcessId(NPT_Integer& id)
+{
+    //id = getpid();
+    id = 0;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem::GetCurrentTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSystem::GetCurrentTimeStamp(NPT_TimeStamp& now)
+{
+    // get the current time
+	ScePspDateTime clock;
+	sceRtcGetCurrentClock(&clock, 0);
+	
+	// converts to POSIX time to get the number of seconds since 1970
+	time_t time;
+	sceRtcGetTime_t(&clock, &time);
+	
+	// converts back to Psp date, it should be truncated
+	// we'll use that to get the number of nanoseconds
+	ScePspDateTime clock_trunk;
+	sceRtcSetTime_t(&clock_trunk, time);
+	
+    //_ftime(&time_stamp);
+    now.m_Seconds     = time;
+    now.m_NanoSeconds = (sceRtcGetMicrosecond(&clock)-sceRtcGetMicrosecond(&clock_trunk))*1000;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem::Sleep
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSystem::Sleep(NPT_UInt32 microseconds)
+{
+    sceKernelDelayThread(microseconds);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSystem::SetRandomSeed
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_PSPSystem::SetRandomSeed(unsigned int seed)
+{
+    srand(seed);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_System::NPT_System
++---------------------------------------------------------------------*/
+NPT_Integer 
+NPT_PSPSystem::GetRandomInteger()
+{
+    if (m_bRandomized == false) {
+        NPT_TimeStamp now;
+        GetCurrentTimeStamp(now);
+        SetRandomSeed( now.m_Seconds );
+        m_bRandomized = true;
+    }
+    NPT_Integer val = 0;
+    val = rand();
+    return val;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_System::NPT_System
++---------------------------------------------------------------------*/
+NPT_System::NPT_System()
+{
+    m_Delegate = new NPT_PSPSystem();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/PSP/NptPSPThreads.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,487 @@
+/*****************************************************************
+|
+|      Neptune - Threads :: PSP Implementation
+|
+|      (c) 2001-2002 Gilles Boccon-Gibod
+|      Author: Sylvain Rebaud
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptThreads.h"
+#include "NptSystem.h"
+#include "NptDebug.h"
+
+#include <stdio.h>
+
+#include <kernel.h>
+#include <psptypes.h>
+#include <psperror.h>
+
+/*----------------------------------------------------------------------
+|       NPT_Mutex
++---------------------------------------------------------------------*/
+class NPT_PSPMutex : public NPT_MutexInterface
+{
+public:
+    // methods
+    NPT_PSPMutex();
+    ~NPT_PSPMutex();
+    NPT_Result Lock();
+    NPT_Result Unlock();
+
+private:
+    SceUID m_semaphore;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPMutex::NPT_PSPMutex
++---------------------------------------------------------------------*/
+NPT_PSPMutex::NPT_PSPMutex()
+{
+    char sema_name[256];
+    sprintf(sema_name, "sema_%d", (int)NPT_System::GetSystem()->GetRandomInteger());
+    m_semaphore = sceKernelCreateSema(sema_name, SCE_KERNEL_SA_THFIFO, 1, 1, NULL);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPMutex::~NPT_PSPMutex
++---------------------------------------------------------------------*/
+NPT_PSPMutex::~NPT_PSPMutex()
+{
+    sceKernelDeleteSema(m_semaphore);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPMutex::Lock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPMutex::Lock()
+{
+    sceKernelWaitSema(m_semaphore, 1, NULL);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPMutex::Unlock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPMutex::Unlock()
+{
+    sceKernelSignalSema(m_semaphore, 1);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Mutex::NPT_Mutex
++---------------------------------------------------------------------*/
+NPT_Mutex::NPT_Mutex()
+{
+    m_Delegate = new NPT_PSPMutex();
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable
++---------------------------------------------------------------------*/
+class NPT_PSPSharedVariable : public NPT_SharedVariableInterface
+{
+public:
+    // methods
+    NPT_PSPSharedVariable(NPT_Integer value);
+    ~NPT_PSPSharedVariable();
+    NPT_Result SetValue(NPT_Integer value);
+    NPT_Result GetValue(NPT_Integer& value);
+    NPT_Result WaitUntilEquals(NPT_Integer value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+    NPT_Result WaitWhileEquals(NPT_Integer value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+private:
+    // members
+    volatile NPT_Integer m_Value;
+    NPT_Mutex            m_Lock;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable::NPT_PSPSharedVariable
++---------------------------------------------------------------------*/
+NPT_PSPSharedVariable::NPT_PSPSharedVariable(NPT_Integer value) : 
+m_Value(value)
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable::~NPT_PSPSharedVariable
++---------------------------------------------------------------------*/
+NPT_PSPSharedVariable::~NPT_PSPSharedVariable()
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable::SetValue
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSharedVariable::SetValue(NPT_Integer value)
+{
+    m_Lock.Lock();
+    m_Value = value;
+    m_Lock.Unlock();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable::GetValue
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSharedVariable::GetValue(NPT_Integer& value)
+{
+    // reading an integer should be atomic on most platforms
+    value = m_Value;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable::WaitUntilEquals
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSharedVariable::WaitUntilEquals(NPT_Integer value, NPT_Timeout timeout)
+{
+    NPT_Timeout sleep = 0;
+    do {
+        m_Lock.Lock();
+        if (m_Value == value) {
+            break;
+        }
+        m_Lock.Unlock();
+        NPT_System::GetSystem()->Sleep(50000);
+        sleep += 50000;
+        if (timeout != NPT_TIMEOUT_INFINITE && sleep > timeout) {
+            return NPT_FAILURE;
+        }
+    } while (1);
+
+    m_Lock.Unlock();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPSharedVariable::WaitWhileEquals
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPSharedVariable::WaitWhileEquals(NPT_Integer value, NPT_Timeout timeout)
+{
+    NPT_Timeout sleep = 0;
+    do {
+        m_Lock.Lock();
+        if (m_Value != value) {
+            break;
+        }
+        m_Lock.Unlock();
+        NPT_System::GetSystem()->Sleep(50000);
+        sleep += 50000;
+        if (timeout != NPT_TIMEOUT_INFINITE && sleep > timeout) {
+            return NPT_FAILURE;
+        }
+    } while (1);
+
+    m_Lock.Unlock();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_SharedVariable::NPT_SharedVariable
++---------------------------------------------------------------------*/
+NPT_SharedVariable::NPT_SharedVariable(NPT_Integer value)
+{
+    m_Delegate = new NPT_PSPSharedVariable(value);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable
++---------------------------------------------------------------------*/
+class NPT_PSPAtomicVariable : public NPT_AtomicVariableInterface
+{
+public:
+    // methods
+    NPT_PSPAtomicVariable(NPT_Integer value);
+    ~NPT_PSPAtomicVariable();
+    NPT_Integer Increment(); 
+    NPT_Integer Decrement();
+    NPT_Integer GetValue();
+    void        SetValue(NPT_Integer value);
+
+private:
+    // members
+    volatile NPT_Integer m_Value;
+    NPT_Mutex            m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable::NPT_PSPAtomicVariable
++---------------------------------------------------------------------*/
+NPT_PSPAtomicVariable::NPT_PSPAtomicVariable(NPT_Integer value) : 
+m_Value(value)
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable::~NPT_PSPAtomicVariable
++---------------------------------------------------------------------*/
+NPT_PSPAtomicVariable::~NPT_PSPAtomicVariable()
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable::Increment
++---------------------------------------------------------------------*/
+NPT_Integer
+NPT_PSPAtomicVariable::Increment()
+{
+    NPT_Integer value;
+
+    m_Mutex.Lock();
+    value = ++m_Value;
+    m_Mutex.Unlock();
+
+    return value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable::Decrement
++---------------------------------------------------------------------*/
+NPT_Integer
+NPT_PSPAtomicVariable::Decrement()
+{
+    NPT_Integer value;
+
+    m_Mutex.Lock();
+    value = --m_Value;
+    m_Mutex.Unlock();
+
+    return value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable::GetValue
++---------------------------------------------------------------------*/
+NPT_Integer
+NPT_PSPAtomicVariable::GetValue()
+{
+    return m_Value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPAtomicVariable::SetValue
++---------------------------------------------------------------------*/
+void
+NPT_PSPAtomicVariable::SetValue(NPT_Integer value)
+{
+    m_Mutex.Lock();
+    m_Value = value;
+    m_Mutex.Unlock();
+}
+
+/*----------------------------------------------------------------------
+|       NPT_AtomicVariable::NPT_AtomicVariable
++---------------------------------------------------------------------*/
+NPT_AtomicVariable::NPT_AtomicVariable(NPT_Integer value)
+{
+    m_Delegate = new NPT_PSPAtomicVariable(value);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread
++---------------------------------------------------------------------*/
+class NPT_PSPThread : public NPT_ThreadInterface
+{
+public:
+    // methods
+                NPT_PSPThread(NPT_Thread*   delegator,
+                              NPT_Runnable& target,
+                              bool   detached);
+               ~NPT_PSPThread();
+    NPT_Result  Start(); 
+    NPT_Result  Wait();
+    NPT_Result  Terminate();
+
+private:
+    // methods
+    static int EntryPoint(SceSize argument_size, void* argument);
+
+    // NPT_Runnable methods
+    void Run();
+
+    // members
+    NPT_Thread*   m_Delegator;
+    NPT_Runnable& m_Target;
+    bool   m_Detached;
+    SceUID        m_ThreadId;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::NPT_PSPThread
++---------------------------------------------------------------------*/
+NPT_PSPThread::NPT_PSPThread(NPT_Thread*   delegator,
+                                 NPT_Runnable& target,
+                                 bool   detached) : 
+    m_Delegator(delegator),
+    m_Target(target),
+    m_Detached(detached),
+    m_ThreadId(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::~NPT_PSPThread
++---------------------------------------------------------------------*/
+NPT_PSPThread::~NPT_PSPThread()
+{
+    if (!m_Detached) {
+        // we're not detached, and not in the Run() method, so we need to 
+        // wait until the thread is done
+        Wait();
+    }
+
+    m_ThreadId = 0;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::Terminate
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPThread::Terminate()
+{
+    // end the thread
+    sceKernelExitDeleteThread(0);
+
+    // if we're detached, we need to delete ourselves
+    if (m_Detached) {
+        delete m_Delegator;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::EntryPoint
++---------------------------------------------------------------------*/
+int
+NPT_PSPThread::EntryPoint(SceSize /* argument_size */, void* argument)
+{
+    NPT_PSPThread** pthread = (NPT_PSPThread**)argument;
+    NPT_PSPThread*  thread  = *pthread;
+
+    //NPT_PSPThread* thread = reinterpret_cast<NPT_PSPThread*>(*argument);
+
+    NPT_Debug(NPT_LOG_LEVEL_1, ":: NPT_PSPThread::EntryPoint - in =======================\n");
+
+    // run the thread 
+    thread->Run();
+
+    NPT_Debug(NPT_LOG_LEVEL_1, ":: NPT_PSPThread::EntryPoint - out ======================\n");
+
+    // we're done with the thread object
+    thread->Terminate();
+
+    // done
+    return 0;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::Start
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPThread::Start()
+{
+    if (m_ThreadId > 0) {
+        NPT_Debug(NPT_LOG_LEVEL_1, ":: NPT_PSPThread::Start already started !\n");
+        return NPT_FAILURE;
+    }
+
+    NPT_Debug(NPT_LOG_LEVEL_1, ":: NPT_PSPThread::Start - creating thread\n");
+    char thread_name[32];
+    sprintf(thread_name, "thread_%d", (int)NPT_System::GetSystem()->GetRandomInteger());
+
+    // create the native thread
+    m_ThreadId = (SceUID)
+        sceKernelCreateThread(
+        thread_name,
+        EntryPoint,
+        SCE_KERNEL_USER_LOWEST_PRIORITY,
+        1024 * 16,
+        0,
+        NULL);
+    if (m_ThreadId <= 0) {
+        // failed
+        return NPT_FAILURE;
+    }
+
+    NPT_PSPThread* thread = this;
+    int ret = sceKernelStartThread(
+        m_ThreadId,
+        sizeof(thread),
+        &thread);
+    if (ret != SCE_KERNEL_ERROR_OK) {
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::Run
++---------------------------------------------------------------------*/
+void
+NPT_PSPThread::Run()
+{
+    m_Target.Run();
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PSPThread::Wait
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PSPThread::Wait()
+{
+    // check that we're not detached
+    if (m_ThreadId <= 0 || m_Detached) {
+        return NPT_FAILURE;
+    }
+
+    // wait for the thread to finish
+    NPT_Debug(NPT_LOG_LEVEL_1, ":: NPT_PSPThread::Wait - joining thread id %d\n", m_ThreadId);
+    int result = sceKernelWaitThreadEnd(m_ThreadId, NULL);
+    if (result < 0) {
+        return NPT_FAILURE;
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Thread::NPT_Thread
++---------------------------------------------------------------------*/
+NPT_Thread::NPT_Thread(bool detached)
+{
+    m_Delegate = new NPT_PSPThread(this, *this, detached);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Thread::NPT_Thread
++---------------------------------------------------------------------*/
+NPT_Thread::NPT_Thread(NPT_Runnable& target, bool detached)
+{
+    m_Delegate = new NPT_PSPThread(this, target, detached);
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixDynamicLibraries.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,105 @@
+/*****************************************************************
+|
+|      Neptune - Dynamic Libraries :: Posix Implementation
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptLogging.h"
+#include "NptDynamicLibraries.h"
+
+#include <dlfcn.h>
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.posix.dynamic-libraries")
+
+/*----------------------------------------------------------------------
+|   NPT_PosixDynamicLibrary
++---------------------------------------------------------------------*/
+class NPT_PosixDynamicLibrary : public NPT_DynamicLibraryInterface
+{
+public:
+    // constructor and destructor
+    NPT_PosixDynamicLibrary(void* library, const char* name) : 
+        m_Library(library), m_Name(name) {}
+    
+    // NPT_DynamicLibraryInterface methods
+    virtual NPT_Result FindSymbol(const char* name, void*& symbol);
+    virtual NPT_Result Unload();
+    
+private:
+    // members
+    void*      m_Library;
+    NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_DynamicLibrary::Load
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_DynamicLibrary::Load(const char* name, NPT_Flags flags, NPT_DynamicLibrary*& library)
+{
+    if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    
+    // default return value
+    library = NULL;
+    
+    // compute the mode
+    int mode = 0;
+    if (flags & NPT_DYANMIC_LIBRARY_LOAD_FLAG_NOW) {
+        mode &= RTLD_NOW;
+    } else {
+        mode &= RTLD_LAZY;
+    }
+    
+    // load the lib
+    NPT_LOG_FINE_2("loading library %s, flags=%x", name, flags);
+    void* handle = dlopen(name, mode);
+    if (handle == NULL) {
+        NPT_LOG_FINE("library not found");
+        return NPT_FAILURE;
+    }
+    
+    // instantiate the object
+    NPT_LOG_FINE_1("library %s loaded", name);
+    library = new NPT_DynamicLibrary(new NPT_PosixDynamicLibrary(handle, name));
+    
+    return NPT_SUCCESS;
+}
+    
+/*----------------------------------------------------------------------
+|   NPT_PosixDynamicLibrary::FindSymbol
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_PosixDynamicLibrary::FindSymbol(const char* name, void*& symbol)
+{
+    if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    symbol = NULL;
+    if (m_Library == NULL) return NPT_ERROR_NO_SUCH_ITEM;
+    
+    NPT_LOG_FINE_1("finding symbol %s", name);
+    symbol = dlsym(m_Library, name);
+    return symbol?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_PosixDynamicLibrary::Unload
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixDynamicLibrary::Unload()
+{
+    NPT_LOG_FINE_1("unloading library %s", (const char*)m_Name);
+    int result = dlclose(m_Library);
+    if (result == 0) {
+        return NPT_SUCCESS;
+    } else {
+        return NPT_FAILURE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixFile.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,253 @@
+/*****************************************************************
+|
+|      Neptune - File :: Posix Implementation
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE64
+#define _FILE_OFFSET_BITS 64
+
+#include <sys/stat.h>
+
+#include <errno.h>
+
+#if defined(_WIN32)
+#include <direct.h>
+#include <stdlib.h>
+#include <stdio.h>
+#else
+#include <unistd.h>
+#include <dirent.h>
+#endif
+
+#include "NptLogging.h"
+#include "NptFile.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+//NPT_SET_LOCAL_LOGGER("neptune.posix.file")
+
+/*----------------------------------------------------------------------
+|   Win32 adaptation
++---------------------------------------------------------------------*/
+#if defined(_WIN32) || defined(_XBOX)
+extern int NPT_stat_utf8(const char* path, NPT_stat_struct* info);
+extern char* NPT_getcwd_utf8(char* path, unsigned int path_size);
+#define getcwd NPT_getcwd_utf8
+#define S_ISDIR(_m) (((_m)&_S_IFMT) == _S_IFDIR) 
+#define S_ISREG(_m) (((_m)&_S_IFMT) == _S_IFREG) 
+#define S_IWUSR _S_IWRITE
+#endif
+
+/*----------------------------------------------------------------------
+|   MapErrno
++---------------------------------------------------------------------*/
+static NPT_Result
+MapErrno(int err) {
+    switch (err) {
+      case EACCES:       return NPT_ERROR_PERMISSION_DENIED;
+      case EPERM:        return NPT_ERROR_PERMISSION_DENIED;
+      case ENOENT:       return NPT_ERROR_NO_SUCH_FILE;
+      case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS;
+      case EBUSY:        return NPT_ERROR_FILE_BUSY;
+      case EROFS:        return NPT_ERROR_FILE_NOT_WRITABLE;
+      case ENOTDIR:      return NPT_ERROR_FILE_NOT_DIRECTORY;
+      case EEXIST:       return NPT_ERROR_FILE_ALREADY_EXISTS;
+      case ENOSPC:       return NPT_ERROR_FILE_NOT_ENOUGH_SPACE;
+      case ENOTEMPTY:    return NPT_ERROR_DIRECTORY_NOT_EMPTY;
+      default:           return NPT_ERROR_ERRNO(err);
+    }
+}
+
+#if !defined(_WIN32)
+/*----------------------------------------------------------------------
+|   NPT_FilePath::Separator
++---------------------------------------------------------------------*/
+const NPT_String NPT_FilePath::Separator("/");
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetRoots
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetRoots(NPT_List<NPT_String>& roots)
+{
+    roots.Clear();
+    roots.Add("/");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::CreateDirectory
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::CreateDirectory(const char* path)
+{
+    int result;
+    
+    result = mkdir(path, 0755);
+    if (result != 0) {
+        return MapErrno(errno);
+    }
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::DeleteFile
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::DeleteFile(const char* path)
+{
+    int result = unlink(path);
+    if (result != 0) return MapErrno(errno);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::DeleteDirectory
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::DeleteDirectory(const char* path)
+{
+    int result = rmdir(path);
+    if (result != 0) return MapErrno(errno);
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Rename
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Rename(const char* from_path, const char* to_path)
+{
+    int result = rename(from_path, to_path);
+    if (result != 0) return MapErrno(errno);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::ListDirectory
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_File::ListDirectory(const char*           path, 
+                        NPT_List<NPT_String>& entries, 
+                        NPT_Ordinal           start /* = 0 */, 
+                        NPT_Cardinal          max   /* = 0 */)
+{
+    // default return value
+    entries.Clear();
+    
+    // check the arguments
+    if (path == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    
+    // list the entries
+    DIR *directory = opendir(path);
+    if (directory == NULL) return NPT_ERROR_OUT_OF_MEMORY;
+    
+    NPT_Cardinal count = 0;
+    for (;;) {
+        struct dirent* entry_pointer = NULL;
+#if defined(NPT_CONFIG_HAVE_READDIR_R)
+        struct dirent entry;
+        int result = readdir_r(directory, &entry, &entry_pointer);
+        if (result != 0 || entry_pointer == NULL) break;
+#else
+        entry_pointer = readdir(directory);
+        if (entry_pointer == NULL) break;
+#endif
+        // ignore odd names
+        if (entry_pointer->d_name[0] == '\0') continue;
+
+        // ignore . and ..
+        if (entry_pointer->d_name[0] == '.' && 
+            entry_pointer->d_name[1] == '\0') {
+            continue;
+        }
+        if (entry_pointer->d_name[0] == '.' && 
+            entry_pointer->d_name[1] == '.' &&
+            entry_pointer->d_name[2] == '\0') {
+            continue;
+        }        
+        
+        // continue if not yet first item requested
+        if (start > 0) {
+            --start;
+            continue;
+        }
+        entries.Add(NPT_String(entry_pointer->d_name));
+
+        // stop when reaching maximum requested
+        if (max && ++count == max) break;
+    }
+    
+    closedir(directory);
+    
+    return NPT_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetWorkingDirectory
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetWorkingDirectory(NPT_String& path)
+{
+    char buffer[1024+1];
+    char* dir = getcwd(buffer, 1024+1);
+    if (dir == NULL) return MapErrno(errno);
+    path = dir;
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
+{
+    // default value
+    if (info) NPT_SetMemory(info, 0, sizeof(*info));
+
+    // On Windows, stat will fail if a dir ends with a separator
+    NPT_String _path = path;
+    _path.TrimRight("\\/");
+    if (NPT_StringLength(path) ==  2 && path[1] == ':') {
+        _path += NPT_FilePath::Separator;
+    }
+
+    // get the file info
+    NPT_stat_struct stat_buffer;
+    int result = NPT_stat(_path, &stat_buffer);
+    if (result != 0) return MapErrno(errno);
+    
+    // setup the returned fields
+    if (info) {
+        info->m_Size = stat_buffer.st_size;
+        if (S_ISREG(stat_buffer.st_mode)) {
+            info->m_Type = NPT_FileInfo::FILE_TYPE_REGULAR;
+        } else if (S_ISDIR(stat_buffer.st_mode)) {
+            info->m_Type = NPT_FileInfo::FILE_TYPE_DIRECTORY;
+        } else {
+            info->m_Type = NPT_FileInfo::FILE_TYPE_OTHER;
+        }
+        info->m_AttributesMask &= NPT_FILE_ATTRIBUTE_READ_ONLY;
+        if ((stat_buffer.st_mode & S_IWUSR) == 0) {
+            info->m_Attributes &= NPT_FILE_ATTRIBUTE_READ_ONLY;
+        }
+    }
+    
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixNetwork.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,35 @@
+/*****************************************************************
+|
+|      Neptune - Network :: POSIX Implementation
+|
+|      (c) 2001-2005 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+
+#if defined(NPT_CONFIG_HAVE_NETCONFIG_H)
+#include <netconfig.h>
+
+#include "NptTypes.h"
+#include "NptStreams.h"
+#include "NptThreads.h"
+#include "NptNetwork.h"
+#include "NptUtils.h"
+#include "NptConstants.h"
+
+/*----------------------------------------------------------------------
+|       NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
+{
+    interfaces.Clear();
+    return NPT_SUCCESS;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,295 @@
+/*****************************************************************
+|
+|      Neptune - Queue :: Posix Implementation
+|
+|      (c) 2001-2002 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#if defined(__SYMBIAN32__)
+#include <stdio.h>
+#endif
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+#if defined(__SYMBIAN32__)
+#include <errno.h>
+#else
+#include <cerrno>
+#endif
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptQueue.h"
+#include "NptThreads.h"
+#include "NptList.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|       logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.queue.posix")
+
+/*----------------------------------------------------------------------
+|       NPT_PosixQueue
++---------------------------------------------------------------------*/
+class NPT_PosixQueue : public NPT_GenericQueue
+{
+public:
+    // methods
+               NPT_PosixQueue(NPT_Cardinal max_items);
+              ~NPT_PosixQueue();
+    NPT_Result Push(NPT_QueueItem* item, NPT_Timeout timeout); 
+    NPT_Result Pop(NPT_QueueItem*& item, NPT_Timeout timeout);
+    NPT_Result Peek(NPT_QueueItem*& item, NPT_Timeout timeout);
+
+private:
+    // members
+    NPT_Cardinal             m_MaxItems;
+    pthread_mutex_t          m_Mutex;
+    pthread_cond_t           m_CanPushCondition;
+    pthread_cond_t           m_CanPopCondition;
+    NPT_Cardinal             m_PushersWaitingCount;
+    NPT_Cardinal             m_PoppersWaitingCount;
+    NPT_List<NPT_QueueItem*> m_Items;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PosixQueue::NPT_PosixQueue
++---------------------------------------------------------------------*/
+NPT_PosixQueue::NPT_PosixQueue(NPT_Cardinal max_items) : 
+    m_MaxItems(max_items), 
+    m_PushersWaitingCount(0),
+    m_PoppersWaitingCount(0)
+{
+    NPT_LOG_FINER("NPT_PosixQueue::NPT_PosixQueue");
+
+    pthread_mutex_init(&m_Mutex, NULL);
+    pthread_cond_init(&m_CanPushCondition, NULL);
+    pthread_cond_init(&m_CanPopCondition, NULL);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixQueue::~NPT_PosixQueue()
++---------------------------------------------------------------------*/
+NPT_PosixQueue::~NPT_PosixQueue()
+{
+    // destroy resources
+    pthread_cond_destroy(&m_CanPushCondition);
+    pthread_cond_destroy(&m_CanPopCondition);
+    pthread_mutex_destroy(&m_Mutex);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixQueue::Push
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixQueue::Push(NPT_QueueItem* item, NPT_Timeout timeout)
+{
+    struct timespec timed;
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        // get current time from system
+        struct timeval now;
+        if (gettimeofday(&now, NULL)) {
+            return NPT_FAILURE;
+        }
+
+        now.tv_usec += timeout * 1000;
+        if (now.tv_usec >= 1000000) {
+            now.tv_sec += now.tv_usec / 1000000;
+            now.tv_usec = now.tv_usec % 1000000;
+        }
+
+        // setup timeout
+        timed.tv_sec  = now.tv_sec;
+        timed.tv_nsec = now.tv_usec * 1000;
+    }
+
+    // lock the mutex that protects the list
+    if (pthread_mutex_lock(&m_Mutex)) {
+        return NPT_FAILURE;
+    }
+
+    NPT_Result result = NPT_SUCCESS;
+    // check that we have not exceeded the max
+    if (m_MaxItems) {
+        while (m_Items.GetItemCount() >= m_MaxItems) {
+            // wait until we can push
+            ++m_PushersWaitingCount;
+            if (timeout == NPT_TIMEOUT_INFINITE) {
+                pthread_cond_wait(&m_CanPushCondition, &m_Mutex);
+                --m_PushersWaitingCount;
+            } else {
+                int wait_res = pthread_cond_timedwait(&m_CanPushCondition, 
+                                                      &m_Mutex, 
+                                                      &timed);
+                --m_PushersWaitingCount;
+                if (wait_res == ETIMEDOUT) {
+                    result = NPT_ERROR_TIMEOUT;
+                    break;
+                }
+            }
+        }
+    }
+
+    // add the item to the list
+    if (result == NPT_SUCCESS) {
+        m_Items.Add(item);
+
+        // wake up any thread that may be waiting to pop
+        if (m_PoppersWaitingCount) { 
+            pthread_cond_signal(&m_CanPopCondition);
+        }
+    }
+
+    // unlock the mutex
+    pthread_mutex_unlock(&m_Mutex);
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixQueue::Pop
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixQueue::Pop(NPT_QueueItem*& item, NPT_Timeout timeout)
+{
+    struct timespec timed;
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        // get current time from system
+        struct timeval now;
+        if (gettimeofday(&now, NULL)) {
+            return NPT_FAILURE;
+        }
+
+        now.tv_usec += timeout * 1000;
+        if (now.tv_usec >= 1000000) {
+            now.tv_sec += now.tv_usec / 1000000;
+            now.tv_usec = now.tv_usec % 1000000;
+        }
+
+        // setup timeout
+        timed.tv_sec  = now.tv_sec;
+        timed.tv_nsec = now.tv_usec * 1000;
+    }
+
+    // lock the mutex that protects the list
+    if (pthread_mutex_lock(&m_Mutex)) {
+        return NPT_FAILURE;
+    }
+
+    NPT_Result result;
+    if (timeout) {
+        while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) {
+            // no item in the list, wait for one
+            ++m_PoppersWaitingCount;
+            if (timeout == NPT_TIMEOUT_INFINITE) {
+                pthread_cond_wait(&m_CanPopCondition, &m_Mutex);
+                --m_PoppersWaitingCount;
+            } else {
+                int wait_res = pthread_cond_timedwait(&m_CanPopCondition, 
+                                                      &m_Mutex, 
+                                                      &timed);
+                --m_PoppersWaitingCount;
+                if (wait_res == ETIMEDOUT) {
+                    result = NPT_ERROR_TIMEOUT;
+                    break;
+                }
+            }
+        }
+    } else {
+        result = m_Items.PopHead(item);
+    }
+    
+    // wake up any thread that my be waiting to push
+    if (m_MaxItems && (result == NPT_SUCCESS) && m_PushersWaitingCount) {
+        pthread_cond_signal(&m_CanPushCondition);
+    }
+
+    // unlock the mutex
+    pthread_mutex_unlock(&m_Mutex);
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixQueue::Peek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixQueue::Peek(NPT_QueueItem*& item, NPT_Timeout timeout)
+{
+    struct timespec timed;
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        // get current time from system
+        struct timeval now;
+        if (gettimeofday(&now, NULL)) {
+            return NPT_FAILURE;
+        }
+
+        now.tv_usec += timeout * 1000;
+        if (now.tv_usec >= 1000000) {
+            now.tv_sec += now.tv_usec / 1000000;
+            now.tv_usec = now.tv_usec % 1000000;
+        }
+
+        // setup timeout
+        timed.tv_sec  = now.tv_sec;
+        timed.tv_nsec = now.tv_usec * 1000;
+    }
+
+    // lock the mutex that protects the list
+    if (pthread_mutex_lock(&m_Mutex)) {
+        return NPT_FAILURE;
+    }
+
+    NPT_Result result = NPT_SUCCESS;
+    NPT_List<NPT_QueueItem*>::Iterator head = m_Items.GetFirstItem();
+    if (timeout) {
+        while (!head) {
+            // no item in the list, wait for one
+            ++m_PoppersWaitingCount;
+            if (timeout == NPT_TIMEOUT_INFINITE) {
+                pthread_cond_wait(&m_CanPopCondition, &m_Mutex);
+                --m_PoppersWaitingCount;
+            } else {
+                int wait_res = pthread_cond_timedwait(&m_CanPopCondition, 
+                                                      &m_Mutex, 
+                                                      &timed);
+                --m_PoppersWaitingCount;
+                if (wait_res == ETIMEDOUT) {
+                    result = NPT_ERROR_TIMEOUT;
+                    break;
+                }
+            }
+
+            head = m_Items.GetFirstItem();
+        }
+    } else {
+        if (!head) result = NPT_ERROR_LIST_EMPTY;
+    }
+
+    item = head?*head:NULL;
+
+    // unlock the mutex
+    pthread_mutex_unlock(&m_Mutex);
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_GenericQueue::CreateInstance
++---------------------------------------------------------------------*/
+NPT_GenericQueue*
+NPT_GenericQueue::CreateInstance(NPT_Cardinal max_items)
+{
+    NPT_LOG_FINER_1("NPT_GenericQueue::CreateInstance - queue max_items = %ld", max_items);
+    return new NPT_PosixQueue(max_items);
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixSystem.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,181 @@
+/*****************************************************************
+|
+|      Neptune - System :: Posix Implementation
+|
+|      (c) 2001-2003 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptSystem.h"
+#include "NptResults.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   NPT_PosixSystem
++---------------------------------------------------------------------*/
+class NPT_PosixSystem
+{
+public:
+    // class variables
+    static NPT_PosixSystem System;
+    
+    // methods
+    NPT_PosixSystem();
+   ~NPT_PosixSystem();
+
+    // members
+    pthread_mutex_t m_SleepMutex;
+    pthread_cond_t  m_SleepCondition;
+};
+NPT_PosixSystem NPT_PosixSystem::System;
+
+/*----------------------------------------------------------------------
+|   NPT_PosixSystem::NPT_PosixSystem
++---------------------------------------------------------------------*/
+NPT_PosixSystem::NPT_PosixSystem()
+{
+    pthread_mutex_init(&m_SleepMutex, NULL);
+    pthread_cond_init(&m_SleepCondition, NULL);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_PosixSystem::~NPT_PosixSystem
++---------------------------------------------------------------------*/
+NPT_PosixSystem::~NPT_PosixSystem()
+{
+    pthread_cond_destroy(&m_SleepCondition);
+    pthread_mutex_destroy(&m_SleepMutex);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetProcessId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetProcessId(NPT_UInt32& id)
+{
+    id = getpid();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetCurrentTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetCurrentTimeStamp(NPT_TimeStamp& now)
+{
+    struct timeval now_tv;
+
+    // get current time from system
+    if (gettimeofday(&now_tv, NULL)) {
+        now.m_Seconds     = 0;
+        now.m_NanoSeconds = 0;
+        return NPT_FAILURE;
+    }
+    
+    // convert format
+    now.m_Seconds     = now_tv.tv_sec;
+    now.m_NanoSeconds = now_tv.tv_usec * 1000;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::Sleep
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::Sleep(const NPT_TimeInterval& duration)
+{
+    struct timespec time_req;
+    struct timespec time_rem;
+    int             result;
+
+    // setup the time value
+    time_req.tv_sec  = duration.m_Seconds;
+    time_req.tv_nsec = duration.m_NanoSeconds;
+
+    // sleep
+    do {
+        result = nanosleep(&time_req, &time_rem);
+        time_req = time_rem;
+    } while (result == -1 && errno == EINTR);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SleepUntil
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::SleepUntil(const NPT_TimeStamp& when)
+{
+    struct timespec timeout;
+    struct timeval  now;
+    int             result;
+
+    // get current time from system
+    if (gettimeofday(&now, NULL)) {
+        return NPT_FAILURE;
+    }
+
+    // setup timeout
+    timeout.tv_sec  = now.tv_sec + when.m_Seconds;
+    timeout.tv_nsec = now.tv_usec * 1000 + when.m_NanoSeconds;
+
+    if (timeout.tv_nsec >= 1000000000) {
+        timeout.tv_sec  += timeout.tv_nsec / 1000000000;
+        timeout.tv_nsec %= 1000000000;
+    }
+
+    // sleep
+    do {
+        result = pthread_cond_timedwait(&NPT_PosixSystem::System.m_SleepCondition, 
+                                        &NPT_PosixSystem::System.m_SleepMutex, 
+                                        &timeout);
+        if (result == ETIMEDOUT) {
+            return NPT_SUCCESS;
+        }
+    } while (result == EINTR);
+
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SetRandomSeed
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_System::SetRandomSeed(unsigned int seed)
+{
+    srand(seed);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetRandomInteger
++---------------------------------------------------------------------*/
+NPT_UInt32 
+NPT_System::GetRandomInteger()
+{
+    static bool seeded = false;
+    if (seeded == false) {
+        NPT_TimeStamp now;
+        GetCurrentTimeStamp(now);
+        SetRandomSeed(now.m_NanoSeconds);
+        seeded = true;
+    }
+
+    return rand();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixThreads.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,573 @@
+/*****************************************************************
+|
+|      Neptune - Threads :: Posix Implementation
+|
+|      (c) 2001-2002 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#if defined(__SYMBIAN32__)
+#include <stdio.h>
+#endif
+#include <pthread.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#if defined(__SYMBIAN32__)
+#include <errno.h>
+#else
+#include <cerrno>
+#endif
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptThreads.h"
+#include "NptLogging.h"
+#include "NptTime.h"
+#include "NptSystem.h"
+
+/*----------------------------------------------------------------------
+|       logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.threads.posix")
+
+/*----------------------------------------------------------------------
+|       NPT_PosixMutex
++---------------------------------------------------------------------*/
+class NPT_PosixMutex : public NPT_MutexInterface
+{
+public:
+    // methods
+             NPT_PosixMutex();
+    virtual ~NPT_PosixMutex();
+
+    // NPT_Mutex methods
+    virtual NPT_Result Lock();
+    virtual NPT_Result Unlock();
+
+private:
+    // members
+    pthread_mutex_t m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PosixMutex::NPT_PosixMutex
++---------------------------------------------------------------------*/
+NPT_PosixMutex::NPT_PosixMutex()
+{
+    pthread_mutex_init(&m_Mutex, NULL);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixMutex::~NPT_PosixMutex
++---------------------------------------------------------------------*/
+NPT_PosixMutex::~NPT_PosixMutex()
+{
+    pthread_mutex_destroy(&m_Mutex);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixMutex::Lock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixMutex::Lock()
+{
+    pthread_mutex_lock(&m_Mutex);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixMutex::Unlock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixMutex::Unlock()
+{
+    pthread_mutex_unlock(&m_Mutex);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Mutex::NPT_Mutex
++---------------------------------------------------------------------*/
+NPT_Mutex::NPT_Mutex()
+{
+    m_Delegate = new NPT_PosixMutex();
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable
++---------------------------------------------------------------------*/
+class NPT_PosixSharedVariable : public NPT_SharedVariableInterface
+{
+public:
+    // methods
+               NPT_PosixSharedVariable(int value);
+              ~NPT_PosixSharedVariable();
+    void       SetValue(int value);
+    int        GetValue();
+    NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout);
+    NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout);
+
+ private:
+    // members
+    volatile int    m_Value;
+    pthread_mutex_t m_Mutex;
+    pthread_cond_t  m_Condition;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable::NPT_PosixSharedVariable
++---------------------------------------------------------------------*/
+NPT_PosixSharedVariable::NPT_PosixSharedVariable(int value) : 
+    m_Value(value)
+{
+    pthread_mutex_init(&m_Mutex, NULL);
+    pthread_cond_init(&m_Condition, NULL);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable::~NPT_PosixSharedVariable
++---------------------------------------------------------------------*/
+NPT_PosixSharedVariable::~NPT_PosixSharedVariable()
+{
+    pthread_cond_destroy(&m_Condition);
+    pthread_mutex_destroy(&m_Mutex);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable::SetValue
++---------------------------------------------------------------------*/
+void
+NPT_PosixSharedVariable::SetValue(int value)
+{
+    pthread_mutex_lock(&m_Mutex);
+    m_Value = value;
+    pthread_cond_broadcast(&m_Condition);
+    pthread_mutex_unlock(&m_Mutex);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable::GetValue
++---------------------------------------------------------------------*/
+int
+NPT_PosixSharedVariable::GetValue()
+{
+    // we assume that int read/write are atomic on the platform
+    return m_Value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable::WaitUntilEquals
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixSharedVariable::WaitUntilEquals(int value, NPT_Timeout timeout)
+{
+    NPT_Result result = NPT_SUCCESS;
+    struct     timespec timed;
+
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        // get current time from system
+        struct timeval now;
+        if (gettimeofday(&now, NULL)) {
+            return NPT_FAILURE;
+        }
+
+        now.tv_usec += timeout * 1000;
+        if (now.tv_usec >= 1000000) {
+            now.tv_sec += now.tv_usec / 1000000;
+            now.tv_usec = now.tv_usec % 1000000;
+        }
+
+        // setup timeout
+        timed.tv_sec  = now.tv_sec;
+        timed.tv_nsec = now.tv_usec * 1000;
+    }
+    
+    pthread_mutex_lock(&m_Mutex);
+    while (value != m_Value) {
+        if (timeout == NPT_TIMEOUT_INFINITE) {
+            pthread_cond_wait(&m_Condition, &m_Mutex);
+        } else {
+            int wait_res = pthread_cond_timedwait(&m_Condition, &m_Mutex, &timed);
+            if (wait_res == ETIMEDOUT) {
+                result = NPT_ERROR_TIMEOUT;
+                break;
+            }
+        }
+    }
+    pthread_mutex_unlock(&m_Mutex);
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixSharedVariable::WaitWhileEquals
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixSharedVariable::WaitWhileEquals(int value, NPT_Timeout timeout)
+{
+    NPT_Result result = NPT_SUCCESS;
+    struct     timespec timed;
+
+    if (timeout != NPT_TIMEOUT_INFINITE) {
+        // get current time from system
+        struct timeval now;
+        if (gettimeofday(&now, NULL)) {
+            return NPT_FAILURE;
+        }
+
+        now.tv_usec += timeout * 1000;
+        if (now.tv_usec >= 1000000) {
+            now.tv_sec += now.tv_usec / 1000000;
+            now.tv_usec = now.tv_usec % 1000000;
+        }
+
+        // setup timeout
+        timed.tv_sec  = now.tv_sec;
+        timed.tv_nsec = now.tv_usec * 1000;
+    }
+    
+    pthread_mutex_lock(&m_Mutex);
+    while (value == m_Value) {
+        if (timeout == NPT_TIMEOUT_INFINITE) {
+            pthread_cond_wait(&m_Condition, &m_Mutex);
+        } else {
+            int wait_res = pthread_cond_timedwait(&m_Condition, &m_Mutex, &timed);
+            if (wait_res == ETIMEDOUT) {
+                result = NPT_ERROR_TIMEOUT;
+                break;
+            }
+        }
+    }
+    pthread_mutex_unlock(&m_Mutex);
+    
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_SharedVariable::NPT_SharedVariable
++---------------------------------------------------------------------*/
+NPT_SharedVariable::NPT_SharedVariable(int value)
+{
+    m_Delegate = new NPT_PosixSharedVariable(value);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable
++---------------------------------------------------------------------*/
+class NPT_PosixAtomicVariable : public NPT_AtomicVariableInterface
+{
+ public:
+    // methods
+         NPT_PosixAtomicVariable(int value);
+        ~NPT_PosixAtomicVariable();
+    int  Increment(); 
+    int  Decrement();
+    int  GetValue();
+    void SetValue(int value);
+
+ private:
+    // members
+    volatile int    m_Value;
+    pthread_mutex_t m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable::NPT_PosixAtomicVariable
++---------------------------------------------------------------------*/
+NPT_PosixAtomicVariable::NPT_PosixAtomicVariable(int value) : 
+    m_Value(value)
+{
+    pthread_mutex_init(&m_Mutex, NULL);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable::~NPT_PosixAtomicVariable
++---------------------------------------------------------------------*/
+NPT_PosixAtomicVariable::~NPT_PosixAtomicVariable()
+{
+    pthread_mutex_destroy(&m_Mutex);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable::Increment
++---------------------------------------------------------------------*/
+int
+NPT_PosixAtomicVariable::Increment()
+{
+    int value;
+
+    pthread_mutex_lock(&m_Mutex);
+    value = ++m_Value;
+    pthread_mutex_unlock(&m_Mutex);
+    
+    return value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable::Decrement
++---------------------------------------------------------------------*/
+int
+NPT_PosixAtomicVariable::Decrement()
+{
+    int value;
+
+    pthread_mutex_lock(&m_Mutex);
+    value = --m_Value;
+    pthread_mutex_unlock(&m_Mutex);
+    
+    return value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable::GetValue
++---------------------------------------------------------------------*/
+int
+NPT_PosixAtomicVariable::GetValue()
+{
+    // we assume that int read/write are atomic on the platform
+    return m_Value;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixAtomicVariable::SetValue
++---------------------------------------------------------------------*/
+void
+NPT_PosixAtomicVariable::SetValue(int value)
+{
+    pthread_mutex_lock(&m_Mutex);
+    m_Value = value;
+    pthread_mutex_unlock(&m_Mutex);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_AtomicVariable::NPT_AtomicVariable
++---------------------------------------------------------------------*/
+NPT_AtomicVariable::NPT_AtomicVariable(int value)
+{
+    m_Delegate = new NPT_PosixAtomicVariable(value);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread
++---------------------------------------------------------------------*/
+class NPT_PosixThread : public NPT_ThreadInterface
+{
+ public:
+    // methods
+                NPT_PosixThread(NPT_Thread*   delegator,
+                                NPT_Runnable& target,
+                                bool          detached);
+               ~NPT_PosixThread();
+    NPT_Result  Start(); 
+    NPT_Result  Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+ private:
+    // methods
+    static void* EntryPoint(void* argument);
+
+    // NPT_Runnable methods
+    void Run();
+
+    // NPT_Interruptible methods
+    NPT_Result Interrupt() { return NPT_ERROR_NOT_IMPLEMENTED; }
+
+    // members
+    NPT_Thread*        m_Delegator;
+    NPT_Runnable&      m_Target;
+    bool               m_Detached;
+    pthread_t          m_ThreadId;
+    bool               m_Joined;
+    NPT_PosixMutex     m_JoinLock;
+    NPT_SharedVariable m_Done;
+};
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread::NPT_PosixThread
++---------------------------------------------------------------------*/
+NPT_PosixThread::NPT_PosixThread(NPT_Thread*   delegator,
+                                 NPT_Runnable& target,
+                                 bool          detached) : 
+    m_Delegator(delegator),
+    m_Target(target),
+    m_Detached(detached),
+    m_ThreadId(0),
+    m_Joined(false)
+{
+    NPT_LOG_FINE("NPT_PosixThread::NPT_PosixThread");
+    m_Done.SetValue(0);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread::~NPT_PosixThread
++---------------------------------------------------------------------*/
+NPT_PosixThread::~NPT_PosixThread()
+{
+    NPT_LOG_FINE_1("NPT_PosixThread::~NPT_PosixThread %d\n", m_ThreadId);
+
+    if (!m_Detached) {
+        // we're not detached, and not in the Run() method, so we need to 
+        // wait until the thread is done
+        Wait();
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Thread::GetCurrentThreadId
++---------------------------------------------------------------------*/
+NPT_Thread::ThreadId 
+NPT_Thread::GetCurrentThreadId()
+{
+    pthread_t pid = pthread_self();
+    return (NPT_Thread::ThreadId)((void*)pid);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread::EntryPoint
++---------------------------------------------------------------------*/
+void*
+NPT_PosixThread::EntryPoint(void* argument)
+{
+    NPT_PosixThread* thread = reinterpret_cast<NPT_PosixThread*>(argument);
+
+    NPT_LOG_FINE("NPT_PosixThread::EntryPoint - in =======================");
+
+    // set random seed per thread
+    NPT_TimeStamp now;
+    NPT_System::GetCurrentTimeStamp(now);
+    NPT_System::SetRandomSeed((unsigned int)(now.m_NanoSeconds + (long)NPT_Thread::GetCurrentThreadId()));
+
+    // run the thread 
+    thread->Run();
+    
+    // Logging here will cause a crash on exit because LogManager may already be destroyed    
+    //NPT_LOG_FINE("NPT_PosixThread::EntryPoint - out ======================");
+
+    // we're done with the thread object
+    // if we're detached, we need to delete ourselves
+    if (thread->m_Detached) {
+        delete thread->m_Delegator;
+    } else {
+        // notify we're done
+        thread->m_Done.SetValue(1);
+    }
+
+    // done
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread::Start
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixThread::Start()
+{
+    NPT_LOG_FINE("NPT_PosixThread::Start - creating thread");
+
+    pthread_attr_t *attributes = NULL;
+
+#if defined(NPT_CONFIG_THREAD_STACK_SIZE)
+    pthread_attr_t stack_size_attributes;
+    pthread_attr_init(&stack_size_attributes);
+    pthread_attr_setstacksize(&stack_size_attributes, NPT_CONFIG_THREAD_STACK_SIZE);
+    attributes = &stack_size_attributes;
+#endif
+
+    // create a stack local id, as if detached, this object
+    // may already be deleted when pthread_create returns and
+    // before we get to call detach on the given thread
+    pthread_t id;
+    bool      detached = m_Detached;
+
+    // create the native thread
+    int result = pthread_create(&id, attributes, EntryPoint, 
+                                reinterpret_cast<void*>(this));
+    NPT_LOG_FINE_2("NPT_PosixThread::Start - id = %d, res=%d", 
+                   id, result);
+    if (result) {
+        // failed
+        return NPT_FAILURE;
+    } else {
+        // detach the thread if we're not joinable
+        if (detached) {
+            pthread_detach(id);
+        } else {
+            m_ThreadId = id;
+        }
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread::Run
++---------------------------------------------------------------------*/
+void
+NPT_PosixThread::Run()
+{
+    m_Target.Run();
+}
+
+/*----------------------------------------------------------------------
+|       NPT_PosixThread::Wait
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_PosixThread::Wait(NPT_Timeout timeout /* = NPT_TIMEOUT_INFINITE */)
+{
+    void* return_value;
+    int   result;
+
+    NPT_LOG_FINE_1("NPT_PosixThread::Wait - waiting for id %d", m_ThreadId);
+
+    // check that we're not detached
+    if (m_ThreadId == 0 || m_Detached) {
+        return NPT_FAILURE;
+    }
+
+    // wait for the thread to finish
+    m_JoinLock.Lock();
+    if (m_Joined) {
+        NPT_LOG_FINE_1("NPT_PosixThread::Wait - %d already joined", m_ThreadId);
+        result = 0;
+    } else {
+        NPT_LOG_FINE_1("NPT_PosixThread::Wait - joining thread id %d", m_ThreadId);
+        if (timeout != NPT_TIMEOUT_INFINITE) {
+            result = m_Done.WaitUntilEquals(1, timeout);
+            if (NPT_FAILED(result)) {
+                result = -1;
+                goto timedout;
+            }
+        }
+
+        result = pthread_join(m_ThreadId, &return_value);
+        m_Joined = true;
+    }
+
+timedout:
+    m_JoinLock.Unlock();
+    if (result != 0) {
+        return NPT_FAILURE;
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Thread::NPT_Thread
++---------------------------------------------------------------------*/
+NPT_Thread::NPT_Thread(bool detached)
+{
+    m_Delegate = new NPT_PosixThread(this, *this, detached);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Thread::NPT_Thread
++---------------------------------------------------------------------*/
+NPT_Thread::NPT_Thread(NPT_Runnable& target, bool detached)
+{
+    m_Delegate = new NPT_PosixThread(this, target, detached);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptSelectableMessageQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,84 @@
+/*****************************************************************
+|
+|      Neptune - Selectable Message Queue
+|
+|      (c) 2001-2003 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <unistd.h>
+
+#include "NptSelectableMessageQueue.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|    NPT_SelectableMessageQueue::NPT_SelectableMessageQueue
++---------------------------------------------------------------------*/
+NPT_SelectableMessageQueue::NPT_SelectableMessageQueue()
+{
+    if (pipe(m_Pipe) != 0) {
+        m_Pipe[0] = -1;
+        m_Pipe[1] = -1;
+    }
+}
+ 
+/*----------------------------------------------------------------------
+|    NPT_SelectableMessageQueue::~NPT_SelectableMessageQueue
++---------------------------------------------------------------------*/
+NPT_SelectableMessageQueue::~NPT_SelectableMessageQueue()
+{
+    close(m_Pipe[0]);
+    close(m_Pipe[1]);
+}
+ 
+/*----------------------------------------------------------------------
+|    NPT_SelectableMessageQueue::QueueMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SelectableMessageQueue::QueueMessage(NPT_Message*        message,
+                                         NPT_MessageHandler* handler)
+{
+    // first, queue the message
+    NPT_Result result = NPT_SimpleMessageQueue::QueueMessage(message, handler);
+
+    // then write a byte on the pipe to signal that there is a message
+    if (write(m_Pipe[1], "\0", 1) != 1) {
+        result = NPT_FAILURE;
+    }
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_SelectableMessageQueue::PumpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SelectableMessageQueue::PumpMessage(NPT_Timeout timeout /* = NPT_TIMEOUT_INFINITE */)
+{
+    NPT_Result result = NPT_SimpleMessageQueue::PumpMessage(timeout);
+    if (NPT_SUCCEEDED(result)) {
+        // flush the event
+        FlushEvent();
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|    NPT_SelectableMessageQueue::FlushEvent
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_SelectableMessageQueue::FlushEvent()
+{
+    char buffer[1];
+    if (read(m_Pipe[0], buffer, 1) != 1) {
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+ 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcConsole.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,25 @@
+/*****************************************************************
+|
+|      Neptune - Console Support: StdC Implementation
+|
+|      (c) 2002-2006 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+
+#include "NptConfig.h"
+#include "NptConsole.h"
+
+/*----------------------------------------------------------------------
+|       NPT_Console::Output
++---------------------------------------------------------------------*/
+void
+NPT_Console::Output(const char* message)
+{
+    printf("%s", message);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcDebug.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,39 @@
+/*****************************************************************
+|
+|      File: NptStdcDebug.c
+|
+|      Atomix - Debug Support: StdC Implementation
+|
+|      (c) 2002-2006 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "NptConfig.h"
+#include "NptDefs.h"
+#include "NptTypes.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|       NPT_Debug
++---------------------------------------------------------------------*/
+void
+NPT_Debug(const char* format, ...)
+{
+#if defined(NPT_DEBUG)
+    va_list args;
+    va_start(args, format);
+
+    vprintf(format, args);
+
+    va_end(args);
+#else
+    NPT_COMPILER_UNUSED(format);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcEnvironment.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,51 @@
+/*****************************************************************
+|
+|      Neptune - Environment variables: StdC Implementation
+|
+|      (c) 2002-2006 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "NptConfig.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   NPT_GetEnvironment
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_GetEnvironment(const char* name, NPT_String& value)
+{
+    char* env;
+
+    /* default value */
+    value.SetLength(0);
+
+#if defined(NPT_CONFIG_HAVE_GETENV)
+    env = getenv(name);
+    if (env) {
+        value = env;
+        return NPT_SUCCESS;
+    } else {
+        return NPT_ERROR_NO_SUCH_ITEM;
+    }
+#elif defined(NPT_CONFIG_HAVE_DUPENV_S)
+    if (dupenv_s(&env, NULL, name) != 0) {
+        return NPT_FAILURE;
+    } else if (env != NULL) {
+        value = env;
+        free(env);
+        return NPT_SUCCESS;
+    } else {
+        return NPT_ERROR_NO_SUCH_ITEM;
+    }
+#else
+#error "no getenv or getenv_s available on this platform"
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/StdC/NptStdcFile.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,560 @@
+/*****************************************************************
+|
+|   Neptune - Files :: Standard C Implementation
+|
+|   (c) 2001-2008 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE64
+#define _FILE_OFFSET_BITS 64
+
+#include <stdio.h>
+#if !defined(_WIN32_WCE)
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#else
+#include <stdio.h>
+#define errno GetLastError()
+#endif
+
+#include "NptConfig.h"
+#include "NptUtils.h"
+#include "NptFile.h"
+#include "NptThreads.h"
+#include "NptInterfaces.h"
+#include "NptStrings.h"
+#include "NptLogging.h"
+
+#if defined(NPT_CONFIG_HAVE_SHARE_H)
+#include <share.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1500
+extern "C" {
+    __int64 __cdecl _ftelli64(FILE *);
+    int __cdecl _fseeki64(FILE *, __int64, int);
+}
+#endif
+
+#if defined(_WIN32)
+extern FILE *NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags);
+extern FILE *NPT_fopen_utf8(const char* path, const char* mode);
+#define fopen   NPT_fopen_utf8
+#define fopen_s NPT_fopen_s_utf8
+#define _fsopen NPT_fsopen_utf8
+#endif
+
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.stdc.file")
+
+/*----------------------------------------------------------------------
+|   compatibility wrappers
++---------------------------------------------------------------------*/
+#if !defined(NPT_CONFIG_HAVE_FOPEN_S)
+static int fopen_s(FILE**      file,
+                   const char* filename,
+                   const char* mode)
+{
+    *file = fopen(filename, mode);
+
+#if defined(_WIN32_WCE)
+    if (*file == NULL) return ENOENT;
+#else
+    if (*file == NULL) return errno;
+#endif
+    return 0;
+}
+#endif // defined(NPT_CONFIG_HAVE_FOPEN_S
+
+/*----------------------------------------------------------------------
+|   MapErrno
++---------------------------------------------------------------------*/
+static NPT_Result
+MapErrno(int err) {
+    switch (err) {
+      case EACCES:       return NPT_ERROR_PERMISSION_DENIED;
+      case EPERM:        return NPT_ERROR_PERMISSION_DENIED;
+      case ENOENT:       return NPT_ERROR_NO_SUCH_FILE;
+#if defined(ENAMETOOLONG)
+      case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS;
+#endif
+      case EBUSY:        return NPT_ERROR_FILE_BUSY;
+      case EROFS:        return NPT_ERROR_FILE_NOT_WRITABLE;
+      case ENOTDIR:      return NPT_ERROR_FILE_NOT_DIRECTORY;
+      default:           return NPT_ERROR_ERRNO(err);
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileWrapper
++---------------------------------------------------------------------*/
+class NPT_StdcFileWrapper
+{
+public:
+    // constructors and destructor
+    NPT_StdcFileWrapper(FILE* file) : m_File(file) {}
+    ~NPT_StdcFileWrapper() {
+        if (m_File != NULL && 
+            m_File != stdin && 
+            m_File != stdout && 
+            m_File != stderr) {
+            fclose(m_File);
+        }
+    }
+
+    // methods
+    FILE* GetFile() { return m_File; }
+
+private:
+    // members
+    FILE* m_File;
+};
+
+typedef NPT_Reference<NPT_StdcFileWrapper> NPT_StdcFileReference;
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileStream
++---------------------------------------------------------------------*/
+class NPT_StdcFileStream
+{
+public:
+    // constructors and destructor
+    NPT_StdcFileStream(NPT_StdcFileReference file) :
+      m_FileReference(file) {}
+
+    // NPT_FileInterface methods
+    NPT_Result Seek(NPT_Position offset);
+    NPT_Result Tell(NPT_Position& offset);
+    NPT_Result Flush();
+
+protected:
+    // constructors and destructors
+    virtual ~NPT_StdcFileStream() {}
+
+    // members
+    NPT_StdcFileReference m_FileReference;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileStream::Seek(NPT_Position offset)
+{
+    size_t result;
+
+    result = NPT_fseek(m_FileReference->GetFile(), offset, SEEK_SET);
+    if (result == 0) {
+        return NPT_SUCCESS;
+    } else {
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileStream::Tell(NPT_Position& offset)
+{
+    offset = 0;
+
+    NPT_Int64 pos = NPT_ftell(m_FileReference->GetFile());
+    if (pos <=0) return NPT_FAILURE;
+
+    offset = pos;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileStream::Flush()
+{
+    fflush(m_FileReference->GetFile());
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileInputStream
++---------------------------------------------------------------------*/
+class NPT_StdcFileInputStream : public NPT_InputStream,
+                                private NPT_StdcFileStream
+                                
+{
+public:
+    // constructors and destructor
+    NPT_StdcFileInputStream(NPT_StdcFileReference& file, NPT_LargeSize size) :
+        NPT_StdcFileStream(file), m_Size(size) {}
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read);
+    NPT_Result Seek(NPT_Position offset) {
+        return NPT_StdcFileStream::Seek(offset);
+    }
+    NPT_Result Tell(NPT_Position& offset) {
+        return NPT_StdcFileStream::Tell(offset);
+    }
+    NPT_Result GetSize(NPT_LargeSize& size);
+    NPT_Result GetAvailable(NPT_LargeSize& available);
+
+private:
+    // members
+    NPT_LargeSize m_Size;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileInputStream::Read(void*     buffer, 
+                              NPT_Size  bytes_to_read, 
+                              NPT_Size* bytes_read)
+{
+    size_t nb_read;
+
+    // check the parameters
+    if (buffer == NULL) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // read from the file
+    nb_read = fread(buffer, 1, bytes_to_read, m_FileReference->GetFile());
+    if (nb_read > 0) {
+        if (bytes_read) *bytes_read = (NPT_Size)nb_read;
+        return NPT_SUCCESS;
+    } else if (feof(m_FileReference->GetFile())) {
+        if (bytes_read) *bytes_read = 0;
+        return NPT_ERROR_EOS;
+    } else {
+        if (bytes_read) *bytes_read = 0;
+        return NPT_ERROR_READ_FAILED;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileInputStream::GetSize(NPT_LargeSize& size)
+{
+    // keep track of where we are
+    NPT_Position offset = NPT_ftell(m_FileReference->GetFile());
+    
+    // seek to the end to get the size
+    NPT_fseek(m_FileReference->GetFile(), 0, SEEK_END);
+    size = NPT_ftell(m_FileReference->GetFile());
+    
+    // seek back to where we were
+    NPT_fseek(m_FileReference->GetFile(), offset, SEEK_SET);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileInputStream::GetAvailable(NPT_LargeSize& available)
+{
+    NPT_LargeSize size;
+    GetSize(size);
+
+    NPT_Int64 offset = NPT_ftell(m_FileReference->GetFile());
+    if (offset >= 0 && (NPT_LargeSize)offset <= size) {
+        available = size - offset;
+        return NPT_SUCCESS;
+    } else {
+        available = 0;
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileOutputStream
++---------------------------------------------------------------------*/
+class NPT_StdcFileOutputStream : public NPT_OutputStream,
+                                 private NPT_StdcFileStream
+{
+public:
+    // constructors and destructor
+    NPT_StdcFileOutputStream(NPT_StdcFileReference& file) :
+        NPT_StdcFileStream(file) {}
+
+    // NPT_InputStream methods
+    NPT_Result Write(const void* buffer, 
+                     NPT_Size    bytes_to_write, 
+                     NPT_Size*   bytes_written);
+    NPT_Result Seek(NPT_Position offset) {
+        return NPT_StdcFileStream::Seek(offset);
+    }
+    NPT_Result Tell(NPT_Position& offset) {
+        return NPT_StdcFileStream::Tell(offset);
+    }
+    NPT_Result Flush() {
+        return NPT_StdcFileStream::Flush();
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFileOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFileOutputStream::Write(const void* buffer, 
+                                NPT_Size    bytes_to_write, 
+                                NPT_Size*   bytes_written)
+{
+    size_t nb_written;
+
+    nb_written = fwrite(buffer, 1, bytes_to_write, m_FileReference->GetFile());
+
+    if (nb_written > 0) {
+        if (bytes_written) *bytes_written = (NPT_Size)nb_written;
+        return NPT_SUCCESS;
+    } else {
+        if (bytes_written) *bytes_written = 0;
+        return NPT_ERROR_WRITE_FAILED;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile
++---------------------------------------------------------------------*/
+class NPT_StdcFile: public NPT_FileInterface
+{
+public:
+    // constructors and destructor
+    NPT_StdcFile(NPT_File& delegator);
+   ~NPT_StdcFile();
+
+    // NPT_FileInterface methods
+    NPT_Result Open(OpenMode mode);
+    NPT_Result Close();
+    NPT_Result GetSize(NPT_LargeSize& size);
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+
+private:
+    // members
+    NPT_File&             m_Delegator;
+    OpenMode              m_Mode;
+    NPT_StdcFileReference m_FileReference;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::NPT_StdcFile
++---------------------------------------------------------------------*/
+NPT_StdcFile::NPT_StdcFile(NPT_File& delegator) :
+    m_Delegator(delegator),
+    m_Mode(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::~NPT_StdcFile
++---------------------------------------------------------------------*/
+NPT_StdcFile::~NPT_StdcFile()
+{
+    Close();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFile::Open(NPT_File::OpenMode mode)
+{
+    FILE* file = NULL;
+    
+    // check if we're already open
+    if (!m_FileReference.IsNull()) {
+        return NPT_ERROR_FILE_ALREADY_OPEN;
+    }
+
+    // store the mode
+    m_Mode = mode;
+
+    // check for special names
+    const char* name = (const char*)m_Delegator.GetPath();
+    if (NPT_StringsEqual(name, NPT_FILE_STANDARD_INPUT)) {
+        file = stdin;
+    } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_OUTPUT)) {
+        file = stdout;
+    } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_ERROR)) {
+        file = stderr;
+    } else {
+        // compute mode
+        const char* fmode = "";
+        if (mode & NPT_FILE_OPEN_MODE_WRITE) {
+            if (mode & NPT_FILE_OPEN_MODE_CREATE) {
+                if (mode & NPT_FILE_OPEN_MODE_TRUNCATE) {
+                    /* write, read, create, truncate */
+                    fmode = "w+b";
+                } else {
+                    /* write, read, create */
+                    fmode = "a+b";
+                }
+            } else {
+                if (mode & NPT_FILE_OPEN_MODE_TRUNCATE) {
+                    /* write, read, truncate */
+                    fmode = "w+b";
+                } else {
+                    /* write, read */
+                    fmode = "r+b";
+                }
+            }
+        } else {
+            /* read only */
+            fmode = "rb";
+        }
+
+        // open the file
+#if defined(NPT_CONFIG_HAVE_FSOPEN)
+        file = _fsopen(name, fmode, _SH_DENYWR);
+        int open_result = file == NULL ? ENOENT : 0; 
+#else
+        int open_result = fopen_s(&file, name, fmode);
+#endif
+
+        // test the result of the open
+        if (open_result != 0) return MapErrno(errno);
+    }
+
+    // unbuffer the file if needed 
+    if ((mode & NPT_FILE_OPEN_MODE_UNBUFFERED) && file != NULL) {
+#if !defined(_WIN32_WCE)
+        setvbuf(file, NULL, _IONBF, 0);
+#endif
+    }   
+    
+    // create a reference to the FILE object
+    m_FileReference = new NPT_StdcFileWrapper(file);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::Close
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_StdcFile::Close()
+{
+    // release the file reference
+    m_FileReference = NULL;
+
+    // reset the mode
+    m_Mode = 0;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::GetSize
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_StdcFile::GetSize(NPT_LargeSize& size)
+{
+    // default value
+    size = 0;
+
+    // check that the file is open
+    if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+    // get the size from the info (call GetInfo() in case it has not
+    // yet been called)
+    NPT_FileInfo info;
+    NPT_CHECK_FATAL(m_Delegator.GetInfo(info));
+    size = info.m_Size;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_StdcFile::GetInputStream(NPT_InputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+    // check that the mode is compatible
+    if (!(m_Mode & NPT_FILE_OPEN_MODE_READ)) {
+        return NPT_ERROR_FILE_NOT_READABLE;
+    }
+
+    // create a stream
+    NPT_LargeSize size = 0;
+    GetSize(size);
+    stream = new NPT_StdcFileInputStream(m_FileReference, size);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_StdcFile::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_StdcFile::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+    // check that the mode is compatible
+    if (!(m_Mode & NPT_FILE_OPEN_MODE_WRITE)) {
+        return NPT_ERROR_FILE_NOT_WRITABLE;
+    }
+    
+    // create a stream
+    stream = new NPT_StdcFileOutputStream(m_FileReference);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::NPT_File
++---------------------------------------------------------------------*/
+NPT_File::NPT_File(const char* path) :
+    m_Path(path)
+{
+    m_Delegate = new NPT_StdcFile(*this);
+    
+    if (NPT_StringsEqual(path, NPT_FILE_STANDARD_INPUT)  ||
+        NPT_StringsEqual(path, NPT_FILE_STANDARD_OUTPUT) ||
+        NPT_StringsEqual(path, NPT_FILE_STANDARD_ERROR)) {
+        m_Info.m_Type = NPT_FileInfo::FILE_TYPE_SPECIAL;
+    } 
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::operator=
++---------------------------------------------------------------------*/
+NPT_File& 
+NPT_File::operator=(const NPT_File& file)
+{
+    if (this != &file) {
+        delete m_Delegate;
+        m_Path = file.m_Path;
+        m_Info = file.m_Info;
+        m_Delegate = new NPT_StdcFile(*this);
+    }
+    return *this;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Symbian/NptSymbianSystem.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,116 @@
+/*****************************************************************
+|
+|   Neptune - System :: Win32 Implementation
+|
+|   (c) 2001-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "e32cmn.h"
+#include "e32math.h"
+#include "sys/time.h"
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptSystem.h"
+#include "NptResults.h"
+#include "NptDebug.h"
+
+
+/*----------------------------------------------------------------------
+|   globals
++---------------------------------------------------------------------*/
+static TInt64 NPT_System_RandomGeneratorSeed = 0;
+
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetProcessId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetProcessId(NPT_UInt32& id)
+{
+    //id = getpid();
+    id = 0;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetCurrentTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetCurrentTimeStamp(NPT_TimeStamp& now)
+{
+    struct timeval now_tv;
+
+    /* get current time from system */
+    if (gettimeofday(&now_tv, NULL)) {
+        now.m_Seconds     = 0;
+        now.m_NanoSeconds = 0;
+        return NPT_FAILURE;
+    }
+
+    /* convert format */
+    now.m_Seconds     = now_tv.tv_sec;
+    now.m_NanoSeconds = now_tv.tv_usec * 1000;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::Sleep
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::Sleep(const NPT_TimeInterval& duration)
+{
+    TTimeIntervalMicroSeconds32  milliseconds = 1000*duration.m_Seconds + duration.m_NanoSeconds/1000000;
+    User::After(milliseconds); /* FIXME: this doesn't behave like a normal sleep() where the processor idles. Need to use CTimer much more complicated logic. */
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SleepUntil
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::SleepUntil(const NPT_TimeStamp& when)
+{
+    NPT_TimeStamp now;
+    GetCurrentTimeStamp(now);
+    if (when > now) {
+        NPT_TimeInterval duration = when-now;
+        return Sleep(duration);
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SetRandomSeed
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_System::SetRandomSeed(unsigned int seed)
+{
+    NPT_System_RandomGeneratorSeed = seed;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::NPT_System
++---------------------------------------------------------------------*/
+NPT_UInt32 
+NPT_System::GetRandomInteger()
+{
+    if (!NPT_System_RandomGeneratorSeed) {
+        TTime time;
+        time.HomeTime();
+        
+        NPT_System::SetRandomSeed(time.Int64());
+    }
+
+    return Math::Rand(NPT_System_RandomGeneratorSeed);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Console.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,28 @@
+/*****************************************************************
+|
+|   Neptune - Console Support: Win32 Implementation
+|
+|   (c) 2002-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <windows.h>
+#include <stdio.h>
+
+#include "NptConfig.h"
+#include "NptConsole.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Console::Output
++---------------------------------------------------------------------*/
+void
+NPT_Console::Output(const char* message)
+{
+    OutputDebugString(message);
+    printf("%s", message);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Debug.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,107 @@
+/*****************************************************************
+|
+|   Neptune - Debug Support: Win32 Implementation
+|
+|   (c) 2002-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <stdarg.h>
+#include <stdio.h>
+#if defined(_XBOX)
+#include <xtl.h>
+#else
+#include <windows.h>
+#endif
+
+#include "NptConfig.h"
+#include "NptDefs.h"
+#include "NptTypes.h"
+#include "NptDebug.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|   constants
++---------------------------------------------------------------------*/
+#define NPT_DEBUG_LOCAL_BUFFER_SIZE 1024
+#define NPT_DEBUG_BUFFER_INCREMENT  4096
+#define NPT_DEBUG_BUFFER_MAX_SIZE   65536
+
+#if defined(NPT_CONFIG_ENABLE_LOGGING)
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune,debug.win32")
+
+/*----------------------------------------------------------------------
+|   NPT_Print
++---------------------------------------------------------------------*/
+static void
+NPT_Print(const char* message)
+{
+#if !defined(_WIN32_WCE)
+    OutputDebugString(message);
+#endif
+    NPT_LOG_FINER_1("%s", message);
+}
+#elif defined(NPT_DEBUG)
+/*----------------------------------------------------------------------
+|   NPT_Print
++---------------------------------------------------------------------*/
+static void
+NPT_Print(const char* message)
+{
+#if !defined(_WIN32_WCE)
+    OutputDebugString(message);
+#endif
+    printf("%s", message);
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_Debug
++---------------------------------------------------------------------*/
+void
+NPT_Debug(const char* format, ...)
+{
+#if defined(NPT_DEBUG) || defined(NPT_CONFIG_ENABLE_LOGGING)
+    char         local_buffer[NPT_DEBUG_LOCAL_BUFFER_SIZE];
+    unsigned int buffer_size = NPT_DEBUG_LOCAL_BUFFER_SIZE;
+    char*        buffer = local_buffer;
+    va_list      args;
+
+    va_start(args, format);
+
+    for(;;) {
+        int result;
+
+        /* try to format the message (it might not fit) */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
+        /* use the secure function for VC 8 and above */
+        result = _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args);
+#else
+        result = _vsnprintf(buffer, buffer_size-1, format, args);
+#endif
+        buffer[buffer_size-1] = 0; /* force a NULL termination */
+        if (result >= 0) break;
+
+        /* the buffer was too small, try something bigger */
+        buffer_size = (buffer_size+NPT_DEBUG_BUFFER_INCREMENT)*2;
+        if (buffer_size > NPT_DEBUG_BUFFER_MAX_SIZE) break;
+        if (buffer != local_buffer) delete[] buffer;
+        buffer = new char[buffer_size];
+        if (buffer == NULL) return;
+    }
+
+    NPT_Print(buffer);
+    if (buffer != local_buffer) delete[] buffer;
+
+    va_end(args);
+#else
+    NPT_COMPILER_UNUSED(format);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32DynamicLibraries.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,98 @@
+/*****************************************************************
+ |
+ |      Neptune - Dynamic Libraries :: Win32 Implementation
+ |
+ |      (c) 2001-2008 Gilles Boccon-Gibod
+ |      Author: Gilles Boccon-Gibod (bok@bok.net)
+ |
+ ****************************************************************/
+
+ /*----------------------------------------------------------------------
+ |   includes
+ +---------------------------------------------------------------------*/
+#include "NptLogging.h"
+#include "NptDynamicLibraries.h"
+
+#include <windows.h>
+
+ /*----------------------------------------------------------------------
+ |   logging
+ +---------------------------------------------------------------------*/
+ NPT_SET_LOCAL_LOGGER("neptune.win32.dynamic-libraries")
+
+ /*----------------------------------------------------------------------
+ |   NPT_Win32DynamicLibrary
+ +---------------------------------------------------------------------*/
+class NPT_Win32DynamicLibrary : public NPT_DynamicLibraryInterface
+{
+public:
+    // constructor and destructor
+    NPT_Win32DynamicLibrary(HMODULE library, const char* name) : 
+      m_Library(library), m_Name(name) {}
+
+      // NPT_DynamicLibraryInterface methods
+      virtual NPT_Result FindSymbol(const char* name, void*& symbol);
+      virtual NPT_Result Unload();
+
+private:
+    // members
+    HMODULE    m_Library;
+    NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_DynamicLibrary::Load
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_DynamicLibrary::Load(const char* name, NPT_Flags flags, NPT_DynamicLibrary*& library)
+{
+    NPT_COMPILER_UNUSED(flags);
+    if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+    // default return value
+    library = NULL;
+
+    // load the lib
+    NPT_LOG_FINE_2("loading library %s, flags=%x", name, flags);
+    HMODULE handle = LoadLibrary(name);
+    if (handle == NULL) {
+        NPT_LOG_FINE("library not found");
+        return NPT_FAILURE;
+    }
+
+    // instantiate the object
+    NPT_LOG_FINE_1("library %s loaded", name);
+    library = new NPT_DynamicLibrary(new NPT_Win32DynamicLibrary(handle, name));
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32DynamicLibrary::FindSymbol
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Win32DynamicLibrary::FindSymbol(const char* name, void*& symbol)
+{
+    if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+    symbol = NULL;
+    if (m_Library == NULL) return NPT_ERROR_NO_SUCH_ITEM;
+
+    NPT_LOG_FINE_1("finding symbol %s", name);
+    symbol = GetProcAddress(m_Library, name);
+    return symbol?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32DynamicLibrary::Unload
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32DynamicLibrary::Unload()
+{
+    NPT_LOG_FINE_1("unloading library %s", (const char*)m_Name);
+    BOOL result = FreeLibrary(m_Library);
+    if (result) {
+        return NPT_SUCCESS;
+    } else {
+        return NPT_FAILURE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32File.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,426 @@
+/*****************************************************************
+|
+|      Neptune - File :: Win32 Implementation
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptLogging.h"
+#include "NptFile.h"
+#include "NptUtils.h"
+
+#if defined(_XBOX)
+#include <xtl.h>
+#else
+#include <windows.h>
+#include <malloc.h>
+#include <limits.h>
+#endif
+#include <assert.h>
+
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+//NPT_SET_LOCAL_LOGGER("neptune.win32.file")
+
+/*----------------------------------------------------------------------
+|   fix windows macros
++---------------------------------------------------------------------*/
+#if !defined(_WIN32_WCE)
+#if defined(CreateDirectory)
+#undef CreateDirectory
+#endif
+
+#if defined(DeleteFile)
+#undef DeleteFile
+#endif
+#endif
+
+/*----------------------------------------------------------------------
+|   A2WHelper
++---------------------------------------------------------------------*/
+static LPWSTR A2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
+{
+    int ret;
+
+    assert(lpa != NULL);
+    assert(lpw != NULL);
+    if (lpw == NULL || lpa == NULL) return NULL;
+
+    lpw[0] = '\0';
+    ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
+    if (ret == 0) {
+        assert(0);
+        return NULL;
+    }        
+    return lpw;
+}
+
+/*----------------------------------------------------------------------
+|   W2AHelper
++---------------------------------------------------------------------*/
+static LPSTR W2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp)
+{
+    int ret;
+
+    assert(lpw != NULL);
+    assert(lpa != NULL);
+    if (lpa == NULL || lpw == NULL) return NULL;
+
+    lpa[0] = '\0';
+    ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
+    if (ret == 0) {
+        assert(0);
+        return NULL;
+    }
+    return lpa;
+}
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+/* UNICODE support */
+#if !defined(_XBOX)
+#define NPT_WIN32_USE_CHAR_CONVERSION int _convert = 0; LPCWSTR _lpw = NULL; LPCSTR _lpa = NULL
+
+#define NPT_WIN32_A2W(lpa) (\
+    ((_lpa = lpa) == NULL) ? NULL : (\
+    _convert = (int)(strlen(_lpa)+1),\
+    (INT_MAX/2<_convert)? NULL :  \
+    A2WHelper((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, CP_UTF8)))
+
+#define NPT_WIN32_W2A(lpw) (\
+    ((_lpw = lpw) == NULL) ? NULL : (\
+    (_convert = (lstrlenW(_lpw)+1), \
+    (_convert>INT_MAX/2) ? NULL : \
+    W2AHelper((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), CP_UTF8))))
+
+#else
+#define NPT_WIN32_USE_CHAR_CONVERSION
+#define NPT_WIN32_W2A(_s)       (_s)
+#define NPT_WIN32_A2W(_s)       (_s)
+#define GetFileAttributesW      GetFileAttributes
+#define FindFirstFileW          FindFirstFile
+#define FindNextFileW           FindNextFile
+#define FindCloseW              FindClose
+#define CreateDirectoryW        CreateDirectoryA
+#define RemoveDirectoryW        RemoveDirectoryA
+#define DeleteFileW             DeleteFileA
+#define MoveFileW               MoveFileA
+#define WIN32_FIND_DATAW        WIN32_FIND_DATA
+#endif
+
+/*----------------------------------------------------------------------
+|   MapError
++---------------------------------------------------------------------*/
+static NPT_Result
+MapError(DWORD err) {
+    switch (err) {
+      case ERROR_ALREADY_EXISTS:      return NPT_ERROR_FILE_ALREADY_EXISTS;
+      case ERROR_PATH_NOT_FOUND:    
+      case ERROR_FILE_NOT_FOUND:    
+      case ERROR_INVALID_DRIVE:
+      case ERROR_BAD_PATHNAME:
+      case ERROR_BAD_NET_NAME:
+      case ERROR_FILENAME_EXCED_RANGE:
+      case ERROR_NO_MORE_FILES:
+      case ERROR_BAD_NETPATH:         return NPT_ERROR_NO_SUCH_FILE;
+      case ERROR_LOCK_VIOLATION:
+      case ERROR_SEEK_ON_DEVICE:
+      case ERROR_CURRENT_DIRECTORY:
+      case ERROR_CANNOT_MAKE:
+      case ERROR_FAIL_I24:
+      case ERROR_NETWORK_ACCESS_DENIED:
+      case ERROR_DRIVE_LOCKED:
+      case ERROR_ACCESS_DENIED:       return NPT_ERROR_PERMISSION_DENIED;
+      case ERROR_NOT_LOCKED:
+      case ERROR_LOCK_FAILED:
+      case ERROR_SHARING_VIOLATION:   return NPT_ERROR_FILE_BUSY;
+      case ERROR_INVALID_FUNCTION:    return NPT_ERROR_INTERNAL;
+      case ERROR_NOT_ENOUGH_QUOTA:    return NPT_ERROR_OUT_OF_MEMORY;
+      case ERROR_ARENA_TRASHED:
+      case ERROR_NOT_ENOUGH_MEMORY:
+      case ERROR_INVALID_BLOCK:       return NPT_ERROR_OUT_OF_MEMORY;
+      case ERROR_DISK_FULL:           return NPT_ERROR_FILE_NOT_ENOUGH_SPACE;
+      case ERROR_TOO_MANY_OPEN_FILES: return NPT_ERROR_OUT_OF_RESOURCES;
+      case ERROR_INVALID_HANDLE:      
+      case ERROR_INVALID_ACCESS:
+      case ERROR_INVALID_DATA:        return NPT_ERROR_INVALID_PARAMETERS;
+      case ERROR_DIR_NOT_EMPTY:       return NPT_ERROR_DIRECTORY_NOT_EMPTY;
+      case ERROR_NEGATIVE_SEEK:       return NPT_ERROR_OUT_OF_RANGE;
+      default:                        return NPT_FAILURE;
+    }
+}
+
+#if defined(_WIN32_WCE)
+/*----------------------------------------------------------------------
+|   NPT_stat_utf8
++---------------------------------------------------------------------*/
+int
+NPT_stat_utf8(const char* path, struct __stat64* info)
+{
+    return -1;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_getcwd_utf8
++---------------------------------------------------------------------*/
+char*
+NPT_getcwd_utf8(char* dir, int max_size)
+{
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_fopen_utf8
++---------------------------------------------------------------------*/
+FILE*
+NPT_fopen_utf8(const char* path, const char* mode)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    return _wfopen(NPT_WIN32_A2W(path), NPT_WIN32_A2W(mode));
+}
+#elif defined(_XBOX)
+#include <sys/stat.h>
+/*----------------------------------------------------------------------
+|   NPT_stat_utf8
++---------------------------------------------------------------------*/
+int
+NPT_stat_utf8(const char* path, struct __stat64* info)
+{
+    return _stat64(path, info);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_getcwd_utf8
++---------------------------------------------------------------------*/
+char*
+NPT_getcwd_utf8(char* dir, unsigned int max_size)
+{
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_fsopen_utf8
++---------------------------------------------------------------------*/
+FILE*
+NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    return _fsopen(path, mode, sh_flags);
+}
+#else
+#include <sys/stat.h>
+#include <direct.h>
+
+/*----------------------------------------------------------------------
+|   NPT_stat_utf8
++---------------------------------------------------------------------*/
+int
+NPT_stat_utf8(const char* path, struct __stat64* info)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    return _wstat64(NPT_WIN32_A2W(path), info);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_getcwd_utf8
++---------------------------------------------------------------------*/
+char*
+NPT_getcwd_utf8(char* dir, unsigned int max_size)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    WCHAR* wdir = (WCHAR*)alloca(2*(max_size+1));
+    WCHAR* result = _wgetcwd(wdir, max_size);
+    if (result == NULL) return NULL;
+    char* converted = NPT_WIN32_W2A(result);
+    NPT_CopyString(dir, converted);
+    return dir;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_fsopen_utf8
++---------------------------------------------------------------------*/
+FILE*
+NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    return _wfsopen(NPT_WIN32_A2W(path), NPT_WIN32_A2W(mode + NPT_String(", ccs=UNICODE")), sh_flags);
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_FilePath::Separator
++---------------------------------------------------------------------*/
+const NPT_String NPT_FilePath::Separator("\\");
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetRoots
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetRoots(NPT_List<NPT_String>& roots)
+{
+    roots.Clear();
+#if defined(_WIN32_WCE) || defined(_XBOX)
+    return NPT_ERROR_NOT_IMPLEMENTED;
+#else
+    DWORD drives = GetLogicalDrives();
+    for (unsigned int i=0; i<26; i++) {
+        if (drives & (1<<i)) {
+            char drive_name[4] = {'A'+i, ':', '\\', 0};
+            roots.Add(drive_name);
+        }
+    }
+    return NPT_SUCCESS;
+#endif
+}
+
+#if defined(_WIN32_WCE)
+/*----------------------------------------------------------------------
+|   NPT_File::GetWorkingDirectory
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetWorkingDirectory(NPT_String& path)
+{
+    path.SetLength(0);
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
+{
+    return NPT_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_File::CreateDirectory
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::CreateDirectory(const char* path)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    BOOL result = ::CreateDirectoryW(NPT_WIN32_A2W(path), NULL);
+    if (result == 0) {
+        return MapError(GetLastError());
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::DeleteFile
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::DeleteFile(const char* path)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    BOOL result = ::DeleteFileW(NPT_WIN32_A2W(path));
+    if (result == 0) {
+        return MapError(GetLastError());
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::DeleteDirectory
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::DeleteDirectory(const char* path)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    BOOL result = RemoveDirectoryW(NPT_WIN32_A2W(path));
+    if (result == 0) {
+        return MapError(GetLastError());
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::Rename
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Rename(const char* from_path, const char* to_path)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+    BOOL result = MoveFileW(NPT_WIN32_A2W(from_path), NPT_WIN32_A2W(to_path));
+    if (result == 0) {
+        return MapError(GetLastError());
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File_ProcessFindData
++---------------------------------------------------------------------*/
+static bool
+NPT_File_ProcessFindData(WIN32_FIND_DATAW* find_data)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+
+    // discard system specific files/shortcuts
+    if (NPT_StringsEqual(NPT_WIN32_W2A(find_data->cFileName), ".") || 
+        NPT_StringsEqual(NPT_WIN32_W2A(find_data->cFileName), "..")) {
+        return false;
+    }
+
+    return true;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_File::ListDirectory
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_File::ListDirectory(const char*           path, 
+                        NPT_List<NPT_String>& entries, 
+                        NPT_Ordinal           start /* = 0 */, 
+                        NPT_Cardinal          max   /* = 0 */)
+{
+    NPT_WIN32_USE_CHAR_CONVERSION;
+
+    // default return value
+    entries.Clear();
+
+    // check the arguments
+    if (path == NULL || path[0] == '\0') return NPT_ERROR_INVALID_PARAMETERS;
+
+    // construct a path name with a \* wildcard at the end
+    NPT_String path_pattern = path;
+    if (path_pattern.EndsWith("\\") || path_pattern.EndsWith("/")) {
+        path_pattern += "*";
+    } else {
+        path_pattern += "\\*";
+    }
+
+    // list the entries
+    WIN32_FIND_DATAW find_data;
+    HANDLE find_handle = FindFirstFileW(NPT_WIN32_A2W(path_pattern.GetChars()), &find_data);
+    if (find_handle == INVALID_HANDLE_VALUE) return MapError(GetLastError());
+    NPT_Cardinal count = 0;
+    do {
+        if (NPT_File_ProcessFindData(&find_data)) {
+            // continue if not yet first item requested
+            if (start > 0) {
+                --start;
+                continue;
+            }
+            entries.Add(NPT_WIN32_W2A(find_data.cFileName));
+
+            // stop when reaching maximum requested
+            if (max && ++count == max) return NPT_SUCCESS;
+        }
+    } while (FindNextFileW(find_handle, &find_data));
+    DWORD last_error = GetLastError();
+    FindClose(find_handle);
+    if (last_error != ERROR_NO_MORE_FILES) return MapError(last_error);
+
+    return NPT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32HttpProxy.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,43 @@
+/*****************************************************************
+|
+|      Neptune - HTTP Proxy :: WinHttp Implementation
+|
+|      (c) 2001-2007 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+//#include <Winhttp.h>
+#include "NptResults.h"
+#include "NptHttp.h"
+#include "NptThreads.h"
+
+#if 0 // not implemented yet
+HINTERNET NPT_Win32HttpHandle = INVALID_HANDLE_VALUE;
+NPT_Lock NPT_Win32HttpLock;
+
+/*----------------------------------------------------------------------
+|       NPT_HttpProxySelector::GetSystemDefault
++---------------------------------------------------------------------*/
+NPT_HttpProxySelector*
+NPT_HttpProxySelector::GetSystemDefault()
+{
+    NPT_AutoLock lock(NPT_Win32HttpLock);
+
+    if (NPT_Win32HttpHandle == INVALID_HANDLE_VALUE) {
+        WINHTTP_CURRENT_USER_IE_PROXY_CONFIG config;
+        BOOL result = WinHttpGetIEProxyConfigForCurrentUser(&config);
+    }
+
+    return NULL;
+}
+#else
+NPT_HttpProxySelector*
+NPT_HttpProxySelector::GetSystemDefault()
+{
+    return NULL;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32MessageQueue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,183 @@
+/*****************************************************************
+|
+|      Neptune - Win32 Message Queue
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include "NptWin32MessageQueue.h"
+
+/*----------------------------------------------------------------------
+|       platform adaptation
++---------------------------------------------------------------------*/
+#if defined(_WIN32_WCE)
+#define GetWindowLongPtr GetWindowLong
+#define SetWindowLongPtr SetWindowLong
+#endif
+
+/*----------------------------------------------------------------------
+|       constants
++---------------------------------------------------------------------*/
+const int NPT_WIN32_MESSAGE_ID_BASE = WM_USER + 9200;
+
+/*----------------------------------------------------------------------
+|       NPT_Win32WindowMessageQueue
++---------------------------------------------------------------------*/
+NPT_Win32WindowMessageQueue::NPT_Win32WindowMessageQueue()
+{
+    // create a hidden window to process our incoming messages
+    WNDCLASS wclass;
+
+    // compute a unique class name
+    m_ClassName[0] = 'N';
+    m_ClassName[1] = 'P';
+    m_ClassName[2] = 'T';
+    m_ClassName[3] = 'H';
+    m_ClassName[4] = 'W';
+    NPT_String tid = NPT_String::FromInteger(GetCurrentThreadId());
+    for (unsigned int i=0; i<=tid.GetLength(); i++) {
+        m_ClassName[5+i] = tid.GetChars()[i];        
+    }
+
+    // register a window class
+    wclass.style         = 0;
+    wclass.lpfnWndProc   = NPT_Win32WindowMessageQueue::WindowProcedure;
+    wclass.cbClsExtra    = 0;
+    wclass.cbWndExtra    = 0;
+    wclass.hInstance     = GetModuleHandle(NULL);
+    wclass.hIcon         = NULL;
+    wclass.hCursor       = NULL;
+    wclass.hbrBackground = NULL;
+    wclass.lpszMenuName  = NULL;
+    wclass.lpszClassName = m_ClassName;
+
+    // register the class and ignore any error because we might
+    // be registering the class more than once                  
+    RegisterClass(&wclass);
+
+    // create the hidden window
+    m_WindowHandle = CreateWindow(
+        wclass.lpszClassName, // pointer to registered class name 
+        TEXT(""),             // pointer to window name 
+        0,                    // window style 
+        0,                    // horizontal position of window 
+        0,                    // vertical position of window 
+        0,                    // window width 
+        0,                    // window height 
+        NULL,                 // handle to parent or owner window 
+        NULL,                 // handle to menu or child-window identifier 
+        wclass.hInstance,     // handle to application instance 
+        NULL);
+
+    // set a pointer to ourself as user data */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable: 4244) // we have to test for this because SetWindowLongPtr
+                                // is incorrectly defined, so we'll get a C4244 warning
+#endif // _MSC_VER
+    if (m_WindowHandle) {
+        SetWindowLongPtr(m_WindowHandle, GWL_USERDATA, NPT_POINTER_TO_LONG(this));
+    }
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif // _MSC_VER
+    m_hInstance = wclass.hInstance;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Win32WindowMessageQueue
++---------------------------------------------------------------------*/
+NPT_Win32WindowMessageQueue::~NPT_Win32WindowMessageQueue() 
+{
+    // remove ourself as user data to ensure we're not called anymore
+    SetWindowLongPtr(m_WindowHandle, GWL_USERDATA, 0);
+
+    // destroy the hidden window
+    DestroyWindow(m_WindowHandle);
+
+    // unregister the window class
+    UnregisterClass(m_ClassName, m_hInstance);
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Win32WindowMessageQueue::WindowProcedure
++---------------------------------------------------------------------*/
+LRESULT CALLBACK 
+NPT_Win32WindowMessageQueue::WindowProcedure(HWND   window, 
+                                             UINT   message,
+                                             WPARAM wparam, 
+                                             LPARAM lparam)
+{
+    // if it is a windows message, just pass it along
+    if (message != (UINT) NPT_WIN32_MESSAGE_ID_BASE) {
+        return DefWindowProc(window, message, wparam, lparam);
+    }
+
+    // dispatch the message to the handler
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable: 4312) // we have to test for this because GetWindowLongPtr
+                                // is incorrectly defined, so we'll get a C4244 warning
+#endif // _MSC_VER
+    NPT_Win32WindowMessageQueue* queue = reinterpret_cast<NPT_Win32WindowMessageQueue *>(GetWindowLongPtr(window, GWL_USERDATA));
+#if defined(_MSC_VER)
+#pragma warning( pop )  
+#endif // _MSC_VER
+    if (queue == NULL) {
+        return 0; 
+    }
+    queue->HandleMessage(reinterpret_cast<NPT_Message*>(lparam),
+        reinterpret_cast<NPT_MessageHandler*>(wparam));
+    return 0;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Win32WindowMessageQueue::PumpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32WindowMessageQueue::PumpMessage(NPT_Timeout)
+{
+    // you cannot pump messages on this type of queue, since they will
+    // be pumped by the main windows message loop 
+    return NPT_ERROR_NOT_SUPPORTED; 
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Win32WindowMessageQueue::QueueMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32WindowMessageQueue::QueueMessage(NPT_Message*        message,
+                                          NPT_MessageHandler* handler)
+{
+    int result;
+
+    result = ::PostMessage(m_WindowHandle, 
+        NPT_WIN32_MESSAGE_ID_BASE, 
+        (WPARAM)handler, 
+        (LPARAM)message);
+
+    if (result == 0) return NPT_FAILURE;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|       NPT_Win32WindowMessageQueue::HandleMessage
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32WindowMessageQueue::HandleMessage(NPT_Message*        message,
+                                           NPT_MessageHandler* handler)
+{
+    NPT_Result result = NPT_FAILURE;
+
+    if (message && handler) {
+        result = handler->HandleMessage(message);
+    }
+    delete message;
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32MessageQueue.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,49 @@
+/*****************************************************************
+|
+|      Neptune - Win32 Message Queue
+|
+|      (c) 2001-2008 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+#ifndef _NPT_WIN32_MESSAGE_QUEUE_
+#define _NPT_WIN32_MESSAGE_QUEUE_
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <windows.h>
+#include <TCHAR.h>
+#include "NptStrings.h"
+#include "NptMessaging.h"
+#include "NptSimpleMessageQueue.h"
+
+/*----------------------------------------------------------------------
+|       NPT_Win32MessageQueue
++---------------------------------------------------------------------*/
+class NPT_Win32WindowMessageQueue : public NPT_MessageQueue
+{
+public:
+    NPT_Win32WindowMessageQueue();
+    ~NPT_Win32WindowMessageQueue();
+
+    // NPT_MessageQueue methods
+    virtual NPT_Result PumpMessage(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+    virtual NPT_Result QueueMessage(NPT_Message*        message,
+                                    NPT_MessageHandler* handler);
+
+    NPT_Result HandleMessage(NPT_Message* message, NPT_MessageHandler* handler);
+
+private:
+    static LRESULT CALLBACK WindowProcedure(HWND   window, 
+                                            UINT   message,
+                                            WPARAM wparam, 
+                                            LPARAM lparam);
+    HWND        m_WindowHandle;
+    TCHAR       m_ClassName[16];
+    HINSTANCE   m_hInstance;
+};
+
+#endif // _NPT_WIN32_MESSAGE_QUEUE_
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Network.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,252 @@
+/*****************************************************************
+|
+|   Neptune - Network :: Winsock Implementation
+|
+|   (c) 2001-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#define STRICT
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include "NptNetwork.h"
+#include "NptWin32Network.h"
+
+/*----------------------------------------------------------------------
+|   static initializer
++---------------------------------------------------------------------*/
+NPT_WinsockSystem::NPT_WinsockSystem() {
+    WORD    wVersionRequested;
+    WSADATA wsaData;
+    wVersionRequested = MAKEWORD(2, 2);
+    /*wVersionRequested = MAKEWORD(1, 1);*/
+    WSAStartup( wVersionRequested, &wsaData );
+}
+NPT_WinsockSystem::~NPT_WinsockSystem() {
+    WSACleanup();
+}
+NPT_WinsockSystem NPT_WinsockSystem::Initializer;
+
+#if defined(_WIN32_WCE)
+// don't use the SIO_GET_INTERFACE_LIST on Windows CE, it is
+// hopelessly broken, and will crash your application.
+#define NPT_NETWORK_USE_IP_HELPER_API
+#else
+#define NPT_NETWORK_USE_SIO_GET_INTERFACE_LIST
+#endif
+
+#if defined(NPT_NETWORK_USE_SIO_GET_INTERFACE_LIST)
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
+{
+    // create a socket to talk to the TCP/IP stack
+    SOCKET net;
+    if((net = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0)) == INVALID_SOCKET) {
+        return NPT_FAILURE;
+    }
+
+    // get a list of interfaces
+    INTERFACE_INFO query[32];  // get up to 32 interfaces 
+    DWORD bytes_returned;
+    int io_result = WSAIoctl(net, 
+                             SIO_GET_INTERFACE_LIST, 
+                             NULL, 0, 
+                             &query, sizeof(query), 
+                             &bytes_returned, 
+                             NULL, NULL);
+    if (io_result == SOCKET_ERROR) {
+        closesocket(net);
+        return NPT_FAILURE;
+    }
+
+    // we don't need the socket anymore
+    closesocket(net);
+
+    // Display interface information
+    int interface_count = (bytes_returned/sizeof(INTERFACE_INFO));
+    unsigned int iface_index = 0;
+    for (int i=0; i<interface_count; i++) {
+        SOCKADDR_IN* address;
+        NPT_Flags    flags = 0;
+
+        // primary address
+        address = (SOCKADDR_IN*)&query[i].iiAddress;
+        NPT_IpAddress primary_address(ntohl(address->sin_addr.s_addr));
+
+        // netmask
+        address = (SOCKADDR_IN*)&query[i].iiNetmask;
+        NPT_IpAddress netmask(ntohl(address->sin_addr.s_addr));
+
+        // broadcast address
+        address = (SOCKADDR_IN*)&query[i].iiBroadcastAddress;
+        NPT_IpAddress broadcast_address(ntohl(address->sin_addr.s_addr));
+
+        {
+            // broadcast address is incorrect
+            unsigned char addr[4];
+            for(int i=0; i<4; i++) {
+                addr[i] = (primary_address.AsBytes()[i] & netmask.AsBytes()[i]) | 
+                    ~netmask.AsBytes()[i];
+            }
+            broadcast_address.Set(addr);
+        }
+
+        // ignore interfaces that are not up
+        if (!(query[i].iiFlags & IFF_UP)) {
+            continue;
+        }
+        if (query[i].iiFlags & IFF_BROADCAST) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST;
+        }
+        if (query[i].iiFlags & IFF_MULTICAST) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
+        }
+        if (query[i].iiFlags & IFF_LOOPBACK) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK;
+        }
+        if (query[i].iiFlags & IFF_POINTTOPOINT) {
+            flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT;
+        }
+
+        // mac address (no support for this for now)
+        NPT_MacAddress mac;
+
+        // create an interface object
+        char iface_name[5];
+        iface_name[0] = 'i';
+        iface_name[1] = 'f';
+        iface_name[2] = '0'+(iface_index/10);
+        iface_name[3] = '0'+(iface_index%10);
+        iface_name[4] = '\0';
+        NPT_NetworkInterface* iface = new NPT_NetworkInterface(iface_name, mac, flags);
+
+        // set the interface address
+        NPT_NetworkInterfaceAddress iface_address(
+            primary_address,
+            broadcast_address,
+            NPT_IpAddress::Any,
+            netmask);
+        iface->AddAddress(iface_address);  
+         
+        // add the interface to the list
+        interfaces.Add(iface);   
+
+        // increment the index (used for generating the name
+        iface_index++;
+    }
+
+    return NPT_SUCCESS;
+}
+#elif defined(NPT_NETWORK_USE_IP_HELPER_API)
+// Use the IP Helper API
+#include <iphlpapi.h>
+
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
+{
+    IP_ADAPTER_ADDRESSES* iface_list = NULL;
+    ULONG                 size = sizeof(IP_ADAPTER_INFO);
+
+    // get the interface table
+    for(;;) {
+        iface_list = (IP_ADAPTER_ADDRESSES*)malloc(size);
+        DWORD result = GetAdaptersAddresses(AF_INET,
+                                            0,
+                                            NULL,
+                                            iface_list, &size);
+        if (result == NO_ERROR) {
+            break;
+        } else {
+            if (result == ERROR_BUFFER_OVERFLOW) {
+                // free and try again
+                free(iface_list);
+            } else {
+                return NPT_FAILURE;
+            }
+        }
+    }
+
+    // iterate over the interfaces
+    for (IP_ADAPTER_ADDRESSES* iface = iface_list; iface; iface = iface->Next) {
+        // skip this interface if it is not up
+        if (iface->OperStatus != IfOperStatusUp) continue;
+
+        // get the interface type and mac address
+        NPT_MacAddress::Type mac_type;
+        switch (iface->IfType) {
+            case IF_TYPE_ETHERNET_CSMACD:   mac_type = NPT_MacAddress::TYPE_ETHERNET; break;
+            case IF_TYPE_SOFTWARE_LOOPBACK: mac_type = NPT_MacAddress::TYPE_LOOPBACK; break;
+            case IF_TYPE_PPP:               mac_type = NPT_MacAddress::TYPE_PPP;      break;
+            default:                        mac_type = NPT_MacAddress::TYPE_UNKNOWN;  break;
+        }
+        NPT_MacAddress mac(mac_type, iface->PhysicalAddress, iface->PhysicalAddressLength);
+
+        // compute interface flags
+        NPT_Flags flags = 0;
+        if (!(iface->Flags & IP_ADAPTER_NO_MULTICAST)) flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
+        if (iface->IfType == IF_TYPE_SOFTWARE_LOOPBACK) flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK;
+        if (iface->IfType == IF_TYPE_PPP) flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT;
+
+        // compute the unicast address (only the first one is supported for now)
+        NPT_IpAddress primary_address;
+        if (iface->FirstUnicastAddress) {
+            if (iface->FirstUnicastAddress->Address.lpSockaddr == NULL) continue;
+            if (iface->FirstUnicastAddress->Address.iSockaddrLength != sizeof(SOCKADDR_IN)) continue;
+            SOCKADDR_IN* address = (SOCKADDR_IN*)iface->FirstUnicastAddress->Address.lpSockaddr;
+            if (address->sin_family != AF_INET) continue;
+            primary_address.Set(ntohl(address->sin_addr.s_addr));
+        }
+        NPT_IpAddress broadcast_address; // not supported yet
+        NPT_IpAddress netmask;           // not supported yet
+
+        // convert the interface name to UTF-8
+        unsigned int iface_name_length = (unsigned int)wcslen(iface->FriendlyName);
+        char* iface_name = new char[4*iface_name_length+1];
+        int result = WideCharToMultiByte(
+            CP_UTF8, 0, iface->FriendlyName, iface_name_length,
+            iface_name, 4*iface_name_length+1,
+            NULL, NULL);
+        if (result > 0) {
+            iface_name[result] = '\0';
+        } else {
+            iface_name[0] = '\0';
+        }
+
+        // create an interface descriptor
+        NPT_NetworkInterface* iface_object = new NPT_NetworkInterface(iface_name, mac, flags);
+        NPT_NetworkInterfaceAddress iface_address(
+            primary_address,
+            broadcast_address,
+            NPT_IpAddress::Any,
+            netmask);
+        iface_object->AddAddress(iface_address);  
+    
+        // cleanup 
+        delete[] iface_name;
+         
+        // add the interface to the list
+        interfaces.Add(iface_object);   
+    }
+
+    return NPT_SUCCESS;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>&)
+{
+    return NPT_SUCCESS;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Network.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,20 @@
+/*****************************************************************
+|
+|   Neptune - Network :: Winsock Implementation
+|
+|   (c) 2001-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   static initializer
++---------------------------------------------------------------------*/
+class NPT_WinsockSystem {
+public:
+    static NPT_WinsockSystem Initializer;
+    ~NPT_WinsockSystem();
+	
+private:
+    NPT_WinsockSystem();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Queue.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,213 @@
+/*****************************************************************
+|
+|   Neptune - Queue :: Win32 Implementation
+|
+|   (c) 2001-2002 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#if defined(_XBOX)
+#include <xtl.h>
+#else
+#include <windows.h>
+#endif
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptQueue.h"
+#include "NptThreads.h"
+#include "NptList.h"
+#include "NptDebug.h"
+#include "NptWin32Threads.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+//NPT_SET_LOCAL_LOGGER("neptune.queue.win32")
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Queue
++---------------------------------------------------------------------*/
+class NPT_Win32Queue : public NPT_GenericQueue
+{
+public:
+    // methods
+               NPT_Win32Queue(NPT_Cardinal max_items);
+              ~NPT_Win32Queue();
+    NPT_Result Push(NPT_QueueItem* item, NPT_Timeout timeout); 
+    NPT_Result Pop(NPT_QueueItem*& item, NPT_Timeout timeout);
+    NPT_Result Peek(NPT_QueueItem*& item, NPT_Timeout timeout);
+
+
+private:
+    // members
+    NPT_Cardinal             m_MaxItems;
+    NPT_Win32CriticalSection m_Mutex;
+    NPT_Win32Event*          m_CanPushCondition;
+    NPT_Win32Event*          m_CanPopCondition;
+    NPT_List<NPT_QueueItem*> m_Items; // should be volatile ?
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Queue::NPT_Win32Queue
++---------------------------------------------------------------------*/
+NPT_Win32Queue::NPT_Win32Queue(NPT_Cardinal max_items) : 
+    m_MaxItems(max_items)
+{
+    m_CanPushCondition = new NPT_Win32Event(true, true);
+    m_CanPopCondition  = new NPT_Win32Event(true, false);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Queue::~NPT_Win32Queue()
++---------------------------------------------------------------------*/
+NPT_Win32Queue::~NPT_Win32Queue()
+{
+    // destroy resources
+    delete m_CanPushCondition;
+    delete m_CanPopCondition;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Queue::Push
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Queue::Push(NPT_QueueItem* item, NPT_Timeout timeout)
+{
+    // lock the mutex that protects the list
+    NPT_CHECK(m_Mutex.Lock());
+
+    // check that we have not exceeded the max
+    if (m_MaxItems) {
+        while (m_Items.GetItemCount() >= m_MaxItems) {
+            // we must wait until some items have been removed
+
+            // reset the condition to indicate that the queue is full
+            m_CanPushCondition->Reset();
+
+            // unlock the mutex so that another thread can pop
+            m_Mutex.Unlock();
+
+            // wait for the condition to signal that we can push
+            NPT_CHECK(m_CanPushCondition->Wait(timeout));
+
+            // relock the mutex so that we can check the list again
+            NPT_CHECK(m_Mutex.Lock());
+        }
+    }
+
+    // add the item to the list
+    m_Items.Add(item);
+
+    // wake up the threads waiting to pop
+    m_CanPopCondition->Signal();
+
+    // unlock the mutex
+    m_Mutex.Unlock();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Queue::Pop
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Queue::Pop(NPT_QueueItem*& item, NPT_Timeout timeout)
+{
+    // default value
+    item = NULL;
+    
+    // lock the mutex that protects the list
+    NPT_CHECK(m_Mutex.Lock());
+
+    NPT_Result result;
+    if (timeout) {
+        while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) {
+            // no item in the list, wait for one
+
+            // reset the condition to indicate that the queue is empty
+            m_CanPopCondition->Reset();
+
+            // unlock the mutex so that another thread can push
+            m_Mutex.Unlock();
+
+            // wait for the condition to signal that we can pop
+            NPT_CHECK(m_CanPopCondition->Wait(timeout));
+
+            // relock the mutex so that we can check the list again
+            NPT_CHECK(m_Mutex.Lock());
+        }
+    } else {
+        result = m_Items.PopHead(item);
+    }
+    
+    if (m_MaxItems && (result == NPT_SUCCESS)) {
+        // wake up the threads waiting to push
+        m_CanPushCondition->Signal();
+    }
+
+    // unlock the mutex
+    m_Mutex.Unlock();
+ 
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Queue::Peek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Queue::Peek(NPT_QueueItem*& item, NPT_Timeout timeout)
+{
+    // default value
+    item = NULL;
+    
+    // lock the mutex that protects the list
+    NPT_CHECK(m_Mutex.Lock());
+
+    NPT_Result result = NPT_SUCCESS;
+    NPT_List<NPT_QueueItem*>::Iterator head = m_Items.GetFirstItem();
+    if (timeout) {
+        while (!head) {
+            // no item in the list, wait for one
+
+            // reset the condition to indicate that the queue is empty
+            m_CanPopCondition->Reset();
+
+            // unlock the mutex so that another thread can push
+            m_Mutex.Unlock();
+
+            // wait for the condition to signal that we can pop
+            NPT_CHECK(m_CanPopCondition->Wait(timeout));
+
+            // relock the mutex so that we can check the list again
+            NPT_CHECK(m_Mutex.Lock());
+
+            // try again
+            head = m_Items.GetFirstItem();
+        }
+    } else {
+        if (!head) result = NPT_ERROR_LIST_EMPTY;
+    }
+
+    if (head) item = *head;
+
+    // unlock the mutex
+    m_Mutex.Unlock();
+
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_GenericQueue::CreateInstance
++---------------------------------------------------------------------*/
+NPT_GenericQueue*
+NPT_GenericQueue::CreateInstance(NPT_Cardinal max_items)
+{
+    return new NPT_Win32Queue(max_items);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32SerialPort.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,337 @@
+/*****************************************************************
+|
+|   Neptune - Serial Ports :: Win32 Implementation
+|
+|   (c) 2001-2007 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <windows.h>
+
+#include "NptUtils.h"
+#include "NptSerialPort.h"
+#include "NptStrings.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Win32HandletWrapper
++---------------------------------------------------------------------*/
+class NPT_Win32HandleWrapper
+{
+public:
+    // constructors and destructor
+    NPT_Win32HandleWrapper(HANDLE handle) : m_Handle(handle) {}
+    ~NPT_Win32HandleWrapper() {
+        CloseHandle(m_Handle);
+    }
+
+    // methods
+    HANDLE GetHandle() { return m_Handle; }
+
+private:
+    // members
+    HANDLE m_Handle;
+};
+
+typedef NPT_Reference<NPT_Win32HandleWrapper> NPT_Win32HandleReference;
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPortStream
++---------------------------------------------------------------------*/
+class NPT_Win32SerialPortStream
+{
+public:
+    // constructors and destructor
+    NPT_Win32SerialPortStream(NPT_Win32HandleReference handle) :
+      m_HandleReference(handle) {}
+
+protected:
+    // constructors and destructors
+    virtual ~NPT_Win32SerialPortStream() {}
+
+    // members
+    NPT_Win32HandleReference m_HandleReference;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPortInputStream
++---------------------------------------------------------------------*/
+class NPT_Win32SerialPortInputStream : public NPT_InputStream,
+                                       private NPT_Win32SerialPortStream
+                                
+{
+public:
+    // constructors and destructor
+    NPT_Win32SerialPortInputStream(NPT_Win32HandleReference& handle) :
+        NPT_Win32SerialPortStream(handle) {}
+
+    // NPT_InputStream methods
+    NPT_Result Read(void*     buffer, 
+                    NPT_Size  bytes_to_read, 
+                    NPT_Size* bytes_read);
+    NPT_Result Seek(NPT_Position /* offset */) {
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+    NPT_Result Tell(NPT_Position& /* offset */) {
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+    NPT_Result GetSize(NPT_LargeSize& /* size */) {
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+    NPT_Result GetAvailable(NPT_LargeSize& /* available */) {
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPortInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32SerialPortInputStream::Read(void*     buffer, 
+                                     NPT_Size  bytes_to_read, 
+                                     NPT_Size* bytes_read)
+{
+    DWORD nb_read = 0;
+    BOOL result = ReadFile(m_HandleReference->GetHandle(), 
+                           buffer, 
+                           bytes_to_read, 
+                           &nb_read, 
+                           NULL);
+    if (result == TRUE) {
+        if (bytes_read) *bytes_read = nb_read;
+        return NPT_SUCCESS;
+    } else {
+        if (bytes_read) *bytes_read = 0;
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPortOutputStream
++---------------------------------------------------------------------*/
+class NPT_Win32SerialPortOutputStream : public NPT_OutputStream,
+                                        private NPT_Win32SerialPortStream
+{
+public:
+    // constructors and destructor
+    NPT_Win32SerialPortOutputStream(NPT_Win32HandleReference& handle) :
+        NPT_Win32SerialPortStream(handle) {}
+
+    // NPT_InputStream methods
+    NPT_Result Write(const void* buffer, 
+                     NPT_Size    bytes_to_write, 
+                     NPT_Size*   bytes_written);
+    NPT_Result Seek(NPT_Position /* offset */) {
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+    NPT_Result Tell(NPT_Position& /* offset */) {
+        return NPT_ERROR_NOT_SUPPORTED;
+    }
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPortOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32SerialPortOutputStream::Write(const void* buffer, 
+                                       NPT_Size    bytes_to_write, 
+                                       NPT_Size*   bytes_written)
+{
+    DWORD nb_written = 0;
+
+    BOOL result = WriteFile(m_HandleReference->GetHandle(), 
+                            buffer, 
+                            bytes_to_write, 
+                            &nb_written, 
+                            NULL);
+    if (result == TRUE) {
+        if (bytes_written) *bytes_written = nb_written;
+        return NPT_SUCCESS;
+    } else {
+        if (bytes_written) *bytes_written = 0;
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort
++---------------------------------------------------------------------*/
+class NPT_Win32SerialPort: public NPT_SerialPortInterface
+{
+public:
+    // constructors and destructor
+    NPT_Win32SerialPort(const char* name);
+   ~NPT_Win32SerialPort();
+
+    // NPT_SerialPortInterface methods
+    NPT_Result Open(unsigned int              speed, 
+                    NPT_SerialPortStopBits    stop_bits = NPT_SERIAL_PORT_STOP_BITS_1,
+                    NPT_SerialPortFlowControl flow_control = NPT_SERIAL_PORT_FLOW_CONTROL_NONE,
+                    NPT_SerialPortParity      parity = NPT_SERIAL_PORT_PARITY_NONE);
+    NPT_Result Close();
+    NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+    NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
+
+private:
+    // members
+    NPT_String               m_Name;
+    NPT_Win32HandleReference m_HandleReference;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort::NPT_Win32SerialPort
++---------------------------------------------------------------------*/
+NPT_Win32SerialPort::NPT_Win32SerialPort(const char* name) :
+    m_Name(name)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort::~NPT_Win32SerialPort
++---------------------------------------------------------------------*/
+NPT_Win32SerialPort::~NPT_Win32SerialPort()
+{
+    Close();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32SerialPort::Open(unsigned int              speed, 
+                          NPT_SerialPortStopBits    stop_bits,
+                          NPT_SerialPortFlowControl flow_control,
+                          NPT_SerialPortParity      parity)
+{
+    // check if we're already open
+    if (!m_HandleReference.IsNull()) {
+        return NPT_ERROR_SERIAL_PORT_ALREADY_OPEN;
+    }
+
+    HANDLE handle = CreateFile(m_Name,  
+                               GENERIC_READ | GENERIC_WRITE, 
+                               0, 
+                               0, 
+                               OPEN_EXISTING,
+                               0,
+                               0);
+    if (handle == INVALID_HANDLE_VALUE) {
+        return NPT_ERROR_NO_SUCH_SERIAL_PORT;
+    }
+
+    // set the parameters
+    DCB dcb;
+    NPT_SetMemory(&dcb, 0, sizeof(dcb));
+    dcb.DCBlength = sizeof(DCB);
+    if (!GetCommState(handle, &dcb)) {
+        CloseHandle(handle);
+        return NPT_FAILURE;
+    }
+    dcb.fBinary = TRUE;
+    dcb.BaudRate = speed;
+    switch (stop_bits) {
+        case NPT_SERIAL_PORT_STOP_BITS_1: dcb.StopBits   = ONESTOPBIT; break;
+        case NPT_SERIAL_PORT_STOP_BITS_1_5: dcb.StopBits = ONE5STOPBITS; break;
+        case NPT_SERIAL_PORT_STOP_BITS_2: dcb.StopBits   = TWOSTOPBITS; break;
+    }
+    switch (flow_control) {
+        case NPT_SERIAL_PORT_FLOW_CONTROL_NONE:
+            dcb.fOutX = dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = FALSE;
+            dcb.fInX = dcb.fDsrSensitivity = FALSE;
+            dcb.fRtsControl = RTS_CONTROL_DISABLE;
+            dcb.fDtrControl = DTR_CONTROL_DISABLE;
+            break;
+
+        case NPT_SERIAL_PORT_FLOW_CONTROL_HARDWARE:
+            dcb.fOutX = dcb.fOutxDsrFlow = FALSE;
+            dcb.fOutxCtsFlow = TRUE;
+            dcb.fInX = dcb.fDsrSensitivity = FALSE;
+            dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+            dcb.fDtrControl = DTR_CONTROL_DISABLE;
+            break;
+
+        case NPT_SERIAL_PORT_FLOW_CONTROL_XON_XOFF:
+            dcb.fOutX = TRUE;
+            dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = FALSE;
+            dcb.fInX = TRUE;
+            dcb.fDsrSensitivity = FALSE;
+            dcb.fRtsControl = RTS_CONTROL_DISABLE;
+            dcb.fDtrControl = DTR_CONTROL_DISABLE;
+            break;
+    }
+    switch (parity) {
+        case NPT_SERIAL_PORT_PARITY_NONE: dcb.fParity = FALSE; dcb.Parity = NOPARITY; break;
+        case NPT_SERIAL_PORT_PARITY_EVEN: dcb.fParity = TRUE;  dcb.Parity = EVENPARITY; break;
+        case NPT_SERIAL_PORT_PARITY_ODD: dcb.fParity  = TRUE;  dcb.Parity = ODDPARITY; break;
+        case NPT_SERIAL_PORT_PARITY_MARK: dcb.fParity = TRUE;  dcb.Parity = MARKPARITY; break;
+    }
+    if (!SetCommState(handle, &dcb)) {
+        CloseHandle(handle);
+        return NPT_FAILURE;
+    }
+
+    // create a reference to the FILE object
+    m_HandleReference = new NPT_Win32HandleWrapper(handle);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort::Close
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32SerialPort::Close()
+{
+    // release the file reference
+    m_HandleReference = NULL;
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Win32SerialPort::GetInputStream(NPT_InputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_HandleReference.IsNull()) return NPT_ERROR_SERIAL_PORT_NOT_OPEN;
+
+    // create a stream
+    stream = new NPT_Win32SerialPortInputStream(m_HandleReference);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SerialPort::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_Win32SerialPort::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+    // default value
+    stream = NULL;
+
+    // check that the file is open
+    if (m_HandleReference.IsNull()) return NPT_ERROR_SERIAL_PORT_NOT_OPEN;
+
+    // create a stream
+    stream = new NPT_Win32SerialPortOutputStream(m_HandleReference);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SerialPort::NPT_SerialPort
++---------------------------------------------------------------------*/
+NPT_SerialPort::NPT_SerialPort(const char* name)
+{
+    m_Delegate = new NPT_Win32SerialPort(name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32System.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,138 @@
+/*****************************************************************
+|
+|   Neptune - System :: Win32 Implementation
+|
+|   (c) 2001-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#if defined(_XBOX)
+#include <xtl.h>
+#else
+#include <windows.h>
+#endif
+
+#if !defined(_WIN32_WCE)
+#include <sys/timeb.h>
+#endif
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptSystem.h"
+#include "NptResults.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   NPT_System::GetProcessId
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetProcessId(NPT_UInt32& id)
+{
+    //id = getpid();
+    id = 0;
+    return NPT_SUCCESS;
+}
+
+#if defined(_WIN32_WCE)
+/*----------------------------------------------------------------------
+|   NPT_System::GetCurrentTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetCurrentTimeStamp(NPT_TimeStamp& now)
+{
+    SYSTEMTIME stime;
+    FILETIME   ftime;
+    __int64    time64;
+    GetSystemTime(&stime);
+    SystemTimeToFileTime(&stime, &ftime);
+
+    /* convert to 64-bits 100-nanoseconds value */
+    time64 = (((unsigned __int64)ftime.dwHighDateTime)<<32) | ((unsigned __int64)ftime.dwLowDateTime);
+    time64 -= 116444736000000000; /* convert from the Windows epoch (Jan. 1, 1601) to the 
+                                   * Unix epoch (Jan. 1, 1970) */
+    
+    now.m_Seconds = (NPT_Int32)(time64/10000000);
+    now.m_NanoSeconds = 100*(NPT_Int32)(time64-((unsigned __int64)now.m_Seconds*10000000));
+
+    return NPT_SUCCESS;
+}
+#else
+/*----------------------------------------------------------------------
+|   NPT_System::GetCurrentTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::GetCurrentTimeStamp(NPT_TimeStamp& now)
+{
+    struct _timeb time_stamp;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+    _ftime_s(&time_stamp);
+#else
+    _ftime(&time_stamp);
+#endif
+    now.m_Seconds     = (long)time_stamp.time;
+    now.m_NanoSeconds = (long)time_stamp.millitm*1000000;
+
+    return NPT_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_System::Sleep
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::Sleep(const NPT_TimeInterval& duration)
+{
+    DWORD milliseconds = 1000*duration.m_Seconds + duration.m_NanoSeconds/1000000;
+    ::Sleep(milliseconds);
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SleepUntil
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_System::SleepUntil(const NPT_TimeStamp& when)
+{
+    NPT_TimeStamp now;
+    GetCurrentTimeStamp(now);
+    if (when > now) {
+        NPT_TimeInterval duration = when-now;
+        return Sleep(duration);
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::SetRandomSeed
++---------------------------------------------------------------------*/
+NPT_Result  
+NPT_System::SetRandomSeed(unsigned int seed)
+{
+    srand(seed);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_System::NPT_System
++---------------------------------------------------------------------*/
+NPT_UInt32 
+NPT_System::GetRandomInteger()
+{
+    static bool seeded = false;
+    if (seeded == false) {
+        NPT_TimeStamp now;
+        GetCurrentTimeStamp(now);
+        srand(now.m_NanoSeconds);
+        seeded = true;
+    }
+
+    return rand();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Threads.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,576 @@
+/*****************************************************************
+|
+|   Neptune - Threads :: Win32 Implementation
+|
+|   (c) 2001-2008 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#if defined(_XBOX)
+#include <xtl.h>
+#else
+#include <windows.h>
+#if !defined(_WIN32_WCE)
+#include <process.h>
+#endif
+#endif
+
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptConstants.h"
+#include "NptThreads.h"
+#include "NptDebug.h"
+#include "NptResults.h"
+#include "NptWin32Threads.h"
+#include "NptTime.h"
+#include "NptSystem.h"
+#include "NptLogging.h"
+
+/*----------------------------------------------------------------------
+|   logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("neptune.threads.win32")
+
+/*----------------------------------------------------------------------
+|   configuration macros
++---------------------------------------------------------------------*/
+#if defined(_WIN32_WCE) || defined(_XBOX)
+#define NPT_WIN32_USE_CREATE_THREAD
+#endif
+
+#if defined(NPT_WIN32_USE_CREATE_THREAD)
+#define _beginthreadex(security, stack_size, start_proc, arg, flags, pid) \
+CreateThread(security, stack_size, (LPTHREAD_START_ROUTINE) start_proc,   \
+             arg, flags, (LPDWORD)pid)
+#define _endthreadex ExitThread
+#endif
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Mutex::NPT_Win32Mutex
++---------------------------------------------------------------------*/
+NPT_Win32Mutex::NPT_Win32Mutex()
+{
+    m_Handle = CreateMutex(NULL, FALSE, NULL);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Mutex::~NPT_Win32Mutex
++---------------------------------------------------------------------*/
+NPT_Win32Mutex::~NPT_Win32Mutex()
+{
+    CloseHandle(m_Handle);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Mutex::Lock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Mutex::Lock()
+{
+    DWORD result = WaitForSingleObject(m_Handle, INFINITE);
+    if (result == WAIT_OBJECT_0) {
+        return NPT_SUCCESS;
+    } else {
+        return NPT_FAILURE;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Mutex::Unlock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Mutex::Unlock()
+{
+    ReleaseMutex(m_Handle);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Mutex::NPT_Mutex
++---------------------------------------------------------------------*/
+NPT_Mutex::NPT_Mutex()
+{
+    m_Delegate = new NPT_Win32Mutex();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32CriticalSection::NPT_Win32CriticalSection
++---------------------------------------------------------------------*/
+NPT_Win32CriticalSection::NPT_Win32CriticalSection()
+{
+    InitializeCriticalSection(&m_CriticalSection);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32CriticalSection::~NPT_Win32CriticalSection
++---------------------------------------------------------------------*/
+NPT_Win32CriticalSection::~NPT_Win32CriticalSection()
+{
+    DeleteCriticalSection(&m_CriticalSection);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32CriticalSection::Lock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32CriticalSection::Lock()
+{
+    EnterCriticalSection(&m_CriticalSection);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32CriticalSection::Unlock
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32CriticalSection::Unlock()
+{
+    LeaveCriticalSection(&m_CriticalSection);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Event::NPT_Win32Event
++---------------------------------------------------------------------*/
+NPT_Win32Event::NPT_Win32Event(bool manual /* = false */, bool initial /* = false */)
+{
+    m_Event = CreateEvent(NULL, (manual==true)?TRUE:FALSE, (initial==true)?TRUE:FALSE, NULL);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Event::~NPT_Win32Event
++---------------------------------------------------------------------*/
+NPT_Win32Event::~NPT_Win32Event()
+{
+    CloseHandle(m_Event);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Event::Wait
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Event::Wait(NPT_Timeout timeout)
+{
+    if (m_Event) {
+        DWORD result = WaitForSingleObject(m_Event, timeout==NPT_TIMEOUT_INFINITE?INFINITE:timeout);
+        if (result == WAIT_TIMEOUT) {
+            return NPT_ERROR_TIMEOUT;
+        }
+        if (result != WAIT_OBJECT_0 && result != WAIT_ABANDONED) {
+            return NPT_FAILURE;
+        }
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Event::Signal
++---------------------------------------------------------------------*/
+void
+NPT_Win32Event::Signal()
+{
+    SetEvent(m_Event);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Event::Reset
++---------------------------------------------------------------------*/
+void
+NPT_Win32Event::Reset()
+{
+    ResetEvent(m_Event);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable
++---------------------------------------------------------------------*/
+class NPT_Win32SharedVariable : public NPT_SharedVariableInterface
+{
+ public:
+    // methods
+               NPT_Win32SharedVariable(int value);
+              ~NPT_Win32SharedVariable();
+    void       SetValue(int value);
+    int        GetValue();
+    NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+    NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+ private:
+    // members
+    volatile int   m_Value;
+    NPT_Mutex      m_Lock;
+    NPT_Win32Event m_Event;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable::NPT_Win32SharedVariable
++---------------------------------------------------------------------*/
+NPT_Win32SharedVariable::NPT_Win32SharedVariable(int value) : 
+    m_Value(value)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable::~NPT_Win32SharedVariable
++---------------------------------------------------------------------*/
+NPT_Win32SharedVariable::~NPT_Win32SharedVariable()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable::SetValue
++---------------------------------------------------------------------*/
+void
+NPT_Win32SharedVariable::SetValue(int value)
+{
+    m_Lock.Lock();
+    if (value != m_Value) {
+        m_Value = value;
+        m_Event.Signal();
+    }
+    m_Lock.Unlock();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable::GetValue
++---------------------------------------------------------------------*/
+int
+NPT_Win32SharedVariable::GetValue()
+{
+    // reading an integer should be atomic on all Win32 platforms
+    return m_Value;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable::WaitUntilEquals
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32SharedVariable::WaitUntilEquals(int value, NPT_Timeout timeout)
+{
+    do {
+        m_Lock.Lock();
+        if (m_Value == value) {
+            break;
+        }
+        m_Lock.Unlock();
+        {
+             NPT_Result result = m_Event.Wait(timeout);
+             if (NPT_FAILED(result)) return result;
+        }
+    } while (1);
+
+    m_Lock.Unlock();
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32SharedVariable::WaitWhileEquals
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32SharedVariable::WaitWhileEquals(int value, NPT_Timeout timeout)
+{
+    do {
+        m_Lock.Lock();
+        if (m_Value != value) {
+            break;
+        }
+        m_Lock.Unlock();
+        {
+             NPT_Result result = m_Event.Wait(timeout);
+             if (NPT_FAILED(result)) return result;
+        }
+    } while (1);
+
+    m_Lock.Unlock();
+    
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_SharedVariable::NPT_SharedVariable
++---------------------------------------------------------------------*/
+NPT_SharedVariable::NPT_SharedVariable(int value)
+{
+    m_Delegate = new NPT_Win32SharedVariable(value);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable
++---------------------------------------------------------------------*/
+class NPT_Win32AtomicVariable : public NPT_AtomicVariableInterface
+{
+ public:
+    // methods
+                NPT_Win32AtomicVariable(int value);
+               ~NPT_Win32AtomicVariable();
+    int  Increment(); 
+    int  Decrement();
+    void SetValue(int value);
+    int  GetValue();
+
+ private:
+    // members
+    volatile LONG m_Value;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable::NPT_Win32AtomicVariable
++---------------------------------------------------------------------*/
+NPT_Win32AtomicVariable::NPT_Win32AtomicVariable(int value) : 
+    m_Value(value)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable::~NPT_Win32AtomicVariable
++---------------------------------------------------------------------*/
+NPT_Win32AtomicVariable::~NPT_Win32AtomicVariable()
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable::Increment
++---------------------------------------------------------------------*/
+int
+NPT_Win32AtomicVariable::Increment()
+{
+    return InterlockedIncrement(const_cast<LONG*>(&m_Value));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable::Decrement
++---------------------------------------------------------------------*/
+int
+NPT_Win32AtomicVariable::Decrement()
+{
+    return InterlockedDecrement(const_cast<LONG*>(&m_Value));
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable::SetValue
++---------------------------------------------------------------------*/
+void
+NPT_Win32AtomicVariable::SetValue(int value)
+{
+    m_Value = value;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32AtomicVariable::GetValue
++---------------------------------------------------------------------*/
+int
+NPT_Win32AtomicVariable::GetValue()
+{
+    return m_Value;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_AtomicVariable::NPT_AtomicVariable
++---------------------------------------------------------------------*/
+NPT_AtomicVariable::NPT_AtomicVariable(int value)
+{
+    m_Delegate = new NPT_Win32AtomicVariable(value);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread
++---------------------------------------------------------------------*/
+class NPT_Win32Thread : public NPT_ThreadInterface
+{
+ public:
+    // methods
+                NPT_Win32Thread(NPT_Thread*   delegator,
+                                NPT_Runnable& target,
+                                bool          detached);
+               ~NPT_Win32Thread();
+    NPT_Result  Start(); 
+    NPT_Result  Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+ private:
+    // methods
+    static unsigned int __stdcall EntryPoint(void* argument);
+
+    // NPT_Runnable methods
+    void Run();
+
+    // NPT_Interruptible methods
+    NPT_Result Interrupt() { return NPT_ERROR_NOT_IMPLEMENTED; } 
+
+    // members
+    NPT_Thread*   m_Delegator;
+    NPT_Runnable& m_Target;
+    bool          m_Detached;
+    HANDLE        m_ThreadHandle;
+    DWORD         m_ThreadId;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread::NPT_Win32Thread
++---------------------------------------------------------------------*/
+NPT_Win32Thread::NPT_Win32Thread(NPT_Thread*   delegator,
+                                 NPT_Runnable& target,
+                                 bool          detached) : 
+    m_Delegator(delegator),
+    m_Target(target),
+    m_Detached(detached),
+    m_ThreadHandle(0),
+    m_ThreadId(0)
+{
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread::~NPT_Win32Thread
++---------------------------------------------------------------------*/
+NPT_Win32Thread::~NPT_Win32Thread()
+{
+    if (!m_Detached) {
+        // we're not detached, and not in the Run() method, so we need to 
+        // wait until the thread is done
+        Wait();
+    }
+
+    // close the thread handle
+#if defined(NPT_WIN32_USE_CREATE_THREAD)
+    CloseHandle(m_ThreadHandle);
+#endif
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread::EntryPoint
++---------------------------------------------------------------------*/
+unsigned int __stdcall
+NPT_Win32Thread::EntryPoint(void* argument)
+{
+    NPT_Win32Thread* thread = reinterpret_cast<NPT_Win32Thread*>(argument);
+
+    NPT_LOG_FINE("thread in =======================");
+
+    // set random seed per thread
+    NPT_TimeStamp now;
+    NPT_System::GetCurrentTimeStamp(now);
+    NPT_System::SetRandomSeed(now.m_NanoSeconds + NPT_Thread::GetCurrentThreadId());
+
+    // run the thread 
+    thread->Run();
+    
+    // Logging here will cause a crash on exit because LogManager may already be destroyed
+    //NPT_LOG_FINE("thread out ======================");
+
+    // if the thread is detached, delete it
+    if (thread->m_Detached) {
+        delete thread->m_Delegator;
+    }
+
+    // end the thread
+    _endthreadex(0);
+
+    // done
+    return 0;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread::Start
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Thread::Start()
+{
+    if (m_ThreadHandle > 0) {
+        // failed
+        NPT_LOG_WARNING("thread already started !");
+        return NPT_ERROR_INVALID_STATE;
+    }
+
+    NPT_LOG_FINE("creating thread");
+
+    // create the native thread
+#if defined(_WIN32_WCE)
+    DWORD thread_id;
+#else
+    unsigned int thread_id;
+#endif
+    // create a stack local detached, as this object
+    // may already be deleted when _beginthreadex returns and
+    // before we get to call detach on the given thread
+    bool detached = m_Detached;
+
+    m_ThreadHandle = (HANDLE)
+        _beginthreadex(NULL, 
+                       NPT_CONFIG_THREAD_STACK_SIZE, 
+                       EntryPoint, 
+                       reinterpret_cast<void*>(this), 
+                       0, 
+                       &thread_id);
+    if (m_ThreadHandle == 0) {
+        // failed
+        m_ThreadId = 0;
+        return NPT_FAILURE;
+    }
+
+    if (!detached) {
+        m_ThreadId = (DWORD)thread_id;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread::Run
++---------------------------------------------------------------------*/
+void
+NPT_Win32Thread::Run()
+{
+    m_Target.Run();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Thread::Wait
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_Win32Thread::Wait(NPT_Timeout timeout /* = NPT_TIMEOUT_INFINITE */)
+{
+    // check that we're not detached
+    if (m_ThreadHandle == 0 || m_Detached) {
+        return NPT_FAILURE;
+    }
+
+    // wait for the thread to finish
+    // Logging here will cause a crash on exit because LogManager may already be destroyed
+    //NPT_LOG_FINE_1("joining thread id %d", m_ThreadId);
+    DWORD result = WaitForSingleObject(m_ThreadHandle, 
+                                       timeout==NPT_TIMEOUT_INFINITE?INFINITE:timeout);
+    if (result != WAIT_OBJECT_0) {
+        return NPT_FAILURE;
+    } else {
+        return NPT_SUCCESS;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Thread::GetCurrentThreadId
++---------------------------------------------------------------------*/
+NPT_Thread::ThreadId 
+NPT_Thread::GetCurrentThreadId()
+{
+    return ::GetCurrentThreadId();
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Thread::NPT_Thread
++---------------------------------------------------------------------*/
+NPT_Thread::NPT_Thread(bool detached)
+{
+    m_Delegate = new NPT_Win32Thread(this, *this, detached);
+}
+
+/*----------------------------------------------------------------------
+|   NPT_Thread::NPT_Thread
++---------------------------------------------------------------------*/
+NPT_Thread::NPT_Thread(NPT_Runnable& target, bool detached)
+{
+    m_Delegate = new NPT_Win32Thread(this, target, detached);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Threads.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,73 @@
+/*****************************************************************
+|
+|   Neptune - Threads :: Win32 Implementation
+|
+|   (c) 2001-2003 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptConfig.h"
+#include "NptTypes.h"
+#include "NptThreads.h"
+#include "NptDebug.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Mutex
++---------------------------------------------------------------------*/
+class NPT_Win32Mutex : public NPT_MutexInterface
+{
+public:
+    // methods
+             NPT_Win32Mutex();
+    virtual ~NPT_Win32Mutex();
+
+    // NPT_Mutex methods
+    virtual NPT_Result Lock();
+    virtual NPT_Result Unlock();
+
+private:
+    // members
+    HANDLE m_Handle;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32Event
++---------------------------------------------------------------------*/
+class NPT_Win32Event
+{
+public:
+    // methods
+             NPT_Win32Event(bool manual = false, bool initial = false);
+    virtual ~NPT_Win32Event();
+
+    virtual NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+    virtual void       Signal();
+    virtual void       Reset();
+
+private:
+    // members
+    HANDLE m_Event;
+};
+
+/*----------------------------------------------------------------------
+|   NPT_Win32CriticalSection
++---------------------------------------------------------------------*/
+class NPT_Win32CriticalSection
+{
+public:
+    // methods
+    NPT_Win32CriticalSection();
+   ~NPT_Win32CriticalSection();
+
+    // NPT_Mutex methods
+    NPT_Result Lock();
+    NPT_Result Unlock();
+
+private:
+    // members
+    CRITICAL_SECTION m_CriticalSection;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinCeUtils.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,92 @@
+/*****************************************************************
+|
+|   Neptune - Windows CE Utils
+|
+|   (c) 2001-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+
+#ifndef _NPT_WINCE_UTILS_H_
+#define _NPT_WINCE_UTILS_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <windows.h>
+
+/*----------------------------------------------------------------------
+|   fix windows macros
++---------------------------------------------------------------------*/
+#if defined(CreateDirectory)
+#undef CreateDirectory
+#endif
+
+#if defined(DeleteFile)
+#undef DeleteFile
+#endif
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "NptTypes.h"
+
+/*----------------------------------------------------------------------
+|   A2WHelper
++---------------------------------------------------------------------*/
+static LPWSTR A2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
+{
+    int ret;
+
+    assert(lpa != NULL);
+    assert(lpw != NULL);
+    if (lpw == NULL || lpa == NULL) return NULL;
+
+    lpw[0] = '\0';
+    ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
+    if (ret == 0) {
+        assert(0);
+        return NULL;
+    }        
+    return lpw;
+}
+
+/*----------------------------------------------------------------------
+|   W2AHelper
++---------------------------------------------------------------------*/
+static LPSTR W2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp)
+{
+    int ret;
+
+    assert(lpw != NULL);
+    assert(lpa != NULL);
+    if (lpa == NULL || lpw == NULL) return NULL;
+
+    lpa[0] = '\0';
+    ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
+    if (ret == 0) {
+        assert(0);
+        return NULL;
+    }
+    return lpa;
+}
+
+/*----------------------------------------------------------------------
+|   macros
++---------------------------------------------------------------------*/
+#define USES_CONVERSION int _convert = 0; LPCWSTR _lpw = NULL; LPCSTR _lpa = NULL
+
+#define A2W(lpa) (\
+    ((_lpa = lpa) == NULL) ? NULL : (\
+    _convert = (strlen(_lpa)+1),\
+    (INT_MAX/2<_convert)? NULL :  \
+    A2WHelper((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, CP_UTF8)))
+
+#define W2A(lpw) (\
+    ((_lpw = lpw) == NULL) ? NULL : (\
+    (_convert = (lstrlenW(_lpw)+1), \
+    (_convert>INT_MAX/2) ? NULL : \
+    W2AHelper((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), CP_UTF8))))
+
+#endif /* _NPT_WINCE_UTILS_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinceConsole.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,26 @@
+/*****************************************************************
+|
+|   Neptune - Console Support: Windows CE Implementation
+|
+|   (c) 2002-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+
+#include "NptConfig.h"
+#include "NptConsole.h"
+
+/*----------------------------------------------------------------------
+|   NPT_Console::Output
++---------------------------------------------------------------------*/
+void
+NPT_Console::Output(const char* message)
+{
+    printf("%s", message);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinceEnvironment.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,63 @@
+/*****************************************************************
+|
+|      Neptune - Environment variables: Windows CE Implementation
+|
+|      (c) 2002-2006 Gilles Boccon-Gibod
+|      Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|       includes
++---------------------------------------------------------------------*/
+#include <windows.h>
+
+#include "NptConfig.h"
+#include "NptUtils.h"
+#include "NptResults.h"
+
+/*----------------------------------------------------------------------
+|   NPT_GetEnvironment
++---------------------------------------------------------------------*/
+NPT_Result 
+NPT_GetEnvironment(const char* name, NPT_String& value)
+{
+    HKEY       key = NULL; 
+    DWORD      type;
+    WCHAR*     name_w;
+    DWORD      name_length;
+    DWORD      value_length;
+    NPT_Result result;
+
+    // default value
+    value.SetLength(0);
+
+    // convert name to unicode
+    name_length = NPT_StringLength(name);
+    name_w = new WCHAR[(name_length+1)];
+    MultiByteToWideChar(CP_UTF8, 0, name, -1, name_w, name_length+1);
+
+    if (RegOpenKeyEx(HKEY_CURRENT_USER, 
+                     _T("Software\\Axiomatic\\Neptune\\Environment"), 
+                     0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) { 
+        if (RegQueryValueEx(key, name_w, 0, &type, (PBYTE)NULL, &value_length ) == ERROR_SUCCESS) { 
+            // convert to UTF-8
+
+            WCHAR* value_w = new WCHAR[(value_length+1)];
+            int    value_size = 4*value_length+1;
+            value.Reserve(value_size);
+
+            if (RegQueryValueEx(key, name_w, 0, &type, (PBYTE)value_w, &value_length ) == ERROR_SUCCESS) {
+                value_size = WideCharToMultiByte(CP_UTF8, 0, value_w, value_length, value.UseChars(), value_size, NULL, FALSE);
+                value.SetLength(value_size);
+            }
+
+            delete[] value_w;
+            result = NPT_SUCCESS;
+        }
+    }
+
+    delete[] name_w;
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/WinCE/NptWinceMain.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,47 @@
+/*****************************************************************
+|
+|   Neptune - Utils : WinCE Implementation
+|
+|   (c) 2002-2006 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <windows.h>
+
+/*----------------------------------------------------------------------
+|   _tmain
++---------------------------------------------------------------------*/
+extern int main(int argc, char** argv);
+
+int
+_tmain(int argc, wchar_t** argv, wchar_t** envp)
+{
+    char** argv_utf8 = new char*[1+argc];
+    int i;
+    int result;
+
+    // allocate and convert args
+    for (i=0; i<argc; i++) {
+        unsigned int arg_length = wcslen(argv[i]);
+        argv_utf8[i] = new char[4*arg_length+1];
+        WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, argv_utf8[i], 4*arg_length+1, 0, 0);
+    }
+
+    // terminate the array
+    argv_utf8[argc] = NULL;
+
+    // call the real main
+    result = main(argc, argv_utf8);
+
+    // cleanup
+    for (i=0; i<argc; i++) {
+        delete [] argv_utf8[i];
+    }
+    delete[] argv_utf8;
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Xbox/NptXboxNetwork.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,97 @@
+/*****************************************************************
+|
+|  Neptune - Network :: Xbox Winsock Implementation
+|
+|  (c) 2001-2005 Gilles Boccon-Gibod
+|  Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <xtl.h>
+#include <winsockx.h>
+
+#include "NptNetwork.h"
+#include "NptXboxNetwork.h"
+
+/*----------------------------------------------------------------------
+|   static initializer
++---------------------------------------------------------------------*/
+NPT_WinsockSystem::NPT_WinsockSystem() {
+    XNetStartupParams xnsp;
+    memset(&xnsp, 0, sizeof(xnsp));
+    xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams);
+    xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;
+
+    // create more memory for networking
+    xnsp.cfgPrivatePoolSizeInPages = 64; // == 256kb, default = 12 (48kb)
+    xnsp.cfgEnetReceiveQueueLength = 16; // == 32kb, default = 8 (16kb)
+    xnsp.cfgIpFragMaxSimultaneous = 16; // default = 4
+    xnsp.cfgIpFragMaxPacketDiv256 = 32; // == 8kb, default = 8 (2kb)
+    xnsp.cfgSockMaxSockets = 64; // default = 64
+    xnsp.cfgSockDefaultRecvBufsizeInK = 128; // default = 16
+    xnsp.cfgSockDefaultSendBufsizeInK = 128; // default = 16
+
+    INT err = XNetStartup(&xnsp);
+
+    WORD    wVersionRequested;
+    WSADATA wsaData;
+    wVersionRequested = MAKEWORD(2, 2);
+    WSAStartup( wVersionRequested, &wsaData );
+}
+NPT_WinsockSystem::~NPT_WinsockSystem() {
+    WSACleanup();
+    XNetCleanup();
+}
+NPT_WinsockSystem NPT_WinsockSystem::Initializer;
+
+/*----------------------------------------------------------------------
+|       NPT_NetworkInterface::GetNetworkInterfaces
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
+{
+    XNADDR xna;
+    DWORD  state;
+    do {
+        state = XNetGetTitleXnAddr(&xna);
+        Sleep(100);
+    } while (state == XNET_GET_XNADDR_PENDING);
+
+    if (state & XNET_GET_XNADDR_STATIC || state & XNET_GET_XNADDR_DHCP) {
+        NPT_IpAddress primary_address(ntohl(xna.ina.s_addr));
+        NPT_IpAddress netmask; /* no support for netmask */
+        NPT_IpAddress broadcast_address(ntohl(xna.ina.s_addr));
+        NPT_Flags     flags = NPT_NETWORK_INTERFACE_FLAG_BROADCAST;
+
+        NPT_MacAddress mac;
+        if (state & XNET_GET_XNADDR_ETHERNET) {
+            mac.SetAddress(NPT_MacAddress::TYPE_ETHERNET, xna.abEnet, 6);
+        }
+
+        // create an interface object
+        char iface_name[5];
+        iface_name[0] = 'i';
+        iface_name[1] = 'f';
+        iface_name[2] = '0';
+        iface_name[3] = '0';
+        iface_name[4] = '\0';
+        NPT_NetworkInterface* iface = new NPT_NetworkInterface(iface_name, mac, flags);
+
+        // set the interface address
+        NPT_NetworkInterfaceAddress iface_address(
+            primary_address,
+            broadcast_address,
+            NPT_IpAddress::Any,
+            netmask);
+        iface->AddAddress(iface_address);  
+
+        // add the interface to the list
+        interfaces.Add(iface);  
+    }
+
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/Source/System/Xbox/NptXboxNetwork.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,19 @@
+/*****************************************************************
+|
+|   Neptune - Network :: Xbox Winsock Implementation
+|
+|   (c) 2001-2005 Gilles Boccon-Gibod
+|   Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   static initializer
++---------------------------------------------------------------------*/
+class NPT_WinsockSystem {
+public:
+    static NPT_WinsockSystem Initializer;
+private:
+    NPT_WinsockSystem();
+    ~NPT_WinsockSystem();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/config/config.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,121 @@
+/*
+ * Automatically generated header file: don't edit
+ */
+
+#define HAVE_DOT_CONFIG 1
+#undef CONFIG_PLATFORM_LINUX
+#undef CONFIG_PLATFORM_CYGWIN
+#undef CONFIG_PLATFORM_WIN32
+
+/*
+ * General Configuration
+ */
+#define PREFIX "/usr/local"
+#undef CONFIG_DEBUG
+#define CONFIG_STRIP_UNWANTED_SECTIONS 1
+#undef CONFIG_VISUAL_STUDIO_7_0
+#undef CONFIG_VISUAL_STUDIO_8_0
+#define CONFIG_VISUAL_STUDIO_7_0_BASE ""
+#define CONFIG_VISUAL_STUDIO_8_0_BASE ""
+#define CONFIG_EXTRA_CFLAGS_OPTIONS ""
+#define CONFIG_EXTRA_LDFLAGS_OPTIONS ""
+
+/*
+ * SSL Library
+ */
+#undef CONFIG_SSL_SERVER_ONLY
+#undef CONFIG_SSL_CERT_VERIFICATION
+#define CONFIG_SSL_ENABLE_CLIENT 1
+#undef CONFIG_SSL_FULL_MODE
+#undef CONFIG_SSL_SKELETON_MODE
+#undef CONFIG_SSL_PROT_LOW
+#define CONFIG_SSL_PROT_MEDIUM 1
+#undef CONFIG_SSL_PROT_HIGH
+#define CONFIG_SSL_USE_DEFAULT_KEY 1
+#define CONFIG_SSL_PRIVATE_KEY_LOCATION ""
+#define CONFIG_SSL_PRIVATE_KEY_PASSWORD ""
+#define CONFIG_SSL_X509_CERT_LOCATION ""
+#undef CONFIG_SSL_GENERATE_X509_CERT
+#define CONFIG_SSL_X509_COMMON_NAME ""
+#define CONFIG_SSL_X509_ORGANIZATION_NAME ""
+#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME ""
+#define CONFIG_SSL_ENABLE_V23_HANDSHAKE 1
+#define CONFIG_SSL_HAS_PEM 1
+#define CONFIG_SSL_USE_PKCS12 1
+#define CONFIG_SSL_EXPIRY_TIME 24
+#define CONFIG_X509_MAX_CA_CERTS 4
+#define CONFIG_SSL_MAX_CERTS 2
+#undef CONFIG_SSL_CTX_MUTEXING
+#undef CONFIG_USE_DEV_URANDOM
+#undef CONFIG_WIN32_USE_CRYPTO_LIB
+#define CONFIG_OPENSSL_COMPATIBLE 1
+#define CONFIG_PERFORMANCE_TESTING 1
+#define CONFIG_SSL_TEST 1
+#define CONFIG_AXHTTPD 1
+
+/*
+ * Axhttpd Configuration
+ */
+#undef CONFIG_HTTP_STATIC_BUILD
+#define CONFIG_HTTP_PORT 80
+#define CONFIG_HTTP_HTTPS_PORT 443
+#define CONFIG_HTTP_SESSION_CACHE_SIZE 5
+#define CONFIG_HTTP_WEBROOT "../www"
+#define CONFIG_HTTP_TIMEOUT 300
+
+/*
+ * CGI
+ */
+#define CONFIG_HTTP_HAS_CGI 1
+#define CONFIG_HTTP_CGI_EXTENSIONS ".lua,.lp"
+#define CONFIG_HTTP_ENABLE_LUA 1
+#define CONFIG_HTTP_LUA_PREFIX "/usr/local"
+#define CONFIG_HTTP_LUA_CGI_LAUNCHER "/bin/cgi"
+#undef CONFIG_HTTP_BUILD_LUA
+#define CONFIG_HTTP_DIRECTORIES 1
+#define CONFIG_HTTP_HAS_AUTHORIZATION 1
+#undef CONFIG_HTTP_HAS_IPV6
+#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER
+#define CONFIG_HTTP_USER ""
+#define CONFIG_HTTP_VERBOSE 1
+#undef CONFIG_HTTP_IS_DAEMON
+
+/*
+ * Language Bindings
+ */
+#undef CONFIG_BINDINGS
+#undef CONFIG_CSHARP_BINDINGS
+#undef CONFIG_VBNET_BINDINGS
+#define CONFIG_DOT_NET_FRAMEWORK_BASE ""
+#undef CONFIG_JAVA_BINDINGS
+#define CONFIG_JAVA_HOME ""
+#undef CONFIG_PERL_BINDINGS
+#define CONFIG_PERL_CORE ""
+#define CONFIG_PERL_LIB ""
+#undef CONFIG_LUA_BINDINGS
+#define CONFIG_LUA_CORE ""
+
+/*
+ * Samples
+ */
+#define CONFIG_SAMPLES 1
+#define CONFIG_C_SAMPLES 1
+#undef CONFIG_CSHARP_SAMPLES
+#undef CONFIG_VBNET_SAMPLES
+#undef CONFIG_JAVA_SAMPLES
+#undef CONFIG_PERL_SAMPLES
+#undef CONFIG_LUA_SAMPLES
+
+/*
+ * BigInt Options
+ */
+#undef CONFIG_BIGINT_CLASSICAL
+#undef CONFIG_BIGINT_MONTGOMERY
+#define CONFIG_BIGINT_BARRETT 1
+#define CONFIG_BIGINT_CRT 1
+#undef CONFIG_BIGINT_KARATSUBA
+#define MUL_KARATSUBA_THRESH 
+#define SQU_KARATSUBA_THRESH 
+#define CONFIG_BIGINT_SLIDING_WINDOW 1
+#define CONFIG_BIGINT_SQUARE 1
+#undef CONFIG_BIGINT_CHECK_ON
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/aes.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * AES implementation - this is a small code version. There are much faster
+ * versions around but they are much larger in size (i.e. they use large 
+ * submix tables).
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/* all commented out in skeleton mode */
+#ifndef CONFIG_SSL_SKELETON_MODE
+
+#define rot1(x) (((x) << 24) | ((x) >> 8))
+#define rot2(x) (((x) << 16) | ((x) >> 16))
+#define rot3(x) (((x) <<  8) | ((x) >> 24))
+
+/* 
+ * This cute trick does 4 'mul by two' at once.  Stolen from
+ * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
+ * a standard graphics trick
+ * The key to this is that we need to xor with 0x1b if the top bit is set.
+ * a 1xxx xxxx   0xxx 0xxx First we mask the 7bit,
+ * b 1000 0000   0000 0000 then we shift right by 7 putting the 7bit in 0bit,
+ * c 0000 0001   0000 0000 we then subtract (c) from (b)
+ * d 0111 1111   0000 0000 and now we and with our mask
+ * e 0001 1011   0000 0000
+ */
+#define mt  0x80808080
+#define ml  0x7f7f7f7f
+#define mh  0xfefefefe
+#define mm  0x1b1b1b1b
+#define mul2(x,t)	((t)=((x)&mt), \
+			((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
+
+#define inv_mix_col(x,f2,f4,f8,f9) (\
+			(f2)=mul2(x,f2), \
+			(f4)=mul2(f2,f4), \
+			(f8)=mul2(f4,f8), \
+			(f9)=(x)^(f8), \
+			(f8)=((f2)^(f4)^(f8)), \
+			(f2)^=(f9), \
+			(f4)^=(f9), \
+			(f8)^=rot3(f2), \
+			(f8)^=rot2(f4), \
+			(f8)^rot1(f9))
+
+/*
+ * AES S-box
+ */
+static const uint8_t aes_sbox[256] =
+{
+	0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
+	0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
+	0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
+	0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
+	0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
+	0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
+	0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
+	0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
+	0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
+	0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
+	0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
+	0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
+	0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
+	0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
+	0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
+	0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
+	0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
+	0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
+	0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
+	0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
+	0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
+	0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
+	0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
+	0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
+	0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
+	0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
+	0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
+	0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
+	0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
+	0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
+	0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
+	0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
+};
+
+/*
+ * AES is-box
+ */
+static const uint8_t aes_isbox[256] = 
+{
+    0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
+    0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
+    0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
+    0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
+    0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
+    0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
+    0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
+    0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
+    0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
+    0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
+    0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
+    0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
+    0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
+    0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
+    0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
+    0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
+    0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
+    0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
+    0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
+    0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
+    0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
+    0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
+    0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
+    0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
+    0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
+    0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
+    0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
+    0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
+    0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
+    0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
+    0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
+    0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+};
+
+static const unsigned char Rcon[30]=
+{
+	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
+	0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
+	0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
+	0xb3,0x7d,0xfa,0xef,0xc5,0x91,
+};
+
+/* ----- static functions ----- */
+static void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
+static void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
+
+/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
+   x^8+x^4+x^3+x+1 */
+static unsigned char AES_xtime(uint32_t x)
+{
+	return x = (x&0x80) ? (x<<1)^0x1b : x<<1;
+}
+
+/**
+ * Set up AES with the key/iv and cipher size.
+ */
+void AES_set_key(AES_CTX *ctx, const uint8_t *key, 
+        const uint8_t *iv, AES_MODE mode)
+{
+    int i, ii;
+    uint32_t *W, tmp, tmp2;
+    const unsigned char *ip;
+    int words;
+
+    switch (mode)
+    {
+        case AES_MODE_128:
+            i = 10;
+            words = 4;
+            break;
+
+        case AES_MODE_256:
+            i = 14;
+            words = 8;
+            break;
+
+        default:        /* fail silently */
+            return;
+    }
+
+    ctx->rounds = i;
+    ctx->key_size = words;
+    W = ctx->ks;
+    for (i = 0; i < words; i+=2)
+    {
+        W[i+0]=	((uint32_t)key[ 0]<<24)|
+            ((uint32_t)key[ 1]<<16)|
+            ((uint32_t)key[ 2]<< 8)|
+            ((uint32_t)key[ 3]    );
+        W[i+1]=	((uint32_t)key[ 4]<<24)|
+            ((uint32_t)key[ 5]<<16)|
+            ((uint32_t)key[ 6]<< 8)|
+            ((uint32_t)key[ 7]    );
+        key += 8;
+    }
+
+    ip = Rcon;
+    ii = 4 * (ctx->rounds+1);
+    for (i = words; i<ii; i++)
+    {
+        tmp = W[i-1];
+
+        if ((i % words) == 0)
+        {
+            tmp2 =(uint32_t)aes_sbox[(tmp    )&0xff]<< 8;
+            tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
+            tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
+            tmp2|=(uint32_t)aes_sbox[(tmp>>24)     ];
+            tmp=tmp2^(((unsigned int)*ip)<<24);
+            ip++;
+        }
+
+        if ((words == 8) && ((i % words) == 4))
+        {
+            tmp2 =(uint32_t)aes_sbox[(tmp    )&0xff]    ;
+            tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
+            tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
+            tmp2|=(uint32_t)aes_sbox[(tmp>>24)     ]<<24;
+            tmp=tmp2;
+        }
+
+        W[i]=W[i-words]^tmp;
+    }
+
+    /* copy the iv across */
+    memcpy(ctx->iv, iv, 16);
+}
+
+/**
+ * Change a key for decryption.
+ */
+void AES_convert_key(AES_CTX *ctx)
+{
+    int i;
+    uint32_t *k,w,t1,t2,t3,t4;
+
+    k = ctx->ks;
+    k += 4;
+
+    for (i= ctx->rounds*4; i > 4; i--)
+    {
+        w= *k;
+        w = inv_mix_col(w,t1,t2,t3,t4);
+        *k++ =w;
+    }
+}
+
+/**
+ * Encrypt a byte sequence (with a block size 16) using the AES cipher.
+ */
+void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
+{
+    int i;
+    uint32_t tin[4], tout[4], iv[4];
+
+    memcpy(iv, ctx->iv, AES_IV_SIZE);
+    for (i = 0; i < 4; i++)
+        tout[i] = ntohl(iv[i]);
+
+    for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
+    {
+        uint32_t msg_32[4];
+        uint32_t out_32[4];
+        memcpy(msg_32, msg, AES_BLOCKSIZE);
+        msg += AES_BLOCKSIZE;
+
+        for (i = 0; i < 4; i++)
+            tin[i] = ntohl(msg_32[i])^tout[i];
+
+        AES_encrypt(ctx, tin);
+
+        for (i = 0; i < 4; i++)
+        {
+            tout[i] = tin[i]; 
+            out_32[i] = htonl(tout[i]);
+        }
+
+        memcpy(out, out_32, AES_BLOCKSIZE);
+        out += AES_BLOCKSIZE;
+    }
+
+    for (i = 0; i < 4; i++)
+        iv[i] = htonl(tout[i]);
+    memcpy(ctx->iv, iv, AES_IV_SIZE);
+}
+
+/**
+ * Decrypt a byte sequence (with a block size 16) using the AES cipher.
+ */
+void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
+{
+    int i;
+    uint32_t tin[4], xor[4], tout[4], data[4], iv[4];
+
+    memcpy(iv, ctx->iv, AES_IV_SIZE);
+    for (i = 0; i < 4; i++)
+        xor[i] = ntohl(iv[i]);
+
+    for (length -= 16; length >= 0; length -= 16)
+    {
+        uint32_t msg_32[4];
+        uint32_t out_32[4];
+        memcpy(msg_32, msg, AES_BLOCKSIZE);
+        msg += AES_BLOCKSIZE;
+
+        for (i = 0; i < 4; i++)
+        {
+            tin[i] = ntohl(msg_32[i]);
+            data[i] = tin[i];
+        }
+
+        AES_decrypt(ctx, data);
+
+        for (i = 0; i < 4; i++)
+        {
+            tout[i] = data[i]^xor[i];
+            xor[i] = tin[i];
+            out_32[i] = htonl(tout[i]);
+        }
+
+        memcpy(out, out_32, AES_BLOCKSIZE);
+        out += AES_BLOCKSIZE;
+    }
+
+    for (i = 0; i < 4; i++)
+        iv[i] = htonl(xor[i]);
+    memcpy(ctx->iv, iv, AES_IV_SIZE);
+}
+
+/**
+ * Encrypt a single block (16 bytes) of data
+ */
+static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
+{
+    /* To make this code smaller, generate the sbox entries on the fly.
+     * This will have a really heavy effect upon performance.
+     */
+    uint32_t tmp[4];
+    uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
+    int curr_rnd;
+    int rounds = ctx->rounds; 
+    const uint32_t *k = ctx->ks;
+
+    /* Pre-round key addition */
+    for (row = 0; row < 4; row++)
+        data[row] ^= *(k++);
+
+    /* Encrypt one block. */
+    for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+    {
+        /* Perform ByteSub and ShiftRow operations together */
+        for (row = 0; row < 4; row++)
+        {
+            a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
+            a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
+            a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF]; 
+            a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
+
+            /* Perform MixColumn iff not last round */
+            if (curr_rnd < (rounds - 1))
+            {
+                tmp1 = a0 ^ a1 ^ a2 ^ a3;
+                old_a0 = a0;
+                a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
+                a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
+                a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
+                a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
+            }
+
+            tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
+        }
+
+        /* KeyAddition - note that it is vital that this loop is separate from
+           the MixColumn operation, which must be atomic...*/ 
+        for (row = 0; row < 4; row++)
+            data[row] = tmp[row] ^ *(k++);
+    }
+}
+
+/**
+ * Decrypt a single block (16 bytes) of data
+ */
+static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
+{ 
+    uint32_t tmp[4];
+    uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
+    uint32_t a0, a1, a2, a3, row;
+    int curr_rnd;
+    int rounds = ctx->rounds;
+    const uint32_t *k = ctx->ks + ((rounds+1)*4);
+
+    /* pre-round key addition */
+    for (row=4; row > 0;row--)
+        data[row-1] ^= *(--k);
+
+    /* Decrypt one block */
+    for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+    {
+        /* Perform ByteSub and ShiftRow operations together */
+        for (row = 4; row > 0; row--)
+        {
+            a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
+            a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
+            a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
+            a3 = aes_isbox[(data[row%4])&0xFF];
+
+            /* Perform MixColumn iff not last round */
+            if (curr_rnd<(rounds-1))
+            {
+                /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
+                   are quite large compared to encryption; this 
+                   operation slows decryption down noticeably. */
+                xt0 = AES_xtime(a0^a1);
+                xt1 = AES_xtime(a1^a2);
+                xt2 = AES_xtime(a2^a3);
+                xt3 = AES_xtime(a3^a0);
+                xt4 = AES_xtime(xt0^xt1);
+                xt5 = AES_xtime(xt1^xt2);
+                xt6 = AES_xtime(xt4^xt5);
+
+                xt0 ^= a1^a2^a3^xt4^xt6;
+                xt1 ^= a0^a2^a3^xt5^xt6;
+                xt2 ^= a0^a1^a3^xt4^xt6;
+                xt3 ^= a0^a1^a2^xt5^xt6;
+                tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
+            }
+            else
+                tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
+        }
+
+        for (row = 4; row > 0; row--)
+            data[row-1] = tmp[row-1] ^ *(--k);
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/bigint.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1576 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup bigint_api Big Integer API
+ * @brief The bigint implementation as used by the axTLS project.
+ *
+ * The bigint library is for RSA encryption/decryption as well as signing.
+ * This code tries to minimise use of malloc/free by maintaining a small 
+ * cache. A bigint context may maintain state by being made "permanent". 
+ * It be be later released with a bi_depermanent() and bi_free() call.
+ *
+ * It supports the following reduction techniques:
+ * - Classical
+ * - Barrett
+ * - Montgomery
+ *
+ * It also implements the following:
+ * - Karatsuba multiplication
+ * - Squaring
+ * - Sliding window exponentiation
+ * - Chinese Remainder Theorem (implemented in rsa.c).
+ *
+ * All the algorithms used are pretty standard, and designed for different
+ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction
+ * may need to be tested for negativity.
+ *
+ * This library steals some ideas from Jef Poskanzer
+ * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
+ * and GMP <http://www.swox.com/gmp>. It gets most of its implementation
+ * detail from "The Handbook of Applied Cryptography"
+ * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
+ * @{
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include "bigint.h"
+
+#define V1      v->comps[v->size-1]                 /**< v1 for division */
+#define V2      v->comps[v->size-2]                 /**< v2 for division */
+#define U(j)    tmp_u->comps[tmp_u->size-j-1]       /**< uj for division */
+#define Q(j)    quotient->comps[quotient->size-j-1] /**< qj for division */
+
+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i);
+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom);
+static bigint *alloc(BI_CTX *ctx, int size);
+static bigint *trim(bigint *bi);
+static void more_comps(bigint *bi, int n);
+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
+    defined(CONFIG_BIGINT_MONTGOMERY)
+static bigint *comp_right_shift(bigint *biR, int num_shifts);
+static bigint *comp_left_shift(bigint *biR, int num_shifts);
+#endif
+
+#ifdef CONFIG_BIGINT_CHECK_ON
+static void check(const bigint *bi);
+#else
+#define check(A)                /**< disappears in normal production mode */
+#endif
+
+
+/**
+ * @brief Start a new bigint context.
+ * @return A bigint context.
+ */
+BI_CTX *bi_initialize(void)
+{
+    /* calloc() sets everything to zero */
+    BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX));
+   
+    /* the radix */
+    ctx->bi_radix = alloc(ctx, 2); 
+    ctx->bi_radix->comps[0] = 0;
+    ctx->bi_radix->comps[1] = 1;
+    bi_permanent(ctx->bi_radix);
+    return ctx;
+}
+
+/**
+ * @brief Close the bigint context and free any resources.
+ *
+ * Free up any used memory - a check is done if all objects were not 
+ * properly freed.
+ * @param ctx [in]   The bigint session context.
+ */
+void bi_terminate(BI_CTX *ctx)
+{
+    bi_depermanent(ctx->bi_radix); 
+    bi_free(ctx, ctx->bi_radix);
+
+    if (ctx->active_count != 0)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("bi_terminate: there were %d un-freed bigints\n",
+                       ctx->active_count);
+#endif
+        abort();
+    }
+
+    bi_clear_cache(ctx);
+    free(ctx);
+}
+
+/**
+ *@brief Clear the memory cache.
+ */
+void bi_clear_cache(BI_CTX *ctx)
+{
+    bigint *p, *pn;
+
+    if (ctx->free_list == NULL)
+        return;
+    
+    for (p = ctx->free_list; p != NULL; p = pn)
+    {
+        pn = p->next;
+        free(p->comps);
+        free(p);
+    }
+
+    ctx->free_count = 0;
+    ctx->free_list = NULL;
+}
+
+/**
+ * @brief Increment the number of references to this object. 
+ * It does not do a full copy.
+ * @param bi [in]   The bigint to copy.
+ * @return A reference to the same bigint.
+ */
+bigint *bi_copy(bigint *bi)
+{
+    check(bi);
+    if (bi->refs != PERMANENT)
+        bi->refs++;
+    return bi;
+}
+
+/**
+ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
+ *
+ * For this object to be freed, bi_depermanent() must be called.
+ * @param bi [in]   The bigint to be made permanent.
+ */
+void bi_permanent(bigint *bi)
+{
+    check(bi);
+    if (bi->refs != 1)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("bi_permanent: refs was not 1\n");
+#endif
+        abort();
+    }
+
+    bi->refs = PERMANENT;
+}
+
+/**
+ * @brief Take a permanent object and make it eligible for freedom.
+ * @param bi [in]   The bigint to be made back to temporary.
+ */
+void bi_depermanent(bigint *bi)
+{
+    check(bi);
+    if (bi->refs != PERMANENT)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("bi_depermanent: bigint was not permanent\n");
+#endif
+        abort();
+    }
+
+    bi->refs = 1;
+}
+
+/**
+ * @brief Free a bigint object so it can be used again. 
+ *
+ * The memory itself it not actually freed, just tagged as being available 
+ * @param ctx [in]   The bigint session context.
+ * @param bi [in]    The bigint to be freed.
+ */
+void bi_free(BI_CTX *ctx, bigint *bi)
+{
+    check(bi);
+    if (bi->refs == PERMANENT)
+    {
+        return;
+    }
+
+    if (--bi->refs > 0)
+    {
+        return;
+    }
+
+    bi->next = ctx->free_list;
+    ctx->free_list = bi;
+    ctx->free_count++;
+
+    if (--ctx->active_count < 0)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("bi_free: active_count went negative "
+                "- double-freed bigint?\n");
+#endif
+        abort();
+    }
+}
+
+/**
+ * @brief Convert an (unsigned) integer into a bigint.
+ * @param ctx [in]   The bigint session context.
+ * @param i [in]     The (unsigned) integer to be converted.
+ * 
+ */
+bigint *int_to_bi(BI_CTX *ctx, comp i)
+{
+    bigint *biR = alloc(ctx, 1);
+    biR->comps[0] = i;
+    return biR;
+}
+
+/**
+ * @brief Do a full copy of the bigint object.
+ * @param ctx [in]   The bigint session context.
+ * @param bi  [in]   The bigint object to be copied.
+ */
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi)
+{
+    bigint *biR = alloc(ctx, bi->size);
+    check(bi);
+    memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE);
+    return biR;
+}
+
+/**
+ * @brief Perform an addition operation between two bigints.
+ * @param ctx [in]  The bigint session context.
+ * @param bia [in]  A bigint.
+ * @param bib [in]  Another bigint.
+ * @return The result of the addition.
+ */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+    int n;
+    comp carry = 0;
+    comp *pa, *pb;
+
+    check(bia);
+    check(bib);
+
+    n = max(bia->size, bib->size);
+    more_comps(bia, n+1);
+    more_comps(bib, n);
+    pa = bia->comps;
+    pb = bib->comps;
+
+    do
+    {
+        comp  sl, rl, cy1;
+        sl = *pa + *pb++;
+        rl = sl + carry;
+        cy1 = sl < *pa;
+        carry = cy1 | (rl < sl);
+        *pa++ = rl;
+    } while (--n != 0);
+
+    *pa = carry;                  /* do overflow */
+    bi_free(ctx, bib);
+    return trim(bia);
+}
+
+/**
+ * @brief Perform a subtraction operation between two bigints.
+ * @param ctx [in]  The bigint session context.
+ * @param bia [in]  A bigint.
+ * @param bib [in]  Another bigint.
+ * @param is_negative [out] If defined, indicates that the result was negative.
+ * is_negative may be null.
+ * @return The result of the subtraction. The result is always positive.
+ */
+bigint *bi_subtract(BI_CTX *ctx, 
+        bigint *bia, bigint *bib, int *is_negative)
+{
+    int n = bia->size;
+    comp *pa, *pb, carry = 0;
+
+    check(bia);
+    check(bib);
+
+    more_comps(bib, n);
+    pa = bia->comps;
+    pb = bib->comps;
+
+    do 
+    {
+        comp sl, rl, cy1;
+        sl = *pa - *pb++;
+        rl = sl - carry;
+        cy1 = sl > *pa;
+        carry = cy1 | (rl > sl);
+        *pa++ = rl;
+    } while (--n != 0);
+
+    if (is_negative)    /* indicate a negative result */
+    {
+        *is_negative = carry;
+    }
+
+    bi_free(ctx, trim(bib));    /* put bib back to the way it was */
+    return trim(bia);
+}
+
+/**
+ * Perform a multiply between a bigint an an (unsigned) integer
+ */
+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
+{
+    int j = 0, n = bia->size;
+    bigint *biR = alloc(ctx, n + 1);
+    comp carry = 0;
+    comp *r = biR->comps;
+    comp *a = bia->comps;
+
+    check(bia);
+
+    /* clear things to start with */
+    memset(r, 0, ((n+1)*COMP_BYTE_SIZE));
+
+    do
+    {
+        long_comp tmp = *r + (long_comp)a[j]*b + carry;
+        *r++ = (comp)tmp;              /* downsize */
+        carry = (comp)(tmp >> COMP_BIT_SIZE);
+    } while (++j < n);
+
+    *r = carry;
+    bi_free(ctx, bia);
+    return trim(biR);
+}
+
+/**
+ * @brief Does both division and modulo calculations. 
+ *
+ * Used extensively when doing classical reduction.
+ * @param ctx [in]  The bigint session context.
+ * @param u [in]    A bigint which is the numerator.
+ * @param v [in]    Either the denominator or the modulus depending on the mode.
+ * @param is_mod [n] Determines if this is a normal division (0) or a reduction
+ * (1).
+ * @return  The result of the division/reduction.
+ */
+bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)
+{
+    int n = v->size, m = u->size-n;
+    int j = 0, orig_u_size = u->size;
+    uint8_t mod_offset = ctx->mod_offset;
+    comp d;
+    bigint *quotient, *tmp_u;
+    comp q_dash;
+
+    check(u);
+    check(v);
+
+    /* if doing reduction and we are < mod, then return mod */
+    if (is_mod && bi_compare(v, u) > 0)
+    {
+        bi_free(ctx, v);
+        return u;
+    }
+
+    quotient = alloc(ctx, m+1);
+    tmp_u = alloc(ctx, n+1);
+    v = trim(v);        /* make sure we have no leading 0's */
+    d = (comp)((long_comp)COMP_RADIX/(V1+1));
+
+    /* clear things to start with */
+    memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));
+
+    /* normalise */
+    if (d > 1)
+    {
+        u = bi_int_multiply(ctx, u, d);
+
+        if (is_mod)
+        {
+            v = ctx->bi_normalised_mod[mod_offset];
+        }
+        else
+        {
+            v = bi_int_multiply(ctx, v, d);
+        }
+    }
+
+    if (orig_u_size == u->size)  /* new digit position u0 */
+    {
+        more_comps(u, orig_u_size + 1);
+    }
+
+    do
+    {
+        /* get a temporary short version of u */
+        memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);
+
+        /* calculate q' */
+        if (U(0) == V1)
+        {
+            q_dash = COMP_RADIX-1;
+        }
+        else
+        {
+            q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1);
+        }
+
+        if (v->size > 1 && V2)
+        {
+            /* we are implementing the following:
+            if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - 
+                    q_dash*V1)*COMP_RADIX) + U(2))) ... */
+            comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - 
+                                        (long_comp)q_dash*V1);
+            if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2))
+            {
+                q_dash--;
+            }
+        }
+
+        /* multiply and subtract */
+        if (q_dash)
+        {
+            int is_negative;
+            tmp_u = bi_subtract(ctx, tmp_u, 
+                    bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);
+            more_comps(tmp_u, n+1);
+
+            Q(j) = q_dash; 
+
+            /* add back */
+            if (is_negative)
+            {
+                Q(j)--;
+                tmp_u = bi_add(ctx, tmp_u, bi_copy(v));
+
+                /* lop off the carry */
+                tmp_u->size--;
+                v->size--;
+            }
+        }
+        else
+        {
+            Q(j) = 0; 
+        }
+
+        /* copy back to u */
+        memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);
+    } while (++j <= m);
+
+    bi_free(ctx, tmp_u);
+    bi_free(ctx, v);
+
+    if (is_mod)     /* get the remainder */
+    {
+        bi_free(ctx, quotient);
+        return bi_int_divide(ctx, trim(u), d);
+    }
+    else            /* get the quotient */
+    {
+        bi_free(ctx, u);
+        return trim(quotient);
+    }
+}
+
+/*
+ * Perform an integer divide on a bigint.
+ */
+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom)
+{
+    int i = biR->size - 1;
+    (void)ctx; /* unused */
+    long_comp r = 0;
+
+    check(biR);
+
+    do
+    {
+        r = (r<<COMP_BIT_SIZE) + biR->comps[i];
+        biR->comps[i] = (comp)(r / denom);
+        r %= denom;
+    } while (--i >= 0);
+
+    return trim(biR);
+}
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+/**
+ * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1, 
+ * where B^-1(B-1) mod N=1. Actually, only the least significant part of 
+ * N' is needed, hence the definition N0'=N' mod b. We reproduce below the 
+ * simple algorithm from an article by Dusse and Kaliski to efficiently 
+ * find N0' from N0 and b */
+static comp modular_inverse(bigint *bim)
+{
+    int i;
+    comp t = 1;
+    comp two_2_i_minus_1 = 2;   /* 2^(i-1) */
+    long_comp two_2_i = 4;      /* 2^i */
+    comp N = bim->comps[0];
+
+    for (i = 2; i <= COMP_BIT_SIZE; i++)
+    {
+        if ((long_comp)N*t%two_2_i >= two_2_i_minus_1)
+        {
+            t += two_2_i_minus_1;
+        }
+
+        two_2_i_minus_1 <<= 1;
+        two_2_i <<= 1;
+    }
+
+    return (comp)(COMP_RADIX-t);
+}
+#endif
+
+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
+    defined(CONFIG_BIGINT_MONTGOMERY)
+/**
+ * Take each component and shift down (in terms of components) 
+ */
+static bigint *comp_right_shift(bigint *biR, int num_shifts)
+{
+    int i = biR->size-num_shifts;
+    comp *x = biR->comps;
+    comp *y = &biR->comps[num_shifts];
+
+    check(biR);
+
+    if (i <= 0)     /* have we completely right shifted? */
+    {
+        biR->comps[0] = 0;  /* return 0 */
+        biR->size = 1;
+        return biR;
+    }
+
+    do
+    {
+        *x++ = *y++;
+    } while (--i > 0);
+
+    biR->size -= num_shifts;
+    return biR;
+}
+
+/**
+ * Take each component and shift it up (in terms of components) 
+ */
+static bigint *comp_left_shift(bigint *biR, int num_shifts)
+{
+    int i = biR->size-1;
+    comp *x, *y;
+
+    check(biR);
+
+    if (num_shifts <= 0)
+    {
+        return biR;
+    }
+
+    more_comps(biR, biR->size + num_shifts);
+
+    x = &biR->comps[i+num_shifts];
+    y = &biR->comps[i];
+
+    do
+    {
+        *x-- = *y--;
+    } while (i--);
+
+    memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */
+    return biR;
+}
+#endif
+
+/**
+ * @brief Allow a binary sequence to be imported as a bigint.
+ * @param ctx [in]  The bigint session context.
+ * @param data [in] The data to be converted.
+ * @param size [in] The number of bytes of data.
+ * @return A bigint representing this data.
+ */
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size)
+{
+    bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE);
+    int i, j = 0, offset = 0;
+
+    memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
+
+    for (i = size-1; i >= 0; i--)
+    {
+        biR->comps[offset] += data[i] << (j*8);
+
+        if (++j == COMP_BYTE_SIZE)
+        {
+            j = 0;
+            offset ++;
+        }
+    }
+
+    return trim(biR);
+}
+
+#ifdef CONFIG_SSL_FULL_MODE
+/**
+ * @brief The testharness uses this code to import text hex-streams and 
+ * convert them into bigints.
+ * @param ctx [in]  The bigint session context.
+ * @param data [in] A string consisting of hex characters. The characters must
+ * be in upper case.
+ * @return A bigint representing this data.
+ */
+bigint *bi_str_import(BI_CTX *ctx, const char *data)
+{
+    int size = strlen(data);
+    bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES);
+    int i, j = 0, offset = 0;
+    memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
+
+    for (i = size-1; i >= 0; i--)
+    {
+        int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);
+        biR->comps[offset] += num << (j*4);
+
+        if (++j == COMP_NUM_NIBBLES)
+        {
+            j = 0;
+            offset ++;
+        }
+    }
+
+    return biR;
+}
+
+void bi_print(const char *label, bigint *x)
+{
+    int i, j;
+
+    if (x == NULL)
+    {
+        printf("%s: (null)\n", label);
+        return;
+    }
+
+    printf("%s: (size %d)\n", label, x->size);
+    for (i = x->size-1; i >= 0; i--)
+    {
+        for (j = COMP_NUM_NIBBLES-1; j >= 0; j--)
+        {
+            comp mask = 0x0f << (j*4);
+            comp num = (x->comps[i] & mask) >> (j*4);
+            putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);
+        }
+    }  
+
+    printf("\n");
+}
+#endif
+
+/**
+ * @brief Take a bigint and convert it into a byte sequence. 
+ *
+ * This is useful after a decrypt operation.
+ * @param ctx [in]  The bigint session context.
+ * @param x [in]  The bigint to be converted.
+ * @param data [out] The converted data as a byte stream.
+ * @param size [in] The maximum size of the byte stream. Unused bytes will be
+ * zeroed.
+ */
+void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)
+{
+    int i, j, k = size-1;
+
+    check(x);
+    memset(data, 0, size);  /* ensure all leading 0's are cleared */
+
+    for (i = 0; i < x->size; i++)
+    {
+        for (j = 0; j < COMP_BYTE_SIZE; j++)
+        {
+            comp mask = 0xff << (j*8);
+            int num = (x->comps[i] & mask) >> (j*8);
+            data[k--] = num;
+
+            if (k < 0)
+            {
+                break;
+            }
+        }
+    }
+
+    bi_free(ctx, x);
+}
+
+/**
+ * @brief Pre-calculate some of the expensive steps in reduction. 
+ *
+ * This function should only be called once (normally when a session starts).
+ * When the session is over, bi_free_mod() should be called. bi_mod_power()
+ * relies on this function being called.
+ * @param ctx [in]  The bigint session context.
+ * @param bim [in]  The bigint modulus that will be used.
+ * @param mod_offset [in] There are three moduluii that can be stored - the
+ * standard modulus, and its two primes p and q. This offset refers to which
+ * modulus we are referring to.
+ * @see bi_free_mod(), bi_mod_power().
+ */
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)
+{
+    int k = bim->size;
+    comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));
+#ifdef CONFIG_BIGINT_MONTGOMERY
+    bigint *R, *R2;
+#endif
+
+    ctx->bi_mod[mod_offset] = bim;
+    bi_permanent(ctx->bi_mod[mod_offset]);
+    ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
+    bi_permanent(ctx->bi_normalised_mod[mod_offset]);
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+    /* set montgomery variables */
+    R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1);     /* R */
+    R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1);  /* R^2 */
+    ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2);             /* R^2 mod m */
+    ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R);               /* R mod m */
+
+    bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
+    bi_permanent(ctx->bi_R_mod_m[mod_offset]);
+
+    ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);
+
+#elif defined (CONFIG_BIGINT_BARRETT)
+    ctx->bi_mu[mod_offset] = 
+        bi_divide(ctx, comp_left_shift(
+            bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);
+    bi_permanent(ctx->bi_mu[mod_offset]);
+#endif
+}
+
+/**
+ * @brief Used when cleaning various bigints at the end of a session.
+ * @param ctx [in]  The bigint session context.
+ * @param mod_offset [in] The offset to use.
+ * @see bi_set_mod().
+ */
+void bi_free_mod(BI_CTX *ctx, int mod_offset)
+{
+    bi_depermanent(ctx->bi_mod[mod_offset]);
+    bi_free(ctx, ctx->bi_mod[mod_offset]);
+#if defined (CONFIG_BIGINT_MONTGOMERY)
+    bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);
+    bi_depermanent(ctx->bi_R_mod_m[mod_offset]);
+    bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);
+    bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);
+#elif defined(CONFIG_BIGINT_BARRETT)
+    bi_depermanent(ctx->bi_mu[mod_offset]); 
+    bi_free(ctx, ctx->bi_mu[mod_offset]);
+#endif
+    bi_depermanent(ctx->bi_normalised_mod[mod_offset]); 
+    bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
+}
+
+/** 
+ * Perform a standard multiplication between two bigints.
+ */
+static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+    int i, j, i_plus_j;
+    int n = bia->size; 
+    int t = bib->size;
+    bigint *biR = alloc(ctx, n + t);
+    comp *sr = biR->comps;
+    comp *sa = bia->comps;
+    comp *sb = bib->comps;
+
+    check(bia);
+    check(bib);
+
+    /* clear things to start with */
+    memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE));
+    i = 0;
+
+    do 
+    {
+        comp carry = 0;
+        comp b = *sb++;
+        i_plus_j = i;
+        j = 0;
+
+        do
+        {
+            long_comp tmp = sr[i_plus_j] + (long_comp)sa[j]*b + carry;
+            sr[i_plus_j++] = (comp)tmp;              /* downsize */
+            carry = (comp)(tmp >> COMP_BIT_SIZE);
+        } while (++j < n);
+
+        sr[i_plus_j] = carry;
+    } while (++i < t);
+
+    bi_free(ctx, bia);
+    bi_free(ctx, bib);
+    return trim(biR);
+}
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+/*
+ * Karatsuba improves on regular multiplication due to only 3 multiplications 
+ * being done instead of 4. The additional additions/subtractions are O(N) 
+ * rather than O(N^2) and so for big numbers it saves on a few operations 
+ */
+static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square)
+{
+    bigint *x0, *x1;
+    bigint *p0, *p1, *p2;
+    int m;
+
+    if (is_square)
+    {
+        m = (bia->size + 1)/2;
+    }
+    else
+    {
+        m = (max(bia->size, bib->size) + 1)/2;
+    }
+
+    x0 = bi_clone(ctx, bia);
+    x0->size = m;
+    x1 = bi_clone(ctx, bia);
+    comp_right_shift(x1, m);
+    bi_free(ctx, bia);
+
+    /* work out the 3 partial products */
+    if (is_square)
+    {
+        p0 = bi_square(ctx, bi_copy(x0));
+        p2 = bi_square(ctx, bi_copy(x1));
+        p1 = bi_square(ctx, bi_add(ctx, x0, x1));
+    }
+    else /* normal multiply */
+    {
+        bigint *y0, *y1;
+        y0 = bi_clone(ctx, bib);
+        y0->size = m;
+        y1 = bi_clone(ctx, bib);
+        comp_right_shift(y1, m);
+        bi_free(ctx, bib);
+
+        p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));
+        p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));
+        p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));
+    }
+
+    p1 = bi_subtract(ctx, 
+            bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL);
+
+    comp_left_shift(p1, m);
+    comp_left_shift(p2, 2*m);
+    return bi_add(ctx, p1, bi_add(ctx, p0, p2));
+}
+#endif
+
+/**
+ * @brief Perform a multiplication operation between two bigints.
+ * @param ctx [in]  The bigint session context.
+ * @param bia [in]  A bigint.
+ * @param bib [in]  Another bigint.
+ * @return The result of the multiplication.
+ */
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+    check(bia);
+    check(bib);
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+    if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH)
+    {
+        return regular_multiply(ctx, bia, bib);
+    }
+
+    return karatsuba(ctx, bia, bib, 0);
+#else
+    return regular_multiply(ctx, bia, bib);
+#endif
+}
+
+#ifdef CONFIG_BIGINT_SQUARE
+/*
+ * Perform the actual square operion. It takes into account overflow.
+ */
+static bigint *regular_square(BI_CTX *ctx, bigint *bi)
+{
+    int t = bi->size;
+    int i = 0, j;
+    bigint *biR = alloc(ctx, t*2);
+    comp *w = biR->comps;
+    comp *x = bi->comps;
+    comp carry;
+
+    memset(w, 0, biR->size*COMP_BYTE_SIZE);
+
+    do
+    {
+        long_comp tmp = w[2*i] + (long_comp)x[i]*x[i];
+        comp u = 0;
+        w[2*i] = (comp)tmp;
+        carry = (comp)(tmp >> COMP_BIT_SIZE);
+
+        for (j = i+1; j < t; j++)
+        {
+            long_comp xx = (long_comp)x[i]*x[j];
+            long_comp xx2 = 2*xx;
+            long_comp blob = (long_comp)w[i+j]+carry;
+
+            if (u)                  /* previous overflow */
+            {
+                blob += COMP_RADIX;
+            }
+
+
+            u = 0;
+            tmp = xx2 + blob;
+
+            /* check for overflow */
+            if ((COMP_MAX-xx) < xx  || (COMP_MAX-xx2) < blob)
+            {
+                u = 1;
+            }
+
+            w[i+j] = (comp)tmp;
+            carry = (comp)(tmp >> COMP_BIT_SIZE);
+        }
+
+        w[i+t] += carry;
+
+        if (u)
+        {
+            w[i+t+1] = 1;   /* add carry */
+        }
+    } while (++i < t);
+
+    bi_free(ctx, bi);
+    return trim(biR);
+}
+
+/**
+ * @brief Perform a square operation on a bigint.
+ * @param ctx [in]  The bigint session context.
+ * @param bia [in]  A bigint.
+ * @return The result of the multiplication.
+ */
+bigint *bi_square(BI_CTX *ctx, bigint *bia)
+{
+    check(bia);
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+    if (bia->size < SQU_KARATSUBA_THRESH) 
+    {
+        return regular_square(ctx, bia);
+    }
+
+    return karatsuba(ctx, bia, NULL, 1);
+#else
+    return regular_square(ctx, bia);
+#endif
+}
+#endif
+
+/**
+ * @brief Compare two bigints.
+ * @param bia [in]  A bigint.
+ * @param bib [in]  Another bigint.
+ * @return -1 if smaller, 1 if larger and 0 if equal.
+ */
+int bi_compare(bigint *bia, bigint *bib)
+{
+    int r, i;
+
+    check(bia);
+    check(bib);
+
+    if (bia->size > bib->size)
+        r = 1;
+    else if (bia->size < bib->size)
+        r = -1;
+    else
+    {
+        comp *a = bia->comps; 
+        comp *b = bib->comps; 
+
+        /* Same number of components.  Compare starting from the high end
+         * and working down. */
+        r = 0;
+        i = bia->size - 1;
+
+        do 
+        {
+            if (a[i] > b[i])
+            { 
+                r = 1;
+                break; 
+            }
+            else if (a[i] < b[i])
+            { 
+                r = -1;
+                break; 
+            }
+        } while (--i >= 0);
+    }
+
+    return r;
+}
+
+/*
+ * Allocate and zero more components.  Does not consume bi. 
+ */
+static void more_comps(bigint *bi, int n)
+{
+    if (n > bi->max_comps)
+    {
+        bi->max_comps = max(bi->max_comps * 2, n);
+        bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);
+    }
+
+    if (n > bi->size)
+    {
+        memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);
+    }
+
+    bi->size = n;
+}
+
+/*
+ * Make a new empty bigint. It may just use an old one if one is available.
+ * Otherwise get one off the heap.
+ */
+static bigint *alloc(BI_CTX *ctx, int size)
+{
+    bigint *biR;
+
+    /* Can we recycle an old bigint? */
+    if (ctx->free_list != NULL)
+    {
+        biR = ctx->free_list;
+        ctx->free_list = biR->next;
+        ctx->free_count--;
+
+        if (biR->refs != 0)
+        {
+#ifdef CONFIG_SSL_FULL_MODE
+            printf("alloc: refs was not 0\n");
+#endif
+            abort();    /* create a stack trace from a core dump */
+        }
+
+        more_comps(biR, size);
+    }
+    else
+    {
+        /* No free bigints available - create a new one. */
+        biR = (bigint *)malloc(sizeof(bigint));
+        biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE);
+        biR->max_comps = size;  /* give some space to spare */
+    }
+
+    biR->size = size;
+    biR->refs = 1;
+    biR->next = NULL;
+    ctx->active_count++;
+    return biR;
+}
+
+/*
+ * Work out the highest '1' bit in an exponent. Used when doing sliding-window
+ * exponentiation.
+ */
+static int find_max_exp_index(bigint *biexp)
+{
+    int i = COMP_BIT_SIZE-1;
+    comp shift = COMP_RADIX/2;
+    comp test = biexp->comps[biexp->size-1];    /* assume no leading zeroes */
+
+    check(biexp);
+
+    do
+    {
+        if (test & shift)
+        {
+            return i+(biexp->size-1)*COMP_BIT_SIZE;
+        }
+
+        shift >>= 1;
+    } while (--i != 0);
+
+    return -1;      /* error - must have been a leading 0 */
+}
+
+/*
+ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
+ * exponentiation.
+ */
+static int exp_bit_is_one(bigint *biexp, int offset)
+{
+    comp test = biexp->comps[offset / COMP_BIT_SIZE];
+    int num_shifts = offset % COMP_BIT_SIZE;
+    comp shift = 1;
+    int i;
+
+    check(biexp);
+
+    for (i = 0; i < num_shifts; i++)
+    {
+        shift <<= 1;
+    }
+
+    return test & shift;
+}
+
+#ifdef CONFIG_BIGINT_CHECK_ON
+/*
+ * Perform a sanity check on bi.
+ */
+static void check(const bigint *bi)
+{
+    if (bi->refs <= 0)
+    {
+        printf("check: zero or negative refs in bigint\n");
+        abort();
+    }
+
+    if (bi->next != NULL)
+    {
+        printf("check: attempt to use a bigint from "
+                "the free list\n");
+        abort();
+    }
+}
+#endif
+
+/*
+ * Delete any leading 0's (and allow for 0).
+ */
+static bigint *trim(bigint *bi)
+{
+    check(bi);
+
+    while (bi->comps[bi->size-1] == 0 && bi->size > 1)
+    {
+        bi->size--;
+    }
+
+    return bi;
+}
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+/**
+ * @brief Perform a single montgomery reduction.
+ * @param ctx [in]  The bigint session context.
+ * @param bixy [in]  A bigint.
+ * @return The result of the montgomery reduction.
+ */
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy)
+{
+    int i = 0, n;
+    uint8_t mod_offset = ctx->mod_offset;
+    bigint *bim = ctx->bi_mod[mod_offset];
+    comp mod_inv = ctx->N0_dash[mod_offset];
+
+    check(bixy);
+
+    if (ctx->use_classical)     /* just use classical instead */
+    {
+        return bi_mod(ctx, bixy);
+    }
+
+    n = bim->size;
+
+    do
+    {
+        bixy = bi_add(ctx, bixy, comp_left_shift(
+                    bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));
+    } while (++i < n);
+
+    comp_right_shift(bixy, n);
+
+    if (bi_compare(bixy, bim) >= 0)
+    {
+        bixy = bi_subtract(ctx, bixy, bim, NULL);
+    }
+
+    return bixy;
+}
+
+#elif defined(CONFIG_BIGINT_BARRETT)
+/*
+ * Stomp on the most significant components to give the illusion of a "mod base
+ * radix" operation 
+ */
+static bigint *comp_mod(bigint *bi, int mod)
+{
+    check(bi);
+
+    if (bi->size > mod)
+    {
+        bi->size = mod;
+    }
+
+    return bi;
+}
+
+/*
+ * Barrett reduction has no need for some parts of the product, so ignore bits
+ * of the multiply. This routine gives Barrett its big performance
+ * improvements over Classical/Montgomery reduction methods. 
+ */
+static bigint *partial_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, 
+        int inner_partial, int outer_partial)
+{
+    int i = 0, j, n = bia->size, t = bib->size;
+    bigint *biR;
+    comp carry;
+    comp *sr, *sa, *sb;
+
+    check(bia);
+    check(bib);
+
+    biR = alloc(ctx, n + t);
+    sa = bia->comps;
+    sb = bib->comps;
+    sr = biR->comps;
+
+    if (inner_partial)
+    {
+        memset(sr, 0, inner_partial*COMP_BYTE_SIZE); 
+    }
+    else    /* outer partial */
+    {
+        if (n < outer_partial || t < outer_partial) /* should we bother? */
+        {
+            bi_free(ctx, bia);
+            bi_free(ctx, bib);
+            biR->comps[0] = 0;      /* return 0 */
+            biR->size = 1;
+            return biR;
+        }
+
+        memset(&sr[outer_partial], 0, (n+t-outer_partial)*COMP_BYTE_SIZE);
+    }
+
+    do 
+    {
+        comp *a = sa;
+        comp b = *sb++;
+        long_comp tmp;
+        int i_plus_j = i;
+        carry = 0;
+        j = n;
+
+        if (outer_partial && i_plus_j < outer_partial)
+        {
+            i_plus_j = outer_partial;
+            a = &sa[outer_partial-i];
+            j = n-(outer_partial-i);
+        }
+
+        do
+        {
+            if (inner_partial && i_plus_j >= inner_partial) 
+            {
+                break;
+            }
+
+            tmp = sr[i_plus_j] + ((long_comp)*a++)*b + carry;
+            sr[i_plus_j++] = (comp)tmp;              /* downsize */
+            carry = (comp)(tmp >> COMP_BIT_SIZE);
+        } while (--j != 0);
+
+        sr[i_plus_j] = carry;
+    } while (++i < t);
+
+    bi_free(ctx, bia);
+    bi_free(ctx, bib);
+    return trim(biR);
+}
+
+/**
+ * @brief Perform a single Barrett reduction.
+ * @param ctx [in]  The bigint session context.
+ * @param bi [in]  A bigint.
+ * @return The result of the Barrett reduction.
+ */
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi)
+{
+    bigint *q1, *q2, *q3, *r1, *r2, *r;
+    uint8_t mod_offset = ctx->mod_offset;
+    bigint *bim = ctx->bi_mod[mod_offset];
+    int k = bim->size;
+
+    check(bi);
+    check(bim);
+
+    /* use Classical method instead  - Barrett cannot help here */
+    if (bi->size > k*2)
+    {
+        return bi_mod(ctx, bi);
+    }
+
+    q1 = comp_right_shift(bi_clone(ctx, bi), k-1);
+
+    /* do outer partial multiply */
+    q2 = partial_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1); 
+    q3 = comp_right_shift(q2, k+1);
+    r1 = comp_mod(bi, k+1);
+
+    /* do inner partial multiply */
+    r2 = comp_mod(partial_multiply(ctx, q3, bim, k+1, 0), k+1);
+    r = bi_subtract(ctx, r1, r2, NULL);
+
+    /* if (r >= m) r = r - m; */
+    if (bi_compare(r, bim) >= 0)
+    {
+        r = bi_subtract(ctx, r, bim, NULL);
+    }
+
+    return r;
+}
+#endif /* CONFIG_BIGINT_BARRETT */
+
+#ifdef CONFIG_BIGINT_SLIDING_WINDOW
+/*
+ * Work out g1, g3, g5, g7... etc for the sliding-window algorithm 
+ */
+static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1)
+{
+    int k = 1, i;
+    bigint *g2;
+
+    for (i = 0; i < window-1; i++)   /* compute 2^(window-1) */
+    {
+        k <<= 1;
+    }
+
+    ctx->g = (bigint **)malloc(k*sizeof(bigint *));
+    ctx->g[0] = bi_clone(ctx, g1);
+    bi_permanent(ctx->g[0]);
+    g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0]));   /* g^2 */
+
+    for (i = 1; i < k; i++)
+    {
+        ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2)));
+        bi_permanent(ctx->g[i]);
+    }
+
+    bi_free(ctx, g2);
+    ctx->window = k;
+}
+#endif
+
+/**
+ * @brief Perform a modular exponentiation.
+ *
+ * This function requires bi_set_mod() to have been called previously. This is 
+ * one of the optimisations used for performance.
+ * @param ctx [in]  The bigint session context.
+ * @param bi  [in]  The bigint on which to perform the mod power operation.
+ * @param biexp [in] The bigint exponent.
+ * @return The result of the mod exponentiation operation
+ * @see bi_set_mod().
+ */
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
+{
+    int i = find_max_exp_index(biexp), j, window_size = 1;
+    bigint *biR = int_to_bi(ctx, 1);
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+    uint8_t mod_offset = ctx->mod_offset;
+    if (!ctx->use_classical)
+    {
+        /* preconvert */
+        bi = bi_mont(ctx, 
+                bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset]));    /* x' */
+        bi_free(ctx, biR);
+        biR = ctx->bi_R_mod_m[mod_offset];                              /* A */
+    }
+#endif
+
+    check(bi);
+    check(biexp);
+
+#ifdef CONFIG_BIGINT_SLIDING_WINDOW
+    for (j = i; j > 32; j /= 5) /* work out an optimum size */
+        window_size++;
+
+    /* work out the slide constants */
+    precompute_slide_window(ctx, window_size, bi);
+#else   /* just one constant */
+    ctx->g = (bigint **)malloc(sizeof(bigint *));
+    ctx->g[0] = bi_clone(ctx, bi);
+    ctx->window = 1;
+    bi_permanent(ctx->g[0]);
+#endif
+
+    /* if sliding-window is off, then only one bit will be done at a time and
+     * will reduce to standard left-to-right exponentiation */
+    do
+    {
+        if (exp_bit_is_one(biexp, i))
+        {
+            int l = i-window_size+1;
+            int part_exp = 0;
+
+            if (l < 0)  /* LSB of exponent will always be 1 */
+                l = 0;
+            else
+            {
+                while (exp_bit_is_one(biexp, l) == 0)
+                    l++;    /* go back up */
+            }
+
+            /* build up the section of the exponent */
+            for (j = i; j >= l; j--)
+            {
+                biR = bi_residue(ctx, bi_square(ctx, biR));
+                if (exp_bit_is_one(biexp, j))
+                    part_exp++;
+
+                if (j != l)
+                    part_exp <<= 1;
+            }
+
+            part_exp = (part_exp-1)/2;  /* adjust for array */
+            biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));
+            i = l-1;
+        }
+        else    /* square it */
+        {
+            biR = bi_residue(ctx, bi_square(ctx, biR));
+            i--;
+        }
+    } while (i >= 0);
+     
+    /* cleanup */
+    for (i = 0; i < ctx->window; i++)
+    {
+        bi_depermanent(ctx->g[i]);
+        bi_free(ctx, ctx->g[i]);
+    }
+
+    free(ctx->g);
+    bi_free(ctx, bi);
+    bi_free(ctx, biexp);
+#if defined CONFIG_BIGINT_MONTGOMERY
+    return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */
+#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
+    return biR;
+#endif
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * @brief Perform a modular exponentiation using a temporary modulus.
+ *
+ * We need this function to check the signatures of certificates. The modulus
+ * of this function is temporary as it's just used for authentication.
+ * @param ctx [in]  The bigint session context.
+ * @param bi  [in]  The bigint to perform the exp/mod.
+ * @param bim [in]  The temporary modulus.
+ * @param biexp [in] The bigint exponent.
+ * @return The result of the mod exponentiation operation
+ * @see bi_set_mod().
+ */
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp)
+{
+    bigint *biR, *tmp_biR;
+
+    /* Set up a temporary bigint context and transfer what we need between
+     * them. We need to do this since we want to keep the original modulus
+     * which is already in this context. This operation is only called when
+     * doing peer verification, and so is not expensive :-) */
+    BI_CTX *tmp_ctx = bi_initialize();
+    bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET);
+    tmp_biR = bi_mod_power(tmp_ctx, 
+                bi_clone(tmp_ctx, bi), 
+                bi_clone(tmp_ctx, biexp));
+    biR = bi_clone(ctx, tmp_biR);
+    bi_free(tmp_ctx, tmp_biR);
+    bi_free_mod(tmp_ctx, BIGINT_M_OFFSET);
+    bi_terminate(tmp_ctx);
+
+    bi_free(ctx, bi);
+    bi_free(ctx, bim);
+    bi_free(ctx, biexp);
+    return biR;
+}
+#endif
+
+#ifdef CONFIG_BIGINT_CRT
+/**
+ * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
+ *
+ * @param ctx [in]  The bigint session context.
+ * @param bi  [in]  The bigint to perform the exp/mod.
+ * @param dP [in] CRT's dP bigint
+ * @param dQ [in] CRT's dQ bigint
+ * @param p [in] CRT's p bigint
+ * @param q [in] CRT's q bigint
+ * @param qInv [in] CRT's qInv bigint
+ * @return The result of the CRT operation
+ */
+bigint *bi_crt(BI_CTX *ctx, bigint *bi,
+        bigint *dP, bigint *dQ,
+        bigint *p, bigint *q, bigint *qInv)
+{
+    bigint *m1, *m2, *h;
+
+    /* Montgomery has a condition the 0 < x, y < m and these products violate
+     * that condition. So disable Montgomery when using CRT */
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+    ctx->use_classical = 1;
+#endif
+    ctx->mod_offset = BIGINT_P_OFFSET;
+    m1 = bi_mod_power(ctx, bi_copy(bi), dP);
+
+    ctx->mod_offset = BIGINT_Q_OFFSET;
+    m2 = bi_mod_power(ctx, bi, dQ);
+
+    h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL);
+    h = bi_multiply(ctx, h, qInv);
+    ctx->mod_offset = BIGINT_P_OFFSET;
+    h = bi_residue(ctx, h);
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+    ctx->use_classical = 0;         /* reset for any further operation */
+#endif
+    return bi_add(ctx, m2, bi_multiply(ctx, q, h));
+}
+#endif
+/** @} */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/bigint.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_HEADER
+#define BIGINT_HEADER
+
+#include "crypto.h"
+
+BI_CTX *bi_initialize(void);
+void bi_terminate(BI_CTX *ctx);
+void bi_permanent(bigint *bi);
+void bi_depermanent(bigint *bi);
+void bi_clear_cache(BI_CTX *ctx);
+void bi_free(BI_CTX *ctx, bigint *bi);
+bigint *bi_copy(bigint *bi);
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
+void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
+bigint *int_to_bi(BI_CTX *ctx, comp i);
+
+/* the functions that actually do something interesting */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_subtract(BI_CTX *ctx, bigint *bia, 
+        bigint *bib, int *is_negative);
+bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
+int bi_compare(bigint *bia, bigint *bib);
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
+void bi_free_mod(BI_CTX *ctx, int mod_offset);
+
+#ifdef CONFIG_SSL_FULL_MODE
+void bi_print(const char *label, bigint *bi);
+bigint *bi_str_import(BI_CTX *ctx, const char *data);
+#endif
+
+/**
+ * @def bi_mod
+ * Find the residue of B. bi_set_mod() must be called before hand.
+ */
+#define bi_mod(A, B)      bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
+
+/**
+ * bi_residue() is technically the same as bi_mod(), but it uses the
+ * appropriate reduction technique (which is bi_mod() when doing classical
+ * reduction).
+ */
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+#define bi_residue(A, B)         bi_mont(A, B)
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
+#elif defined(CONFIG_BIGINT_BARRETT)
+#define bi_residue(A, B)         bi_barrett(A, B)
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
+#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
+#define bi_residue(A, B)         bi_mod(A, B)
+#endif
+
+#ifdef CONFIG_BIGINT_SQUARE
+bigint *bi_square(BI_CTX *ctx, bigint *bi);
+#else
+#define bi_square(A, B)     bi_multiply(A, bi_copy(B), B)
+#endif
+
+#ifdef CONFIG_BIGINT_CRT
+bigint *bi_crt(BI_CTX *ctx, bigint *bi,
+        bigint *dP, bigint *dQ,
+        bigint *p, bigint *q,
+        bigint *qInv);
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/bigint_impl.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_IMPL_HEADER
+#define BIGINT_IMPL_HEADER
+
+/* Maintain a number of precomputed variables when doing reduction */
+#define BIGINT_M_OFFSET     0    /**< Normal modulo offset. */
+#ifdef CONFIG_BIGINT_CRT
+#define BIGINT_P_OFFSET     1    /**< p modulo offset. */
+#define BIGINT_Q_OFFSET     2    /**< q module offset. */
+#define BIGINT_NUM_MODS     3    /**< The number of modulus constants used. */
+#else
+#define BIGINT_NUM_MODS     1    
+#endif
+
+/* Architecture specific functions for big ints */
+#ifdef WIN32
+#define COMP_RADIX          4294967296i64         
+#define COMP_MAX            0xFFFFFFFFFFFFFFFFui64
+#else
+#define COMP_RADIX          4294967296ULL         /**< Max component + 1 */
+#define COMP_MAX            0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */
+#endif
+#define COMP_BIT_SIZE       32  /**< Number of bits in a component. */
+#define COMP_BYTE_SIZE      4   /**< Number of bytes in a component. */
+#define COMP_NUM_NIBBLES    8   /**< Used For diagnostics only. */
+
+typedef uint32_t comp;	        /**< A single precision component. */
+typedef uint64_t long_comp;     /**< A double precision component. */
+typedef int64_t slong_comp;     /**< A signed double precision component. */
+
+/**
+ * @struct  _bigint
+ * @brief A big integer basic object
+ */
+struct _bigint
+{
+    struct _bigint* next;       /**< The next bigint in the cache. */
+    short size;                 /**< The number of components in this bigint. */
+    short max_comps;            /**< The heapsize allocated for this bigint */
+    int refs;                   /**< An internal reference count. */
+    comp* comps;                /**< A ptr to the actual component data */
+};
+
+typedef struct _bigint bigint;  /**< An alias for _bigint */
+
+/**
+ * Maintains the state of the cache, and a number of variables used in 
+ * reduction.
+ */
+typedef struct /**< A big integer "session" context. */
+{
+    bigint *active_list;                    /**< Bigints currently used. */
+    bigint *free_list;                      /**< Bigints not used. */
+    bigint *bi_radix;                       /**< The radix used. */
+    bigint *bi_mod[BIGINT_NUM_MODS];        /**< modulus */
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+    bigint *bi_RR_mod_m[BIGINT_NUM_MODS];   /**< R^2 mod m */
+    bigint *bi_R_mod_m[BIGINT_NUM_MODS];    /**< R mod m */
+    comp N0_dash[BIGINT_NUM_MODS];
+#elif defined(CONFIG_BIGINT_BARRETT)
+    bigint *bi_mu[BIGINT_NUM_MODS];         /**< Storage for mu */
+#endif
+    bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
+    bigint **g;                 /**< Used by sliding-window. */
+    int window;                 /**< The size of the sliding window */
+    int active_count;           /**< Number of active bigints. */
+    int free_count;             /**< Number of free bigints. */
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+    uint8_t use_classical;      /**< Use classical reduction. */
+#endif
+    uint8_t mod_offset;         /**< The mod offset we are using */
+} BI_CTX;
+
+#ifndef WIN32
+#define max(a,b) ((a)>(b)?(a):(b))  /**< Find the maximum of 2 numbers. */
+#define min(a,b) ((a)<(b)?(a):(b))  /**< Find the minimum of 2 numbers. */
+#endif
+
+#define PERMANENT           0x7FFF55AA  /**< A magic number for permanents. */
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/crypto.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file crypto.h
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "os_port.h"
+#include "bigint_impl.h"
+#include "bigint.h"
+
+/* enable features based on a 'super-set' capbaility. */
+#if defined(CONFIG_SSL_FULL_MODE) 
+#define CONFIG_SSL_ENABLE_CLIENT
+#define CONFIG_SSL_CERT_VERIFICATION
+#elif defined(CONFIG_SSL_ENABLE_CLIENT)
+#define CONFIG_SSL_CERT_VERIFICATION
+#endif
+
+/**************************************************************************
+ * AES declarations 
+ **************************************************************************/
+
+#define AES_MAXROUNDS			14
+#define AES_BLOCKSIZE           16
+#define AES_IV_SIZE             16
+
+typedef struct aes_key_st 
+{
+    uint16_t rounds;
+    uint16_t key_size;
+    uint32_t ks[(AES_MAXROUNDS+1)*8];
+    uint8_t iv[AES_IV_SIZE];
+} AES_CTX;
+
+typedef enum
+{
+    AES_MODE_128,
+    AES_MODE_256
+} AES_MODE;
+
+void AES_set_key(AES_CTX *ctx, const uint8_t *key, 
+        const uint8_t *iv, AES_MODE mode);
+void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, 
+        uint8_t *out, int length);
+void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
+void AES_convert_key(AES_CTX *ctx);
+
+/**************************************************************************
+ * RC4 declarations 
+ **************************************************************************/
+
+typedef struct 
+{
+    uint8_t x, y, m[256];
+} RC4_CTX;
+
+void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
+void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
+
+/**************************************************************************
+ * SHA1 declarations 
+ **************************************************************************/
+
+#define SHA1_SIZE   20
+
+/*
+ *  This structure will hold context information for the SHA-1
+ *  hashing operation
+ */
+typedef struct 
+{
+    uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */
+    uint32_t Length_Low;            /* Message length in bits */
+    uint32_t Length_High;           /* Message length in bits */
+    uint16_t Message_Block_Index;   /* Index into message block array   */
+    uint8_t Message_Block[64];      /* 512-bit message blocks */
+} SHA1_CTX;
+
+void SHA1_Init(SHA1_CTX *);
+void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len);
+void SHA1_Final(uint8_t *digest, SHA1_CTX *);
+
+/**************************************************************************
+ * MD2 declarations 
+ **************************************************************************/
+
+#define MD2_SIZE 16
+
+typedef struct
+{
+    unsigned char cksum[16];    /* checksum of the data block */
+    unsigned char state[48];    /* intermediate digest state */
+    unsigned char buffer[16];   /* data block being processed */
+    int left;                   /* amount of data in buffer */
+} MD2_CTX;
+
+EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx);
+EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen);
+EXP_FUNC void STDCALL MD2_Final(uint8_t *digest, MD2_CTX *ctx);
+
+/**************************************************************************
+ * MD5 declarations 
+ **************************************************************************/
+
+#define MD5_SIZE    16
+
+typedef struct 
+{
+  uint32_t state[4];        /* state (ABCD) */
+  uint32_t count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  uint8_t buffer[64];       /* input buffer */
+} MD5_CTX;
+
+EXP_FUNC void STDCALL MD5_Init(MD5_CTX *);
+EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len);
+EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *);
+
+/**************************************************************************
+ * HMAC declarations 
+ **************************************************************************/
+void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest);
+void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest);
+
+/**************************************************************************
+ * RSA declarations 
+ **************************************************************************/
+
+typedef struct 
+{
+    bigint *m;              /* modulus */
+    bigint *e;              /* public exponent */
+    bigint *d;              /* private exponent */
+#ifdef CONFIG_BIGINT_CRT
+    bigint *p;              /* p as in m = pq */
+    bigint *q;              /* q as in m = pq */
+    bigint *dP;             /* d mod (p-1) */
+    bigint *dQ;             /* d mod (q-1) */
+    bigint *qInv;           /* q^-1 mod p */
+#endif
+    int num_octets;
+    BI_CTX *bi_ctx;
+} RSA_CTX;
+
+void RSA_priv_key_new(RSA_CTX **rsa_ctx, 
+        const uint8_t *modulus, int mod_len,
+        const uint8_t *pub_exp, int pub_len,
+        const uint8_t *priv_exp, int priv_len
+#ifdef CONFIG_BIGINT_CRT
+      , const uint8_t *p, int p_len,
+        const uint8_t *q, int q_len,
+        const uint8_t *dP, int dP_len,
+        const uint8_t *dQ, int dQ_len,
+        const uint8_t *qInv, int qInv_len
+#endif
+        );
+void RSA_pub_key_new(RSA_CTX **rsa_ctx, 
+        const uint8_t *modulus, int mod_len,
+        const uint8_t *pub_exp, int pub_len);
+void RSA_free(RSA_CTX *ctx);
+int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
+        int is_decryption);
+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
+#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
+bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
+        bigint *modulus, bigint *pub_exp);
+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, 
+        uint8_t *out_data, int is_signing);
+void RSA_print(const RSA_CTX *ctx);
+#endif
+
+/**************************************************************************
+ * RNG declarations 
+ **************************************************************************/
+EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size);
+EXP_FUNC void STDCALL RNG_terminate(void);
+EXP_FUNC void STDCALL get_random(unsigned int num_rand_bytes, uint8_t *rand_data);
+void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/crypto_misc.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Some misc. routines to help things out
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "crypto_misc.h"
+#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
+#include "wincrypt.h"
+#endif
+
+#ifndef WIN32
+static int rng_fd = -1;
+#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
+static HCRYPTPROV gCryptProv;
+#endif
+
+#if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
+static uint64_t rng_num;
+#endif
+
+static int rng_ref_count;
+const char * const unsupported_str = "Error: Feature not supported\n";
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+/** 
+ * Retrieve a file and put it into memory
+ * @return The size of the file, or -1 on failure.
+ */
+int get_file(const char *filename, uint8_t **buf)
+{
+    int total_bytes = 0;
+    int bytes_read = 0; 
+    int filesize;
+    FILE *stream = fopen(filename, "rb");
+
+    if (stream == NULL)
+    {
+#ifdef CONFIG_SSL_FULL_MODE         
+        printf("file '%s' does not exist\n", filename); TTY_FLUSH();
+#endif
+        return -1;
+    }
+
+    /* Win CE doesn't support stat() */
+    fseek(stream, 0, SEEK_END);
+    filesize = ftell(stream);
+    *buf = (uint8_t *)malloc(filesize);
+    fseek(stream, 0, SEEK_SET);
+
+    do
+    {
+        bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream);
+        total_bytes += bytes_read;
+    } while (total_bytes < filesize && bytes_read > 0);
+    
+    fclose(stream);
+    return filesize;
+}
+#endif
+
+/**
+ * Initialise the Random Number Generator engine.
+ * - On Win32 use the platform SDK's crypto engine.
+ * - On Linux use /dev/urandom
+ * - If none of these work then use a custom RNG.
+ */
+EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size)
+{
+    if (rng_ref_count == 0)
+    {
+#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
+        rng_fd = ax_open("/dev/urandom", O_RDONLY);
+#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
+        if (!CryptAcquireContext(&gCryptProv, 
+                          NULL, NULL, PROV_RSA_FULL, 0))
+        {
+            if (GetLastError() == NTE_BAD_KEYSET &&
+                    !CryptAcquireContext(&gCryptProv, 
+                           NULL, 
+                           NULL, 
+                           PROV_RSA_FULL, 
+                           CRYPT_NEWKEYSET))
+            {
+                printf("CryptoLib: %x\n", unsupported_str, GetLastError());
+                exit(1);
+            }
+        }
+#else   
+        /* help seed with the user's private key - this is a number that 
+           should be hard to find, due to the fact that it relies on knowing 
+           the private key */
+        int i;  
+
+        for (i = 0; i < size/(int)sizeof(uint64_t); i++)
+            rng_num ^= *((uint64_t *)&seed_buf[i*sizeof(uint64_t)]);
+
+        srand((long)&seed_buf);  /* use the stack ptr as another rnd seed */
+#endif
+    }
+
+    rng_ref_count++;
+}
+
+/**
+ * Terminate the RNG engine.
+ */
+EXP_FUNC void STDCALL RNG_terminate(void)
+{
+    if (--rng_ref_count == 0)
+    {
+#ifndef WIN32
+        close(rng_fd);
+#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
+        CryptReleaseContext(gCryptProv, 0);
+#endif
+    }
+}
+
+/**
+ * Set a series of bytes with a random number. Individual bytes can be 0
+ */
+EXP_FUNC void STDCALL get_random(unsigned int num_rand_bytes, uint8_t *rand_data)
+{   
+#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
+    /* use the Linux default */
+    read(rng_fd, rand_data, num_rand_bytes);    /* read from /dev/urandom */
+#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
+    /* use Microsoft Crypto Libraries */
+    CryptGenRandom(gCryptProv, num_rand_bytes, rand_data);
+#else   /* nothing else to use, so use a custom RNG */
+    /* The method we use when we've got nothing better. Use RC4, time 
+       and a couple of random seeds to generate a random sequence */
+    RC4_CTX rng_ctx;
+    struct timeval tv;
+    uint64_t big_num1, big_num2;
+
+    gettimeofday(&tv, NULL);    /* yes I know we shouldn't do this */
+
+    /* all numbers by themselves are pretty simple, but combined should 
+     * be a challenge */
+    big_num1 = (uint64_t)tv.tv_sec*(tv.tv_usec+1); 
+    big_num2 = (uint64_t)rand()*big_num1;
+    big_num1 ^= rng_num;
+
+    memcpy(rand_data, &big_num1, sizeof(uint64_t));
+    if (num_rand_bytes > sizeof(uint64_t))
+        memcpy(&rand_data[8], &big_num2, sizeof(uint64_t));
+
+    if (num_rand_bytes > 16)
+    {
+        /* clear rest of data */
+        memset(&rand_data[16], 0, num_rand_bytes-16); 
+    }
+
+    RC4_setup(&rng_ctx, rand_data, 16); /* use as a key */
+    RC4_crypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
+    
+    /* use last 8 bytes for next time */
+    memcpy(&rng_num, &rand_data[num_rand_bytes-8], sizeof(uint64_t));    
+#endif
+}
+
+/**
+ * Set a series of bytes with a random number. Individual bytes are not zero.
+ */
+void get_random_NZ(int num_rand_bytes, uint8_t *rand_data)
+{
+    int i;
+    get_random(num_rand_bytes, rand_data);
+
+    for (i = 0; i < num_rand_bytes; i++)
+    {
+        while (rand_data[i] == 0)  /* can't be 0 */
+            rand_data[i] = (uint8_t)(rand());
+    }
+}
+
+/**
+ * Some useful diagnostic routines
+ */
+#if defined(CONFIG_SSL_FULL_MODE) || defined(CONFIG_DEBUG)
+int hex_finish;
+int hex_index;
+
+static void print_hex_init(int finish)
+{
+    hex_finish = finish;
+    hex_index = 0;
+}
+
+static void print_hex(uint8_t hex)
+{
+    static int column;
+
+    if (hex_index == 0)
+    {
+        column = 0;
+    }
+
+    printf("%02x ", hex);
+    if (++column == 8)
+    {
+        printf(": ");
+    }
+    else if (column >= 16)
+    {
+        printf("\n");
+        column = 0;
+    }
+
+    if (++hex_index >= hex_finish && column > 0)
+    {
+        printf("\n");
+    }
+}
+
+/**
+ * Spit out a blob of data for diagnostics. The data is is a nice column format
+ * for easy reading.
+ *
+ * @param format   [in]    The string (with possible embedded format characters)
+ * @param size     [in]    The number of numbers to print
+ * @param data     [in]    The start of data to use
+ * @param ...      [in]    Any additional arguments
+ */
+EXP_FUNC void STDCALL print_blob(const char *format, 
+        const uint8_t *data, int size, ...)
+{
+    int i;
+    char tmp[80];
+    va_list(ap);
+
+    va_start(ap, size);
+    sprintf(tmp, "%s\n", format);
+    vprintf(tmp, ap);
+    print_hex_init(size);
+    for (i = 0; i < size; i++)
+    {
+        print_hex(data[i]);
+    }
+
+    va_end(ap);
+    TTY_FLUSH();
+}
+#elif defined(WIN32)
+/* VC6.0 doesn't handle variadic macros */
+EXP_FUNC void STDCALL print_blob(const char *format, const unsigned char *data,
+        int size, ...) {}
+#endif
+
+#if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
+/* base64 to binary lookup table */
+static const uint8_t map[128] =
+{
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
+    52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
+    255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
+    7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
+    19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
+    255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+    49,  50,  51, 255, 255, 255, 255, 255
+};
+
+EXP_FUNC int STDCALL base64_decode(const char *in, int len,
+                    uint8_t *out, int *outlen)
+{
+    int g, t, x, y, z;
+    uint8_t c;
+    int ret = -1;
+
+    g = 3;
+    for (x = y = z = t = 0; x < len; x++)
+    {
+        if ((c = map[in[x]&0x7F]) == 0xff)
+            continue;
+
+        if (c == 254)   /* this is the end... */
+        {
+            c = 0;
+
+            if (--g < 0)
+                goto error;
+        }
+        else if (g != 3) /* only allow = at end */
+            goto error;
+
+        t = (t<<6) | c;
+
+        if (++y == 4)
+        {
+            out[z++] = (uint8_t)((t>>16)&255);
+
+            if (g > 1)
+                out[z++] = (uint8_t)((t>>8)&255);
+
+            if (g > 2)
+                out[z++] = (uint8_t)(t&255);
+
+            y = t = 0;
+        }
+    }
+
+    if (y != 0)
+        goto error;
+
+    if (outlen)
+        *outlen = z;
+    ret = 0;
+
+error:
+#ifdef CONFIG_SSL_FULL_MODE
+    if (ret < 0)
+        printf("Error: Invalid base64\n"); TTY_FLUSH();
+#endif
+    TTY_FLUSH();
+    return ret;
+
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/hmac.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * HMAC implementation - This code was originally taken from RFC2104
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/**
+ * Perform HMAC-MD5
+ */
+void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest)
+{
+    MD5_CTX context;
+    uint8_t k_ipad[64];
+    uint8_t k_opad[64];
+    int i;
+
+    memset(k_ipad, 0, sizeof k_ipad);
+    memset(k_opad, 0, sizeof k_opad);
+    memcpy(k_ipad, key, key_len);
+    memcpy(k_opad, key, key_len);
+
+    for (i = 0; i < 64; i++) 
+    {
+        k_ipad[i] ^= 0x36;
+        k_opad[i] ^= 0x5c;
+    }
+
+    MD5_Init(&context);
+    MD5_Update(&context, k_ipad, 64);
+    MD5_Update(&context, msg, length);
+    MD5_Final(digest, &context);
+    MD5_Init(&context);
+    MD5_Update(&context, k_opad, 64);
+    MD5_Update(&context, digest, MD5_SIZE);
+    MD5_Final(digest, &context);
+}
+
+/**
+ * Perform HMAC-SHA1
+ */
+void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest)
+{
+    SHA1_CTX context;
+    uint8_t k_ipad[64];
+    uint8_t k_opad[64];
+    int i;
+
+    memset(k_ipad, 0, sizeof k_ipad);
+    memset(k_opad, 0, sizeof k_opad);
+    memcpy(k_ipad, key, key_len);
+    memcpy(k_opad, key, key_len);
+
+    for (i = 0; i < 64; i++) 
+    {
+        k_ipad[i] ^= 0x36;
+        k_opad[i] ^= 0x5c;
+    }
+
+    SHA1_Init(&context);
+    SHA1_Update(&context, k_ipad, 64);
+    SHA1_Update(&context, msg, length);
+    SHA1_Final(digest, &context);
+    SHA1_Init(&context);
+    SHA1_Update(&context, k_opad, 64);
+    SHA1_Update(&context, digest, SHA1_SIZE);
+    SHA1_Final(digest, &context);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/md2.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  RFC 1115/1319 compliant MD2 implementation
+ *  The MD2 algorithm was designed by Ron Rivest in 1989.
+ *
+ *  http://www.ietf.org/rfc/rfc1115.txt
+ *  http://www.ietf.org/rfc/rfc1319.txt
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "crypto.h"
+
+/**
+ * This code is only here to enable the verification of Verisign root
+ * certificates. So only enable it for verification mode.
+ */
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+
+static const uint8_t PI_SUBST[256] =
+{
+    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
+    0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
+    0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
+    0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+    0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
+    0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
+    0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
+    0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
+    0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
+    0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
+    0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+    0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
+    0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
+    0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
+    0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
+    0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
+    0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
+    0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+    0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
+    0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
+    0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
+    0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
+    0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+/*
+ * MD2 context setup
+ */
+EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx)
+{
+    memset(ctx, 0, sizeof *ctx);
+}
+
+static void md2_process(MD2_CTX *ctx)
+{
+    int i, j;
+    uint8_t t = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        ctx->state[i + 16] = ctx->buffer[i];
+        ctx->state[i + 32] = ctx->buffer[i] ^ ctx->state[i];
+    }
+
+    for (i = 0; i < 18; i++)
+    {
+        for (j = 0; j < 48; j++)
+            t = (ctx->state[j] ^= PI_SUBST[t]);
+
+        t = (t + i) & 0xFF;
+    }
+
+    t = ctx->cksum[15];
+
+    for (i = 0; i < 16; i++)
+        t = (ctx->cksum[i] ^= PI_SUBST[ctx->buffer[i] ^ t]);
+}
+
+/*
+ * MD2 process buffer
+ */
+EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen)
+{
+    int fill;
+
+    while (ilen > 0)
+    {
+        if (ctx->left + ilen > 16)
+            fill = 16 - ctx->left;
+        else
+            fill = ilen;
+
+        memcpy(ctx->buffer + ctx->left, input, fill);
+
+        ctx->left += fill;
+        input += fill;
+        ilen  -= fill;
+
+        if (ctx->left == 16)
+        {
+            ctx->left = 0;
+            md2_process(ctx);
+        }
+    }
+}
+
+/*
+ * MD2 final digest
+ */
+EXP_FUNC void STDCALL MD2_Final(uint8_t *output, MD2_CTX *ctx)
+{
+    int i;
+    uint8_t x;
+
+    x = (uint8_t)(16 - ctx->left);
+
+    for (i = ctx->left; i < 16; i++)
+        ctx->buffer[i] = x;
+
+    md2_process(ctx);
+
+    memcpy(ctx->buffer, ctx->cksum, 16);
+    md2_process(ctx);
+
+    memcpy(output, ctx->state, 16);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/md5.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This file implements the MD5 algorithm as defined in RFC1321
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+/* ----- static functions ----- */
+static void MD5Transform(uint32_t state[4], const uint8_t block[64]);
+static void Encode(uint8_t *output, uint32_t *input, uint32_t len);
+static void Decode(uint32_t *output, const uint8_t *input, uint32_t len);
+
+static const uint8_t PADDING[64] = 
+{
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.  */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+   Rotation is separate from addition to prevent recomputation.  */
+#define FF(a, b, c, d, x, s, ac) { \
+    (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+    (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+    (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+    (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+
+/**
+ * MD5 initialization - begins an MD5 operation, writing a new ctx.
+ */
+EXP_FUNC void STDCALL MD5_Init(MD5_CTX *ctx)
+{
+    ctx->count[0] = ctx->count[1] = 0;
+
+    /* Load magic initialization constants.
+     */
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xefcdab89;
+    ctx->state[2] = 0x98badcfe;
+    ctx->state[3] = 0x10325476;
+}
+
+/**
+ * Accepts an array of octets as the next portion of the message.
+ */
+EXP_FUNC void STDCALL MD5_Update(MD5_CTX *ctx, const uint8_t * msg, int len)
+{
+    uint32_t x;
+    int i, partLen;
+
+    /* Compute number of bytes mod 64 */
+    x = (uint32_t)((ctx->count[0] >> 3) & 0x3F);
+
+    /* Update number of bits */
+    if ((ctx->count[0] += ((uint32_t)len << 3)) < ((uint32_t)len << 3))
+        ctx->count[1]++;
+    ctx->count[1] += ((uint32_t)len >> 29);
+
+    partLen = 64 - x;
+
+    /* Transform as many times as possible.  */
+    if (len >= partLen) 
+    {
+        memcpy(&ctx->buffer[x], msg, partLen);
+        MD5Transform(ctx->state, ctx->buffer);
+
+        for (i = partLen; i + 63 < len; i += 64)
+            MD5Transform(ctx->state, &msg[i]);
+
+        x = 0;
+    }
+    else
+        i = 0;
+
+    /* Buffer remaining input */
+    memcpy(&ctx->buffer[x], &msg[i], len-i);
+}
+
+/**
+ * Return the 128-bit message digest into the user's array
+ */
+EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *ctx)
+{
+    uint8_t bits[8];
+    uint32_t x, padLen;
+
+    /* Save number of bits */
+    Encode(bits, ctx->count, 8);
+
+    /* Pad out to 56 mod 64.
+     */
+    x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
+    padLen = (x < 56) ? (56 - x) : (120 - x);
+    MD5_Update(ctx, PADDING, padLen);
+
+    /* Append length (before padding) */
+    MD5_Update(ctx, bits, 8);
+
+    /* Store state in digest */
+    Encode(digest, ctx->state, MD5_SIZE);
+}
+
+/**
+ * MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform(uint32_t state[4], const uint8_t block[64])
+{
+    uint32_t a = state[0], b = state[1], c = state[2], 
+             d = state[3], x[MD5_SIZE];
+
+    Decode(x, block, 64);
+
+    /* Round 1 */
+    FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+    FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+    FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+    FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+    FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+    FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+    FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+    FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+    FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+    FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+    FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+    FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+    FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+    FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+    FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+    FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+    /* Round 2 */
+    GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+    GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+    GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+    GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+    GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+    GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+    GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+    GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+    GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+    GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+    GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+    GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+    GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+    GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+    GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+    GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+    /* Round 3 */
+    HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+    HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+    HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+    HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+    HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+    HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+    HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+    HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+    HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+    HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+    HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+    HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+    HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+    HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+    HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+    HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+    /* Round 4 */
+    II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+    II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+    II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+    II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+    II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+    II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+    II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+    II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+    II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+    II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+    II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+    II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+    II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+    II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+    II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+    II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+}
+
+/**
+ * Encodes input (uint32_t) into output (uint8_t). Assumes len is
+ *   a multiple of 4.
+ */
+static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
+{
+    uint32_t i, j;
+
+    for (i = 0, j = 0; j < len; i++, j += 4) 
+    {
+        output[j] = (uint8_t)(input[i] & 0xff);
+        output[j+1] = (uint8_t)((input[i] >> 8) & 0xff);
+        output[j+2] = (uint8_t)((input[i] >> 16) & 0xff);
+        output[j+3] = (uint8_t)((input[i] >> 24) & 0xff);
+    }
+}
+
+/**
+ *  Decodes input (uint8_t) into output (uint32_t). Assumes len is
+ *   a multiple of 4.
+ */
+static void Decode(uint32_t *output, const uint8_t *input, uint32_t len)
+{
+    uint32_t i, j;
+
+    for (i = 0, j = 0; j < len; i++, j += 4)
+        output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
+            (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/rc4.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * An implementation of the RC4/ARC4 algorithm.
+ * Originally written by Christophe Devine.
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/**
+ * Get ready for an encrypt/decrypt operation
+ */
+void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length)
+{
+    int i, j = 0, k = 0, a;
+    uint8_t *m;
+
+    ctx->x = 0;
+    ctx->y = 0;
+    m = ctx->m;
+
+    for (i = 0; i < 256; i++)
+        m[i] = i;
+
+    for (i = 0; i < 256; i++)
+    {
+        a = m[i];
+        j = (uint8_t)(j + a + key[k]);
+        m[i] = m[j]; 
+        m[j] = a;
+
+        if (++k >= length) 
+            k = 0;
+    }
+}
+
+/**
+ * Perform the encrypt/decrypt operation (can use it for either since
+ * this is a stream cipher).
+ */
+void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
+{ 
+    int i;
+    uint8_t *m, x, y, a, b;
+    out = (uint8_t *)msg; 
+
+    x = ctx->x;
+    y = ctx->y;
+    m = ctx->m;
+
+    for (i = 0; i < length; i++)
+    {
+        a = m[++x];
+        y += a;
+        m[x] = b = m[y];
+        m[y] = a;
+        out[i] ^= m[(uint8_t)(a + b)];
+    }
+
+    ctx->x = x;
+    ctx->y = y;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/rsa.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Implements the RSA public encryption algorithm. Uses the bigint library to
+ * perform its calculations.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include "crypto.h"
+
+void RSA_priv_key_new(RSA_CTX **ctx, 
+        const uint8_t *modulus, int mod_len,
+        const uint8_t *pub_exp, int pub_len,
+        const uint8_t *priv_exp, int priv_len
+#if CONFIG_BIGINT_CRT
+      , const uint8_t *p, int p_len,
+        const uint8_t *q, int q_len,
+        const uint8_t *dP, int dP_len,
+        const uint8_t *dQ, int dQ_len,
+        const uint8_t *qInv, int qInv_len
+#endif
+    )
+{
+    RSA_CTX *rsa_ctx;
+    BI_CTX *bi_ctx;
+    RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);
+    rsa_ctx = *ctx;
+    bi_ctx = rsa_ctx->bi_ctx;
+    rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);
+    bi_permanent(rsa_ctx->d);
+
+#ifdef CONFIG_BIGINT_CRT
+    rsa_ctx->p = bi_import(bi_ctx, p, p_len);
+    rsa_ctx->q = bi_import(bi_ctx, q, q_len);
+    rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);
+    rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);
+    rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);
+    bi_permanent(rsa_ctx->dP);
+    bi_permanent(rsa_ctx->dQ);
+    bi_permanent(rsa_ctx->qInv);
+    bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);
+    bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);
+#endif
+}
+
+void RSA_pub_key_new(RSA_CTX **ctx, 
+        const uint8_t *modulus, int mod_len,
+        const uint8_t *pub_exp, int pub_len)
+{
+    RSA_CTX *rsa_ctx;
+    BI_CTX *bi_ctx;
+
+    if (*ctx)   /* if we load multiple certs, dump the old one */
+        RSA_free(*ctx);
+
+    bi_ctx = bi_initialize();
+    *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX));
+    rsa_ctx = *ctx;
+    rsa_ctx->bi_ctx = bi_ctx;
+    rsa_ctx->num_octets = (mod_len & 0xFFF0);
+    rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len);
+    bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET);
+    rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len);
+    bi_permanent(rsa_ctx->e);
+}
+
+/**
+ * Free up any RSA context resources.
+ */
+void RSA_free(RSA_CTX *rsa_ctx)
+{
+    BI_CTX *bi_ctx;
+    if (rsa_ctx == NULL)                /* deal with ptrs that are null */
+        return;
+
+    bi_ctx = rsa_ctx->bi_ctx;
+
+    bi_depermanent(rsa_ctx->e);
+    bi_free(bi_ctx, rsa_ctx->e);
+    bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET);
+
+    if (rsa_ctx->d)
+    {
+        bi_depermanent(rsa_ctx->d);
+        bi_free(bi_ctx, rsa_ctx->d);
+#ifdef CONFIG_BIGINT_CRT
+        bi_depermanent(rsa_ctx->dP);
+        bi_depermanent(rsa_ctx->dQ);
+        bi_depermanent(rsa_ctx->qInv);
+        bi_free(bi_ctx, rsa_ctx->dP);
+        bi_free(bi_ctx, rsa_ctx->dQ);
+        bi_free(bi_ctx, rsa_ctx->qInv);
+        bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET);
+        bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET);
+#endif
+    }
+
+    bi_terminate(bi_ctx);
+    free(rsa_ctx);
+}
+
+/**
+ * @brief Use PKCS1.5 for decryption/verification.
+ * @param ctx [in] The context
+ * @param in_data [in] The data to encrypt (must be < modulus size-11)
+ * @param out_data [out] The encrypted data.
+ * @param is_decryption [in] Decryption or verify operation.
+ * @return  The number of bytes that were originally encrypted. -1 on error.
+ * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
+ */
+int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, 
+                            uint8_t *out_data, int is_decryption)
+{
+    const int byte_size = ctx->num_octets;
+    int i, size;
+    bigint *decrypted_bi, *dat_bi;
+    uint8_t *block = (uint8_t *)alloca(byte_size);
+
+    memset(out_data, 0, byte_size); /* initialise */
+
+    /* decrypt */
+    dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    decrypted_bi = is_decryption ?  /* decrypt or verify? */
+            RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);
+#else   /* always a decryption */
+    decrypted_bi = RSA_private(ctx, dat_bi);
+#endif
+
+    /* convert to a normal block */
+    bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size);
+
+    i = 10; /* start at the first possible non-padded byte */
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
+    {
+        while (block[i++] == 0xff && i < byte_size);
+
+        if (block[i-2] != 0xff)
+            i = byte_size;     /*ensure size is 0 */   
+    }
+    else                    /* PKCS1.5 encryption padding is random */
+#endif
+    {
+        while (block[i++] && i < byte_size);
+    }
+    size = byte_size - i;
+
+    /* get only the bit we want */
+    if (size > 0)
+        memcpy(out_data, &block[i], size);
+    
+    return size ? size : -1;
+}
+
+/**
+ * Performs m = c^d mod n
+ */
+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
+{
+#ifdef CONFIG_BIGINT_CRT
+    return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv);
+#else
+    BI_CTX *ctx = c->bi_ctx;
+    ctx->mod_offset = BIGINT_M_OFFSET;
+    return bi_mod_power(ctx, bi_msg, c->d);
+#endif
+}
+
+#ifdef CONFIG_SSL_FULL_MODE
+/**
+ * Used for diagnostics.
+ */
+void RSA_print(const RSA_CTX *rsa_ctx) 
+{
+    if (rsa_ctx == NULL)
+        return;
+
+    printf("-----------------   RSA DEBUG   ----------------\n");
+    printf("Size:\t%d\n", rsa_ctx->num_octets);
+    bi_print("Modulus", rsa_ctx->m);
+    bi_print("Public Key", rsa_ctx->e);
+    bi_print("Private Key", rsa_ctx->d);
+}
+#endif
+
+#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
+/**
+ * Performs c = m^e mod n
+ */
+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)
+{
+    c->bi_ctx->mod_offset = BIGINT_M_OFFSET;
+    return bi_mod_power(c->bi_ctx, bi_msg, c->e);
+}
+
+/**
+ * Use PKCS1.5 for encryption/signing.
+ * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
+ */
+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, 
+        uint8_t *out_data, int is_signing)
+{
+    int byte_size = ctx->num_octets;
+    int num_pads_needed = byte_size-in_len-3;
+    bigint *dat_bi, *encrypt_bi;
+
+    /* note: in_len+11 must be > byte_size */
+    out_data[0] = 0;     /* ensure encryption block is < modulus */
+
+    if (is_signing)
+    {
+        out_data[1] = 1;        /* PKCS1.5 signing pads with "0xff"'s */
+        memset(&out_data[2], 0xff, num_pads_needed);
+    }
+    else /* randomize the encryption padding with non-zero bytes */   
+    {
+        out_data[1] = 2;
+        get_random_NZ(num_pads_needed, &out_data[2]);
+    }
+
+    out_data[2+num_pads_needed] = 0;
+    memcpy(&out_data[3+num_pads_needed], in_data, in_len);
+
+    /* now encrypt it */
+    dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size);
+    encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) : 
+                              RSA_public(ctx, dat_bi);
+    bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size);
+
+    /* save a few bytes of memory */
+    bi_clear_cache(ctx->bi_ctx);
+    return byte_size;
+}
+
+#endif  /* CONFIG_SSL_CERT_VERIFICATION */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/crypto/sha1.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
+ * This code was originally taken from RFC3174
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/*
+ *  Define the SHA1 circular left shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+                (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/* ----- static functions ----- */
+static void SHA1PadMessage(SHA1_CTX *ctx);
+static void SHA1ProcessMessageBlock(SHA1_CTX *ctx);
+
+/**
+ * Initialize the SHA1 context 
+ */
+void SHA1_Init(SHA1_CTX *ctx)
+{
+    ctx->Length_Low             = 0;
+    ctx->Length_High            = 0;
+    ctx->Message_Block_Index    = 0;
+    ctx->Intermediate_Hash[0]   = 0x67452301;
+    ctx->Intermediate_Hash[1]   = 0xEFCDAB89;
+    ctx->Intermediate_Hash[2]   = 0x98BADCFE;
+    ctx->Intermediate_Hash[3]   = 0x10325476;
+    ctx->Intermediate_Hash[4]   = 0xC3D2E1F0;
+}
+
+/**
+ * Accepts an array of octets as the next portion of the message.
+ */
+void SHA1_Update(SHA1_CTX *ctx, const uint8_t *msg, int len)
+{
+    while (len--)
+    {
+        ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF);
+        ctx->Length_Low += 8;
+
+        if (ctx->Length_Low == 0)
+            ctx->Length_High++;
+
+        if (ctx->Message_Block_Index == 64)
+            SHA1ProcessMessageBlock(ctx);
+
+        msg++;
+    }
+}
+
+/**
+ * Return the 160-bit message digest into the user's array
+ */
+void SHA1_Final(uint8_t *digest, SHA1_CTX *ctx)
+{
+    int i;
+
+    SHA1PadMessage(ctx);
+    memset(ctx->Message_Block, 0, 64);
+    ctx->Length_Low = 0;    /* and clear length */
+    ctx->Length_High = 0;
+
+    for  (i = 0; i < SHA1_SIZE; i++)
+    {
+        digest[i] = ctx->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) );
+    }
+}
+
+/**
+ * Process the next 512 bits of the message stored in the array.
+ */
+static void SHA1ProcessMessageBlock(SHA1_CTX *ctx)
+{
+    const uint32_t K[] =    {       /* Constants defined in SHA-1   */
+                            0x5A827999,
+                            0x6ED9EBA1,
+                            0x8F1BBCDC,
+                            0xCA62C1D6
+                            };
+    int        t;                 /* Loop counter                */
+    uint32_t      temp;              /* Temporary word value        */
+    uint32_t      W[80];             /* Word sequence               */
+    uint32_t      A, B, C, D, E;     /* Word buffers                */
+
+    /*
+     *  Initialize the first 16 words in the array W
+     */
+    for  (t = 0; t < 16; t++)
+    {
+        W[t] = ctx->Message_Block[t * 4] << 24;
+        W[t] |= ctx->Message_Block[t * 4 + 1] << 16;
+        W[t] |= ctx->Message_Block[t * 4 + 2] << 8;
+        W[t] |= ctx->Message_Block[t * 4 + 3];
+    }
+
+    for (t = 16; t < 80; t++)
+    {
+       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = ctx->Intermediate_Hash[0];
+    B = ctx->Intermediate_Hash[1];
+    C = ctx->Intermediate_Hash[2];
+    D = ctx->Intermediate_Hash[3];
+    E = ctx->Intermediate_Hash[4];
+
+    for (t = 0; t < 20; t++)
+    {
+        temp =  SHA1CircularShift(5,A) +
+                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+
+        B = A;
+        A = temp;
+    }
+
+    for (t = 20; t < 40; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for (t = 40; t < 60; t++)
+    {
+        temp = SHA1CircularShift(5,A) +
+               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for (t = 60; t < 80; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    ctx->Intermediate_Hash[0] += A;
+    ctx->Intermediate_Hash[1] += B;
+    ctx->Intermediate_Hash[2] += C;
+    ctx->Intermediate_Hash[3] += D;
+    ctx->Intermediate_Hash[4] += E;
+    ctx->Message_Block_Index = 0;
+}
+
+/*
+ * According to the standard, the message must be padded to an even
+ * 512 bits.  The first padding bit must be a '1'.  The last 64
+ * bits represent the length of the original message.  All bits in
+ * between should be 0.  This function will pad the message
+ * according to those rules by filling the Message_Block array
+ * accordingly.  It will also call the ProcessMessageBlock function
+ * provided appropriately.  When it returns, it can be assumed that
+ * the message digest has been computed.
+ *
+ * @param ctx [in, out] The SHA1 context
+ */
+static void SHA1PadMessage(SHA1_CTX *ctx)
+{
+    /*
+     *  Check to see if the current message block is too small to hold
+     *  the initial padding bits and length.  If so, we will pad the
+     *  block, process it, and then continue padding into a second
+     *  block.
+     */
+    if (ctx->Message_Block_Index > 55)
+    {
+        ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
+        while(ctx->Message_Block_Index < 64)
+        {
+            ctx->Message_Block[ctx->Message_Block_Index++] = 0;
+        }
+
+        SHA1ProcessMessageBlock(ctx);
+
+        while (ctx->Message_Block_Index < 56)
+        {
+            ctx->Message_Block[ctx->Message_Block_Index++] = 0;
+        }
+    }
+    else
+    {
+        ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
+        while(ctx->Message_Block_Index < 56)
+        {
+
+            ctx->Message_Block[ctx->Message_Block_Index++] = 0;
+        }
+    }
+
+    /*
+     *  Store the message length as the last 8 octets
+     */
+    ctx->Message_Block[56] = ctx->Length_High >> 24;
+    ctx->Message_Block[57] = ctx->Length_High >> 16;
+    ctx->Message_Block[58] = ctx->Length_High >> 8;
+    ctx->Message_Block[59] = ctx->Length_High;
+    ctx->Message_Block[60] = ctx->Length_Low >> 24;
+    ctx->Message_Block[61] = ctx->Length_Low >> 16;
+    ctx->Message_Block[62] = ctx->Length_Low >> 8;
+    ctx->Message_Block[63] = ctx->Length_Low;
+    SHA1ProcessMessageBlock(ctx);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/asn1.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Some primitive asn methods for extraction ASN.1 data.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "os_port.h"
+#include "crypto.h"
+#include "crypto_misc.h"
+
+#define SIG_OID_PREFIX_SIZE 8
+#define SIG_IIS6_OID_SIZE   5
+
+/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
+static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] = 
+{
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
+};
+
+static const uint8_t sig_iis6_oid[SIG_IIS6_OID_SIZE] =
+{
+    0x2b, 0x0e, 0x03, 0x02, 0x1d
+};
+
+/* CN, O, OU */
+static const uint8_t g_dn_types[] = { 3, 10, 11 };
+
+int get_asn1_length(const uint8_t *buf, int *offset)
+{
+    int len, i;
+
+    if (!(buf[*offset] & 0x80)) /* short form */
+    {
+        len = buf[(*offset)++];
+    }
+    else  /* long form */
+    {
+        int length_bytes = buf[(*offset)++]&0x7f;
+        len = 0;
+        for (i = 0; i < length_bytes; i++)
+        {
+            len <<= 8;
+            len += buf[(*offset)++];
+        }
+    }
+
+    return len;
+}
+
+/**
+ * Skip the ASN1.1 object type and its length. Get ready to read the object's
+ * data.
+ */
+int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
+{
+    if (buf[*offset] != obj_type)
+        return X509_NOT_OK;
+    (*offset)++;
+    return get_asn1_length(buf, offset);
+}
+
+/**
+ * Skip over an ASN.1 object type completely. Get ready to read the next
+ * object.
+ */
+int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
+{
+    int len;
+
+    if (buf[*offset] != obj_type)
+        return X509_NOT_OK;
+    (*offset)++;
+    len = get_asn1_length(buf, offset);
+    *offset += len;
+    return 0;
+}
+
+/**
+ * Read an integer value for ASN.1 data
+ * Note: This function allocates memory which must be freed by the user.
+ */
+int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
+{
+    int len;
+
+    if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
+        goto end_int_array;
+
+    if (len > 1 && buf[*offset] == 0x00)    /* ignore the negative byte */
+    {
+        len--;
+        (*offset)++;
+    }
+
+    *object = (uint8_t *)malloc(len);
+    memcpy(*object, &buf[*offset], len);
+    *offset += len;
+
+end_int_array:
+    return len;
+}
+
+/**
+ * Get all the RSA private key specifics from an ASN.1 encoded file 
+ */
+int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
+{
+    int offset = 7;
+    uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL;
+    int mod_len, priv_len, pub_len;
+#ifdef CONFIG_BIGINT_CRT
+    uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL;
+    int p_len, q_len, dP_len, dQ_len, qInv_len;
+#endif
+
+    /* not in der format */
+    if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: This is not a valid ASN.1 file\n");
+#endif
+        return X509_INVALID_PRIV_KEY;
+    }
+
+    /* initialise the RNG */
+    RNG_initialize(buf, len);
+
+    mod_len = asn1_get_int(buf, &offset, &modulus);
+    pub_len = asn1_get_int(buf, &offset, &pub_exp);
+    priv_len = asn1_get_int(buf, &offset, &priv_exp);
+
+    if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
+        return X509_INVALID_PRIV_KEY;
+
+#ifdef CONFIG_BIGINT_CRT
+    p_len = asn1_get_int(buf, &offset, &p);
+    q_len = asn1_get_int(buf, &offset, &q);
+    dP_len = asn1_get_int(buf, &offset, &dP);
+    dQ_len = asn1_get_int(buf, &offset, &dQ);
+    qInv_len = asn1_get_int(buf, &offset, &qInv);
+
+    if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
+        return X509_INVALID_PRIV_KEY;
+
+    RSA_priv_key_new(rsa_ctx, 
+            modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
+            p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
+
+    free(p);
+    free(q);
+    free(dP);
+    free(dQ);
+    free(qInv);
+#else
+    RSA_priv_key_new(rsa_ctx, 
+            modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
+#endif
+
+    free(modulus);
+    free(priv_exp);
+    free(pub_exp);
+    return X509_OK;
+}
+
+/**
+ * Get the time of a certificate. Ignore hours/minutes/seconds.
+ */
+static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
+{
+    int ret = X509_NOT_OK, len, t_offset;
+    struct tm tm;
+
+    if (buf[(*offset)++] != ASN1_UTC_TIME)
+        goto end_utc_time;
+    len = get_asn1_length(buf, offset);
+    t_offset = *offset;
+
+    memset(&tm, 0, sizeof(struct tm));
+    tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
+
+    if (tm.tm_year <= 50)    /* 1951-2050 thing */
+    {
+        tm.tm_year += 100;
+    }
+
+    tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
+    tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
+    *t = mktime(&tm);
+    *offset += len;
+    ret = X509_OK;
+
+end_utc_time:
+    return ret;
+}
+
+/**
+ * Get the version type of a certificate (which we don't actually care about)
+ */
+int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
+{
+    int ret = X509_NOT_OK;
+
+    (*offset) += 2;        /* get past explicit tag */
+    if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
+        goto end_version;
+
+    ret = X509_OK;
+end_version:
+    return ret;
+}
+
+/**
+ * Retrieve the notbefore and notafter certificate times.
+ */
+int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
+{
+    return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
+              asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
+              asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
+}
+
+/**
+ * Get the components of a distinguished name 
+ */
+static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
+{
+    int dn_type = 0;
+    int len;
+
+    if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
+        goto end_oid;
+
+    /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
+       components we are interested in. */
+    if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
+        dn_type = buf[(*offset)++];
+    else
+    {
+        *offset += len;     /* skip over it */
+    }
+
+end_oid:
+    return dn_type;
+}
+
+/**
+ * Obtain an ASN.1 printable string type.
+ */
+static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
+{
+    int len = X509_NOT_OK;
+
+    /* some certs have this awful crud in them for some reason */
+    if (buf[*offset] != ASN1_PRINTABLE_STR &&  
+            buf[*offset] != ASN1_TELETEX_STR &&  
+            buf[*offset] != ASN1_IA5_STR &&  
+            buf[*offset] != ASN1_UNICODE_STR)
+        goto end_pnt_str;
+
+        (*offset)++;
+        len = get_asn1_length(buf, offset);
+
+        if (buf[*offset - 1] == ASN1_UNICODE_STR)
+        {
+            int i;
+            *str = (char *)malloc(len/2+1);     /* allow for null */
+
+            for (i = 0; i < len; i += 2)
+                (*str)[i/2] = buf[*offset + i + 1];
+
+            (*str)[len/2] = 0;                  /* null terminate */
+        }
+        else
+        {
+            *str = (char *)malloc(len+1);       /* allow for null */
+            memcpy(*str, &buf[*offset], len);
+            (*str)[len] = 0;                    /* null terminate */
+        }
+
+        *offset += len;
+
+end_pnt_str:
+    return len;
+}
+
+/**
+ * Get the subject name (or the issuer) of a certificate.
+ */
+int asn1_name(const uint8_t *cert, int *offset, char *dn[])
+{
+    int ret = X509_NOT_OK;
+    int dn_type;
+    char *tmp = NULL;
+
+    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
+        goto end_name;
+
+    while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
+    {
+        int i, found = 0;
+
+        if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
+               (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
+            goto end_name;
+
+        if (asn1_get_printable_str(cert, offset, &tmp) < 0)
+        {
+            free(tmp);
+            goto end_name;
+        }
+
+        /* find the distinguished named type */
+        for (i = 0; i < X509_NUM_DN_TYPES; i++)
+        {
+            if (dn_type == g_dn_types[i])
+            {
+                if (dn[i] == NULL)
+                {
+                    dn[i] = tmp;
+                    found = 1;
+                    break;
+                }
+            }
+        }
+
+        if (found == 0) /* not found so get rid of it */
+        {
+            free(tmp);
+        }
+    }
+
+    ret = X509_OK;
+end_name:
+    return ret;
+}
+
+/**
+ * Read the modulus and public exponent of a certificate.
+ */
+int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
+{
+    int ret = X509_NOT_OK, mod_len, pub_len;
+    uint8_t *modulus = NULL, *pub_exp = NULL;
+
+    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
+            asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
+            asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
+        goto end_pub_key;
+
+    (*offset)++;        /* ignore the padding bit field */
+
+    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
+        goto end_pub_key;
+
+    mod_len = asn1_get_int(cert, offset, &modulus);
+    pub_len = asn1_get_int(cert, offset, &pub_exp);
+
+    RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
+
+    free(modulus);
+    free(pub_exp);
+    ret = X509_OK;
+
+end_pub_key:
+    return ret;
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * Read the signature of the certificate.
+ */
+int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
+{
+    int ret = X509_NOT_OK;
+
+    if (cert[(*offset)++] != ASN1_BIT_STRING)
+        goto end_sig;
+
+    x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
+    (*offset)++;            /* ignore bit string padding bits */
+    x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
+    memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
+    *offset += x509_ctx->sig_len;
+    ret = X509_OK;
+
+end_sig:
+    return ret;
+}
+
+/*
+ * Compare 2 distinguished name components for equality 
+ * @return 0 if a match
+ */
+static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
+{
+    int ret = 1;
+
+    if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
+
+    ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
+
+err_no_match:
+    return ret;
+}
+
+/**
+ * Clean up all of the CA certificates.
+ */
+void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
+{
+    int i = 0;
+
+    if (ca_cert_ctx == NULL)
+        return;
+
+    while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
+    {
+        x509_free(ca_cert_ctx->cert[i]);
+        ca_cert_ctx->cert[i++] = NULL;
+    }
+
+    free(ca_cert_ctx);
+}
+
+/*
+ * Compare 2 distinguished names for equality 
+ * @return 0 if a match
+ */
+int asn1_compare_dn(char * const dn1[], char * const dn2[])
+{
+    int i;
+
+    for (i = 0; i < X509_NUM_DN_TYPES; i++)
+    {
+        if (asn1_compare_dn_comp(dn1[i], dn2[i]))
+            return 1;
+    }
+
+    return 0;       /* all good */
+}
+
+#endif
+
+/**
+ * Read the signature type of the certificate. We only support RSA-MD5 and
+ * RSA-SHA1 signature types.
+ */
+int asn1_signature_type(const uint8_t *cert, 
+                                int *offset, X509_CTX *x509_ctx)
+{
+    int ret = X509_NOT_OK, len;
+
+    if (cert[(*offset)++] != ASN1_OID)
+        goto end_check_sig;
+
+    len = get_asn1_length(cert, offset);
+
+    if (len == 5 && memcmp(sig_iis6_oid, &cert[*offset], 
+                                    SIG_IIS6_OID_SIZE) == 0)
+    {
+        x509_ctx->sig_type = SIG_TYPE_SHA1;
+    }
+    else
+    {
+        if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
+            goto end_check_sig;     /* unrecognised cert type */
+
+        x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
+    }
+
+    *offset += len;
+    asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
+    ret = X509_OK;
+
+end_check_sig:
+    return ret;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/cert.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,43 @@
+unsigned char default_certificate[] = {
+  0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xf1,
+  0xc3, 0x87, 0xc0, 0xd4, 0xf4, 0x57, 0xc3, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34,
+  0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x29, 0x61,
+  0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+  0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
+  0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
+  0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36,
+  0x30, 0x37, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x33,
+  0x33, 0x31, 0x30, 0x32, 0x33, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a,
+  0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+  0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65,
+  0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+  0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81,
+  0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+  0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+  0x81, 0x81, 0x00, 0xd8, 0xe0, 0xbf, 0x15, 0xde, 0xea, 0xaf, 0xe8, 0xd5,
+  0xfd, 0x0b, 0xa8, 0xa8, 0xb3, 0xd7, 0x46, 0x5d, 0xa7, 0x26, 0x6c, 0x0c,
+  0xb5, 0xd9, 0xbc, 0xc6, 0xf8, 0xc0, 0x78, 0xd0, 0xf6, 0x56, 0x65, 0xf8,
+  0x29, 0x48, 0x0e, 0x7b, 0x0b, 0xa6, 0x25, 0x7e, 0xe8, 0x7b, 0x79, 0x6f,
+  0x38, 0xe5, 0xb5, 0xb7, 0xf4, 0xe0, 0x9c, 0x91, 0x60, 0xf4, 0x06, 0xf3,
+  0x40, 0x1e, 0xf9, 0x91, 0x19, 0xa9, 0x2f, 0x47, 0x43, 0xb5, 0x9b, 0x1e,
+  0xdc, 0xf6, 0xaa, 0x1c, 0x49, 0x79, 0x21, 0x28, 0xcb, 0xaa, 0x49, 0x73,
+  0xd9, 0x09, 0x05, 0x4c, 0x02, 0xf2, 0x4c, 0x4d, 0x6c, 0x1c, 0x80, 0xa7,
+  0x14, 0x91, 0x44, 0xfc, 0x12, 0xb3, 0xe1, 0xe7, 0xe3, 0x4f, 0x44, 0xba,
+  0x8c, 0xc3, 0x74, 0x39, 0xe8, 0x4c, 0xd0, 0xd4, 0x4c, 0x24, 0x61, 0xb4,
+  0x40, 0x95, 0x8c, 0xc0, 0x0a, 0xb7, 0x02, 0x39, 0x31, 0x85, 0x93, 0x02,
+  0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+  0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x0b,
+  0x47, 0x24, 0x52, 0x7d, 0xb6, 0x63, 0x78, 0xbc, 0x80, 0xdd, 0x87, 0x6c,
+  0x90, 0x4c, 0x33, 0xc3, 0x5c, 0xa7, 0x97, 0x09, 0x1c, 0x09, 0x4f, 0x9b,
+  0x6e, 0xb3, 0x5a, 0x3e, 0x46, 0x92, 0x1a, 0xc7, 0x87, 0x15, 0x59, 0xe1,
+  0x88, 0x5c, 0xce, 0x6a, 0xe2, 0x96, 0xaa, 0x32, 0xec, 0xc2, 0xed, 0x78,
+  0x8b, 0xe0, 0x90, 0x66, 0x93, 0x14, 0xc3, 0x98, 0xab, 0x33, 0x35, 0xd3,
+  0x7d, 0x5d, 0x51, 0x0a, 0x9c, 0xb9, 0x10, 0x58, 0x47, 0x7a, 0x98, 0x95,
+  0x64, 0xff, 0x4c, 0x5d, 0x82, 0x19, 0xf9, 0xea, 0x0f, 0x5e, 0x9a, 0xcb,
+  0x32, 0x27, 0x64, 0xca, 0x6f, 0x58, 0x8a, 0xd0, 0xc0, 0x36, 0xf4, 0xb9,
+  0x63, 0x34, 0xa5, 0xda, 0x36, 0x50, 0x36, 0x49, 0xd2, 0xb7, 0x3a, 0x21,
+  0x33, 0x5b, 0x3e, 0xd6, 0x5f, 0x0c, 0x99, 0x83, 0xb7, 0xb2, 0xf7, 0x8b,
+  0x44, 0xc4, 0x5e, 0x73, 0x41, 0xa9, 0x02
+};
+unsigned int default_certificate_len = 475;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/crypto_misc.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file crypto_misc.h
+ */
+
+#ifndef HEADER_CRYPTO_MISC_H
+#define HEADER_CRYPTO_MISC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "crypto.h"
+#include "bigint.h"
+
+/**************************************************************************
+ * X509 declarations 
+ **************************************************************************/
+#define X509_OK                             0
+#define X509_NOT_OK                         -1
+#define X509_VFY_ERROR_NO_TRUSTED_CERT      -2
+#define X509_VFY_ERROR_BAD_SIGNATURE        -3      
+#define X509_VFY_ERROR_NOT_YET_VALID        -4
+#define X509_VFY_ERROR_EXPIRED              -5
+#define X509_VFY_ERROR_SELF_SIGNED          -6
+#define X509_VFY_ERROR_INVALID_CHAIN        -7
+#define X509_VFY_ERROR_UNSUPPORTED_DIGEST   -8
+#define X509_INVALID_PRIV_KEY               -9
+
+/*
+ * The Distinguished Name
+ */
+#define X509_NUM_DN_TYPES                   3
+#define X509_COMMON_NAME                    0
+#define X509_ORGANIZATION                   1
+#define X509_ORGANIZATIONAL_UNIT            2
+
+struct _x509_ctx
+{
+    char *ca_cert_dn[X509_NUM_DN_TYPES];
+    char *cert_dn[X509_NUM_DN_TYPES];
+    time_t not_before;
+    time_t not_after;
+    uint8_t *signature;
+    uint16_t sig_len;
+    uint8_t sig_type;
+    RSA_CTX *rsa_ctx;
+    bigint *digest;
+    struct {
+        unsigned char md5[MD5_SIZE];
+        unsigned char sha1[SHA1_SIZE];
+    } fingerprint;
+    struct _x509_ctx *next;
+};
+
+typedef struct _x509_ctx X509_CTX;
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+typedef struct 
+{
+    X509_CTX *cert[CONFIG_X509_MAX_CA_CERTS];
+} CA_CERT_CTX;
+#endif
+
+int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx);
+void x509_free(X509_CTX *x509_ctx);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
+#endif
+#ifdef CONFIG_SSL_FULL_MODE
+void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx);
+const char * x509_display_error(int error);
+#endif
+
+/**************************************************************************
+ * ASN1 declarations 
+ **************************************************************************/
+#define ASN1_INTEGER            0x02
+#define ASN1_BIT_STRING         0x03
+#define ASN1_OCTET_STRING       0x04
+#define ASN1_NULL               0x05
+#define ASN1_OID                0x06
+#define ASN1_PRINTABLE_STR      0x13
+#define ASN1_TELETEX_STR        0x14
+#define ASN1_IA5_STR            0x16
+#define ASN1_UTC_TIME           0x17
+#define ASN1_UNICODE_STR        0x1e
+#define ASN1_SEQUENCE           0x30
+#define ASN1_SET                0x31
+#define ASN1_IMPLICIT_TAG       0x80
+#define ASN1_EXPLICIT_TAG       0xa0
+
+#define SIG_TYPE_MD2            0x02
+#define SIG_TYPE_MD5            0x04
+#define SIG_TYPE_SHA1           0x05
+
+int get_asn1_length(const uint8_t *buf, int *offset);
+int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx);
+int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type);
+int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type);
+int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object);
+int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
+int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
+int asn1_name(const uint8_t *cert, int *offset, char *dn[]);
+int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
+int asn1_compare_dn(char * const dn1[], char * const dn2[]);
+#endif
+int asn1_signature_type(const uint8_t *cert, 
+                                int *offset, X509_CTX *x509_ctx);
+
+/**************************************************************************
+ * MISC declarations 
+ **************************************************************************/
+#define SALT_SIZE               8
+
+extern const char * const unsupported_str;
+
+typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int);
+typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest);
+
+int get_file(const char *filename, uint8_t **buf);
+
+#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG)
+EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...);
+#else
+/*#define print_blob(...)*/
+EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...);
+#endif
+
+EXP_FUNC int STDCALL base64_decode(const char *in,  int len,
+                    uint8_t *out, int *outlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/gen_cert.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#ifdef CONFIG_SSL_GENERATE_X509_CERT
+#include <string.h>
+#include <stdlib.h>
+#include "ssl.h"
+
+/**
+ * Generate a basic X.509 certificate
+ */
+
+static uint8_t set_gen_length(int len, uint8_t *buf, int *offset)
+{
+    if (len < 0x80) /* short form */
+    {
+        buf[(*offset)++] = len;
+        return 1;
+    }
+    else /* long form */
+    {
+        int i, length_bytes = 0;
+
+        if (len & 0x00FF0000)
+            length_bytes = 3;
+        else if (len & 0x0000FF00)
+            length_bytes = 2;
+        else if (len & 0x000000FF)
+            length_bytes = 1;
+            
+        buf[(*offset)++] = 0x80 + length_bytes;
+
+        for (i = length_bytes-1; i >= 0; i--)
+        {
+            buf[*offset+i] = len & 0xFF;
+            len >>= 8;
+        }
+
+        *offset += length_bytes;
+        return length_bytes+1;
+    }
+}
+
+static int pre_adjust_with_size(uint8_t type,
+        int *seq_offset, uint8_t *buf, int *offset)
+{
+    buf[(*offset)++] = type;
+    *seq_offset = *offset;
+    *offset += 4;   /* fill in later */
+    return *offset;
+}
+
+static void adjust_with_size(int seq_size, int seq_start, 
+                uint8_t *buf, int *offset)
+{
+    uint8_t seq_byte_size; 
+    int orig_seq_size = seq_size;
+    int orig_seq_start = seq_start;
+
+    seq_size = *offset-seq_size;
+    seq_byte_size = set_gen_length(seq_size, buf, &seq_start);
+
+    if (seq_byte_size != 4)
+    {
+        memmove(&buf[orig_seq_start+seq_byte_size], 
+                &buf[orig_seq_size], seq_size);
+        *offset -= 4-seq_byte_size;
+    }
+}
+
+static void gen_serial_number(uint8_t *buf, int *offset)
+{
+    static const uint8_t ser_oid[] = { ASN1_INTEGER, 1, 0x7F };
+    memcpy(&buf[*offset], ser_oid , sizeof(ser_oid));
+    *offset += sizeof(ser_oid);
+}
+
+static void gen_signature_alg(uint8_t *buf, int *offset)
+{
+    /* OBJECT IDENTIFIER sha1withRSAEncryption (1 2 840 113549 1 1 5) */
+    static const uint8_t sig_oid[] = 
+    {
+        ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09, 
+        0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+        ASN1_NULL, 0x00
+    };
+
+    memcpy(&buf[*offset], sig_oid, sizeof(sig_oid));
+    *offset += sizeof(sig_oid);
+}
+
+static int gen_dn(const char *name, uint8_t dn_type, 
+                        uint8_t *buf, int *offset)
+{
+    int ret = X509_OK;
+    int name_size = strlen(name);
+
+    if (name_size > 0x70)    /* just too big */
+    {
+        ret = X509_NOT_OK;
+        goto error;
+    }
+
+    buf[(*offset)++] = ASN1_SET;
+    set_gen_length(9+name_size, buf, offset);
+    buf[(*offset)++] = ASN1_SEQUENCE;
+    set_gen_length(7+name_size, buf, offset);
+    buf[(*offset)++] = ASN1_OID;
+    buf[(*offset)++] = 3;
+    buf[(*offset)++] = 0x55;
+    buf[(*offset)++] = 0x04;
+    buf[(*offset)++] = dn_type;
+    buf[(*offset)++] = ASN1_PRINTABLE_STR;
+    buf[(*offset)++] = name_size;
+    strcpy(&buf[*offset], name);
+    *offset += name_size;
+
+error:
+    return ret;
+}
+
+static int gen_issuer(const char * dn[], uint8_t *buf, int *offset)
+{
+    int ret = X509_OK;
+    int seq_offset;
+    int seq_size = pre_adjust_with_size(
+                            ASN1_SEQUENCE, &seq_offset, buf, offset);
+    char fqdn[128]; 
+
+    /* we need the common name, so if not configured, work out the fully
+     * qualified domain name */
+    if (dn[X509_COMMON_NAME] == NULL || strlen(dn[X509_COMMON_NAME]) == 0)
+    {
+        int fqdn_len;
+        gethostname(fqdn, sizeof(fqdn));
+        fqdn_len = strlen(fqdn);
+        fqdn[fqdn_len++] = '.';
+        getdomainname(&fqdn[fqdn_len], sizeof(fqdn)-fqdn_len);
+        fqdn_len = strlen(fqdn);
+
+        if (fqdn[fqdn_len-1] == '.')    /* ensure '.' is not last char */
+            fqdn[fqdn_len-1] = 0;
+
+        dn[X509_COMMON_NAME] = fqdn;
+    }
+
+    if ((ret = gen_dn(dn[X509_COMMON_NAME], 3, buf, offset)))
+        goto error;
+
+    if (dn[X509_ORGANIZATION] != NULL && strlen(dn[X509_ORGANIZATION]) > 0)
+    {
+        if ((ret = gen_dn(dn[X509_ORGANIZATION], 10, buf, offset)))
+            goto error;
+    }
+
+    if (dn[X509_ORGANIZATIONAL_UNIT] != NULL &&
+                                strlen(dn[X509_ORGANIZATIONAL_UNIT]) > 0)
+    {
+        if ((ret = gen_dn(dn[X509_ORGANIZATIONAL_UNIT], 11, buf, offset)))
+            goto error;
+    }
+
+    adjust_with_size(seq_size, seq_offset, buf, offset);
+
+error:
+    return ret;
+}
+
+static void gen_utc_time(uint8_t *buf, int *offset)
+{
+    static const uint8_t time_seq[] = 
+    {
+        ASN1_SEQUENCE, 30, 
+        ASN1_UTC_TIME, 13, 
+        '0', '7', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z', 
+        ASN1_UTC_TIME, 13,  /* make it good for 30 or so years */
+        '3', '8', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z'
+    };
+
+    /* fixed time */
+    memcpy(&buf[*offset], time_seq, sizeof(time_seq));
+    *offset += sizeof(time_seq);
+}
+
+static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
+{
+    static const uint8_t pub_key_seq[] = 
+    {
+        ASN1_INTEGER, 0x03, 0x01, 0x00, 0x01 /* INTEGER 65537 */
+    };
+
+    int seq_offset;
+    int pub_key_size = rsa_ctx->num_octets;
+    uint8_t *block = (uint8_t *)alloca(pub_key_size);
+    int seq_size = pre_adjust_with_size(
+                            ASN1_SEQUENCE, &seq_offset, buf, offset);
+    buf[(*offset)++] = ASN1_INTEGER;
+    bi_export(rsa_ctx->bi_ctx, rsa_ctx->m, block, pub_key_size);
+
+    if (*block & 0x80)  /* make integer positive */
+    {
+        set_gen_length(pub_key_size+1, buf, offset);
+        buf[(*offset)++] = 0;
+    }
+    else
+        set_gen_length(pub_key_size, buf, offset);
+
+    memcpy(&buf[*offset], block, pub_key_size);
+    *offset += pub_key_size;
+    memcpy(&buf[*offset], pub_key_seq, sizeof(pub_key_seq));
+    *offset += sizeof(pub_key_seq);
+    adjust_with_size(seq_size, seq_offset, buf, offset);
+}
+
+static void gen_pub_key1(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
+{
+    int seq_offset;
+    int seq_size = pre_adjust_with_size(
+                            ASN1_BIT_STRING, &seq_offset, buf, offset);
+    buf[(*offset)++] = 0;   /* bit string is multiple of 8 */
+    gen_pub_key2(rsa_ctx, buf, offset);
+    adjust_with_size(seq_size, seq_offset, buf, offset);
+}
+
+static void gen_pub_key(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
+{
+    /*  OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) */
+    static const uint8_t rsa_enc_oid[] =
+    {
+        ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09,
+        0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+        ASN1_NULL, 0x00
+    };
+
+    int seq_offset;
+    int seq_size = pre_adjust_with_size(
+                            ASN1_SEQUENCE, &seq_offset, buf, offset);
+
+    memcpy(&buf[*offset], rsa_enc_oid, sizeof(rsa_enc_oid));
+    *offset += sizeof(rsa_enc_oid);
+    gen_pub_key1(rsa_ctx, buf, offset);
+    adjust_with_size(seq_size, seq_offset, buf, offset);
+}
+
+static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, 
+                        uint8_t *buf, int *offset)
+{
+    static const uint8_t asn1_sig[] = 
+    {
+        ASN1_SEQUENCE,  0x21, ASN1_SEQUENCE, 0x09, ASN1_OID, 0x05, 
+        0x2b, 0x0e, 0x03, 0x02, 0x1a, /* sha1 (1 3 14 3 2 26) */
+        ASN1_NULL, 0x00, ASN1_OCTET_STRING, 0x14 
+    };
+
+    uint8_t *enc_block = (uint8_t *)alloca(rsa_ctx->num_octets);
+    uint8_t *block = (uint8_t *)alloca(sizeof(asn1_sig) + SHA1_SIZE);
+    int sig_size;
+
+    /* add the digest as an embedded asn.1 sequence */
+    memcpy(block, asn1_sig, sizeof(asn1_sig));
+    memcpy(&block[sizeof(asn1_sig)], sha_dgst, SHA1_SIZE);
+
+    sig_size = RSA_encrypt(rsa_ctx, block, 
+                            sizeof(asn1_sig) + SHA1_SIZE, enc_block, 1);
+
+    buf[(*offset)++] = ASN1_BIT_STRING;
+    set_gen_length(sig_size+1, buf, offset);
+    buf[(*offset)++] = 0;   /* bit string is multiple of 8 */
+    memcpy(&buf[*offset], enc_block, sig_size);
+    *offset += sig_size;
+}
+
+static int gen_tbs_cert(const char * dn[],
+                    const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset,
+                    uint8_t *sha_dgst)
+{
+    int ret = X509_OK;
+    SHA1_CTX sha_ctx;
+    int seq_offset;
+    int begin_tbs = *offset;
+    int seq_size = pre_adjust_with_size(
+                        ASN1_SEQUENCE, &seq_offset, buf, offset);
+
+    gen_serial_number(buf, offset);
+    gen_signature_alg(buf, offset);
+
+    /* CA certicate issuer */
+    if ((ret = gen_issuer(dn, buf, offset)))
+        goto error;
+
+    gen_utc_time(buf, offset);
+
+    /* certificate issuer */
+    if ((ret = gen_issuer(dn, buf, offset)))
+        goto error;
+
+    gen_pub_key(rsa_ctx, buf, offset);
+    adjust_with_size(seq_size, seq_offset, buf, offset);
+
+    SHA1_Init(&sha_ctx);
+    SHA1_Update(&sha_ctx, &buf[begin_tbs], *offset-begin_tbs);
+    SHA1_Final(sha_dgst, &sha_ctx);
+
+error:
+    return ret;
+}
+
+/**
+ * Create a new certificate.
+ */
+EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data)
+{
+    int ret = X509_OK, offset = 0, seq_offset;
+    /* allocate enough space to load a new certificate */
+    uint8_t *buf = (uint8_t *)alloca(ssl_ctx->rsa_ctx->num_octets*2 + 512);
+    uint8_t sha_dgst[SHA1_SIZE];
+    int seq_size = pre_adjust_with_size(ASN1_SEQUENCE, 
+                                    &seq_offset, buf, &offset);
+
+    if ((ret = gen_tbs_cert(dn, ssl_ctx->rsa_ctx, buf, &offset, sha_dgst)) < 0)
+        goto error;
+
+    gen_signature_alg(buf, &offset);
+    gen_signature(ssl_ctx->rsa_ctx, sha_dgst, buf, &offset);
+    adjust_with_size(seq_size, seq_offset, buf, &offset);
+    *cert_data = (uint8_t *)malloc(offset); /* create the exact memory for it */
+    memcpy(*cert_data, buf, offset);
+
+error:
+    return ret < 0 ? ret : offset;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/loader.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Load certificates/keys into memory. These can be in many different formats.
+ * PEM support and other formats can be processed here.
+ *
+ * The PEM private keys may be optionally encrypted with AES128 or AES256. 
+ * The encrypted PEM keys were generated with something like:
+ *
+ * openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "ssl.h"
+
+static int do_obj(SSL_CTX *ssl_ctx, int obj_type, 
+                    SSLObjLoader *ssl_obj, const char *password);
+#ifdef CONFIG_SSL_HAS_PEM
+static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, 
+                        SSLObjLoader *ssl_obj, const char *password);
+#endif
+
+/*
+ * Load a file into memory that is in binary DER (or ascii PEM) format.
+ */
+EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, 
+                            const char *filename, const char *password)
+{
+#ifndef CONFIG_SSL_SKELETON_MODE
+    static const char * const begin = "-----BEGIN";
+    int ret = SSL_OK;
+    SSLObjLoader *ssl_obj = NULL;
+
+    if (filename == NULL)
+    {
+        ret = SSL_ERROR_INVALID_KEY;
+        goto error;
+    }
+
+    ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
+    ssl_obj->len = get_file(filename, &ssl_obj->buf); 
+    if (ssl_obj->len <= 0)
+    {
+        ret = SSL_ERROR_INVALID_KEY;
+        goto error;
+    }
+
+    /* is the file a PEM file? */
+    if (strncmp((char *)ssl_obj->buf, begin, strlen(begin)) == 0)
+    {
+#ifdef CONFIG_SSL_HAS_PEM
+        ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
+#else
+        printf(unsupported_str);
+        ret = SSL_ERROR_NOT_SUPPORTED;
+#endif
+    }
+    else
+        ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
+
+error:
+    ssl_obj_free(ssl_obj);
+    return ret;
+#else
+    printf(unsupported_str);
+    return SSL_ERROR_NOT_SUPPORTED;
+#endif /* CONFIG_SSL_SKELETON_MODE */
+}
+
+/*
+ * Transfer binary data into the object loader.
+ */
+EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int mem_type, 
+        const uint8_t *data, int len, const char *password)
+{
+    int ret;
+    SSLObjLoader *ssl_obj;
+
+    ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
+    ssl_obj->buf = (uint8_t *)malloc(len);
+    memcpy(ssl_obj->buf, data, len);
+    ssl_obj->len = len;
+    ret = do_obj(ssl_ctx, mem_type, ssl_obj, password);
+    ssl_obj_free(ssl_obj);
+    return ret;
+}
+
+/*
+ * Actually work out what we are doing 
+ */
+static int do_obj(SSL_CTX *ssl_ctx, int obj_type, 
+                    SSLObjLoader *ssl_obj, const char *password)
+{
+    int ret = SSL_OK;
+
+    switch (obj_type)
+    {
+        case SSL_OBJ_RSA_KEY:
+            ret = add_private_key(ssl_ctx, ssl_obj);
+            break;
+
+        case SSL_OBJ_X509_CERT:
+            ret = add_cert(ssl_ctx, ssl_obj->buf, ssl_obj->len);
+            break;
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+        case SSL_OBJ_X509_CACERT:
+            ret = add_cert_auth(ssl_ctx, ssl_obj->buf, ssl_obj->len);
+            break;
+#endif
+
+#ifdef CONFIG_SSL_USE_PKCS12
+        case SSL_OBJ_PKCS8:
+            ret = pkcs8_decode(ssl_ctx, ssl_obj, password);
+            break;
+
+        case SSL_OBJ_PKCS12:
+            ret = pkcs12_decode(ssl_ctx, ssl_obj, password);
+            break;
+#endif
+        default:
+            printf(unsupported_str);
+            ret = SSL_ERROR_NOT_SUPPORTED;
+            break;
+    }
+
+    return ret;
+}
+
+/*
+ * Clean up our mess.
+ */
+void ssl_obj_free(SSLObjLoader *ssl_obj)
+{
+    if (ssl_obj)
+    {
+        free(ssl_obj->buf);
+        free(ssl_obj);
+    }
+}
+
+/*
+ * Support for PEM encoded keys/certificates.
+ */
+#ifdef CONFIG_SSL_HAS_PEM
+
+#define NUM_PEM_TYPES               3
+#define IV_SIZE                     16
+#define IS_RSA_PRIVATE_KEY          0
+#define IS_ENCRYPTED_PRIVATE_KEY    1
+#define IS_CERTIFICATE              2
+
+static const char * const begins[NUM_PEM_TYPES] =
+{
+    "-----BEGIN RSA PRIVATE KEY-----",
+    "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+    "-----BEGIN CERTIFICATE-----",
+};
+
+static const char * const ends[NUM_PEM_TYPES] =
+{
+    "-----END RSA PRIVATE KEY-----",
+    "-----END ENCRYPTED PRIVATE KEY-----",
+    "-----END CERTIFICATE-----",
+};
+
+static const char * const aes_str[2] =
+{
+    "DEK-Info: AES-128-CBC,",
+    "DEK-Info: AES-256-CBC," 
+};
+
+/**
+ * Take a base64 blob of data and decrypt it (using AES) into its 
+ * proper ASN.1 form.
+ */
+static int pem_decrypt(const char *where, const char *end,
+                        const char *password, SSLObjLoader *ssl_obj)
+{
+    int ret = -1;
+    int is_aes_256 = 0;
+    char *start = NULL;
+    uint8_t iv[IV_SIZE];
+    int i, pem_size;
+    MD5_CTX md5_ctx;
+    AES_CTX aes_ctx;
+    uint8_t key[32];        /* AES256 size */
+
+    if (password == NULL || strlen(password) == 0)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: Need a password for this PEM file\n"); TTY_FLUSH();
+#endif
+        goto error;
+    }
+
+    if ((start = strstr((const char *)where, aes_str[0])))         /* AES128? */
+    {
+        start += strlen(aes_str[0]);
+    }
+    else if ((start = strstr((const char *)where, aes_str[1])))    /* AES256? */
+    {
+        is_aes_256 = 1;
+        start += strlen(aes_str[1]);
+    }
+    else 
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: Unsupported password cipher\n"); TTY_FLUSH();
+#endif
+        goto error;
+    }
+
+    /* convert from hex to binary - assumes uppercase hex */
+    for (i = 0; i < IV_SIZE; i++)
+    {
+        char c = *start++ - '0';
+        iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
+        c = *start++ - '0';
+        iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
+    }
+
+    while (*start == '\r' || *start == '\n')
+        start++;
+
+    /* turn base64 into binary */
+    pem_size = (int)(end-start);
+    if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
+        goto error;
+
+    /* work out the key */
+    MD5_Init(&md5_ctx);
+    MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
+    MD5_Update(&md5_ctx, iv, SALT_SIZE);
+    MD5_Final(key, &md5_ctx);
+
+    if (is_aes_256)
+    {
+        MD5_Init(&md5_ctx);
+        MD5_Update(&md5_ctx, key, MD5_SIZE);
+        MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
+        MD5_Update(&md5_ctx, iv, SALT_SIZE);
+        MD5_Final(&key[MD5_SIZE], &md5_ctx);
+    }
+
+    /* decrypt using the key/iv */
+    AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
+    AES_convert_key(&aes_ctx);
+    AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
+    ret = 0;
+
+error:
+    return ret; 
+}
+
+/**
+ * Take a base64 blob of data and turn it into its proper ASN.1 form.
+ */
+static int new_pem_obj(SSL_CTX *ssl_ctx, int is_cacert, char *where, 
+                    int remain, const char *password)
+{
+    int ret = SSL_OK;
+    SSLObjLoader *ssl_obj = NULL;
+    int i, pem_size, obj_type;
+    char *start = NULL, *end = NULL;
+
+    for (i = 0; i < NUM_PEM_TYPES; i++)
+    {
+        if ((start = strstr(where, begins[i])) &&
+                (end = strstr(where, ends[i])))
+        {
+            remain -= (int)(end-start);
+            start += strlen(begins[i]);
+            pem_size = (int)(end-start);
+
+            ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
+
+            /* 4/3 bigger than what we need but so what */
+            ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
+
+            if (i == IS_RSA_PRIVATE_KEY && 
+                        strstr(start, "Proc-Type:") && 
+                        strstr(start, "4,ENCRYPTED"))
+            {
+                /* check for encrypted PEM file */
+                if (pem_decrypt(start, end, password, ssl_obj) < 0)
+                    goto error;
+            }
+            else if (base64_decode(start, pem_size, 
+                        ssl_obj->buf, &ssl_obj->len) != 0)
+                goto error;
+
+            switch (i)
+            {
+                case IS_RSA_PRIVATE_KEY:
+                    obj_type = SSL_OBJ_RSA_KEY;
+                    break;
+
+                case IS_ENCRYPTED_PRIVATE_KEY:
+                    obj_type = SSL_OBJ_PKCS8;
+                    break;
+
+                case IS_CERTIFICATE:
+                    obj_type = is_cacert ?
+                                    SSL_OBJ_X509_CACERT : SSL_OBJ_X509_CERT;
+                    break;
+
+                default:
+                    goto error;
+            }
+
+            /* In a format we can now understand - so process it */
+            if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
+                goto error;
+
+            end += strlen(ends[i]);
+            remain -= strlen(ends[i]);
+            while (remain > 0 && (*end == '\r' || *end == '\n'))
+            {
+                end++;
+                remain--;
+            }
+
+            break;
+        }
+    }
+
+    if (i == NUM_PEM_TYPES)
+        goto error;
+
+    /* more PEM stuff to process? */
+    if (remain)
+        ret = new_pem_obj(ssl_ctx, is_cacert, end, remain, password);
+
+error:
+    ssl_obj_free(ssl_obj);
+    return ret;
+}
+
+/*
+ * Load a file into memory that is in ASCII PEM format.
+ */
+static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, 
+                        SSLObjLoader *ssl_obj, const char *password)
+{
+    char *start;
+
+    /* add a null terminator */
+    ssl_obj->len++;
+    ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
+    ssl_obj->buf[ssl_obj->len-1] = 0;
+    start = (char *)ssl_obj->buf;
+    return new_pem_obj(ssl_ctx, obj_type == SSL_OBJ_X509_CACERT,
+                                start, ssl_obj->len, password);
+}
+#endif /* CONFIG_SSL_HAS_PEM */
+
+/**
+ * Load the key/certificates in memory depending on compile-time and user
+ * options. 
+ */
+int load_key_certs(SSL_CTX *ssl_ctx)
+{
+    int ret = SSL_OK;
+    uint32_t options = ssl_ctx->options;
+#ifdef CONFIG_SSL_GENERATE_X509_CERT 
+    uint8_t *cert_data = NULL;
+    int cert_size;
+    static const char *dn[] = 
+    {
+        CONFIG_SSL_X509_COMMON_NAME,
+        CONFIG_SSL_X509_ORGANIZATION_NAME,
+        CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
+    };
+#endif
+
+    /* do the private key first */
+    if (strlen(CONFIG_SSL_PRIVATE_KEY_LOCATION) > 0)
+    {
+        if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, 
+                                CONFIG_SSL_PRIVATE_KEY_LOCATION,
+                                CONFIG_SSL_PRIVATE_KEY_PASSWORD)) < 0)
+            goto error;
+    }
+    else if (!(options & SSL_NO_DEFAULT_KEY))
+    {
+#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
+        static const    /* saves a few more bytes */
+#include "private_key.h"
+
+        ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key,
+                default_private_key_len, NULL); 
+#endif
+    }
+
+    /* now load the certificate */
+#ifdef CONFIG_SSL_GENERATE_X509_CERT 
+    if ((cert_size = ssl_x509_create(ssl_ctx, 0, dn, &cert_data)) < 0)
+    {
+        ret = cert_size;
+        goto error;
+    }
+
+    ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, cert_data, cert_size, NULL);
+    free(cert_data);
+#else
+    if (strlen(CONFIG_SSL_X509_CERT_LOCATION))
+    {
+        if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, 
+                                CONFIG_SSL_X509_CERT_LOCATION, NULL)) < 0)
+            goto error;
+    }
+    else if (!(options & SSL_NO_DEFAULT_KEY))
+    {
+#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
+        static const    /* saves a few bytes and RAM */
+#include "cert.h"
+        ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, 
+                    default_certificate, default_certificate_len, NULL);
+#endif
+    }
+#endif
+
+error:
+#ifdef CONFIG_SSL_FULL_MODE
+    if (ret)
+    {
+        printf("Error: Certificate or key not loaded\n"); TTY_FLUSH();
+    }
+#endif
+
+    return ret;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/os_port.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,64 @@
+/*****************************************************************
+|
+|   abstraction layer for axTLS
+|
+| Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+| All rights reserved.
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|     * Redistributions of source code must retain the above copyright
+|       notice, this list of conditions and the following disclaimer.
+|     * Redistributions in binary form must reproduce the above copyright
+|       notice, this list of conditions and the following disclaimer in the
+|       documentation and/or other materials provided with the distribution.
+|     * Neither the name of Axiomatic Systems nor the
+|       names of its contributors may be used to endorse or promote products
+|       derived from this software without specific prior written permission.
+|
+| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+|
+ ****************************************************************/
+
+#ifndef _OS_PORT_H_
+#define _OS_PORT_H_
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <time.h>
+
+/*----------------------------------------------------------------------
+|   types
++---------------------------------------------------------------------*/
+typedef struct SSL_SOCKET SSL_SOCKET;
+
+struct SSL_SOCKET {
+    int (*Read)(SSL_SOCKET* self, void* buffer, unsigned int size);
+    int (*Write)(SSL_SOCKET* self, const void* buffer, unsigned int size);
+};
+
+#define STDCALL
+#define EXP_FUNC
+
+#define SSL_CTX_MUTEX_INIT(A)
+#define SSL_CTX_MUTEX_DESTROY(A)
+#define SSL_CTX_LOCK(A)
+#define SSL_CTX_UNLOCK(A)
+
+#define TTY_FLUSH(X)
+#define SOCKET_BLOCK(X)
+#define SOCKET_READ(s,b,z) (s)->Read((s), (b), (z))
+#define SOCKET_WRITE(s,b,z) (s)->Write((s), (b), (z))
+
+#endif /* _OS_PORT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/p12.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Process PKCS#8/PKCS#12 keys.
+ *
+ * The decoding of a PKCS#12 key is fairly specific - this code was tested on a
+ * key generated with:
+ *
+ * openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
+ * -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 
+ * -name "p12_withoutCA" -out axTLS.withoutCA.p12 -password pass:abcd
+ *
+ * or with a certificate chain:
+ *
+ * openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
+ * -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe
+ * PBE-SHA1-RC4-128 -name "p12_withCA" -out axTLS.withCA.p12 -password pass:abcd
+ *
+ * Note that the PBE has to be specified with PBE-SHA1-RC4-128. The
+ * private/public keys/certs have to use RSA encryption. Both the integrity
+ * and privacy passwords are the same.
+ *
+ * The PKCS#8 files were generated with something like:
+ *
+ * PEM format:
+ * openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1
+ * PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
+ *
+ * DER format:
+ * openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER
+ * -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "ssl.h"
+
+/* all commented out if not used */
+#ifdef CONFIG_SSL_USE_PKCS12
+
+#define BLOCK_SIZE          64
+#define PKCS12_KEY_ID       1
+#define PKCS12_IV_ID        2
+#define PKCS12_MAC_ID       3
+
+static char *make_uni_pass(const char *password, int *uni_pass_len);
+static int p8_decrypt(const char *uni_pass, int uni_pass_len, 
+                        const uint8_t *salt, int iter, 
+                        uint8_t *priv_key, int priv_key_len, int id);
+static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key);
+static int get_pbe_params(uint8_t *buf, int *offset, 
+        const uint8_t **salt, int *iterations);
+
+/*
+ * Take a raw pkcs8 block and then decrypt it and turn it into a normal key.
+ */
+int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
+{
+    uint8_t *buf = ssl_obj->buf;
+    int len, offset = 0;
+    int iterations;
+    int ret = SSL_NOT_OK;
+    uint8_t *version = NULL;
+    const uint8_t *salt;
+    uint8_t *priv_key;
+    int uni_pass_len;
+    char *uni_pass = make_uni_pass(password, &uni_pass_len);
+
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: Invalid p8 ASN.1 file\n");
+#endif
+        goto error;
+    }
+
+    /* unencrypted key? */
+    if (asn1_get_int(buf, &offset, &version) > 0 && *version == 0)
+    {
+        ret = p8_add_key(ssl_ctx, buf);
+        goto error;
+    }
+
+    if (get_pbe_params(buf, &offset, &salt, &iterations) < 0)
+        goto error;
+
+    if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
+        goto error;
+
+    priv_key = &buf[offset];
+
+    p8_decrypt(uni_pass, uni_pass_len, salt, 
+                        iterations, priv_key, len, PKCS12_KEY_ID);
+    ret = p8_add_key(ssl_ctx, priv_key);
+
+error:
+    free(version);
+    free(uni_pass);
+    return ret;
+}
+
+/*
+ * Take the unencrypted pkcs8 and turn it into a private key 
+ */
+static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key)
+{
+    uint8_t *buf = priv_key;
+    int len, offset = 0;
+    int ret = SSL_NOT_OK;
+
+    /* Skip the preamble and go straight to the private key.
+       We only support rsaEncryption (1.2.840.113549.1.1.1)  */
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
+            asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
+        goto error;
+
+    ret = asn1_get_private_key(&buf[offset], len, &ssl_ctx->rsa_ctx);
+
+error:
+    return ret;
+}
+
+/*
+ * Create the unicode password 
+ */
+static char *make_uni_pass(const char *password, int *uni_pass_len)
+{
+    int pass_len = 0, i;
+    char *uni_pass;
+
+    if (password == NULL)
+    {
+        password = "";
+    }
+
+    uni_pass = (char *)malloc((strlen(password)+1)*2);
+
+    /* modify the password into a unicode version */
+    for (i = 0; i < (int)strlen(password); i++)
+    {
+        uni_pass[pass_len++] = 0;
+        uni_pass[pass_len++] = password[i];
+    }
+
+    uni_pass[pass_len++] = 0;       /* null terminate */
+    uni_pass[pass_len++] = 0;
+    *uni_pass_len = pass_len;
+    return uni_pass;
+}
+
+/*
+ * Decrypt a pkcs8 block.
+ */
+static int p8_decrypt(const char *uni_pass, int uni_pass_len,
+                        const uint8_t *salt, int iter, 
+                        uint8_t *priv_key, int priv_key_len, int id)
+{
+    uint8_t p[BLOCK_SIZE*2];
+    uint8_t d[BLOCK_SIZE];
+    uint8_t Ai[SHA1_SIZE];
+    SHA1_CTX sha_ctx;
+    RC4_CTX rc4_ctx;
+    int i;
+
+    for (i = 0; i < BLOCK_SIZE; i++)
+    {
+        p[i] = salt[i % SALT_SIZE];
+        p[BLOCK_SIZE+i] = uni_pass[i % uni_pass_len];
+        d[i] = id;
+    }
+
+    /* get the key - no IV since we are using RC4 */
+    SHA1_Init(&sha_ctx);
+    SHA1_Update(&sha_ctx, d, sizeof(d));
+    SHA1_Update(&sha_ctx, p, sizeof(p));
+    SHA1_Final(Ai, &sha_ctx);
+
+    for (i = 1; i < iter; i++)
+    {
+        SHA1_Init(&sha_ctx);
+        SHA1_Update(&sha_ctx, Ai, SHA1_SIZE);
+        SHA1_Final(Ai, &sha_ctx);
+    }
+
+    /* do the decryption */
+    if (id == PKCS12_KEY_ID)
+    {
+        RC4_setup(&rc4_ctx, Ai, 16);
+        RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len);
+    }
+    else  /* MAC */
+        memcpy(priv_key, Ai, SHA1_SIZE);
+
+    return 0;
+}
+
+/*
+ * Take a raw pkcs12 block and the decrypt it and turn it into a certificate(s)
+ * and keys.
+ */
+int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
+{
+    uint8_t *buf = ssl_obj->buf;
+    int all_ok = 0, len, iterations, auth_safes_start, 
+              auth_safes_end, auth_safes_len, key_offset, offset = 0;
+    int all_certs = 0;
+    uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac;
+    uint8_t key[SHA1_SIZE];
+    uint8_t mac[SHA1_SIZE];
+    const uint8_t *salt;
+    int uni_pass_len, ret;
+    int error_code = SSL_ERROR_NOT_SUPPORTED;
+    char *uni_pass = make_uni_pass(password, &uni_pass_len);
+    static const uint8_t pkcs_data[] = /* pkc7 data */
+        { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 };
+    static const uint8_t pkcs_encrypted[] = /* pkc7 encrypted */
+        { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 };
+    static const uint8_t pkcs8_key_bag[] = /* 1.2.840.113549.1.12.10.1.2 */
+        { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 };
+
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: Invalid p12 ASN.1 file\n");
+#endif
+        goto error;
+    }
+
+    if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3)
+    {
+        error_code = SSL_ERROR_INVALID_VERSION;
+        goto error;
+    }
+
+    /* remove all the boring pcks7 bits */
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 
+                (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
+                len != sizeof(pkcs_data) || 
+                memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
+        goto error;
+
+    offset += len;
+
+    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0)
+        goto error;
+
+    /* work out the MAC start/end points (done on AuthSafes) */
+    auth_safes_start = offset;
+    auth_safes_end = offset;
+    if (asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE) < 0)
+        goto error;
+
+    auth_safes_len = auth_safes_end - auth_safes_start;
+    auth_safes = malloc(auth_safes_len);
+
+    memcpy(auth_safes, &buf[auth_safes_start], auth_safes_len);
+
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
+            (len != sizeof(pkcs_encrypted) || 
+            memcmp(&buf[offset], pkcs_encrypted, sizeof(pkcs_encrypted))))
+        goto error;
+
+    offset += len;
+
+    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
+            len != sizeof(pkcs_data) || 
+            memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
+        goto error;
+
+    offset += len;
+
+    /* work out the salt for the certificate */
+    if (get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_IMPLICIT_TAG)) < 0)
+        goto error;
+
+    /* decrypt the certificate */
+    cert = &buf[offset];
+    if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert, 
+                            len, PKCS12_KEY_ID)) < 0)
+        goto error;
+
+    offset += len;
+
+    /* load the certificate */
+    key_offset = 0;
+    all_certs = asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE);
+
+    /* keep going until all certs are loaded */
+    while (key_offset < all_certs)
+    {
+        int cert_offset = key_offset;
+
+        if (asn1_skip_obj(cert, &cert_offset, ASN1_SEQUENCE) < 0 ||
+                asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
+                asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
+                asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
+                asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
+                asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
+                asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
+                (len = asn1_next_obj(cert, &key_offset, ASN1_OCTET_STRING)) < 0)
+            goto error;
+
+        if ((ret = add_cert(ssl_ctx, &cert[key_offset], len)) < 0)
+            goto error;
+
+        key_offset = cert_offset;
+    }
+
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
+            len != sizeof(pkcs_data) || 
+            memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
+        goto error;
+
+    offset += len;
+
+    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
+            (len != sizeof(pkcs8_key_bag)) || 
+            memcmp(&buf[offset], pkcs8_key_bag, sizeof(pkcs8_key_bag)))
+        goto error;
+
+    offset += len;
+
+    /* work out the salt for the private key */
+    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
+        goto error;
+
+    /* decrypt the private key */
+    cert = &buf[offset];
+    if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert, 
+                            len, PKCS12_KEY_ID)) < 0)
+        goto error;
+
+    offset += len;
+
+    /* load the private key */
+    if ((ret = p8_add_key(ssl_ctx, cert)) < 0)
+        goto error;
+
+    /* miss out on friendly name, local key id etc */
+    if (asn1_skip_obj(buf, &offset, ASN1_SET) < 0)
+        goto error;
+
+    /* work out the MAC */
+    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 ||
+            len != SHA1_SIZE)
+        goto error;
+
+    orig_mac = &buf[offset];
+    offset += len;
+
+    /* get the salt */
+    if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
+        goto error;
+
+    salt = &buf[offset];
+
+    /* work out what the mac should be */
+    if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, 
+                            key, SHA1_SIZE, PKCS12_MAC_ID)) < 0)
+        goto error;
+
+    hmac_sha1(auth_safes, auth_safes_len, key, SHA1_SIZE, mac);
+
+    if (memcmp(mac, orig_mac, SHA1_SIZE))
+    {
+        error_code = SSL_ERROR_INVALID_HMAC;                  
+        goto error;
+    }
+
+    all_ok = 1;
+
+error:
+    free(version);
+    free(uni_pass);
+    free(auth_safes);
+    return all_ok ? SSL_OK : error_code;
+}
+
+/*
+ * Retrieve the salt/iteration details from a PBE block.
+ */
+static int get_pbe_params(uint8_t *buf, int *offset, 
+        const uint8_t **salt, int *iterations)
+{
+    static const uint8_t pbeSH1RC4[] = /* pbeWithSHAAnd128BitRC4  */
+            { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01 };
+
+    int i, len;
+    uint8_t *iter = NULL;
+    int error_code = SSL_ERROR_NOT_SUPPORTED;
+
+    /* Get the PBE type */
+    if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
+        goto error;
+
+    /* we expect pbeWithSHAAnd128BitRC4 (1.2.840.113549.1.12.1.1) 
+       which is the only algorithm we support */
+    if (len != sizeof(pbeSH1RC4) || 
+                    memcmp(&buf[*offset], pbeSH1RC4, sizeof(pbeSH1RC4)))
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: pkcs8/pkcs12 must use \"PBE-SHA1-RC4-128\"\n");
+#endif
+        goto error;
+    }
+
+    *offset += len;
+
+    if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
+            (len = asn1_next_obj(buf, offset, ASN1_OCTET_STRING)) < 0 || 
+            len != 8)
+        goto error;
+
+    *salt = &buf[*offset];
+    *offset += len;
+
+    if ((len = asn1_get_int(buf, offset, &iter)) < 0)
+        goto error;
+
+    *iterations = 0;
+    for (i = 0; i < len; i++)
+    {
+        (*iterations) <<= 8;
+        (*iterations) += iter[i];
+    }
+
+    free(iter);
+    error_code = SSL_OK;       /* got here - we are ok */
+
+error:
+    return error_code;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/ssl.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @mainpage axTLS API
+ *
+ * @image html axolotl.jpg
+ *
+ * The axTLS library has features such as:
+ * - The TLSv1 SSL client/server protocol
+ * - No requirement to use any openssl libraries.
+ * - A choice between AES block (128/256 bit) and RC4 (128 bit) stream ciphers.
+ * - RSA encryption/decryption with variable sized keys (up to 4096 bits).
+ * - Certificate chaining and peer authentication.
+ * - Session resumption, session renegotiation.
+ * - ASN.1, X.509, PKCS#8, PKCS#12 keys/certificates with DER/PEM encoding.
+ * - Highly configurable compile time options.
+ * - Portable across many platforms (written in ANSI C), and has language
+ * bindings in C, C#, VB.NET, Java, Perl and Lua.
+ * - Partial openssl API compatibility (via a wrapper).
+ * - A very small footprint (around 50-60kB for the library in 'server-only' 
+ *   mode).
+ * - No dependencies on sockets - can use serial connections for example.
+ * - A very simple API - ~ 20 functions/methods.
+ *
+ * A list of these functions/methods are described below.
+ *
+ *  @ref c_api 
+ *
+ *  @ref bigint_api 
+ *
+ *  @ref csharp_api 
+ *
+ *  @ref java_api 
+ */
+#ifndef HEADER_SSL_H
+#define HEADER_SSL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+/*#include "crypto.h"*/
+
+/* need to predefine before ssl_lib.h gets to it */
+#define SSL_SESSION_ID_SIZE                     32
+
+#include "tls1.h"
+
+/* The optional parameters that can be given to the client/server SSL engine */
+#define SSL_CLIENT_AUTHENTICATION               0x00010000
+#define SSL_SERVER_VERIFY_LATER                 0x00020000
+#define SSL_NO_DEFAULT_KEY                      0x00040000
+#define SSL_DISPLAY_STATES                      0x00080000
+#define SSL_DISPLAY_BYTES                       0x00100000
+#define SSL_DISPLAY_CERTS                       0x00200000
+#define SSL_DISPLAY_RSA                         0x00400000
+
+/* errors that can be generated */
+#define SSL_OK                                  0
+#define SSL_NOT_OK                              -1
+#define SSL_ERROR_DEAD                          -2
+#define SSL_ERROR_CONN_LOST                     -256
+#define SSL_ERROR_SOCK_SETUP_FAILURE            -258
+#define SSL_ERROR_INVALID_HANDSHAKE             -260
+#define SSL_ERROR_INVALID_PROT_MSG              -261
+#define SSL_ERROR_INVALID_HMAC                  -262
+#define SSL_ERROR_INVALID_VERSION               -263
+#define SSL_ERROR_INVALID_SESSION               -265
+#define SSL_ERROR_NO_CIPHER                     -266
+#define SSL_ERROR_BAD_CERTIFICATE               -268
+#define SSL_ERROR_INVALID_KEY                   -269
+#define SSL_ERROR_FINISHED_INVALID              -271
+#define SSL_ERROR_NO_CERT_DEFINED               -272
+#define SSL_ERROR_NOT_SUPPORTED                 -274
+#define SSL_ERROR_TIMEOUT                       -275 /* GBG */
+#define SSL_ERROR_EOS                           -276 /* GBG */
+#define SSL_X509_OFFSET                         -512
+#define SSL_X509_ERROR(A)                       (SSL_X509_OFFSET+A)
+
+/* these are all the alerts that are recognized */
+#define SSL_ALERT_CLOSE_NOTIFY                  0
+#define SSL_ALERT_UNEXPECTED_MESSAGE            10
+#define SSL_ALERT_BAD_RECORD_MAC                20
+#define SSL_ALERT_HANDSHAKE_FAILURE             40
+#define SSL_ALERT_BAD_CERTIFICATE               42
+#define SSL_ALERT_ILLEGAL_PARAMETER             47
+#define SSL_ALERT_DECODE_ERROR                  50
+#define SSL_ALERT_DECRYPT_ERROR                 51
+#define SSL_ALERT_INVALID_VERSION               70
+
+/* The ciphers that are supported */
+#define SSL_AES128_SHA                          0x2f
+#define SSL_AES256_SHA                          0x35
+#define SSL_RC4_128_SHA                         0x05
+#define SSL_RC4_128_MD5                         0x04
+
+/* build mode ids' */
+#define SSL_BUILD_SKELETON_MODE                 0x01
+#define SSL_BUILD_SERVER_ONLY                   0x02
+#define SSL_BUILD_ENABLE_VERIFICATION           0x03
+#define SSL_BUILD_ENABLE_CLIENT                 0x04
+#define SSL_BUILD_FULL_MODE                     0x05
+
+/* offsets to retrieve configuration information */
+#define SSL_BUILD_MODE                          0
+#define SSL_MAX_CERT_CFG_OFFSET                 1
+#define SSL_MAX_CA_CERT_CFG_OFFSET              2
+#define SSL_HAS_PEM                             3
+
+/* default session sizes */
+#define SSL_DEFAULT_SVR_SESS                    5
+#define SSL_DEFAULT_CLNT_SESS                   1
+
+/* X.509/X.520 distinguished name types */
+#define SSL_X509_CERT_COMMON_NAME               0
+#define SSL_X509_CERT_ORGANIZATION              1
+#define SSL_X509_CERT_ORGANIZATIONAL_NAME       2
+#define SSL_X509_CA_CERT_COMMON_NAME            3
+#define SSL_X509_CA_CERT_ORGANIZATION           4
+#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME    5
+
+/* SSL object loader types */
+#define SSL_OBJ_X509_CERT                       1
+#define SSL_OBJ_X509_CACERT                     2
+#define SSL_OBJ_RSA_KEY                         3
+#define SSL_OBJ_PKCS8                           4
+#define SSL_OBJ_PKCS12                          5
+
+/**
+ * @defgroup c_api Standard C API
+ * @brief The standard interface in C.
+ * @{
+ */
+
+/**
+ * @brief Establish a new client/server context.
+ *
+ * This function is called before any client/server SSL connections are made. 
+ *
+ * Each new connection will use the this context's private key and 
+ * certificate chain. If a different certificate chain is required, then a 
+ * different context needs to be be used.
+ *
+ * There are two threading models supported - a single thread with one
+ * SSL_CTX can support any number of SSL connections - and multiple threads can 
+ * support one SSL_CTX object each (the default). But if a single SSL_CTX 
+ * object uses many SSL objects in individual threads, then the 
+ * CONFIG_SSL_CTX_MUTEXING option needs to be configured.
+ *
+ * @param options [in]  Any particular options. At present the options
+ * supported are:
+ * - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if the server
+ * authentication fails. The certificate can be authenticated later with a
+ * call to ssl_verify_cert().
+ * - SSL_CLIENT_AUTHENTICATION (server only): Enforce client authentication
+ * i.e. each handshake will include a "certificate request" message from the
+ * server. Only available if verification has been enabled.
+ * - SSL_DISPLAY_BYTES (full mode build only): Display the byte sequences
+ * during the handshake.
+ * - SSL_DISPLAY_STATES (full mode build only): Display the state changes
+ * during the handshake.
+ * - SSL_DISPLAY_CERTS (full mode build only): Display the certificates that
+ * are passed during a handshake.
+ * - SSL_DISPLAY_RSA (full mode build only): Display the RSA key details that
+ * are passed during a handshake.
+ *
+ * @param num_sessions [in] The number of sessions to be used for session
+ * caching. If this value is 0, then there is no session caching. This option
+ * is not used in skeleton mode.
+ * @return A client/server context.
+ */
+EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions);
+
+/**
+ * @brief Remove a client/server context.
+ *
+ * Frees any used resources used by this context. Each connection will be 
+ * sent a "Close Notify" alert (if possible).
+ * @param ssl_ctx [in] The client/server context.
+ */
+EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
+
+/**
+ * @brief (server only) Establish a new SSL connection to an SSL client.
+ *
+ * It is up to the application to establish the logical connection (whether it
+ * is  a socket, serial connection etc).
+ * @param ssl_ctx [in] The server context.
+ * @param client_fd [in] The client's file descriptor. 
+ * @return An SSL object reference.
+ */
+EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, SSL_SOCKET* client_fd);
+
+/**
+ * @brief (client only) Establish a new SSL connection to an SSL server.
+ *
+ * It is up to the application to establish the initial logical connection 
+ * (whether it is  a socket, serial connection etc).
+ *
+ * This is a blocking call - it will finish when the handshake is complete (or
+ * has failed).
+ * @param ssl_ctx [in] The client context.
+ * @param client_fd [in] The client's file descriptor.
+ * @param session_id [in] A 32 byte session id for session resumption. This 
+ * can be null if no session resumption is being used or required. This option
+ * is not used in skeleton mode.
+ * @param sess_id_size The size of the session id (max 32)
+ * @return An SSL object reference. Use ssl_handshake_status() to check 
+ * if a handshake succeeded.
+ */
+EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, SSL_SOCKET* client_fd, const uint8_t *session_id, uint8_t sess_id_size);
+
+/**
+ * @brief Free any used resources on this connection. 
+ 
+ * A "Close Notify" message is sent on this connection (if possible). It is up 
+ * to the application to close the socket or file descriptor.
+ * @param ssl [in] The ssl object reference.
+ */
+EXP_FUNC void STDCALL ssl_free(SSL *ssl);
+
+/**
+ * @brief Read the SSL data stream.
+ * The socket must be in blocking mode.
+ * @param ssl [in] An SSL object reference.
+ * @param in_data [out] If the read was successful, a pointer to the read
+ * buffer will be here. Do NOT ever free this memory as this buffer is used in
+ * sucessive calls. If the call was unsuccessful, this value will be null.
+ * @return The number of decrypted bytes:
+ * - if > 0, then the handshaking is complete and we are returning the number 
+ *   of decrypted bytes. 
+ * - SSL_OK if the handshaking stage is successful (but not yet complete).  
+ * - < 0 if an error.
+ * @see ssl.h for the error code list.
+ * @note Use in_data before doing any successive ssl calls.
+ */
+EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
+
+/**
+ * @brief Write to the SSL data stream. 
+ * The socket must be in blocking mode.
+ * @param ssl [in] An SSL obect reference.
+ * @param out_data [in] The data to be written
+ * @param out_len [in] The number of bytes to be written.
+ * @return The number of bytes sent, or if < 0 if an error.
+ * @see ssl.h for the error code list.
+ */
+EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len);
+
+/**
+ * @brief Find an ssl object based on a file descriptor.
+ *
+ * Goes through the list of SSL objects maintained in a client/server context
+ * to look for a file descriptor match.
+ * @param ssl_ctx [in] The client/server context.
+ * @param client_fd [in]  The file descriptor.
+ * @return A reference to the SSL object. Returns null if the object could not 
+ * be found.
+ */
+EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, SSL_SOCKET* client_fd);
+
+/**
+ * @brief Get the session id for a handshake. 
+ * 
+ * This will be a 32 byte sequence and is available after the first
+ * handshaking messages are sent.
+ * @param ssl [in] An SSL object reference.
+ * @return The session id as a 32 byte sequence.
+ * @note A SSLv23 handshake may have only 16 valid bytes.
+ */
+EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl);
+
+/**
+ * @brief Get the session id size for a handshake. 
+ * 
+ * This will normally be 32 but could be 0 (no session id) or something else.
+ * @param ssl [in] An SSL object reference.
+ * @return The size of the session id.
+ */
+EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl);
+
+/**
+ * @brief Return the cipher id (in the SSL form).
+ * @param ssl [in] An SSL object reference.
+ * @return The cipher id. This will be one of the following:
+ * - SSL_AES128_SHA (0x2f)
+ * - SSL_AES256_SHA (0x35)
+ * - SSL_RC4_128_SHA (0x05)
+ * - SSL_RC4_128_MD5 (0x04)
+ */
+EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
+
+/**
+ * @brief Return the status of the handshake.
+ * @param ssl [in] An SSL object reference.
+ * @return SSL_OK if the handshake is complete and ok. 
+ * @see ssl.h for the error code list.
+ */
+EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl);
+
+/**
+ * @brief Retrieve various parameters about the axTLS engine.
+ * @param offset [in] The configuration offset. It will be one of the following:
+ * - SSL_BUILD_MODE The build mode. This will be one of the following:
+ *   - SSL_BUILD_SERVER_ONLY            (basic server mode)
+ *   - SSL_BUILD_ENABLE_VERIFICATION    (server can do client authentication)
+ *   - SSL_BUILD_ENABLE_CLIENT          (client/server capabilties)
+ *   - SSL_BUILD_FULL_MODE              (client/server with diagnostics)
+ *   - SSL_BUILD_SKELETON_MODE          (skeleton mode)
+ * - SSL_MAX_CERT_CFG_OFFSET The maximum number of certificates allowed.
+ * - SSL_MAX_CA_CERT_CFG_OFFSET The maximum number of CA certificates allowed.
+ * - SSL_HAS_PEM                        1 if supported
+ * @return The value of the requested parameter.
+ */
+EXP_FUNC int STDCALL ssl_get_config(int offset);
+
+/**
+ * @brief Display why the handshake failed.
+ *
+ * This call is only useful in a 'full mode' build. The output is to stdout.
+ * @param error_code [in] An error code.
+ * @see ssl.h for the error code list.
+ */
+EXP_FUNC void STDCALL ssl_display_error(int error_code);
+
+/**
+ * @brief Authenticate a received certificate.
+ * 
+ * This call is usually made by a client after a handshake is complete and the
+ * context is in SSL_SERVER_VERIFY_LATER mode.
+ * @param ssl [in] An SSL object reference.
+ * @return SSL_OK if the certificate is verified.
+ */
+EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
+
+/**
+ * @brief Retrieve an X.509 distinguished name component.
+ * 
+ * When a handshake is complete and a certificate has been exchanged, then the
+ * details of the remote certificate can be retrieved.
+ *
+ * This will usually be used by a client to check that the server's common 
+ * name matches the URL.
+ *
+ * A full handshake needs to occur for this call to work properly.
+ *
+ * @param ssl [in] An SSL object reference.
+ * @param component [in] one of:
+ * - SSL_X509_CERT_COMMON_NAME
+ * - SSL_X509_CERT_ORGANIZATION
+ * - SSL_X509_CERT_ORGANIZATIONAL_NAME
+ * - SSL_X509_CA_CERT_COMMON_NAME
+ * - SSL_X509_CA_CERT_ORGANIZATION
+ * - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
+ * @return The appropriate string (or null if not defined)
+ * @note Verification build mode must be enabled.
+ */
+EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component);
+
+/* GBG added */
+EXP_FUNC void ssl_get_cert_fingerprints(const SSL* ssl, unsigned char* md5, unsigned char* sha1);
+
+/**
+ * @brief Force the client to perform its handshake again.
+ *
+ * For a client this involves sending another "client hello" message.
+ * For the server is means sending a "hello request" message.
+ *
+ * This is a blocking call on the client (until the handshake completes).
+ *
+ * @param ssl [in] An SSL object reference.
+ * @return SSL_OK if renegotiation instantiation was ok
+ */
+EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl);
+
+/**
+ * @brief Process a file that is in binary DER or ASCII PEM format.
+ *
+ * These are temporary objects that are used to load private keys,
+ * certificates etc into memory.
+ * @param ssl_ctx [in] The client/server context.
+ * @param obj_type [in] The format of the file. Can be one of:
+ * - SSL_OBJ_X509_CERT (no password required)
+ * - SSL_OBJ_X509_CACERT (no password required)
+ * - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
+ * - SSL_OBJ_PKCS8 (RC4-128 encrypted data supported)
+ * - SSL_OBJ_PKCS12 (RC4-128 encrypted data supported)
+ *
+ * PEM files are automatically detected (if supported). The object type is
+ * also detected, and so is not relevant for these types of files.
+ * @param filename [in] The location of a file in DER/PEM format.
+ * @param password [in] The password used. Can be null if not required.
+ * @return SSL_OK if all ok
+ * @note Not available in skeleton build mode.
+ */
+EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, const char *filename, const char *password);
+
+/**
+ * @brief Process binary data.
+ *
+ * These are temporary objects that are used to load private keys,
+ * certificates etc into memory.
+ * @param ssl_ctx [in] The client/server context.
+ * @param obj_type [in] The format of the memory data.
+ * @param data [in] The binary data to be loaded.
+ * @param len [in] The amount of data to be loaded.
+ * @param password [in] The password used. Can be null if not required.
+ * @return SSL_OK if all ok
+ * @see ssl_obj_load for more details on obj_type.
+ */
+EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int obj_type, const uint8_t *data, int len, const char *password);
+
+#ifdef CONFIG_SSL_GENERATE_X509_CERT
+/**
+ * @brief Create an X.509 certificate. 
+ * 
+ * This certificate is a self-signed v1 cert with a fixed start/stop validity 
+ * times. It is signed with an internal private key in ssl_ctx.
+ *
+ * @param ssl_ctx [in] The client/server context.
+ * @param options [in] Not used yet.
+ * @param dn [in] An array of distinguished name strings. The array is defined
+ * by:
+ * - SSL_X509_CERT_COMMON_NAME (0)
+ *      - If SSL_X509_CERT_COMMON_NAME is empty or not defined, then the 
+ *        hostname will be used.
+ * - SSL_X509_CERT_ORGANIZATION (1)
+ *      - If SSL_X509_CERT_ORGANIZATION is empty or not defined, then $USERNAME 
+ *        will be used.
+ * - SSL_X509_CERT_ORGANIZATIONAL_NAME (2)
+ *      - SSL_X509_CERT_ORGANIZATIONAL_NAME is optional.
+ * @param cert_data [out] The certificate as a sequence of bytes.
+ * @return < 0 if an error, or the size of the certificate in bytes.
+ * @note cert_data must be freed when there is no more need for it.
+ */
+EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data);
+#endif
+
+/**
+ * @brief Return the axTLS library version as a string.
+ */
+EXP_FUNC const char * STDCALL ssl_version(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,2077 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Common ssl/tlsv1 code to both the client and server implementations.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "ssl.h"
+
+/* The session expiry time */
+#define SSL_EXPIRY_TIME     (CONFIG_SSL_EXPIRY_TIME*3600)
+
+static const uint8_t g_hello_request[] = { HS_HELLO_REQUEST, 0, 0, 0 };
+static const uint8_t g_chg_cipher_spec_pkt[] = { 1 };
+static const char * server_finished = "server finished";
+static const char * client_finished = "client finished";
+
+static int do_handshake(SSL *ssl, uint8_t *buf, int read_len);
+static void set_key_block(SSL *ssl, int is_write);
+static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len);
+static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt);
+static int send_raw_packet(SSL *ssl, uint8_t protocol);
+
+/**
+ * The server will pick the cipher based on the order that the order that the
+ * ciphers are listed. This order is defined at compile time.
+ */
+#ifdef CONFIG_SSL_SKELETON_MODE
+const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = 
+{ SSL_RC4_128_SHA };
+#else
+static void session_free(SSL_SESS *ssl_sessions[], int sess_index);
+
+const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = 
+#ifdef CONFIG_SSL_PROT_LOW                  /* low security, fast speed */
+{ SSL_RC4_128_SHA, SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_MD5 };
+#elif CONFIG_SSL_PROT_MEDIUM                /* medium security, medium speed */
+{ SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 };    
+#else /* CONFIG_SSL_PROT_HIGH */            /* high security, low speed */
+{ SSL_AES256_SHA, SSL_AES128_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 };
+#endif
+#endif /* CONFIG_SSL_SKELETON_MODE */
+
+/**
+ * The cipher map containing all the essentials for each cipher.
+ */
+#ifdef CONFIG_SSL_SKELETON_MODE
+static const cipher_info_t cipher_info[NUM_PROTOCOLS] = 
+{
+    {   /* RC4-SHA */
+        SSL_RC4_128_SHA,                /* RC4-SHA */
+        16,                             /* key size */
+        0,                              /* iv size */ 
+        2*(SHA1_SIZE+16),               /* key block size */
+        0,                              /* no padding */
+        SHA1_SIZE,                      /* digest size */
+        hmac_sha1,                      /* hmac algorithm */
+        (crypt_func)RC4_crypt,          /* encrypt */
+        (crypt_func)RC4_crypt           /* decrypt */
+    },
+};
+#else
+static const cipher_info_t cipher_info[NUM_PROTOCOLS] = 
+{
+    {   /* AES128-SHA */
+        SSL_AES128_SHA,                 /* AES128-SHA */
+        16,                             /* key size */
+        16,                             /* iv size */ 
+        2*(SHA1_SIZE+16+16),            /* key block size */
+        16,                             /* block padding size */
+        SHA1_SIZE,                      /* digest size */
+        hmac_sha1,                      /* hmac algorithm */
+        (crypt_func)AES_cbc_encrypt,    /* encrypt */
+        (crypt_func)AES_cbc_decrypt     /* decrypt */
+    },
+    {   /* AES256-SHA */
+        SSL_AES256_SHA,                 /* AES256-SHA */
+        32,                             /* key size */
+        16,                             /* iv size */ 
+        2*(SHA1_SIZE+32+16),            /* key block size */
+        16,                             /* block padding size */
+        SHA1_SIZE,                      /* digest size */
+        hmac_sha1,                      /* hmac algorithm */
+        (crypt_func)AES_cbc_encrypt,    /* encrypt */
+        (crypt_func)AES_cbc_decrypt     /* decrypt */
+    },       
+    {   /* RC4-SHA */
+        SSL_RC4_128_SHA,                /* RC4-SHA */
+        16,                             /* key size */
+        0,                              /* iv size */ 
+        2*(SHA1_SIZE+16),               /* key block size */
+        0,                              /* no padding */
+        SHA1_SIZE,                      /* digest size */
+        hmac_sha1,                      /* hmac algorithm */
+        (crypt_func)RC4_crypt,          /* encrypt */
+        (crypt_func)RC4_crypt           /* decrypt */
+    },
+    /*
+     * This protocol is from SSLv2 days and is unlikely to be used - but was
+     * useful for testing different possible digest algorithms.
+     */
+    {   /* RC4-MD5 */
+        SSL_RC4_128_MD5,                /* RC4-MD5 */
+        16,                             /* key size */
+        0,                              /* iv size */ 
+        2*(MD5_SIZE+16),                /* key block size */
+        0,                              /* no padding */
+        MD5_SIZE,                       /* digest size */
+        hmac_md5,                       /* hmac algorithm */
+        (crypt_func)RC4_crypt,          /* encrypt */
+        (crypt_func)RC4_crypt           /* decrypt */
+    },
+};
+#endif
+
+static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
+        uint8_t *out, int olen);
+static const cipher_info_t *get_cipher_info(uint8_t cipher);
+static void increment_read_sequence(SSL *ssl);
+static void increment_write_sequence(SSL *ssl);
+static void add_hmac_digest(SSL *ssl, int snd, uint8_t *hmac_header,
+        const uint8_t *buf, int buf_len, uint8_t *hmac_buf);
+
+/* win32 VC6.0 doesn't have variadic macros */
+/*#if defined(WIN32) && !defined(CONFIG_SSL_FULL_MODE)*/
+#if 1
+void DISPLAY_BYTES(SSL *ssl, const char *format, 
+        const uint8_t *data, int size, ...) {}
+#endif
+
+/**
+ * Establish a new client/server context.
+ */
+EXP_FUNC SSL_CTX *STDCALL ssl_ctx_new(uint32_t options, int num_sessions)
+{
+    SSL_CTX *ssl_ctx = (SSL_CTX *)calloc(1, sizeof (SSL_CTX));
+    ssl_ctx->options = options;
+
+    if (load_key_certs(ssl_ctx) < 0)
+    {
+        free(ssl_ctx);  /* can't load our key/certificate pair, so die */
+        return NULL;
+    }
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+    ssl_ctx->num_sessions = num_sessions;
+#endif
+
+    SSL_CTX_MUTEX_INIT(ssl_ctx->mutex);
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+    if (num_sessions)
+    {
+        ssl_ctx->ssl_sessions = (SSL_SESS **)
+                        calloc(1, num_sessions*sizeof(SSL_SESS *));
+    }
+#endif
+
+    return ssl_ctx;
+}
+
+/*
+ * Remove a client/server context.
+ */
+EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx)
+{
+    SSL *ssl;
+    int i;
+
+    if (ssl_ctx == NULL)
+        return;
+
+    ssl = ssl_ctx->head;
+
+    /* clear out all the ssl entries */
+    while (ssl)
+    {
+        SSL *next = ssl->next;
+        ssl_free(ssl);
+        ssl = next;
+    }
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+    /* clear out all the sessions */
+    for (i = 0; i < ssl_ctx->num_sessions; i++)
+        session_free(ssl_ctx->ssl_sessions, i);
+
+    free(ssl_ctx->ssl_sessions);
+#endif
+
+    i = 0;
+    while (i < CONFIG_SSL_MAX_CERTS && ssl_ctx->certs[i].buf)
+    {
+        free(ssl_ctx->certs[i].buf);
+        ssl_ctx->certs[i++].buf = NULL;
+    }
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    remove_ca_certs(ssl_ctx->ca_cert_ctx);
+#endif
+    ssl_ctx->chain_length = 0;
+    SSL_CTX_MUTEX_DESTROY(ssl_ctx->mutex);
+    RSA_free(ssl_ctx->rsa_ctx);
+    RNG_terminate();
+    free(ssl_ctx);
+}
+
+/*
+ * Free any used resources used by this connection.
+ */
+EXP_FUNC void STDCALL ssl_free(SSL *ssl)
+{
+    SSL_CTX *ssl_ctx;
+
+    if (ssl == NULL)        /* just ignore null pointers */
+        return;
+
+    /* spec says we must notify when we are dying */
+    send_alert(ssl, SSL_ALERT_CLOSE_NOTIFY);
+
+    ssl_ctx = ssl->ssl_ctx;
+
+    SSL_CTX_LOCK(ssl_ctx->mutex);
+
+    /* adjust the server SSL list */
+    if (ssl->prev)
+        ssl->prev->next = ssl->next;
+    else
+        ssl_ctx->head = ssl->next;
+
+    if (ssl->next)
+        ssl->next->prev = ssl->prev;
+    else
+        ssl_ctx->tail = ssl->prev;
+
+    SSL_CTX_UNLOCK(ssl_ctx->mutex);
+
+    /* may already be free - but be sure */
+    free(ssl->encrypt_ctx);
+    free(ssl->decrypt_ctx);
+    disposable_free(ssl);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    x509_free(ssl->x509_ctx);
+#endif
+
+    free(ssl);
+}
+
+/*
+ * Read the SSL connection and send any alerts for various errors.
+ */
+EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data)
+{
+    int ret = basic_read(ssl, in_data);
+
+    /* check for return code so we can send an alert */
+    if (ret < SSL_OK)
+    {
+        if (ret != SSL_ERROR_CONN_LOST && 
+            ret != SSL_ERROR_TIMEOUT   && /* GBG */
+            ret != SSL_ERROR_EOS          /* GBG */ )
+        {
+            send_alert(ssl, ret);
+#ifndef CONFIG_SSL_SKELETON_MODE
+            /* something nasty happened, so get rid of this session */
+            kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl);
+#endif
+        }
+    }
+
+    return ret;
+}
+
+/*
+ * Write application data to the client
+ */
+EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len)
+{
+    int n = out_len, nw, i, tot = 0;
+
+    /* maximum size of a TLS packet is around 16kB, so fragment */
+    do 
+    {
+        nw = n;
+
+        if (nw > RT_MAX_PLAIN_LENGTH)    /* fragment if necessary */
+            nw = RT_MAX_PLAIN_LENGTH;
+
+        if ((i = send_packet(ssl, PT_APP_PROTOCOL_DATA, 
+                                            &out_data[tot], nw)) <= 0)
+        {
+            out_len = i;    /* an error */
+            break;
+        }
+
+        tot += i;
+        n -= i;
+    } while (n > 0);
+
+    return out_len;
+}
+
+/**
+ * Add a certificate to the certificate chain.
+ */
+int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
+{
+    int ret = SSL_ERROR_NO_CERT_DEFINED, i = 0;
+    SSL_CERT *ssl_cert;
+    X509_CTX *cert = NULL;
+    int offset;
+
+    while (ssl_ctx->certs[i].buf && i < CONFIG_SSL_MAX_CERTS) 
+        i++;
+
+    if (i == CONFIG_SSL_MAX_CERTS) /* too many certs */
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: maximum number of certs added - change of "
+                "compile-time configuration required\n");
+#endif
+        goto error;
+    }
+
+    if ((ret = x509_new(buf, &offset, &cert)))
+        goto error;
+
+#if defined (CONFIG_SSL_FULL_MODE)
+    if (ssl_ctx->options & SSL_DISPLAY_CERTS)
+        x509_print(cert, NULL);
+#endif
+
+    ssl_cert = &ssl_ctx->certs[i];
+    ssl_cert->size = len;
+    ssl_cert->buf = (uint8_t *)malloc(len);
+    memcpy(ssl_cert->buf, buf, len);
+    ssl_ctx->chain_length++;
+    len -= offset;
+    ret = SSL_OK;           /* ok so far */
+
+    /* recurse? */
+    if (len > 0)
+    {
+        ret = add_cert(ssl_ctx, &buf[offset], len);
+    }
+
+error:
+    x509_free(cert);        /* don't need anymore */
+    return ret;
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * Add a certificate authority.
+ */
+int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
+{
+    int ret = SSL_ERROR_NO_CERT_DEFINED;
+    int i = 0;
+    int offset;
+    X509_CTX *cert = NULL;
+    CA_CERT_CTX *ca_cert_ctx;
+
+    if (ssl_ctx->ca_cert_ctx == NULL)
+        ssl_ctx->ca_cert_ctx = (CA_CERT_CTX *)calloc(1, sizeof(CA_CERT_CTX));
+
+    ca_cert_ctx = ssl_ctx->ca_cert_ctx;
+
+    while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) 
+        i++;
+
+    if (i > CONFIG_X509_MAX_CA_CERTS)
+    {
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: maximum number of CA certs added - change of "
+                "compile-time configuration required\n");
+#endif
+        goto error;
+    }
+
+    if ((ret = x509_new(buf, &offset, &ca_cert_ctx->cert[i])))
+        goto error;
+
+    /* make sure the cert is valid */
+    cert = ca_cert_ctx->cert[i];
+    SSL_CTX_LOCK(ssl_ctx->mutex);
+
+    if ((ret = x509_verify(ca_cert_ctx, cert)) != X509_VFY_ERROR_SELF_SIGNED)
+    {
+        SSL_CTX_UNLOCK(ssl_ctx->mutex);
+        x509_free(cert);        /* get rid of it */
+        ca_cert_ctx->cert[i] = NULL;
+#ifdef CONFIG_SSL_FULL_MODE
+        printf("Error: %s\n", x509_display_error(ret)); TTY_FLUSH();
+#endif
+        goto error;
+    }
+
+    SSL_CTX_UNLOCK(ssl_ctx->mutex);
+    len -= offset;
+    ret = SSL_OK;           /* ok so far */
+
+    /* recurse? */
+    if (len > 0)
+        ret = add_cert_auth(ssl_ctx, &buf[offset], len);
+
+error:
+    return ret;
+}
+
+/*
+ * Retrieve an X.509 distinguished name component
+ */
+EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
+{
+    if (ssl->x509_ctx == NULL)
+        return NULL;
+
+    switch (component)
+    {
+        case SSL_X509_CERT_COMMON_NAME:
+            return ssl->x509_ctx->cert_dn[X509_COMMON_NAME];
+
+        case SSL_X509_CERT_ORGANIZATION:
+            return ssl->x509_ctx->cert_dn[X509_ORGANIZATION];
+
+        case SSL_X509_CERT_ORGANIZATIONAL_NAME:       
+            return ssl->x509_ctx->cert_dn[X509_ORGANIZATIONAL_UNIT];
+
+        case SSL_X509_CA_CERT_COMMON_NAME:
+            return ssl->x509_ctx->ca_cert_dn[X509_COMMON_NAME];
+
+        case SSL_X509_CA_CERT_ORGANIZATION:
+            return ssl->x509_ctx->ca_cert_dn[X509_ORGANIZATION];
+
+        case SSL_X509_CA_CERT_ORGANIZATIONAL_NAME:       
+            return ssl->x509_ctx->ca_cert_dn[X509_ORGANIZATIONAL_UNIT];
+
+        default:
+            return NULL;
+    }
+}
+
+/* GBG added */
+EXP_FUNC void ssl_get_cert_fingerprints(const SSL* ssl, unsigned char* md5, unsigned char* sha1)
+{
+    if (ssl->x509_ctx == NULL) {
+        memset(md5, 0, MD5_SIZE);
+        memset(sha1, 0, SHA1_SIZE);
+        return;
+    }
+    memcpy(md5,  ssl->x509_ctx->fingerprint.md5, MD5_SIZE);
+    memcpy(sha1, ssl->x509_ctx->fingerprint.sha1, SHA1_SIZE);
+}
+
+/* /GBG added */
+
+#endif
+
+/*
+ * Find an ssl object based on the client's file descriptor.
+ */
+EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, SSL_SOCKET* client_fd)
+{
+    SSL *ssl;
+
+    SSL_CTX_LOCK(ssl_ctx->mutex);
+    ssl = ssl_ctx->head;
+
+    /* search through all the ssl entries */
+    while (ssl)
+    {
+        if (ssl->client_fd == client_fd)
+        {
+            SSL_CTX_UNLOCK(ssl_ctx->mutex);
+            return ssl;
+        }
+
+        ssl = ssl->next;
+    }
+
+    SSL_CTX_UNLOCK(ssl_ctx->mutex);
+    return NULL;
+}
+
+/*
+ * Force the client to perform its handshake again.
+ */
+EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl)
+{
+    int ret = SSL_OK;
+
+    disposable_new(ssl);
+#ifdef CONFIG_SSL_ENABLE_CLIENT
+    if (IS_SET_SSL_FLAG(SSL_IS_CLIENT))
+    {
+        ret = do_client_connect(ssl);
+    }
+    else
+#endif
+    {
+        send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 
+                g_hello_request, sizeof(g_hello_request));
+        SET_SSL_FLAG(SSL_NEED_RECORD);
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Get what we need for key info.
+ * @param cipher    [in]    The cipher information we are after
+ * @param key_size  [out]   The key size for the cipher
+ * @param iv_size   [out]   The iv size for the cipher
+ * @return  The amount of key information we need.
+ */
+static const cipher_info_t *get_cipher_info(uint8_t cipher)
+{
+    int i;
+
+    for (i = 0; i < NUM_PROTOCOLS; i++)
+    {
+        if (cipher_info[i].cipher == cipher)
+        {
+            return &cipher_info[i];
+        }
+    }
+
+    return NULL;  /* error */
+}
+
+/*
+ * Get a new ssl context for a new connection.
+ */
+SSL *ssl_new(SSL_CTX *ssl_ctx, void* client_fd)
+{
+    SSL *ssl = (SSL *)calloc(1, sizeof(SSL));
+    ssl->ssl_ctx = ssl_ctx;
+    ssl->need_bytes = SSL_RECORD_SIZE;      /* need a record */
+    ssl->client_fd = client_fd;
+    ssl->flag = SSL_NEED_RECORD;
+    ssl->bm_data = ssl->bm_all_data+BM_RECORD_OFFSET; /* space at the start */
+    ssl->hs_status = SSL_NOT_OK;            /* not connected */
+#ifdef CONFIG_ENABLE_VERIFICATION
+    ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx;
+#endif
+    disposable_new(ssl);
+
+    /* a bit hacky but saves a few bytes of memory */
+    ssl->flag |= ssl_ctx->options;
+    SSL_CTX_LOCK(ssl_ctx->mutex);
+
+    if (ssl_ctx->head == NULL)
+    {
+        ssl_ctx->head = ssl;
+        ssl_ctx->tail = ssl;
+    }
+    else
+    {
+        ssl->prev = ssl_ctx->tail;
+        ssl_ctx->tail->next = ssl;
+        ssl_ctx->tail = ssl;
+    }
+
+    SSL_CTX_UNLOCK(ssl_ctx->mutex);
+    return ssl;
+}
+
+/*
+ * Add a private key to a context.
+ */
+int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj)
+{
+    int ret = SSL_OK;
+
+    /* get the private key details */
+    if (asn1_get_private_key(ssl_obj->buf, ssl_obj->len, &ssl_ctx->rsa_ctx))
+    {
+        ret = SSL_ERROR_INVALID_KEY;
+        goto error;
+    }
+
+error:
+    return ret;
+}
+
+/** 
+ * Increment the read sequence number (as a 64 bit endian indepenent #)
+ */     
+static void increment_read_sequence(SSL *ssl)
+{
+    int i;
+
+    for (i = 7; i >= 0; i--) 
+    {       
+        if (++ssl->read_sequence[i])
+            break;
+    }
+}
+            
+/**
+ * Increment the read sequence number (as a 64 bit endian indepenent #)
+ */      
+static void increment_write_sequence(SSL *ssl)
+{        
+    int i;                  
+         
+    for (i = 7; i >= 0; i--)
+    {                       
+        if (++ssl->write_sequence[i])
+            break;
+    }                       
+}
+
+/**
+ * Work out the HMAC digest in a packet.
+ */
+static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
+        const uint8_t *buf, int buf_len, uint8_t *hmac_buf)
+{
+    int hmac_len = buf_len + 8 + SSL_RECORD_SIZE;
+    uint8_t *t_buf = (uint8_t *)alloca(hmac_len+10);
+
+    memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? 
+                    ssl->write_sequence : ssl->read_sequence, 8);
+    memcpy(&t_buf[8], hmac_header, SSL_RECORD_SIZE);
+    memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len);
+
+    ssl->cipher_info->hmac(t_buf, hmac_len, 
+            (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ? 
+                ssl->server_mac : ssl->client_mac, 
+            ssl->cipher_info->digest_size, hmac_buf);
+
+#if 0
+    print_blob("record", ssl->hmac_tx, SSL_RECORD_SIZE);
+    print_blob("buf", buf, buf_len);
+    if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE)
+    {
+        print_blob("write seq", ssl->write_sequence, 8);
+    }
+    else
+    {
+        print_blob("read seq", ssl->read_sequence, 8);
+    }
+
+    if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ)
+    {
+        print_blob("server mac", 
+                ssl->server_mac, ssl->cipher_info->digest_size);
+    }
+    else
+    {
+        print_blob("client mac", 
+                ssl->client_mac, ssl->cipher_info->digest_size);
+    }
+    print_blob("hmac", hmac_buf, SHA1_SIZE);
+#endif
+}
+
+/**
+ * Verify that the digest of a packet is correct.
+ */
+static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
+{   
+    uint8_t hmac_buf[SHA1_SIZE];
+    int hmac_offset;
+   
+    if (ssl->cipher_info->padding_size)
+    {
+        hmac_offset = read_len-buf[read_len-1]-ssl->cipher_info->digest_size-1;
+    }
+    else
+    {
+        hmac_offset = read_len - ssl->cipher_info->digest_size;
+    }
+
+    /* sanity check the offset */
+    if (hmac_offset < 0)
+    {
+        return SSL_ERROR_INVALID_HMAC;
+    }
+
+    ssl->hmac_header[3] = hmac_offset >> 8;      /* insert size */
+    ssl->hmac_header[4] = hmac_offset & 0xff;
+    add_hmac_digest(ssl, mode, ssl->hmac_header, buf, hmac_offset, hmac_buf);
+
+    if (memcmp(hmac_buf, &buf[hmac_offset], ssl->cipher_info->digest_size))
+    {
+        return SSL_ERROR_INVALID_HMAC;
+    }
+
+    return hmac_offset;
+}
+
+/**
+ * Add a packet to the end of our sent and received packets, so that we may use
+ * it to calculate the hash at the end.
+ */
+void add_packet(SSL *ssl, const uint8_t *pkt, int len)
+{
+    MD5_Update(&ssl->dc->md5_ctx, pkt, len);
+    SHA1_Update(&ssl->dc->sha1_ctx, pkt, len);
+}
+
+/**
+ * Work out the MD5 PRF.
+ */
+static void p_hash_md5(const uint8_t *sec, int sec_len, 
+        uint8_t *seed, int seed_len, uint8_t *out, int olen)
+{
+    uint8_t a1[128];
+
+    /* A(1) */
+    hmac_md5(seed, seed_len, sec, sec_len, a1);
+    memcpy(&a1[MD5_SIZE], seed, seed_len);
+    hmac_md5(a1, MD5_SIZE+seed_len, sec, sec_len, out);
+
+    while (olen > MD5_SIZE)
+    {
+        uint8_t a2[MD5_SIZE];
+        out += MD5_SIZE;
+        olen -= MD5_SIZE;
+
+        /* A(N) */
+        hmac_md5(a1, MD5_SIZE, sec, sec_len, a2);
+        memcpy(a1, a2, MD5_SIZE);
+
+        /* work out the actual hash */
+        hmac_md5(a1, MD5_SIZE+seed_len, sec, sec_len, out);
+    }
+}
+
+/**
+ * Work out the SHA1 PRF.
+ */
+static void p_hash_sha1(const uint8_t *sec, int sec_len, 
+        uint8_t *seed, int seed_len, uint8_t *out, int olen)
+{
+    uint8_t a1[128];
+
+    /* A(1) */
+    hmac_sha1(seed, seed_len, sec, sec_len, a1);
+    memcpy(&a1[SHA1_SIZE], seed, seed_len);
+    hmac_sha1(a1, SHA1_SIZE+seed_len, sec, sec_len, out);
+
+    while (olen > SHA1_SIZE)
+    {
+        uint8_t a2[SHA1_SIZE];
+        out += SHA1_SIZE;
+        olen -= SHA1_SIZE;
+
+        /* A(N) */
+        hmac_sha1(a1, SHA1_SIZE, sec, sec_len, a2);
+        memcpy(a1, a2, SHA1_SIZE);
+
+        /* work out the actual hash */
+        hmac_sha1(a1, SHA1_SIZE+seed_len, sec, sec_len, out);
+    }
+}
+
+/**
+ * Work out the PRF.
+ */
+static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
+        uint8_t *out, int olen)
+{
+    int len, i;
+    const uint8_t *S1, *S2;
+    uint8_t xbuf[256]; /* needs to be > the amount of key data */
+    uint8_t ybuf[256]; /* needs to be > the amount of key data */
+
+    len = sec_len/2;
+    S1 = sec;
+    S2 = &sec[len];
+    len += (sec_len & 1); /* add for odd, make longer */
+
+    p_hash_md5(S1, len, seed, seed_len, xbuf, olen);
+    p_hash_sha1(S2, len, seed, seed_len, ybuf, olen);
+
+    for (i = 0; i < olen; i++)
+        out[i] = xbuf[i] ^ ybuf[i];
+}
+
+/**
+ * Generate a master secret based on the client/server random data and the
+ * premaster secret.
+ */
+void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret)
+{
+    uint8_t buf[128];   /* needs to be > 13+32+32 in size */
+    strcpy((char *)buf, "master secret");
+    memcpy(&buf[13], ssl->dc->client_random, SSL_RANDOM_SIZE);
+    memcpy(&buf[45], ssl->dc->server_random, SSL_RANDOM_SIZE);
+    prf(premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
+            SSL_SECRET_SIZE);
+}
+
+/**
+ * Generate a 'random' blob of data used for the generation of keys.
+ */
+static void generate_key_block(uint8_t *client_random, uint8_t *server_random,
+        uint8_t *master_secret, uint8_t *key_block, int key_block_size)
+{
+    uint8_t buf[128];
+    strcpy((char *)buf, "key expansion");
+    memcpy(&buf[13], server_random, SSL_RANDOM_SIZE);
+    memcpy(&buf[45], client_random, SSL_RANDOM_SIZE);
+    prf(master_secret, SSL_SECRET_SIZE, buf, 77, key_block, key_block_size);
+}
+
+/** 
+ * Calculate the digest used in the finished message. This function also
+ * doubles up as a certificate verify function.
+ */
+void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
+{
+    uint8_t mac_buf[128]; 
+    uint8_t *q = mac_buf;
+    MD5_CTX md5_ctx = ssl->dc->md5_ctx;
+    SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
+
+    if (label)
+    {
+        strcpy((char *)q, label);
+        q += strlen(label);
+    }
+
+    MD5_Final(q, &md5_ctx);
+    q += MD5_SIZE;
+    
+    SHA1_Final(q, &sha1_ctx);
+    q += SHA1_SIZE;
+
+    if (label)
+    {
+        prf(ssl->dc->master_secret, SSL_SECRET_SIZE, mac_buf, (int)(q-mac_buf),
+            digest, SSL_FINISHED_HASH_SIZE);
+    }
+    else    /* for use in a certificate verify */
+    {
+        memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE);
+    }
+
+#if 0
+    printf("label: %s\n", label);
+    print_blob("master secret", ssl->dc->master_secret, 48);
+    print_blob("mac_buf", mac_buf, q-mac_buf);
+    print_blob("finished digest", digest, SSL_FINISHED_HASH_SIZE);
+#endif
+}   
+    
+/**
+ * Retrieve (and initialise) the context of a cipher.
+ */
+static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
+{
+    switch (ssl->cipher)
+    {
+#ifndef CONFIG_SSL_SKELETON_MODE
+        case SSL_AES128_SHA:
+            {
+                AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
+                AES_set_key(aes_ctx, key, iv, AES_MODE_128);
+
+                if (is_decrypt)
+                {
+                    AES_convert_key(aes_ctx);
+                }
+
+                return (void *)aes_ctx;
+            }
+
+        case SSL_AES256_SHA:
+            {
+                AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
+                AES_set_key(aes_ctx, key, iv, AES_MODE_256);
+
+                if (is_decrypt)
+                {
+                    AES_convert_key(aes_ctx);
+                }
+
+                return (void *)aes_ctx;
+            }
+            break;
+
+        case SSL_RC4_128_MD5:
+#endif
+        case SSL_RC4_128_SHA:
+            {
+                RC4_CTX *rc4_ctx = (RC4_CTX *)malloc(sizeof(RC4_CTX));
+                RC4_setup(rc4_ctx, key, 16);
+                return (void *)rc4_ctx;
+            }
+            break;
+    }
+
+    return NULL;    /* its all gone wrong */
+}
+
+/**
+ * Send a packet over the socket.
+ */
+static int send_raw_packet(SSL *ssl, uint8_t protocol)
+{
+    uint8_t *rec_buf = ssl->bm_all_data;
+    int pkt_size = SSL_RECORD_SIZE+ssl->bm_index;
+    int sent = 0;
+    int ret = SSL_OK;
+
+    rec_buf[0] = protocol;
+    rec_buf[1] = 0x03;      /* version = 3.1 (TLS) */
+    rec_buf[2] = 0x01;
+    rec_buf[3] = ssl->bm_index >> 8;
+    rec_buf[4] = ssl->bm_index & 0xff;
+
+    DISPLAY_BYTES(ssl, "sending %d bytes", ssl->bm_all_data, 
+                             pkt_size, pkt_size);
+
+    while (sent < pkt_size)
+    {
+        if ((ret = SOCKET_WRITE(ssl->client_fd, 
+                        &ssl->bm_all_data[sent], pkt_size)) < 0)
+        {
+            /*ret = SSL_ERROR_CONN_LOST*/;
+            break;
+        }
+
+        sent += ret;
+    }
+
+    SET_SSL_FLAG(SSL_NEED_RECORD);  /* reset for next time */
+    ssl->bm_index = 0;
+
+    if (protocol != PT_APP_PROTOCOL_DATA)  
+    {
+        /* always return SSL_OK during handshake */   
+        ret = SSL_OK;
+    }
+
+    return ret;
+}
+
+/**
+ * Send an encrypted packet with padding bytes if necessary.
+ */
+int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
+{
+    int msg_length = length;
+    int ret, pad_bytes = 0;
+    ssl->bm_index = msg_length;
+
+    /* if our state is bad, don't bother */
+    if (ssl->hs_status == SSL_ERROR_DEAD)
+        return SSL_ERROR_CONN_LOST;
+
+    if (in) /* has the buffer already been initialised? */
+    {
+        memcpy(ssl->bm_data, in, length);
+    }
+
+    if (IS_SET_SSL_FLAG(SSL_TX_ENCRYPTED))
+    {
+        int mode = IS_SET_SSL_FLAG(SSL_IS_CLIENT) ? 
+                            SSL_CLIENT_WRITE : SSL_SERVER_WRITE;
+        uint8_t hmac_header[SSL_RECORD_SIZE];
+
+        hmac_header[0] = protocol;
+        hmac_header[1] = 0x03;
+        hmac_header[2] = 0x01;
+        hmac_header[3] = length >> 8; 
+        hmac_header[4] = length & 0xff;
+
+        if (protocol == PT_HANDSHAKE_PROTOCOL)
+        {
+            DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
+
+            if (ssl->bm_data[0] != HS_HELLO_REQUEST)
+            {
+                add_packet(ssl, ssl->bm_data, ssl->bm_index);
+            }
+        }
+
+        /* add the packet digest */
+        msg_length += ssl->cipher_info->digest_size;
+        ssl->bm_index = msg_length;
+        add_hmac_digest(ssl, mode, hmac_header, ssl->bm_data, length, 
+                                                &ssl->bm_data[length]);
+
+        /* add padding? */
+        if (ssl->cipher_info->padding_size)
+        {
+            int last_blk_size = msg_length%ssl->cipher_info->padding_size;
+            pad_bytes = ssl->cipher_info->padding_size - last_blk_size;
+
+            /* ensure we always have at least 1 padding byte */
+            if (pad_bytes == 0)
+                pad_bytes += ssl->cipher_info->padding_size;
+
+            memset(&ssl->bm_data[msg_length], pad_bytes-1, pad_bytes);
+            msg_length += pad_bytes;
+            ssl->bm_index = msg_length;
+        }
+
+        DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_data, msg_length);
+        increment_write_sequence(ssl);
+
+        /* now encrypt the packet */
+        ssl->cipher_info->encrypt(ssl->encrypt_ctx, ssl->bm_data, 
+                                            ssl->bm_data, msg_length);
+    }
+    else if (protocol == PT_HANDSHAKE_PROTOCOL)
+    {
+        DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
+
+        if (ssl->bm_data[0] != HS_HELLO_REQUEST)
+        {
+            add_packet(ssl, ssl->bm_data, ssl->bm_index);
+        }
+    }
+
+    if ((ret = send_raw_packet(ssl, protocol)) <= 0)
+        return ret;
+
+    return length;  /* just return what we wanted to send */
+}
+
+/**
+ * Work out the cipher keys we are going to use for this session based on the
+ * master secret.
+ */
+static void set_key_block(SSL *ssl, int is_write)
+{
+    const cipher_info_t *ciph_info = get_cipher_info(ssl->cipher);
+    uint8_t *q;
+    uint8_t client_key[32], server_key[32]; /* big enough for AES256 */
+    uint8_t client_iv[16], server_iv[16];   /* big enough for AES128/256 */
+    int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
+
+    /* only do once in a handshake */
+    if (ssl->dc->key_block == NULL)
+    {
+        ssl->dc->key_block = (uint8_t *)malloc(ciph_info->key_block_size);
+
+#if 0
+        print_blob("client", ssl->dc->client_random, 32);
+        print_blob("server", ssl->dc->server_random, 32);
+        print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
+#endif
+        generate_key_block(ssl->dc->client_random, ssl->dc->server_random,
+            ssl->dc->master_secret, ssl->dc->key_block, 
+            ciph_info->key_block_size);
+#if 0
+        print_blob("keyblock", ssl->key_block, ciph_info->key_block_size);
+#endif
+    }
+
+    q = ssl->dc->key_block;
+
+    if ((is_client && is_write) || (!is_client && !is_write))
+    {
+        memcpy(ssl->client_mac, q, ciph_info->digest_size);
+    }
+
+    q += ciph_info->digest_size;
+
+    if ((!is_client && is_write) || (is_client && !is_write))
+    {
+        memcpy(ssl->server_mac, q, ciph_info->digest_size);
+    }
+
+    q += ciph_info->digest_size;
+    memcpy(client_key, q, ciph_info->key_size);
+    q += ciph_info->key_size;
+    memcpy(server_key, q, ciph_info->key_size);
+    q += ciph_info->key_size;
+
+#ifndef CONFIG_SSL_SKELETON_MODE 
+    if (ciph_info->iv_size)    /* RC4 has no IV, AES does */
+    {
+        memcpy(client_iv, q, ciph_info->iv_size);
+        q += ciph_info->iv_size;
+        memcpy(server_iv, q, ciph_info->iv_size);
+        q += ciph_info->iv_size;
+    }
+#endif
+
+    free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx);
+
+    /* now initialise the ciphers */
+    if (is_client)
+    {
+        finished_digest(ssl, server_finished, ssl->dc->final_finish_mac);
+
+        if (is_write)
+            ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0);
+        else
+            ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1);
+    }
+    else
+    {
+        finished_digest(ssl, client_finished, ssl->dc->final_finish_mac);
+
+        if (is_write)
+            ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0);
+        else
+            ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1);
+    }
+
+    ssl->cipher_info = ciph_info;
+}
+
+/**
+ * Read the SSL connection.
+ */
+int basic_read(SSL *ssl, uint8_t **in_data)
+{
+    int ret = SSL_OK;
+    int read_len, is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
+    uint8_t *buf = ssl->bm_data;
+
+    read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_read_index], 
+                            ssl->need_bytes-ssl->got_bytes);
+
+    /* connection has gone, so die */
+    if (read_len <= 0)
+    {
+        ret = read_len;
+        ssl->hs_status = SSL_ERROR_DEAD;  /* make sure it stays dead */
+        goto error;
+    }
+
+    DISPLAY_BYTES(ssl, "received %d bytes", 
+            &ssl->bm_data[ssl->bm_read_index], read_len, read_len);
+
+    ssl->got_bytes += read_len;
+    ssl->bm_read_index += read_len;
+
+    /* haven't quite got what we want, so try again later */
+    if (ssl->got_bytes < ssl->need_bytes)
+        return SSL_OK;
+
+    read_len = ssl->got_bytes;
+    ssl->got_bytes = 0;
+
+    if (IS_SET_SSL_FLAG(SSL_NEED_RECORD))
+    {
+        /* check for sslv2 "client hello" */
+        if (buf[0] & 0x80 && buf[2] == 1 && buf[3] == 0x03)
+        {
+#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
+            DISPLAY_BYTES(ssl, "ssl2 record", buf, 5);
+            add_packet(ssl, &buf[2], 3);
+            ret = process_sslv23_client_hello(ssl); 
+#else
+            printf("Error: no SSLv23 handshaking allowed\n"); TTY_FLUSH();
+            ret = SSL_ERROR_NOT_SUPPORTED;
+#endif
+            goto error; /* not an error - just get out of here */
+        }
+
+        ssl->need_bytes = (buf[3] << 8) + buf[4];
+
+        /* do we violate the spec with the message size?  */
+        if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET)
+        {
+            ret = SSL_ERROR_INVALID_PROT_MSG;              
+            goto error;
+        }
+
+        CLR_SSL_FLAG(SSL_NEED_RECORD);
+        memcpy(ssl->hmac_header, buf, 3);       /* store for hmac */
+        ssl->record_type = buf[0];
+        goto error;                         /* no error, we're done */
+    }
+
+    /* for next time - just do it now in case of an error */
+    SET_SSL_FLAG(SSL_NEED_RECORD);
+    ssl->need_bytes = SSL_RECORD_SIZE;
+
+    /* decrypt if we need to */
+    if (IS_SET_SSL_FLAG(SSL_RX_ENCRYPTED))
+    {
+        ssl->cipher_info->decrypt(ssl->decrypt_ctx, buf, buf, read_len);
+        read_len = verify_digest(ssl, 
+                is_client ? SSL_CLIENT_READ : SSL_SERVER_READ, buf, read_len);
+
+        /* does the hmac work? */
+        if (read_len < 0)
+        {
+            ret = read_len;
+            goto error;
+        }
+
+        DISPLAY_BYTES(ssl, "decrypted", buf, read_len);
+        increment_read_sequence(ssl);
+    }
+
+    /* The main part of the SSL packet */
+    switch (ssl->record_type)
+    {
+        case PT_HANDSHAKE_PROTOCOL:
+            ssl->dc->bm_proc_index = 0;
+            ret = do_handshake(ssl, buf, read_len);
+            break;
+
+        case PT_CHANGE_CIPHER_SPEC:
+            if (ssl->next_state != HS_FINISHED)
+            {
+                ret = SSL_ERROR_INVALID_HANDSHAKE;
+                goto error;
+            }
+
+            /* all encrypted from now on */
+            SET_SSL_FLAG(SSL_RX_ENCRYPTED);
+            set_key_block(ssl, 0);
+            memset(ssl->read_sequence, 0, 8);
+            break;
+
+        case PT_APP_PROTOCOL_DATA:
+            if (in_data)
+            {
+                *in_data = ssl->bm_data;   /* point to the work buffer */
+                (*in_data)[read_len] = 0;  /* null terminate just in case */
+            }
+
+            ret = read_len;
+            break;
+
+        case PT_ALERT_PROTOCOL:
+            /* return the alert # with alert bit set */
+            ret = -buf[1]; 
+            DISPLAY_ALERT(ssl, buf[1]);
+            break;
+
+        default:
+            ret = SSL_ERROR_INVALID_PROT_MSG;
+            break;
+    }
+
+error:
+    ssl->bm_read_index = 0;          /* reset to go again */
+
+    if (ret < SSL_OK && in_data)/* if all wrong, then clear this buffer ptr */
+        *in_data = NULL;
+
+    return ret;
+}
+
+/**
+ * Do some basic checking of data and then perform the appropriate handshaking.
+ */
+static int do_handshake(SSL *ssl, uint8_t *buf, int read_len)
+{
+    int hs_len = (buf[2]<<8) + buf[3];
+    uint8_t handshake_type = buf[0];
+    int ret = SSL_OK;
+    int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
+
+    /* some integrity checking on the handshake */
+    PARANOIA_CHECK(read_len-SSL_HS_HDR_SIZE, hs_len);
+
+    if (handshake_type != ssl->next_state)
+    {
+        /* handle a special case on the client */
+        if (!is_client || handshake_type != HS_CERT_REQ ||
+                        ssl->next_state != HS_SERVER_HELLO_DONE)
+        {
+            ret = SSL_ERROR_INVALID_HANDSHAKE;
+            goto error;
+        }
+    }
+
+    hs_len += SSL_HS_HDR_SIZE;  /* adjust for when adding packets */
+    ssl->bm_index = hs_len;     /* store the size and check later */
+    DISPLAY_STATE(ssl, 0, handshake_type, 0);
+
+    if (handshake_type != HS_CERT_VERIFY && handshake_type != HS_HELLO_REQUEST)
+        add_packet(ssl, buf, hs_len); 
+
+#if defined(CONFIG_SSL_ENABLE_CLIENT)
+    ret = is_client ? 
+        do_clnt_handshake(ssl, handshake_type, buf, hs_len) :
+        do_svr_handshake(ssl, handshake_type, buf, hs_len);
+#else
+    ret = do_svr_handshake(ssl, handshake_type, buf, hs_len);
+#endif
+
+    /* just use recursion to get the rest */
+    if (hs_len < read_len && ret == SSL_OK)
+        ret = do_handshake(ssl, &buf[hs_len], read_len-hs_len);
+
+error:
+    return ret;
+}
+
+/**
+ * Sends the change cipher spec message. We have just read a finished message
+ * from the client.
+ */
+int send_change_cipher_spec(SSL *ssl)
+{
+    int ret = send_packet(ssl, PT_CHANGE_CIPHER_SPEC, 
+            g_chg_cipher_spec_pkt, sizeof(g_chg_cipher_spec_pkt));
+    SET_SSL_FLAG(SSL_TX_ENCRYPTED);
+    set_key_block(ssl, 1);
+    memset(ssl->write_sequence, 0, 8);
+    return ret;
+}
+
+/**
+ * Send a "finished" message
+ */
+int send_finished(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+
+    buf[0] = HS_FINISHED;
+    buf[1] = 0;
+    buf[2] = 0;
+    buf[3] = SSL_FINISHED_HASH_SIZE;
+
+    /* now add the finished digest mac (12 bytes) */
+    finished_digest(ssl, 
+        IS_SET_SSL_FLAG(SSL_IS_CLIENT) ?
+                    client_finished : server_finished, &buf[4]);
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+    /* store in the session cache */
+    if (!IS_SET_SSL_FLAG(SSL_SESSION_RESUME) && ssl->ssl_ctx->num_sessions)
+    {
+        memcpy(ssl->session->master_secret,
+                ssl->dc->master_secret, SSL_SECRET_SIZE);
+    }
+#endif
+
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
+                                NULL, SSL_FINISHED_HASH_SIZE+4);
+}
+
+/**
+ * Send an alert message.
+ * Return 1 if the alert was an "error".
+ */
+int send_alert(SSL *ssl, int error_code)
+{
+    int alert_num = 0;
+    int is_warning = 0;
+    uint8_t buf[2];
+
+    /* Don't bother we're already dead */
+    if (ssl->hs_status == SSL_ERROR_DEAD)
+    {
+        return SSL_ERROR_CONN_LOST;
+    }
+
+#ifdef CONFIG_SSL_FULL_MODE
+    if (IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
+        ssl_display_error(error_code);
+#endif
+
+    switch (error_code)
+    {
+        case SSL_ALERT_CLOSE_NOTIFY:
+            is_warning = 1;
+            alert_num = SSL_ALERT_CLOSE_NOTIFY;
+            break;
+
+        case SSL_ERROR_CONN_LOST:       /* don't send alert just yet */
+            is_warning = 1;
+            break;
+
+        case SSL_ERROR_INVALID_HANDSHAKE:
+        case SSL_ERROR_INVALID_PROT_MSG:
+            alert_num = SSL_ALERT_HANDSHAKE_FAILURE;
+            break;
+
+        case SSL_ERROR_INVALID_HMAC:
+        case SSL_ERROR_FINISHED_INVALID:
+            alert_num = SSL_ALERT_BAD_RECORD_MAC;
+            break;
+
+        case SSL_ERROR_INVALID_VERSION:
+            alert_num = SSL_ALERT_INVALID_VERSION;
+            break;
+
+        case SSL_ERROR_INVALID_SESSION:
+        case SSL_ERROR_NO_CIPHER:
+        case SSL_ERROR_INVALID_KEY:
+            alert_num = SSL_ALERT_ILLEGAL_PARAMETER;
+            break;
+
+        case SSL_ERROR_BAD_CERTIFICATE:
+            alert_num = SSL_ALERT_BAD_CERTIFICATE;
+            break;
+
+        default:
+            /* a catch-all for any badly verified certificates */
+            alert_num = (error_code <= SSL_X509_OFFSET) ?  
+                SSL_ALERT_BAD_CERTIFICATE : SSL_ALERT_UNEXPECTED_MESSAGE;
+            break;
+    }
+
+    buf[0] = is_warning ? 1 : 2;
+    buf[1] = alert_num;
+    send_packet(ssl, PT_ALERT_PROTOCOL, buf, sizeof(buf));
+    DISPLAY_ALERT(ssl, alert_num);
+    return is_warning ? 0 : 1;
+}
+
+/**
+ * Process a client finished message.
+ */
+int process_finished(SSL *ssl, int hs_len)
+{
+    uint8_t *buf = ssl->bm_data;
+    int ret = SSL_OK;
+    int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
+    int resume = IS_SET_SSL_FLAG(SSL_SESSION_RESUME);
+
+    PARANOIA_CHECK(ssl->bm_index, SSL_FINISHED_HASH_SIZE+4);
+
+    /* check that we all work before we continue */
+    if (memcmp(ssl->dc->final_finish_mac, &buf[4], SSL_FINISHED_HASH_SIZE))
+        return SSL_ERROR_FINISHED_INVALID;
+
+    if ((!is_client && !resume) || (is_client && resume))
+    {
+        if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
+            ret = send_finished(ssl);
+    }
+
+    /* if we ever renegotiate */
+    ssl->next_state = is_client ? HS_HELLO_REQUEST : HS_CLIENT_HELLO;  
+    ssl->hs_status = ret;  /* set the final handshake status */
+
+error:
+    return ret;
+}
+
+/**
+ * Send a certificate.
+ */
+int send_certificate(SSL *ssl)
+{
+    int i = 0;
+    uint8_t *buf = ssl->bm_data;
+    int offset = 7;
+    int chain_length;
+
+    buf[0] = HS_CERTIFICATE;
+    buf[1] = 0;
+    buf[4] = 0;
+
+    while (i < ssl->ssl_ctx->chain_length)
+    {
+        SSL_CERT *cert = &ssl->ssl_ctx->certs[i];
+        buf[offset++] = 0;        
+        buf[offset++] = cert->size >> 8;        /* cert 1 length */
+        buf[offset++] = cert->size & 0xff;
+        memcpy(&buf[offset], cert->buf, cert->size);
+        offset += cert->size;
+        i++;
+    }
+
+    chain_length = offset - 7;
+    buf[5] = chain_length >> 8;        /* cert chain length */
+    buf[6] = chain_length & 0xff;
+    chain_length += 3;
+    buf[2] = chain_length >> 8;        /* handshake length */
+    buf[3] = chain_length & 0xff;
+    ssl->bm_index = offset;
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
+}
+
+/**
+ * Create a blob of memory that we'll get rid of once the handshake is
+ * complete.
+ */
+void disposable_new(SSL *ssl)
+{
+    if (ssl->dc == NULL)
+    {
+        ssl->dc = (DISPOSABLE_CTX *)calloc(1, sizeof(DISPOSABLE_CTX));
+        MD5_Init(&ssl->dc->md5_ctx);
+        SHA1_Init(&ssl->dc->sha1_ctx);
+    }
+}
+
+/**
+ * Remove the temporary blob of memory.
+ */
+void disposable_free(SSL *ssl)
+{
+    if (ssl->dc)
+    {
+	    free(ssl->dc->key_block);
+        memset(ssl->dc, 0, sizeof(DISPOSABLE_CTX));
+        free(ssl->dc);
+        ssl->dc = NULL;
+    }
+
+}
+
+#ifndef CONFIG_SSL_SKELETON_MODE     /* no session resumption in this mode */
+/**
+ * Find if an existing session has the same session id. If so, use the
+ * master secret from this session for session resumption.
+ */
+SSL_SESS *ssl_session_update(int max_sessions, SSL_SESS *ssl_sessions[], 
+        SSL *ssl, const uint8_t *session_id)
+{
+    time_t tm = time(NULL);
+    time_t oldest_sess_time = tm;
+    SSL_SESS *oldest_sess = NULL;
+    int i;
+
+    /* no sessions? Then bail */
+    if (max_sessions == 0)
+        return NULL;
+
+    SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+    if (session_id)
+    {
+        for (i = 0; i < max_sessions; i++)
+        {
+            if (ssl_sessions[i])
+            {
+                /* kill off any expired sessions */
+                if (tm > ssl_sessions[i]->conn_time + SSL_EXPIRY_TIME)
+                {
+                    session_free(ssl_sessions, i);
+                    continue;
+                }
+
+                /* if the session id matches, it must still be less than 
+                   the expiry time */
+                if (memcmp(ssl_sessions[i]->session_id, session_id,
+                                                SSL_SESSION_ID_SIZE) == 0)
+                {
+                    ssl->session_index = i;
+                    memcpy(ssl->dc->master_secret, 
+                            ssl_sessions[i]->master_secret, SSL_SECRET_SIZE);
+                    SET_SSL_FLAG(SSL_SESSION_RESUME);
+                    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+                    return ssl_sessions[i];  /* a session was found */
+                }
+            }
+        }
+    }
+
+    /* If we've got here, no matching session was found - so create one */
+    for (i = 0; i < max_sessions; i++)
+    {
+        if (ssl_sessions[i] == NULL)
+        {
+            /* perfect, this will do */
+            ssl_sessions[i] = (SSL_SESS *)calloc(1, sizeof(SSL_SESS));
+            ssl_sessions[i]->conn_time = tm;
+            ssl->session_index = i;
+            SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+            return ssl_sessions[i]; /* return the session object */
+        }
+        else if (ssl_sessions[i]->conn_time <= oldest_sess_time)
+        {
+            /* find the oldest session */
+            oldest_sess_time = ssl_sessions[i]->conn_time;
+            oldest_sess = ssl_sessions[i];
+            ssl->session_index = i;
+        }
+    }
+
+    /* ok, we've used up all of our sessions. So blow the oldest session away */
+    oldest_sess->conn_time = tm;
+    memset(oldest_sess->session_id, 0, sizeof(SSL_SESSION_ID_SIZE));
+    memset(oldest_sess->master_secret, 0, sizeof(SSL_SECRET_SIZE));
+    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+    return oldest_sess;
+}
+
+/**
+ * Free an existing session.
+ */
+static void session_free(SSL_SESS *ssl_sessions[], int sess_index)
+{
+    if (ssl_sessions[sess_index])
+    {
+        free(ssl_sessions[sess_index]);
+        ssl_sessions[sess_index] = NULL;
+    }
+}
+
+/**
+ * This ssl object doesn't want this session anymore.
+ */
+void kill_ssl_session(SSL_SESS **ssl_sessions, SSL *ssl)
+{
+    SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+
+    if (ssl->ssl_ctx->num_sessions)
+    {
+        session_free(ssl_sessions, ssl->session_index);
+        ssl->session = NULL;
+    }
+
+    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+}
+#endif /* CONFIG_SSL_SKELETON_MODE */
+
+/*
+ * Get the session id for a handshake. This will be a 32 byte sequence.
+ */
+EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl)
+{
+    return ssl->session_id;
+}
+
+/*
+ * Get the session id size for a handshake. 
+ */
+EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl)
+{
+    return ssl->sess_id_size;
+}
+
+/*
+ * Return the cipher id (in the SSL form).
+ */
+EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl)
+{
+    return ssl->cipher;
+}
+
+/*
+ * Return the status of the handshake.
+ */
+EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl)
+{
+    return ssl->hs_status;
+}
+
+/*
+ * Retrieve various parameters about the SSL engine.
+ */
+EXP_FUNC int STDCALL ssl_get_config(int offset)
+{
+    switch (offset)
+    {
+        /* return the appropriate build mode */
+        case SSL_BUILD_MODE:
+#if defined(CONFIG_SSL_FULL_MODE)
+            return SSL_BUILD_FULL_MODE;
+#elif defined(CONFIG_SSL_ENABLE_CLIENT)
+            return SSL_BUILD_ENABLE_CLIENT;
+#elif defined(CONFIG_ENABLE_VERIFICATION)
+            return SSL_BUILD_ENABLE_VERIFICATION;
+#elif defined(CONFIG_SSL_SERVER_ONLY )
+            return SSL_BUILD_SERVER_ONLY;
+#else 
+            return SSL_BUILD_SKELETON_MODE;
+#endif
+
+        case SSL_MAX_CERT_CFG_OFFSET:
+            return CONFIG_SSL_MAX_CERTS;
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+        case SSL_MAX_CA_CERT_CFG_OFFSET:
+            return CONFIG_X509_MAX_CA_CERTS;
+#endif
+#ifdef CONFIG_SSL_HAS_PEM
+        case SSL_HAS_PEM:
+            return 1;
+#endif
+        default:
+            return 0;
+    }
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * Authenticate a received certificate.
+ */
+EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
+{
+    int ret;
+    SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+    ret = x509_verify(ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
+    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+
+    if (ret)        /* modify into an SSL error type */
+    {
+        ret = SSL_X509_ERROR(ret);
+    }
+
+    return ret;
+}
+
+/**
+ * Process a certificate message.
+ */
+int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
+{
+    int ret = SSL_OK;
+    uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
+    int pkt_size = ssl->bm_index;
+    int cert_size, offset = 5;
+    int total_cert_size = (buf[offset]<<8) + buf[offset+1];
+    int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
+    X509_CTX **chain = x509_ctx;
+    offset += 2;
+
+    PARANOIA_CHECK(total_cert_size, offset);
+
+    while (offset < total_cert_size)
+    {
+        offset++;       /* skip empty char */
+        cert_size = (buf[offset]<<8) + buf[offset+1];
+        offset += 2;
+        
+        if (x509_new(&buf[offset], NULL, chain))
+        {
+            ret = SSL_ERROR_BAD_CERTIFICATE;
+            goto error;
+        }
+
+        chain = &((*chain)->next);
+        offset += cert_size;
+    }
+
+    PARANOIA_CHECK(pkt_size, offset);
+
+    /* if we are client we can do the verify now or later */
+    if (is_client && !IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER))
+    {
+        ret = ssl_verify_cert(ssl);
+    }
+
+    DISPLAY_CERT(ssl, *x509_ctx);
+    ssl->next_state = is_client ? HS_SERVER_HELLO_DONE : HS_CLIENT_KEY_XCHG;
+    ssl->dc->bm_proc_index += offset;
+error:
+    return ret;
+}
+
+#endif /* CONFIG_SSL_CERT_VERIFICATION */
+
+/**
+ * Debugging routine to display SSL handshaking stuff.
+ */
+#ifdef CONFIG_SSL_FULL_MODE
+/**
+ * Debugging routine to display SSL states.
+ */
+void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok)
+{
+    const char *str;
+
+    if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
+        return;
+
+    printf(not_ok ? "Error - invalid State:\t" : "State:\t");
+    printf(is_send ? "sending " : "receiving ");
+
+    switch (state)
+    {
+        case HS_HELLO_REQUEST:
+            str = "Hello Request (0)";
+            break;
+
+        case HS_CLIENT_HELLO:
+            str = "Client Hello (1)";
+            break;
+
+        case HS_SERVER_HELLO:
+            str = "Server Hello (2)";
+            break;
+
+        case HS_CERTIFICATE:
+            str = "Certificate (11)";
+            break;
+
+        case HS_SERVER_KEY_XCHG:
+            str = "Certificate Request (12)";
+            break;
+
+        case HS_CERT_REQ:
+            str = "Certificate Request (13)";
+            break;
+
+        case HS_SERVER_HELLO_DONE:
+            str = "Server Hello Done (14)";
+            break;
+
+        case HS_CERT_VERIFY:
+            str = "Certificate Verify (15)";
+            break;
+
+        case HS_CLIENT_KEY_XCHG:
+            str = "Client Key Exchange (16)";
+            break;
+
+        case HS_FINISHED:
+            str = "Finished (16)";
+            break;
+
+        default:
+            str = "Error (Unknown)";
+            
+            break;
+    }
+
+    printf("%s\n", str);
+    TTY_FLUSH();
+}
+
+/**
+ * Debugging routine to display X509 certificates.
+ */
+void DISPLAY_CERT(SSL *ssl, const X509_CTX *x509_ctx)
+{
+    if (!IS_SET_SSL_FLAG(SSL_DISPLAY_CERTS))
+        return;
+
+    x509_print(x509_ctx, ssl->ssl_ctx->ca_cert_ctx);
+    TTY_FLUSH();
+}
+
+/**
+ * Debugging routine to display RSA objects
+ */
+void DISPLAY_RSA(SSL *ssl, const RSA_CTX *rsa_ctx)
+{
+    if (!IS_SET_SSL_FLAG(SSL_DISPLAY_RSA))
+        return;
+
+    RSA_print(rsa_ctx);
+    TTY_FLUSH();
+}
+
+/**
+ * Debugging routine to display SSL handshaking bytes.
+ */
+void DISPLAY_BYTES(SSL *ssl, const char *format, 
+        const uint8_t *data, int size, ...)
+{
+    va_list(ap);
+
+    if (!IS_SET_SSL_FLAG(SSL_DISPLAY_BYTES))
+        return;
+
+    va_start(ap, size);
+    print_blob(format, data, size, va_arg(ap, char *));
+    va_end(ap);
+    TTY_FLUSH();
+}
+
+/**
+ * Debugging routine to display SSL handshaking errors.
+ */
+EXP_FUNC void STDCALL ssl_display_error(int error_code)
+{
+    if (error_code == SSL_OK)
+        return;
+
+    printf("Error: ");
+
+    /* X509 error? */
+    if (error_code < SSL_X509_OFFSET)
+    {
+        printf("%s\n", x509_display_error(error_code - SSL_X509_OFFSET));
+        return;
+    }
+
+    /* SSL alert error code */
+    if (error_code > SSL_ERROR_CONN_LOST)
+    {
+        printf("SSL error %d\n", -error_code);
+        return;
+    }
+
+    switch (error_code)
+    {
+        case SSL_ERROR_DEAD:
+            printf("connection dead");
+            break;
+
+        case SSL_ERROR_INVALID_HANDSHAKE:
+            printf("invalid handshake");
+            break;
+
+        case SSL_ERROR_INVALID_PROT_MSG:
+            printf("invalid protocol message");
+            break;
+
+        case SSL_ERROR_INVALID_HMAC:
+            printf("invalid mac");
+            break;
+
+        case SSL_ERROR_INVALID_VERSION:
+            printf("invalid version");
+            break;
+
+        case SSL_ERROR_INVALID_SESSION:
+            printf("invalid session");
+            break;
+
+        case SSL_ERROR_NO_CIPHER:
+            printf("no cipher");
+            break;
+
+        case SSL_ERROR_CONN_LOST:
+            printf("connection lost");
+            break;
+
+        case SSL_ERROR_BAD_CERTIFICATE:
+            printf("bad certificate");
+            break;
+
+        case SSL_ERROR_INVALID_KEY:
+            printf("invalid key");
+            break;
+
+        case SSL_ERROR_FINISHED_INVALID:
+            printf("finished invalid");
+            break;
+
+        case SSL_ERROR_NO_CERT_DEFINED:
+            printf("no certificate defined");
+            break;
+
+        case SSL_ERROR_NOT_SUPPORTED:
+            printf("Option not supported");
+            break;
+
+        default:
+            printf("undefined as yet - %d", error_code);
+            break;
+    }
+
+    printf("\n");
+    TTY_FLUSH();
+}
+
+/**
+ * Debugging routine to display alerts.
+ */
+void DISPLAY_ALERT(SSL *ssl, int alert)
+{
+    if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
+        return;
+
+    printf("Alert: ");
+
+    switch (alert)
+    {
+        case SSL_ALERT_CLOSE_NOTIFY:
+            printf("close notify");
+            break;
+
+        case SSL_ALERT_INVALID_VERSION:
+            printf("invalid version");
+            break;
+
+        case SSL_ALERT_BAD_CERTIFICATE:
+            printf("bad certificate");
+            break;
+
+        case SSL_ALERT_UNEXPECTED_MESSAGE:
+            printf("unexpected message");
+            break;
+
+        case SSL_ALERT_BAD_RECORD_MAC:
+            printf("bad record mac");
+            break;
+
+        case SSL_ALERT_HANDSHAKE_FAILURE:
+            printf("handshake failure");
+            break;
+
+        case SSL_ALERT_ILLEGAL_PARAMETER:
+            printf("illegal parameter");
+            break;
+
+        case SSL_ALERT_DECODE_ERROR:
+            printf("decode error");
+            break;
+
+        case SSL_ALERT_DECRYPT_ERROR:
+            printf("decrypt error");
+            break;
+
+        default:
+            printf("alert - (unknown %d)", alert);
+            break;
+    }
+
+    printf("\n");
+    TTY_FLUSH();
+}
+
+#endif /* CONFIG_SSL_FULL_MODE */
+
+/**
+ * Return the version of this library.
+ */
+EXP_FUNC const char  * STDCALL ssl_version()
+{
+    static const char * axtls_version = AXTLS_VERSION;
+    return axtls_version;
+}
+
+/**
+ * Enable the various language bindings to work regardless of the
+ * configuration - they just return an error statement and a bad return code.
+ */
+#if !defined(CONFIG_SSL_FULL_MODE)
+EXP_FUNC void STDCALL ssl_display_error(int error_code) {}
+#endif
+
+#ifdef CONFIG_BINDINGS
+#if !defined(CONFIG_SSL_ENABLE_CLIENT)
+EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
+        uint8_t *session_id, uint8_t sess_id_size)
+{
+    printf(unsupported_str);
+    return NULL;
+}
+#endif
+
+#if !defined(CONFIG_SSL_CERT_VERIFICATION)
+EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
+{
+    printf(unsupported_str);
+    return -1;
+}
+
+EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
+{
+    printf(unsupported_str);
+    return NULL;
+}
+
+#endif  /* CONFIG_SSL_CERT_VERIFICATION */
+
+#endif /* CONFIG_BINDINGS */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file tls1.h
+ *
+ * @brief The definitions for the TLS library.
+ */
+#ifndef HEADER_SSL_LIB_H
+#define HEADER_SSL_LIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "version.h"
+#include "crypto.h"
+#include "os_port.h"
+#include "crypto_misc.h"
+
+#define SSL_RANDOM_SIZE             32
+#define SSL_SECRET_SIZE             48
+#define SSL_FINISHED_HASH_SIZE      12
+#define SSL_RECORD_SIZE             5
+#define SSL_SERVER_READ             0
+#define SSL_SERVER_WRITE            1
+#define SSL_CLIENT_READ             2
+#define SSL_CLIENT_WRITE            3
+#define SSL_HS_HDR_SIZE             4
+
+/* the flags we use while establishing a connection */
+#define SSL_NEED_RECORD             0x0001
+#define SSL_TX_ENCRYPTED            0x0002 
+#define SSL_RX_ENCRYPTED            0x0004
+#define SSL_SESSION_RESUME          0x0008
+#define SSL_IS_CLIENT               0x0010
+#define SSL_HAS_CERT_REQ            0x0020
+
+/* some macros to muck around with flag bits */
+#define SET_SSL_FLAG(A)             (ssl->flag |= A)
+#define CLR_SSL_FLAG(A)             (ssl->flag &= ~A)
+#define IS_SET_SSL_FLAG(A)          (ssl->flag & A)
+
+#define MAX_KEY_BYTE_SIZE           512     /* for a 4096 bit key */
+#define RT_MAX_PLAIN_LENGTH         16384
+#define RT_EXTRA                    1024
+#define BM_RECORD_OFFSET            5
+
+#ifdef CONFIG_SSL_SKELETON_MODE
+#define NUM_PROTOCOLS               1
+#else
+#define NUM_PROTOCOLS               4
+#endif
+
+#define PARANOIA_CHECK(A, B)        if (A < B) { \
+    ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
+
+/* protocol types */
+enum
+{
+    PT_CHANGE_CIPHER_SPEC = 20,
+    PT_ALERT_PROTOCOL,
+    PT_HANDSHAKE_PROTOCOL,
+    PT_APP_PROTOCOL_DATA
+};
+
+/* handshaking types */
+enum
+{
+    HS_HELLO_REQUEST,
+    HS_CLIENT_HELLO,
+    HS_SERVER_HELLO,
+    HS_CERTIFICATE = 11,
+    HS_SERVER_KEY_XCHG,
+    HS_CERT_REQ,
+    HS_SERVER_HELLO_DONE,
+    HS_CERT_VERIFY,
+    HS_CLIENT_KEY_XCHG,
+    HS_FINISHED = 20
+};
+
+typedef struct 
+{
+    uint8_t cipher;
+    uint8_t key_size;
+    uint8_t iv_size;
+    uint8_t key_block_size;
+    uint8_t padding_size;
+    uint8_t digest_size;
+    hmac_func hmac;
+    crypt_func encrypt;
+    crypt_func decrypt;
+} cipher_info_t;
+
+struct _SSLObjLoader 
+{
+    uint8_t *buf;
+    int len;
+};
+
+typedef struct _SSLObjLoader SSLObjLoader;
+
+typedef struct 
+{
+    time_t conn_time;
+    uint8_t session_id[SSL_SESSION_ID_SIZE];
+    uint8_t master_secret[SSL_SECRET_SIZE];
+} SSL_SESS;
+
+typedef struct
+{
+    uint8_t *buf;
+    int size;
+} SSL_CERT;
+
+typedef struct
+{
+    MD5_CTX md5_ctx;
+    SHA1_CTX sha1_ctx;
+    uint8_t final_finish_mac[SSL_FINISHED_HASH_SIZE];
+    uint8_t *key_block;
+    uint8_t master_secret[SSL_SECRET_SIZE];
+    uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
+    uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
+    uint16_t bm_proc_index;
+} DISPOSABLE_CTX;
+
+struct _SSL
+{
+    uint32_t flag;
+    uint16_t need_bytes;
+    uint16_t got_bytes;
+    uint8_t record_type;
+    uint8_t cipher;
+    uint8_t sess_id_size;
+    int16_t next_state;
+    int16_t hs_status;
+    DISPOSABLE_CTX *dc;         /* temporary data which we'll get rid of soon */
+    SSL_SOCKET* client_fd;
+    const cipher_info_t *cipher_info;
+    void *encrypt_ctx;
+    void *decrypt_ctx;
+    uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA];
+    uint8_t *bm_data;
+    uint16_t bm_index;
+    uint16_t bm_read_index;
+    struct _SSL *next;                  /* doubly linked list */
+    struct _SSL *prev;
+    struct _SSL_CTX *ssl_ctx;           /* back reference to a clnt/svr ctx */
+#ifndef CONFIG_SSL_SKELETON_MODE
+    uint16_t session_index;
+    SSL_SESS *session;
+#endif
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    X509_CTX *x509_ctx;
+#endif
+
+    uint8_t session_id[SSL_SESSION_ID_SIZE]; 
+    uint8_t client_mac[SHA1_SIZE];  /* for HMAC verification */
+    uint8_t server_mac[SHA1_SIZE];  /* for HMAC verification */
+    uint8_t read_sequence[8];       /* 64 bit sequence number */
+    uint8_t write_sequence[8];      /* 64 bit sequence number */
+    uint8_t hmac_header[SSL_RECORD_SIZE];    /* rx hmac */
+};
+
+typedef struct _SSL SSL;
+
+struct _SSL_CTX
+{
+    uint32_t options;
+    uint8_t chain_length;
+    RSA_CTX *rsa_ctx;
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    CA_CERT_CTX *ca_cert_ctx;
+#endif
+    SSL *head;
+    SSL *tail;
+    SSL_CERT certs[CONFIG_SSL_MAX_CERTS];
+#ifndef CONFIG_SSL_SKELETON_MODE
+    uint16_t num_sessions;
+    SSL_SESS **ssl_sessions;
+#endif
+#ifdef CONFIG_SSL_CTX_MUTEXING
+    SSL_CTX_MUTEX_TYPE mutex;
+#endif
+#ifdef CONFIG_OPENSSL_COMPATIBLE
+    void *bonus_attr;
+#endif
+};
+
+typedef struct _SSL_CTX SSL_CTX;
+
+/* backwards compatibility */
+typedef struct _SSL_CTX SSLCTX;
+
+extern const uint8_t ssl_prot_prefs[NUM_PROTOCOLS];
+
+SSL *ssl_new(SSL_CTX *ssl_ctx, void* client_fd);
+void disposable_new(SSL *ssl);
+void disposable_free(SSL *ssl);
+int send_packet(SSL *ssl, uint8_t protocol, 
+        const uint8_t *in, int length);
+int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
+int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
+int process_finished(SSL *ssl, int hs_len);
+int process_sslv23_client_hello(SSL *ssl);
+int send_alert(SSL *ssl, int error_code);
+int send_finished(SSL *ssl);
+int send_certificate(SSL *ssl);
+int basic_read(SSL *ssl, uint8_t **in_data);
+int send_change_cipher_spec(SSL *ssl);
+void finished_digest(SSL *ssl, const char *label, uint8_t *digest);
+void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
+void add_packet(SSL *ssl, const uint8_t *pkt, int len);
+int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
+int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj);
+void ssl_obj_free(SSLObjLoader *ssl_obj);
+int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
+int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
+int load_key_certs(SSL_CTX *ssl_ctx);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
+void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx);
+#endif
+#ifdef CONFIG_SSL_ENABLE_CLIENT
+int do_client_connect(SSL *ssl);
+#endif
+
+#ifdef CONFIG_SSL_FULL_MODE
+void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok);
+void DISPLAY_BYTES(SSL *ssl, const char *format, 
+        const uint8_t *data, int size, ...);
+void DISPLAY_CERT(SSL *ssl, const X509_CTX *x509_ctx);
+void DISPLAY_RSA(SSL *ssl,  const RSA_CTX *rsa_ctx);
+void DISPLAY_ALERT(SSL *ssl, int alert);
+#else
+#define DISPLAY_STATE(A,B,C,D)
+#define DISPLAY_CERT(A,B)
+#define DISPLAY_RSA(A,B)
+#define DISPLAY_ALERT(A, B)
+#ifdef WIN32
+void DISPLAY_BYTES(SSL *ssl, const char *format,/* win32 has no variadic macros */
+        const uint8_t *data, int size, ...);
+#else
+void DISPLAY_BYTES(SSL *ssl, const char *format,/* win32 has no variadic macros */
+        const uint8_t *data, int size, ...);
+#endif
+#endif
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+int process_certificate(SSL *ssl, X509_CTX **x509_ctx);
+#endif
+
+SSL_SESS *ssl_session_update(int max_sessions, 
+        SSL_SESS *ssl_sessions[], SSL *ssl,
+        const uint8_t *session_id);
+void kill_ssl_session(SSL_SESS **ssl_sessions, SSL *ssl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1_clnt.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include "ssl.h"
+
+#ifdef CONFIG_SSL_ENABLE_CLIENT        /* all commented out if no client */
+
+static int send_client_hello(SSL *ssl);
+static int process_server_hello(SSL *ssl);
+static int process_server_hello_done(SSL *ssl);
+static int send_client_key_xchg(SSL *ssl);
+static int process_cert_req(SSL *ssl);
+static int send_cert_verify(SSL *ssl);
+
+/*
+ * Establish a new SSL connection to an SSL server.
+ */
+EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, SSL_SOCKET* client_fd, const
+        uint8_t *session_id, uint8_t sess_id_size)
+{
+    SSL *ssl;
+    int ret;
+
+    SOCKET_BLOCK(client_fd);    /* ensure blocking mode */
+    ssl = ssl_new(ssl_ctx, client_fd);
+
+    if (session_id && ssl_ctx->num_sessions)
+    {
+        if (sess_id_size > SSL_SESSION_ID_SIZE) /* validity check */
+        {
+            ssl_free(ssl);
+            return NULL;
+        }
+
+        memcpy(ssl->session_id, session_id, sess_id_size);
+        ssl->sess_id_size = sess_id_size;
+        SET_SSL_FLAG(SSL_SESSION_RESUME);   /* just flag for later */
+    }
+
+    SET_SSL_FLAG(SSL_IS_CLIENT);
+    ret = do_client_connect(ssl);
+    return ssl;
+}
+
+/*
+ * Process the handshake record.
+ */
+int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
+{
+    int ret = SSL_OK;
+
+    /* To get here the state must be valid */
+    switch (handshake_type)
+    {
+        case HS_SERVER_HELLO:
+            ret = process_server_hello(ssl);
+            break;
+
+        case HS_CERTIFICATE:
+            ret = process_certificate(ssl, &ssl->x509_ctx);
+            break;
+
+        case HS_SERVER_HELLO_DONE:
+            if ((ret = process_server_hello_done(ssl)) == SSL_OK)
+            {
+                if (IS_SET_SSL_FLAG(SSL_HAS_CERT_REQ))
+                {
+                    if ((ret = send_certificate(ssl)) == SSL_OK &&
+                        (ret = send_client_key_xchg(ssl)) == SSL_OK)
+                    {
+                        send_cert_verify(ssl);
+                    }
+                }
+                else
+                {
+                    ret = send_client_key_xchg(ssl);
+                }
+
+                if (ret == SSL_OK && 
+                     (ret = send_change_cipher_spec(ssl)) == SSL_OK)
+                {
+                    ret = send_finished(ssl);
+                }
+            }
+            break;
+
+        case HS_CERT_REQ:
+            ret = process_cert_req(ssl);
+            break;
+
+        case HS_FINISHED:
+            ret = process_finished(ssl, hs_len);
+            disposable_free(ssl);   /* free up some memory */
+            break;
+
+        case HS_HELLO_REQUEST:
+            disposable_new(ssl);
+            ret = do_client_connect(ssl);
+            break;
+    }
+
+    return ret;
+}
+
+/*
+ * Do the handshaking from the beginning.
+ */
+int do_client_connect(SSL *ssl)
+{
+    int ret = SSL_OK;
+
+    send_client_hello(ssl);                 /* send the client hello */
+    ssl->bm_read_index = 0;
+    ssl->next_state = HS_SERVER_HELLO;
+    ssl->hs_status = SSL_NOT_OK;            /* not connected */
+    x509_free(ssl->x509_ctx);
+
+    /* sit in a loop until it all looks good */
+    while (ssl->hs_status != SSL_OK)
+    {
+        ret = basic_read(ssl, NULL);
+        
+        if (ret < SSL_OK)
+        { 
+            if (ret != SSL_ERROR_CONN_LOST &&
+                ret != SSL_ERROR_TIMEOUT   && /* GBG */
+                ret != SSL_ERROR_EOS          /* GBG */)
+            {
+                /* let the server know we are dying and why */
+                if (send_alert(ssl, ret))
+                {
+                    /* something nasty happened, so get rid of it */
+                    kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl);
+                }
+            }
+
+            break;
+        }
+    }
+
+    ssl->hs_status = ret;            /* connected? */
+    return ret;
+}
+
+/*
+ * Send the initial client hello.
+ */
+static int send_client_hello(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    time_t tm = time(NULL);
+    uint8_t *tm_ptr = &buf[6]; /* time will go here */
+    int i, offset;
+
+    buf[0] = HS_CLIENT_HELLO;
+    buf[1] = 0;
+    buf[2] = 0;
+    /* byte 3 is calculated later */
+    buf[4] = 0x03;
+    buf[5] = 0x01;
+
+    /* client random value - spec says that 1st 4 bytes are big endian time */
+    *tm_ptr++ = (uint8_t)(((long)tm & 0xff000000) >> 24);
+    *tm_ptr++ = (uint8_t)(((long)tm & 0x00ff0000) >> 16);
+    *tm_ptr++ = (uint8_t)(((long)tm & 0x0000ff00) >> 8);
+    *tm_ptr++ = (uint8_t)(((long)tm & 0x000000ff));
+    get_random(SSL_RANDOM_SIZE-4, &buf[10]);
+    memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE);
+    offset = 6 + SSL_RANDOM_SIZE;
+
+    /* give session resumption a go */
+    if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))    /* set initially by user */
+    {
+        buf[offset++] = ssl->sess_id_size;
+        memcpy(&buf[offset], ssl->session_id, ssl->sess_id_size);
+        offset += ssl->sess_id_size;
+        CLR_SSL_FLAG(SSL_SESSION_RESUME);       /* clear so we can set later */
+    }
+    else
+    {
+        /* no session id - because no session resumption just yet */
+        buf[offset++] = 0;
+    }
+
+    buf[offset++] = 0;              /* number of ciphers */
+    buf[offset++] = NUM_PROTOCOLS*2;/* number of ciphers */
+
+    /* put all our supported protocols in our request */
+    for (i = 0; i < NUM_PROTOCOLS; i++)
+    {
+        buf[offset++] = 0;          /* cipher we are using */
+        buf[offset++] = ssl_prot_prefs[i];
+    }
+
+    buf[offset++] = 1;              /* no compression */
+    buf[offset++] = 0;
+    buf[3] = offset - 4;            /* handshake size */
+
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
+}
+
+/*
+ * Process the server hello.
+ */
+static int process_server_hello(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    int pkt_size = ssl->bm_index;
+    int version = (buf[4] << 4) + buf[5];
+    int num_sessions = ssl->ssl_ctx->num_sessions;
+    uint8_t sess_id_size;
+    int offset, ret = SSL_OK;
+
+    /* check that we are talking to a TLSv1 server */
+    if (version != 0x31)
+        return SSL_ERROR_INVALID_VERSION;
+
+    /* get the server random value */
+    memcpy(ssl->dc->server_random, &buf[6], SSL_RANDOM_SIZE);
+    offset = 6 + SSL_RANDOM_SIZE; /* skip of session id size */
+    sess_id_size = buf[offset++];
+
+    if (num_sessions)
+    {
+        ssl->session = ssl_session_update(num_sessions,
+                ssl->ssl_ctx->ssl_sessions, ssl, &buf[offset]);
+        memcpy(ssl->session->session_id, &buf[offset], sess_id_size);
+
+        /* pad the rest with 0's */
+        if (sess_id_size < SSL_SESSION_ID_SIZE)
+        {
+            memset(&ssl->session->session_id[sess_id_size], 0,
+                SSL_SESSION_ID_SIZE-sess_id_size);
+        }
+    }
+
+    memcpy(ssl->session_id, &buf[offset], sess_id_size);
+    ssl->sess_id_size = sess_id_size;
+    offset += sess_id_size;
+
+    /* get the real cipher we are using */
+    ssl->cipher = buf[++offset];
+    ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ? 
+                                        HS_FINISHED : HS_CERTIFICATE;
+
+    offset++;   // skip the compr
+    PARANOIA_CHECK(pkt_size, offset);
+    ssl->dc->bm_proc_index = offset+1; 
+
+error:
+    return ret;
+}
+
+/**
+ * Process the server hello done message.
+ */
+static int process_server_hello_done(SSL *ssl)
+{
+    ssl->next_state = HS_FINISHED;
+    return SSL_OK;
+}
+
+/*
+ * Send a client key exchange message.
+ */
+static int send_client_key_xchg(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    uint8_t premaster_secret[SSL_SECRET_SIZE];
+    int enc_secret_size = -1;
+
+    buf[0] = HS_CLIENT_KEY_XCHG;
+    buf[1] = 0;
+
+    premaster_secret[0] = 0x03; /* encode the version number */
+    premaster_secret[1] = 0x01;
+    get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]);
+    DISPLAY_RSA(ssl, ssl->x509_ctx->rsa_ctx);
+
+    /* rsa_ctx->bi_ctx is not thread-safe */
+    SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+    enc_secret_size = RSA_encrypt(ssl->x509_ctx->rsa_ctx, premaster_secret,
+            SSL_SECRET_SIZE, &buf[6], 0);
+    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+
+    buf[2] = (enc_secret_size + 2) >> 8;
+    buf[3] = (enc_secret_size + 2) & 0xff;
+    buf[4] = enc_secret_size >> 8;
+    buf[5] = enc_secret_size & 0xff;
+
+    generate_master_secret(ssl, premaster_secret);
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, enc_secret_size+6);
+}
+
+/*
+ * Process the certificate request.
+ */
+static int process_cert_req(SSL *ssl)
+{
+    uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
+    int ret = SSL_OK;
+    int offset = (buf[2] << 4) + buf[3];
+    int pkt_size = ssl->bm_index;
+
+    /* don't do any processing - we will send back an RSA certificate anyway */
+    ssl->next_state = HS_SERVER_HELLO_DONE;
+    SET_SSL_FLAG(SSL_HAS_CERT_REQ);
+    ssl->dc->bm_proc_index += offset;
+    PARANOIA_CHECK(pkt_size, offset);
+error:
+    return ret;
+}
+
+/*
+ * Send a certificate verify message.
+ */
+static int send_cert_verify(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    uint8_t dgst[MD5_SIZE+SHA1_SIZE];
+    RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
+    int n = 0, ret;
+
+    DISPLAY_RSA(ssl, rsa_ctx);
+
+    buf[0] = HS_CERT_VERIFY;
+    buf[1] = 0;
+
+    finished_digest(ssl, NULL, dgst);   /* calculate the digest */
+
+    /* rsa_ctx->bi_ctx is not thread-safe */
+    if (rsa_ctx)
+    {
+        SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+        n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1);
+        SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+
+        if (n == 0)
+        {
+            ret = SSL_ERROR_INVALID_KEY;
+            goto error;
+        }
+    }
+    
+    buf[4] = n >> 8;        /* add the RSA size (not officially documented) */
+    buf[5] = n & 0xff;
+    n += 2;
+    buf[2] = n >> 8;
+    buf[3] = n & 0xff;
+    ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4);
+
+error:
+    return ret;
+}
+
+#endif      /* CONFIG_SSL_ENABLE_CLIENT */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/tls1_svr.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "ssl.h"
+
+static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
+
+static int process_client_hello(SSL *ssl);
+static int send_server_hello_sequence(SSL *ssl);
+static int send_server_hello(SSL *ssl);
+static int send_server_hello_done(SSL *ssl);
+static int process_client_key_xchg(SSL *ssl);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+static int send_certificate_request(SSL *ssl);
+static int process_cert_verify(SSL *ssl);
+#endif
+
+/*
+ * Establish a new SSL connection to an SSL client.
+ */
+EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, SSL_SOCKET* client_fd)
+{
+    SSL *ssl;
+
+    ssl = ssl_new(ssl_ctx, client_fd);
+    ssl->next_state = HS_CLIENT_HELLO;
+
+#ifdef CONFIG_SSL_FULL_MODE
+    if (ssl_ctx->chain_length == 0)
+        printf("Warning - no server certificate defined\n"); TTY_FLUSH();
+#endif
+
+    return ssl;
+}
+
+/*
+ * Process the handshake record.
+ */
+int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
+{
+    int ret = SSL_OK;
+    ssl->hs_status = SSL_NOT_OK;            /* not connected */
+
+    /* To get here the state must be valid */
+    switch (handshake_type)
+    {
+        case HS_CLIENT_HELLO:
+            if ((ret = process_client_hello(ssl)) == SSL_OK)
+                ret = send_server_hello_sequence(ssl);
+            break;
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+        case HS_CERTIFICATE:/* the client sends its cert */
+            ret = process_certificate(ssl, &ssl->x509_ctx);
+
+            if (ret == SSL_OK)    /* verify the cert */
+            { 
+                int cert_res;
+                cert_res = x509_verify(
+                        ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
+                ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res);
+            }
+            break;
+
+        case HS_CERT_VERIFY:    
+            ret = process_cert_verify(ssl);
+            add_packet(ssl, buf, hs_len);   /* needs to be done after */
+            break;
+#endif
+        case HS_CLIENT_KEY_XCHG:
+            ret = process_client_key_xchg(ssl);
+            break;
+
+        case HS_FINISHED:
+            ret = process_finished(ssl, hs_len);
+            disposable_free(ssl);   /* free up some memory */
+            break;
+    }
+
+    return ret;
+}
+
+/* 
+ * Process a client hello message.
+ */
+static int process_client_hello(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    uint8_t *record_buf = ssl->hmac_header;
+    int pkt_size = ssl->bm_index;
+    int i, j, cs_len, id_len, offset = 6 + SSL_RANDOM_SIZE;
+    int version = (record_buf[1] << 4) + record_buf[2];
+    int ret = SSL_OK;
+    
+    /* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
+    if (version < 0x31) 
+    {
+        ret = SSL_ERROR_INVALID_VERSION;
+        ssl_display_error(ret);
+        goto error;
+    }
+
+    memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE);
+
+    /* process the session id */
+    id_len = buf[offset++];
+    if (id_len > SSL_SESSION_ID_SIZE)
+    {
+        return SSL_ERROR_INVALID_SESSION;
+    }
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+    ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
+            ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
+#endif
+
+    offset += id_len;
+    cs_len = (buf[offset]<<8) + buf[offset+1];
+    offset += 3;        /* add 1 due to all cipher suites being 8 bit */
+
+    PARANOIA_CHECK(pkt_size, offset);
+
+    /* work out what cipher suite we are going to use */
+    for (j = 0; j < NUM_PROTOCOLS; j++)
+    {
+        for (i = 0; i < cs_len; i += 2)
+        {
+            if (ssl_prot_prefs[j] == buf[offset+i])   /* got a match? */
+            {
+                ssl->cipher = ssl_prot_prefs[j];
+                goto do_state;
+            }
+        }
+    }
+
+    /* ouch! protocol is not supported */
+    ret = SSL_ERROR_NO_CIPHER;
+
+do_state:
+error:
+    return ret;
+}
+
+#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
+/*
+ * Some browsers use a hybrid SSLv2 "client hello" 
+ */
+int process_sslv23_client_hello(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
+    int version = (buf[3] << 4) + buf[4];
+    int ret = SSL_OK;
+
+    /* we have already read 3 extra bytes so far */
+    int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
+    int cs_len = buf[1];
+    int id_len = buf[3];
+    int ch_len = buf[5];
+    int i, j, offset = 8;   /* start at first cipher */
+    int random_offset = 0;
+
+    DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
+    
+    /* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
+    if (version < 0x31)
+    {
+        return SSL_ERROR_INVALID_VERSION;
+    }
+
+    add_packet(ssl, buf, read_len);
+
+    /* connection has gone, so die */
+    if (bytes_needed < 0)
+    {
+        return SSL_ERROR_CONN_LOST;
+    }
+
+    /* now work out what cipher suite we are going to use */
+    for (j = 0; j < NUM_PROTOCOLS; j++)
+    {
+        for (i = 0; i < cs_len; i += 3)
+        {
+            if (ssl_prot_prefs[j] == buf[offset+i])
+            {
+                ssl->cipher = ssl_prot_prefs[j];
+                goto server_hello;
+            }
+        }
+    }
+
+    /* ouch! protocol is not supported */
+    ret = SSL_ERROR_NO_CIPHER;
+    goto error;
+
+server_hello:
+    /* get the session id */
+    offset += cs_len - 2;   /* we've gone 2 bytes past the end */
+#ifndef CONFIG_SSL_SKELETON_MODE
+    ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
+            ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
+#endif
+
+    /* get the client random data */
+    offset += id_len;
+
+    /* random can be anywhere between 16 and 32 bytes long - so it is padded
+     * with 0's to the left */
+    if (ch_len == 0x10)
+    {
+        random_offset += 0x10;
+    }
+
+    memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len);
+    ret = send_server_hello_sequence(ssl);
+
+error:
+    return ret;
+}
+#endif
+
+/*
+ * Send the entire server hello sequence
+ */
+static int send_server_hello_sequence(SSL *ssl)
+{
+    int ret;
+
+    if ((ret = send_server_hello(ssl)) == SSL_OK)
+    {
+#ifndef CONFIG_SSL_SKELETON_MODE
+        /* resume handshake? */
+        if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
+        {
+            if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
+            {
+                ret = send_finished(ssl);
+                ssl->next_state = HS_FINISHED;
+            }
+        }
+        else 
+#endif
+        if ((ret = send_certificate(ssl)) == SSL_OK)
+        {
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+            /* ask the client for its certificate */
+            if (IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION))
+            {
+                if ((ret = send_certificate_request(ssl)) == SSL_OK)
+                {
+                    ret = send_server_hello_done(ssl);
+                    ssl->next_state = HS_CERTIFICATE;
+                }
+            }
+            else
+#endif
+            {
+                ret = send_server_hello_done(ssl);
+                ssl->next_state = HS_CLIENT_KEY_XCHG;
+            }
+        }
+    }
+
+    return ret;
+}
+
+/*
+ * Send a server hello message.
+ */
+static int send_server_hello(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    int offset = 0;
+
+    buf[0] = HS_SERVER_HELLO;
+    buf[1] = 0;
+    buf[2] = 0;
+    /* byte 3 is calculated later */
+    buf[4] = 0x03;
+    buf[5] = 0x01;
+
+    /* server random value */
+    get_random(SSL_RANDOM_SIZE, &buf[6]);
+    memcpy(ssl->dc->server_random, &buf[6], SSL_RANDOM_SIZE);
+    offset = 6 + SSL_RANDOM_SIZE;
+
+#ifndef CONFIG_SSL_SKELETON_MODE
+    if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
+    {
+        /* retrieve id from session cache */
+        buf[offset++] = SSL_SESSION_ID_SIZE;
+        memcpy(&buf[offset], ssl->session->session_id, SSL_SESSION_ID_SIZE);
+        memcpy(ssl->session_id, ssl->session->session_id, SSL_SESSION_ID_SIZE);
+        ssl->sess_id_size = SSL_SESSION_ID_SIZE;
+        offset += SSL_SESSION_ID_SIZE;
+    }
+    else    /* generate our own session id */
+#endif
+    {
+#ifndef CONFIG_SSL_SKELETON_MODE
+        buf[offset++] = SSL_SESSION_ID_SIZE;
+        get_random(SSL_SESSION_ID_SIZE, &buf[offset]);
+        memcpy(ssl->session_id, &buf[offset], SSL_SESSION_ID_SIZE);
+        ssl->sess_id_size = SSL_SESSION_ID_SIZE;
+
+        /* store id in session cache */
+        if (ssl->ssl_ctx->num_sessions)
+        {
+            memcpy(ssl->session->session_id, 
+                    ssl->session_id, SSL_SESSION_ID_SIZE);
+        }
+
+        offset += SSL_SESSION_ID_SIZE;
+#else
+        buf[offset++] = 0;  /* don't bother with session id in skelton mode */
+#endif
+    }
+
+    buf[offset++] = 0;      /* cipher we are using */
+    buf[offset++] = ssl->cipher;
+    buf[offset++] = 0;      /* no compression */
+    buf[3] = offset - 4;    /* handshake size */
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
+}
+
+/*
+ * Send the server hello done message.
+ */
+static int send_server_hello_done(SSL *ssl)
+{
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 
+                            g_hello_done, sizeof(g_hello_done));
+}
+
+/*
+ * Pull apart a client key exchange message. Decrypt the pre-master key (using
+ * our RSA private key) and then work out the master key. Initialise the
+ * ciphers.
+ */
+static int process_client_key_xchg(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    int pkt_size = ssl->bm_index;
+    int premaster_size, secret_length = (buf[2] << 8) + buf[3];
+    uint8_t premaster_secret[MAX_KEY_BYTE_SIZE];
+    RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
+    int offset = 4;
+    int ret = SSL_OK;
+    
+    DISPLAY_RSA(ssl, rsa_ctx);
+
+    /* is there an extra size field? */
+    if ((secret_length - 2) == rsa_ctx->num_octets)
+        offset += 2;
+
+    PARANOIA_CHECK(pkt_size, rsa_ctx->num_octets+offset);
+
+    /* rsa_ctx->bi_ctx is not thread-safe */
+    SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+    premaster_size = RSA_decrypt(rsa_ctx, &buf[offset], premaster_secret, 1);
+    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+
+    if (premaster_size != SSL_SECRET_SIZE || 
+            premaster_secret[0] != 0x03 ||  /* check version is 3.1 (TLS) */
+            premaster_secret[1] != 0x01)
+    {
+        /* guard against a Bleichenbacher attack */
+        memset(premaster_secret, 0, SSL_SECRET_SIZE);
+        /* and continue - will die eventually when checking the mac */
+    }
+
+#if 0
+    print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
+#endif
+
+    generate_master_secret(ssl, premaster_secret);
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+    ssl->next_state = IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION) ?  
+                                            HS_CERT_VERIFY : HS_FINISHED;
+#else
+    ssl->next_state = HS_FINISHED; 
+#endif
+error:
+    return ret;
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
+
+/*
+ * Send the certificate request message.
+ */
+static int send_certificate_request(SSL *ssl)
+{
+    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 
+            g_cert_request, sizeof(g_cert_request));
+}
+
+/*
+ * Ensure the client has the private key by first decrypting the packet and
+ * then checking the packet digests.
+ */
+static int process_cert_verify(SSL *ssl)
+{
+    uint8_t *buf = ssl->bm_data;
+    int pkt_size = ssl->bm_index;
+    uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
+    uint8_t dgst[MD5_SIZE+SHA1_SIZE];
+    X509_CTX *x509_ctx = ssl->x509_ctx;
+    int ret = SSL_OK;
+    int n;
+
+    PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6);
+
+    DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
+
+    /* rsa_ctx->bi_ctx is not thread-safe */
+    SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
+    n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, 0);
+    SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
+
+    if (n != SHA1_SIZE + MD5_SIZE)
+    {
+        ret = SSL_ERROR_INVALID_KEY;
+        goto end_cert_vfy;
+    }
+
+    finished_digest(ssl, NULL, dgst);       /* calculate the digest */
+    if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE))
+    {
+        ret = SSL_ERROR_INVALID_KEY;
+    }
+
+end_cert_vfy:
+    ssl->next_state = HS_FINISHED;
+error:
+    return ret;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/version.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1 @@
+#define AXTLS_VERSION    "(no version)"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/x509.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2007, Cameron Rich
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the axTLS project nor the names of its contributors 
+ *   may be used to endorse or promote products derived from this software 
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file x509.c
+ * 
+ * Certificate processing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "os_port.h"
+#include "crypto_misc.h"
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * Retrieve the signature from a certificate.
+ */
+static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
+{
+    int offset = 0;
+    const uint8_t *ptr = NULL;
+
+    if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || 
+            asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
+        goto end_get_sig;
+
+    if (asn1_sig[offset++] != ASN1_OCTET_STRING)
+        goto end_get_sig;
+    *len = get_asn1_length(asn1_sig, &offset);
+    ptr = &asn1_sig[offset];          /* all ok */
+
+end_get_sig:
+    return ptr;
+}
+
+#endif
+
+/**
+ * Construct a new x509 object.
+ * @return 0 if ok. < 0 if there was a problem.
+ */
+int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
+{
+    int begin_tbs, end_tbs;
+    int ret = X509_NOT_OK, offset = 0, cert_size = 0;
+    X509_CTX *x509_ctx;
+    BI_CTX *bi_ctx;
+
+    *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
+    x509_ctx = *ctx;
+
+    /* get the certificate size */
+    asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 
+
+    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
+        goto end_cert;
+
+    begin_tbs = offset;         /* start of the tbs */
+    end_tbs = begin_tbs;        /* work out the end of the tbs */
+    asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
+
+    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
+        goto end_cert;
+
+    if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
+    {
+        if (asn1_version(cert, &offset, x509_ctx))
+            goto end_cert;
+    }
+
+    if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
+            asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
+        goto end_cert;
+
+    /* make sure the signature is ok */
+    if (asn1_signature_type(cert, &offset, x509_ctx))
+    {
+        ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
+        goto end_cert;
+    }
+
+    if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
+            asn1_validity(cert, &offset, x509_ctx) ||
+            asn1_name(cert, &offset, x509_ctx->cert_dn) ||
+            asn1_public_key(cert, &offset, x509_ctx))
+        goto end_cert;
+
+    bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
+    /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
+    if (x509_ctx->sig_type == SIG_TYPE_MD5)
+    {
+        MD5_CTX md5_ctx;
+        uint8_t md5_dgst[MD5_SIZE];
+        MD5_Init(&md5_ctx);
+        MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
+        MD5_Final(md5_dgst, &md5_ctx);
+        x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
+    }
+    else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
+    {
+        SHA1_CTX sha_ctx;
+        uint8_t sha_dgst[SHA1_SIZE];
+        SHA1_Init(&sha_ctx);
+        SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
+        SHA1_Final(sha_dgst, &sha_ctx);
+        x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
+    }
+    else if (x509_ctx->sig_type == SIG_TYPE_MD2)
+    {
+        MD2_CTX md2_ctx;
+        uint8_t md2_dgst[MD2_SIZE];
+        MD2_Init(&md2_ctx);
+        MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
+        MD2_Final(md2_dgst, &md2_ctx);
+        x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
+    }
+
+    offset = end_tbs;   /* skip the v3 data */
+    if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
+            asn1_signature(cert, &offset, x509_ctx))
+        goto end_cert;
+#endif
+
+    /* GBG: compute the fingerprints */
+    {
+        MD5_CTX md5_ctx;
+        MD5_Init(&md5_ctx);
+        MD5_Update(&md5_ctx, cert, cert_size);
+        MD5_Final(x509_ctx->fingerprint.md5, &md5_ctx);
+    }
+    {
+        SHA1_CTX sha1_ctx;
+        SHA1_Init(&sha1_ctx);
+        SHA1_Update(&sha1_ctx, cert, cert_size);
+        SHA1_Final(x509_ctx->fingerprint.sha1, &sha1_ctx);
+    }
+    /* /GBG: compute the fingerprints */
+    
+    if (len)
+    {
+        *len = cert_size;
+    }
+
+    ret = X509_OK;
+end_cert:
+
+#ifdef CONFIG_SSL_FULL_MODE
+    if (ret)
+    {
+        printf("Error: Invalid X509 ASN.1 file\n");
+    }
+#endif
+
+    return ret;
+}
+
+/**
+ * Free an X.509 object's resources.
+ */
+void x509_free(X509_CTX *x509_ctx)
+{
+    X509_CTX *next;
+    int i;
+
+    if (x509_ctx == NULL)       /* if already null, then don't bother */
+        return;
+
+    for (i = 0; i < X509_NUM_DN_TYPES; i++)
+    {
+        free(x509_ctx->ca_cert_dn[i]);
+        free(x509_ctx->cert_dn[i]);
+    }
+
+    free(x509_ctx->signature);
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION 
+    if (x509_ctx->digest)
+    {
+        bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
+    }
+#endif
+
+    RSA_free(x509_ctx->rsa_ctx);
+
+    next = x509_ctx->next;
+    free(x509_ctx);
+    x509_free(next);        /* clear the chain */
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * Take a signature and decrypt it.
+ */
+static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
+        bigint *modulus, bigint *pub_exp)
+{
+    int i, size;
+    bigint *decrypted_bi, *dat_bi;
+    bigint *bir = NULL;
+    uint8_t *block = (uint8_t *)alloca(sig_len);
+
+    /* decrypt */
+    dat_bi = bi_import(ctx, sig, sig_len);
+    ctx->mod_offset = BIGINT_M_OFFSET;
+
+    /* convert to a normal block */
+    decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
+
+    bi_export(ctx, decrypted_bi, block, sig_len);
+    ctx->mod_offset = BIGINT_M_OFFSET;
+
+    i = 10; /* start at the first possible non-padded byte */
+    while (block[i++] && i < sig_len);
+    size = sig_len - i;
+
+    /* get only the bit we want */
+    if (size > 0)
+    {
+        int len;
+        const uint8_t *sig_ptr = get_signature(&block[i], &len);
+
+        if (sig_ptr)
+        {
+            bir = bi_import(ctx, sig_ptr, len);
+        }
+    }
+
+    /* save a few bytes of memory */
+    bi_clear_cache(ctx);
+    return bir;
+}
+
+/**
+ * Do some basic checks on the certificate chain.
+ *
+ * Certificate verification consists of a number of checks:
+ * - A root certificate exists in the certificate store.
+ * - The date of the certificate is after the start date.
+ * - The date of the certificate is before the finish date.
+ * - The certificate chain is valid.
+ * - That the certificate(s) are not self-signed.
+ * - The signature of the certificate is valid.
+ */
+int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
+{
+    int ret = X509_OK, i = 0;
+    bigint *cert_sig;
+    X509_CTX *next_cert = NULL;
+    BI_CTX *ctx;
+    bigint *mod = NULL, *expn = NULL;
+    struct timeval tv;
+    int match_ca_cert = 0;
+    uint8_t is_self_signed = 0;
+
+    if (cert == NULL || ca_cert_ctx == NULL)
+    {
+        ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
+        goto end_verify;
+    }
+
+    /* last cert in the chain - look for a trusted cert */
+    if (cert->next == NULL && ca_cert_ctx)
+    {
+        while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
+        {
+            if (asn1_compare_dn(cert->ca_cert_dn,
+                                        ca_cert_ctx->cert[i]->cert_dn) == 0)
+            {
+                match_ca_cert = 1;
+                next_cert = ca_cert_ctx->cert[i];
+                break;
+            }
+
+            i++;
+        }
+
+        /* trusted cert not found */
+        if (match_ca_cert == 0)
+        {
+            ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
+            goto end_verify;
+        }
+    }
+    else
+    {
+        next_cert = cert->next;
+    }
+
+    gettimeofday(&tv, NULL);
+
+    /* check the not before date */
+    if (tv.tv_sec < cert->not_before)
+    {
+        ret = X509_VFY_ERROR_NOT_YET_VALID;
+        goto end_verify;
+    }
+
+    /* check the not after date */
+    if (tv.tv_sec > cert->not_after)
+    {
+        ret = X509_VFY_ERROR_EXPIRED;
+        goto end_verify;
+    }
+
+    ctx = cert->rsa_ctx->bi_ctx;
+
+    /* check for self-signing */
+    if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
+    {
+        is_self_signed = 1;
+        mod = cert->rsa_ctx->m;
+        expn = cert->rsa_ctx->e;
+    }
+    else if (next_cert != NULL)
+    {
+        mod = next_cert->rsa_ctx->m;
+        expn = next_cert->rsa_ctx->e;
+
+        /* check the chain integrity */
+        if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
+        {
+            ret = X509_VFY_ERROR_INVALID_CHAIN;
+            goto end_verify;
+        }
+    }
+
+    /* check the signature */
+    if (mod != NULL)
+    {
+        cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, 
+                bi_clone(ctx, mod), bi_clone(ctx, expn));
+
+        if (cert_sig && cert->digest)
+        {
+            if (bi_compare(cert_sig, cert->digest))
+            {
+                ret = X509_VFY_ERROR_BAD_SIGNATURE;
+            }
+
+            bi_free(ctx, cert_sig);
+
+            if (ret)
+                goto end_verify;
+        }
+        else
+        {
+            ret = X509_VFY_ERROR_BAD_SIGNATURE;
+            goto end_verify;
+        }
+    }
+
+    if (is_self_signed)
+    {
+        ret = X509_VFY_ERROR_SELF_SIGNED;
+        goto end_verify;
+    }
+
+    /* go down the certificate chain using recursion. */
+    if (ret == 0 && cert->next)
+    {
+        ret = x509_verify(ca_cert_ctx, next_cert);
+    }
+
+end_verify:
+    return ret;
+}
+#endif
+
+#if defined (CONFIG_SSL_FULL_MODE)
+/**
+ * Used for diagnostics.
+ */
+static const char *not_part_of_cert = "<Not Part Of Certificate>";
+void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) 
+{
+    if (cert == NULL)
+        return;
+
+    printf("=== CERTIFICATE ISSUED TO ===\n");
+    printf("Common Name (CN):\t\t");
+    printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ?
+                    cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
+
+    printf("Organization (O):\t\t");
+    printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
+        cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
+
+    printf("Organizational Unit (OU):\t");
+    printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
+        cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
+
+    printf("=== CERTIFICATE ISSUED BY ===\n");
+    printf("Common Name (CN):\t\t");
+    printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
+                    cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
+
+    printf("Organization (O):\t\t");
+    printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
+        cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
+
+    printf("Organizational Unit (OU):\t");
+    printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
+        cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
+
+    printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
+    printf("Not After:\t\t\t%s", ctime(&cert->not_after));
+    printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8);
+    printf("Sig Type:\t\t\t");
+    switch (cert->sig_type)
+    {
+        case SIG_TYPE_MD5:
+            printf("MD5\n");
+            break;
+        case SIG_TYPE_SHA1:
+            printf("SHA1\n");
+            break;
+        case SIG_TYPE_MD2:
+            printf("MD2\n");
+            break;
+        default:
+            printf("Unrecognized: %d\n", cert->sig_type);
+            break;
+    }
+
+    if (ca_cert_ctx)
+    {
+        printf("Verify:\t\t\t%s\n",
+                x509_display_error(x509_verify(ca_cert_ctx, cert)));
+    }
+
+#if 0
+    print_blob("Signature", cert->signature, cert->sig_len);
+    bi_print("Modulus", cert->rsa_ctx->m);
+    bi_print("Pub Exp", cert->rsa_ctx->e);
+#endif
+
+    if (ca_cert_ctx)
+    {
+        x509_print(cert->next, ca_cert_ctx);
+    }
+
+    TTY_FLUSH();
+}
+
+const char * x509_display_error(int error)
+{
+    switch (error)
+    {
+        case X509_NOT_OK:
+            return "X509 not ok";
+
+        case X509_VFY_ERROR_NO_TRUSTED_CERT:
+            return "No trusted cert is available";
+
+        case X509_VFY_ERROR_BAD_SIGNATURE:
+            return "Bad signature";
+
+        case X509_VFY_ERROR_NOT_YET_VALID:
+            return "Cert is not yet valid";
+
+        case X509_VFY_ERROR_EXPIRED:
+            return "Cert has expired";
+
+        case X509_VFY_ERROR_SELF_SIGNED:
+            return "Cert is self-signed";
+
+        case X509_VFY_ERROR_INVALID_CHAIN:
+            return "Chain is invalid (check order of certs)";
+
+        case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
+            return "Unsupported digest";
+
+        case X509_INVALID_PRIV_KEY:
+            return "Invalid private key";
+
+        default:
+            return "Unknown";
+    }
+}
+#endif      /* CONFIG_SSL_FULL_MODE */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/README	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,125 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.3 is a general purpose data compression library.  All the code is
+thread safe.  The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format). These documents are also available in other
+formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
+of the library is given in the file example.c which also tests that the library
+is working correctly. Another example is given in the file minigzip.c. The
+compression library itself is composed of all source files except example.c and
+minigzip.c.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile. In short "make test; make install" should work for most
+machines. For Unix: "./configure; make test; make install". For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
+
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version. The zlib home page is
+http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
+please check this site to verify that you have the latest version of zlib;
+otherwise get the latest version and check whether the problem still exists or
+not.
+
+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
+for help.
+
+Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
+issue of  Dr. Dobb's Journal; a copy of the article is available in
+http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+
+The changes made in version 1.2.3 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory "contrib".
+
+A Java implementation of zlib is available in the Java Development Kit
+http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
+See the zlib home page http://www.zlib.org for details.
+
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
+CPAN (Comprehensive Perl Archive Network) sites
+http://www.cpan.org/modules/by-module/Compress/
+
+A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
+available in Python 1.5 and later versions, see
+http://www.python.org/doc/lib/module-zlib.html
+
+A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
+availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+  compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+  when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+  necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+  other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+- When building a shared, i.e. dynamic library on Mac OS X, the library must be
+  installed before testing (do "make install" before "make test"), since the
+  library location is specified in the library.
+
+
+Acknowledgments:
+
+  The deflate format used by zlib was defined by Phil Katz. The deflate
+  and zlib specifications were written by L. Peter Deutsch. Thanks to all the
+  people who reported problems and suggested various improvements in zlib;
+  they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind.  The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/adler32.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,149 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: adler32.c 87 2008-08-15 19:03:36Z bok $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+#  define MOD(a) \
+    do { \
+        if (a >= (BASE << 16)) a -= (BASE << 16); \
+        if (a >= (BASE << 15)) a -= (BASE << 15); \
+        if (a >= (BASE << 14)) a -= (BASE << 14); \
+        if (a >= (BASE << 13)) a -= (BASE << 13); \
+        if (a >= (BASE << 12)) a -= (BASE << 12); \
+        if (a >= (BASE << 11)) a -= (BASE << 11); \
+        if (a >= (BASE << 10)) a -= (BASE << 10); \
+        if (a >= (BASE << 9)) a -= (BASE << 9); \
+        if (a >= (BASE << 8)) a -= (BASE << 8); \
+        if (a >= (BASE << 7)) a -= (BASE << 7); \
+        if (a >= (BASE << 6)) a -= (BASE << 6); \
+        if (a >= (BASE << 5)) a -= (BASE << 5); \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#  define MOD4(a) \
+    do { \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#  define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long sum2;
+    unsigned n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == Z_NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD4(sum2);             /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off_t len2;
+{
+    unsigned long sum1;
+    unsigned long sum2;
+    unsigned rem;
+
+    /* the derivation of this formula is left as an exercise for the reader */
+    rem = (unsigned)(len2 % BASE);
+    sum1 = adler1 & 0xffff;
+    sum2 = rem * sum1;
+    MOD(sum2);
+    sum1 += (adler2 & 0xffff) + BASE - 1;
+    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+    if (sum1 > BASE) sum1 -= BASE;
+    if (sum1 > BASE) sum1 -= BASE;
+    if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+    if (sum2 > BASE) sum2 -= BASE;
+    return sum1 | (sum2 << 16);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/compress.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,79 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: compress.c 87 2008-08-15 19:03:36Z bok $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+    int level;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = deflateEnd(&stream);
+    return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+     If the default memLevel or windowBits for deflateInit() is changed, then
+   this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+    uLong sourceLen;
+{
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/crc32.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,423 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id: crc32.c 87 2008-08-15 19:03:36Z bok $ */
+
+/*
+  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+  protection on the static variables used to control the first-use generation
+  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+  first call get_crc_table() to initialize the tables before allowing more than
+  one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+#  include <stdio.h>
+#  ifndef DYNAMIC_CRC_TABLE
+#    define DYNAMIC_CRC_TABLE
+#  endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h"      /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
+#    include <limits.h>
+#    define BYFOUR
+#    if (UINT_MAX == 0xffffffffUL)
+       typedef unsigned int u4;
+#    else
+#      if (ULONG_MAX == 0xffffffffUL)
+         typedef unsigned long u4;
+#      else
+#        if (USHRT_MAX == 0xffffffffUL)
+           typedef unsigned short u4;
+#        else
+#          undef BYFOUR     /* can't find a four-byte integer type! */
+#        endif
+#      endif
+#    endif
+#  endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+#  define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+   local unsigned long crc32_little OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+   local unsigned long crc32_big OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+#  define TBLS 8
+#else
+#  define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+                                         unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+   local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The first table is simply the CRC of all possible eight bit values.  This is
+  all the information needed to generate CRCs on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.  The remaining tables
+  allow for word-at-a-time CRC calculation for both big-endian and little-
+  endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+    unsigned long c;
+    int n, k;
+    unsigned long poly;                 /* polynomial exclusive-or pattern */
+    /* terms of polynomial defining this crc (except x^32): */
+    static volatile int first = 1;      /* flag to limit concurrent making */
+    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+    /* See if another task is already doing this (not thread-safe, but better
+       than nothing -- significantly reduces duration of vulnerability in
+       case the advice about DYNAMIC_CRC_TABLE is ignored) */
+    if (first) {
+        first = 0;
+
+        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+        poly = 0UL;
+        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+            poly |= 1UL << (31 - p[n]);
+
+        /* generate a crc for every 8-bit value */
+        for (n = 0; n < 256; n++) {
+            c = (unsigned long)n;
+            for (k = 0; k < 8; k++)
+                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+            crc_table[0][n] = c;
+        }
+
+#ifdef BYFOUR
+        /* generate crc for each value followed by one, two, and three zeros,
+           and then the byte reversal of those as well as the first table */
+        for (n = 0; n < 256; n++) {
+            c = crc_table[0][n];
+            crc_table[4][n] = REV(c);
+            for (k = 1; k < 4; k++) {
+                c = crc_table[0][c & 0xff] ^ (c >> 8);
+                crc_table[k][n] = c;
+                crc_table[k + 4][n] = REV(c);
+            }
+        }
+#endif /* BYFOUR */
+
+        crc_table_empty = 0;
+    }
+    else {      /* not first */
+        /* wait for the other guy to finish (not efficient, but rare) */
+        while (crc_table_empty)
+            ;
+    }
+
+#ifdef MAKECRCH
+    /* write out CRC tables to crc32.h */
+    {
+        FILE *out;
+
+        out = fopen("crc32.h", "w");
+        if (out == NULL) return;
+        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+        fprintf(out, "local const unsigned long FAR ");
+        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
+        write_table(out, crc_table[0]);
+#  ifdef BYFOUR
+        fprintf(out, "#ifdef BYFOUR\n");
+        for (k = 1; k < 8; k++) {
+            fprintf(out, "  },\n  {\n");
+            write_table(out, crc_table[k]);
+        }
+        fprintf(out, "#endif\n");
+#  endif /* BYFOUR */
+        fprintf(out, "  }\n};\n");
+        fclose(out);
+    }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+    FILE *out;
+    const unsigned long FAR *table;
+{
+    int n;
+
+    for (n = 0; n < 256; n++)
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
+                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+    return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+    if (sizeof(void *) == sizeof(ptrdiff_t)) {
+        u4 endian;
+
+        endian = 1;
+        if (*((unsigned char *)(&endian)))
+            return crc32_little(crc, buf, len);
+        else
+            return crc32_big(crc, buf, len);
+    }
+#endif /* BYFOUR */
+    crc = crc ^ 0xffffffffUL;
+    while (len >= 8) {
+        DO8;
+        len -= 8;
+    }
+    if (len) do {
+        DO1;
+    } while (--len);
+    return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = (u4)crc;
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = REV((u4)crc);
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4--;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf4++;
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+    unsigned long *mat;
+    unsigned long vec;
+{
+    unsigned long sum;
+
+    sum = 0;
+    while (vec) {
+        if (vec & 1)
+            sum ^= *mat;
+        vec >>= 1;
+        mat++;
+    }
+    return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+    unsigned long *square;
+    unsigned long *mat;
+{
+    int n;
+
+    for (n = 0; n < GF2_DIM; n++)
+        square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off_t len2;
+{
+    int n;
+    unsigned long row;
+    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
+    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
+
+    /* degenerate case */
+    if (len2 == 0)
+        return crc1;
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
+    row = 1;
+    for (n = 1; n < GF2_DIM; n++) {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(even, odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(odd, even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    do {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(even, odd);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(even, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if (len2 == 0)
+            break;
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(odd, even);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(odd, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+    } while (len2 != 0);
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/crc32.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+#ifdef BYFOUR
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+#endif
+  }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/deflate.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1736 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id: deflate.c 87 2008-08-15 19:03:36Z bok $ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+                         Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+                  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+    if (windowBits < 0) { /* suppress zlib wrapper */
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+#ifdef GZIP
+    else if (windowBits > 15) {
+        wrap = 2;       /* write gzip wrapper instead */
+        windowBits -= 16;
+    }
+#endif
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+        strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->wrap = wrap;
+    s->gzhead = Z_NULL;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        s->status = FINISH_STATE;
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->wrap == 2 ||
+        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+        return Z_STREAM_ERROR;
+
+    s = strm->state;
+    if (s->wrap)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > MAX_DIST(s)) {
+        length = MAX_DIST(s);
+        dictionary += dictLength - length; /* use the tail of the dictionary */
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+        INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+        return Z_STREAM_ERROR;
+    }
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->wrap < 0) {
+        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+    }
+    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+    strm->adler =
+#ifdef GZIP
+        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+        adler32(0L, Z_NULL, 0);
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+    z_streamp strm;
+    gz_headerp head;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+    strm->state->gzhead = head;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+    z_streamp strm;
+    int bits;
+    int value;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    strm->state->bi_valid = bits;
+    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if (func != configuration_table[level].func && strm->total_in != 0) {
+        /* Flush the last buffer: */
+        err = deflate(strm, Z_PARTIAL_FLUSH);
+    }
+    if (s->level != level) {
+        s->level = level;
+        s->max_lazy_match   = configuration_table[level].max_lazy;
+        s->good_match       = configuration_table[level].good_length;
+        s->nice_match       = configuration_table[level].nice_length;
+        s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+    z_streamp strm;
+    int good_length;
+    int max_lazy;
+    int nice_length;
+    int max_chain;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+    s->good_match = good_length;
+    s->max_lazy_match = max_lazy;
+    s->nice_match = nice_length;
+    s->max_chain_length = max_chain;
+    return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well.  The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+    z_streamp strm;
+    uLong sourceLen;
+{
+    deflate_state *s;
+    uLong destLen;
+
+    /* conservative upper bound */
+    destLen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+    /* if can't get parameters, return conservative bound */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return destLen;
+
+    /* if not default parameters, return conservative bound */
+    s = strm->state;
+    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+        return destLen;
+
+    /* default settings: return tight bound for that case */
+    return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        flush > Z_FINISH || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the header */
+    if (s->status == INIT_STATE) {
+#ifdef GZIP
+        if (s->wrap == 2) {
+            strm->adler = crc32(0L, Z_NULL, 0);
+            put_byte(s, 31);
+            put_byte(s, 139);
+            put_byte(s, 8);
+            if (s->gzhead == NULL) {
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, OS_CODE);
+                s->status = BUSY_STATE;
+            }
+            else {
+                put_byte(s, (s->gzhead->text ? 1 : 0) +
+                            (s->gzhead->hcrc ? 2 : 0) +
+                            (s->gzhead->extra == Z_NULL ? 0 : 4) +
+                            (s->gzhead->name == Z_NULL ? 0 : 8) +
+                            (s->gzhead->comment == Z_NULL ? 0 : 16)
+                        );
+                put_byte(s, (Byte)(s->gzhead->time & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, s->gzhead->os & 0xff);
+                if (s->gzhead->extra != NULL) {
+                    put_byte(s, s->gzhead->extra_len & 0xff);
+                    put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+                }
+                if (s->gzhead->hcrc)
+                    strm->adler = crc32(strm->adler, s->pending_buf,
+                                        s->pending);
+                s->gzindex = 0;
+                s->status = EXTRA_STATE;
+            }
+        }
+        else
+#endif
+        {
+            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+            uInt level_flags;
+
+            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+                level_flags = 0;
+            else if (s->level < 6)
+                level_flags = 1;
+            else if (s->level == 6)
+                level_flags = 2;
+            else
+                level_flags = 3;
+            header |= (level_flags << 6);
+            if (s->strstart != 0) header |= PRESET_DICT;
+            header += 31 - (header % 31);
+
+            s->status = BUSY_STATE;
+            putShortMSB(s, header);
+
+            /* Save the adler32 of the preset dictionary: */
+            if (s->strstart != 0) {
+                putShortMSB(s, (uInt)(strm->adler >> 16));
+                putShortMSB(s, (uInt)(strm->adler & 0xffff));
+            }
+            strm->adler = adler32(0L, Z_NULL, 0);
+        }
+    }
+#ifdef GZIP
+    if (s->status == EXTRA_STATE) {
+        if (s->gzhead->extra != NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+
+            while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size)
+                        break;
+                }
+                put_byte(s, s->gzhead->extra[s->gzindex]);
+                s->gzindex++;
+            }
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (s->gzindex == s->gzhead->extra_len) {
+                s->gzindex = 0;
+                s->status = NAME_STATE;
+            }
+        }
+        else
+            s->status = NAME_STATE;
+    }
+    if (s->status == NAME_STATE) {
+        if (s->gzhead->name != NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->name[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0) {
+                s->gzindex = 0;
+                s->status = COMMENT_STATE;
+            }
+        }
+        else
+            s->status = COMMENT_STATE;
+    }
+    if (s->status == COMMENT_STATE) {
+        if (s->gzhead->comment != NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->comment[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0)
+                s->status = HCRC_STATE;
+        }
+        else
+            s->status = HCRC_STATE;
+    }
+    if (s->status == HCRC_STATE) {
+        if (s->gzhead->hcrc) {
+            if (s->pending + 2 > s->pending_buf_size)
+                flush_pending(strm);
+            if (s->pending + 2 <= s->pending_buf_size) {
+                put_byte(s, (Byte)(strm->adler & 0xff));
+                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+                strm->adler = crc32(0L, Z_NULL, 0);
+                s->status = BUSY_STATE;
+            }
+        }
+        else
+            s->status = BUSY_STATE;
+    }
+#endif
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+            /* Since avail_out is 0, deflate will be called again with
+             * more output space, but possibly with both pending and
+             * avail_in equal to zero. There won't be anything to do,
+             * but this is not an error situation so make sure we
+             * return OK instead of BUF_ERROR at next call of deflate:
+             */
+            s->last_flush = -1;
+            return Z_OK;
+        }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+               flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+        bstate = (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+             * of deflate should use the same flush parameter to make sure
+             * that the flush is complete. So we don't have to output an
+             * empty block here, this will be done at next call. This also
+             * ensures that for a very small output buffer, we emit at most
+             * one empty block.
+             */
+        }
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                }
+            }
+            flush_pending(strm);
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->wrap <= 0) return Z_STREAM_END;
+
+    /* Write the trailer */
+#ifdef GZIP
+    if (s->wrap == 2) {
+        put_byte(s, (Byte)(strm->adler & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+        put_byte(s, (Byte)(strm->total_in & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+    }
+    else
+#endif
+    {
+        putShortMSB(s, (uInt)(strm->adler >> 16));
+        putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    }
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE &&
+        status != EXTRA_STATE &&
+        status != NAME_STATE &&
+        status != COMMENT_STATE &&
+        status != HCRC_STATE &&
+        status != BUSY_STATE &&
+        status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    zmemcpy(dest, source, sizeof(z_stream));
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    zmemcpy(ds, ss, sizeof(deflate_state));
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (strm->state->wrap == 1) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+#ifdef GZIP
+    else if (strm->state->wrap == 2) {
+        strm->adler = crc32(strm->adler, strm->next_in, len);
+    }
+#endif
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2.  Note that the checks below
+         * for insufficient lookahead only occur occasionally for performance
+         * reasons.  Therefore uninitialized memory will be accessed, and
+         * conditional jumps will be made that depend on those values.
+         * However the length of the match is limited to the lookahead, so
+         * the output of deflate is not affected by the uninitialized values.
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+                start, match, length);
+        do {
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (sizeof(int) <= 2) {
+            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+                more = wsize;
+
+            } else if (more == (unsigned)(-1)) {
+                /* Very unlikely, but possible on 16 bit machine if
+                 * strstart == 0 && lookahead == 1 (input done a byte at time)
+                 */
+                more--;
+            }
+        }
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+            /* %%% avoid this when Z_RLE */
+            n = s->hash_size;
+            p = &s->head[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+            } while (--n);
+
+            n = wsize;
+#ifndef FASTEST
+            p = &s->prev[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+                (ulg)((long)s->strstart - s->block_start), \
+                (eof)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+   FLUSH_BLOCK_ONLY(s, eof); \
+   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+                   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+        Assert(s->block_start >= 0L, "block gone");
+
+        s->strstart += s->lookahead;
+        s->lookahead = 0;
+
+        /* Emit a stored block if pending_buf will be full: */
+        max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+            /* strstart == 0 is possible when wraparound on 16-bit machine */
+            s->lookahead = (uInt)(s->strstart - max_start);
+            s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+        }
+        /* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+        }
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL; /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+#ifdef FASTEST
+            if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
+                (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#else
+            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#endif
+            /* longest_match() or longest_match_fast() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++;
+            } else
+#endif
+            {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL;    /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+            /* longest_match() or longest_match_fast() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+                || (s->match_length == MIN_MATCH &&
+                    s->strstart - s->match_start > TOO_FAR)
+#endif
+                )) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+                           s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;         /* set if current block must be flushed */
+    uInt run;           /* length of run */
+    uInt max;           /* maximum length of run */
+    uInt prev;          /* byte at distance one to match */
+    Bytef *scan;        /* scan for end of run */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the longest encodable run.
+         */
+        if (s->lookahead < MAX_MATCH) {
+            fill_window(s);
+            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* See how many times the previous byte repeats */
+        run = 0;
+        if (s->strstart > 0) {      /* if there is a previous byte, that is */
+            max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+            scan = s->window + s->strstart - 1;
+            prev = *scan++;
+            do {
+                if (*scan++ != prev)
+                    break;
+            } while (++run < max);
+        }
+
+        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+        if (run >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, run);
+            _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+            s->lookahead -= run;
+            s->strstart += run;
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/deflate.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,331 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2004 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: deflate.h 87 2008-08-15 19:03:36Z bok $ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip encoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define EXTRA_STATE   69
+#define NAME_STATE    73
+#define COMMENT_STATE 91
+#define HCRC_STATE   103
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    uInt   pending;      /* nb of bytes in the pending buffer */
+    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    gz_headerp  gzhead;  /* gzip header information to write */
+    uInt   gzindex;      /* where in extra, name, or comment */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+        /* in trees.c */
+void _tr_init         OF((deflate_state *s));
+int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+void _tr_align        OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch _length_code[];
+  extern uch _dist_code[];
+#else
+  extern const uch _length_code[];
+  extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/infback.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,623 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+   This code is largely copied from inflate.c.  Normally either infback.o or
+   inflate.o would be linked into an application--not both.  The interface
+   with inffast.c is retained so that optimized assembler-coded versions of
+   inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+   strm provides memory allocation functions in zalloc and zfree, or
+   Z_NULL to use the library memory allocation functions.
+
+   windowBits is in the range 8..15, and window is a user-supplied
+   window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_streamp strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL || window == Z_NULL ||
+        windowBits < 8 || windowBits > 15)
+        return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+                                               sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->dmax = 32768U;
+    state->wbits = windowBits;
+    state->wsize = 1U << windowBits;
+    state->window = window;
+    state->write = 0;
+    state->whave = 0;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Assure that some input is available.  If input is requested, but denied,
+   then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+    do { \
+        if (have == 0) { \
+            have = in(in_desc, &next); \
+            if (have == 0) { \
+                next = Z_NULL; \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+   with an error if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        PULL(); \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflateBack() with
+   an error. */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Assure that some output space is available, by writing out the window
+   if it's full.  If the write fails, return from inflateBack() with a
+   Z_BUF_ERROR. */
+#define ROOM() \
+    do { \
+        if (left == 0) { \
+            put = state->window; \
+            left = state->wsize; \
+            state->whave = left; \
+            if (out(out_desc, put, left)) { \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/*
+   strm provides the memory allocation functions and window buffer on input,
+   and provides information on the unused input on return.  For Z_DATA_ERROR
+   returns, strm will also provide an error message.
+
+   in() and out() are the call-back input and output functions.  When
+   inflateBack() needs more input, it calls in().  When inflateBack() has
+   filled the window with output, or when it completes with data in the
+   window, it calls out() to write out the data.  The application must not
+   change the provided input until in() is called again or inflateBack()
+   returns.  The application must not change the window/output buffer until
+   inflateBack() returns.
+
+   in() and out() are called with a descriptor parameter provided in the
+   inflateBack() call.  This parameter can be a structure that provides the
+   information required to do the read or write, as well as accumulated
+   information on the input and output such as totals and check values.
+
+   in() should return zero on failure.  out() should return non-zero on
+   failure.  If either in() or out() fails, than inflateBack() returns a
+   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
+   was in() or out() that caused in the error.  Otherwise,  inflateBack()
+   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+   error, or Z_MEM_ERROR if it could not allocate memory for the state.
+   inflateBack() can also return Z_STREAM_ERROR if the input parameters
+   are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_streamp strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    /* Check that the strm exists and that the state was initialized */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* Reset the state */
+    strm->msg = Z_NULL;
+    state->mode = TYPE;
+    state->last = 0;
+    state->whave = 0;
+    next = strm->next_in;
+    have = next != Z_NULL ? strm->avail_in : 0;
+    hold = 0;
+    bits = 0;
+    put = state->window;
+    left = state->wsize;
+
+    /* Inflate until end of block marked as last */
+    for (;;)
+        switch (state->mode) {
+        case TYPE:
+            /* determine and dispatch block type */
+            if (state->last) {
+                BYTEBITS();
+                state->mode = DONE;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+
+        case STORED:
+            /* get and verify stored block length */
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+
+            /* copy stored block from input to output */
+            while (state->length != 0) {
+                copy = state->length;
+                PULL();
+                ROOM();
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+
+        case TABLE:
+            /* get dynamic table entries descriptor */
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+
+            /* get code length code lengths (not a typo) */
+            state->have = 0;
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+
+            /* get length and distance code code lengths */
+            state->have = 0;
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = (unsigned)(state->lens[state->have - 1]);
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+
+        case LEN:
+            /* use inflate_fast() if we have enough input and output */
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                if (state->whave < state->wsize)
+                    state->whave = state->wsize - left;
+                inflate_fast(strm, state->wsize);
+                LOAD();
+                break;
+            }
+
+            /* get a literal, length, or end-of-block code */
+            for (;;) {
+                this = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            state->length = (unsigned)this.val;
+
+            /* process literal */
+            if (this.op == 0) {
+                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", this.val));
+                ROOM();
+                *put++ = (unsigned char)(state->length);
+                left--;
+                state->mode = LEN;
+                break;
+            }
+
+            /* process end of block */
+            if (this.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+
+            /* invalid code */
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+
+            /* length code -- get extra bits, if any */
+            state->extra = (unsigned)(this.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+
+            /* get distance code */
+            for (;;) {
+                this = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)this.val;
+
+            /* get distance extra bits, if any */
+            state->extra = (unsigned)(this.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            if (state->offset > state->wsize - (state->whave < state->wsize ?
+                                                left : 0)) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+
+            /* copy match from window to output */
+            do {
+                ROOM();
+                copy = state->wsize - state->offset;
+                if (copy < left) {
+                    from = put + copy;
+                    copy = left - copy;
+                }
+                else {
+                    from = put - state->offset;
+                    copy = left;
+                }
+                if (copy > state->length) copy = state->length;
+                state->length -= copy;
+                left -= copy;
+                do {
+                    *put++ = *from++;
+                } while (--copy);
+            } while (state->length != 0);
+            break;
+
+        case DONE:
+            /* inflate stream terminated properly -- write leftover output */
+            ret = Z_STREAM_END;
+            if (left < state->wsize) {
+                if (out(out_desc, state->window, state->wsize - left))
+                    ret = Z_BUF_ERROR;
+            }
+            goto inf_leave;
+
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+
+        default:                /* can't happen, but makes compilers happy */
+            ret = Z_STREAM_ERROR;
+            goto inf_leave;
+        }
+
+    /* Return unused input */
+  inf_leave:
+    strm->next_in = next;
+    strm->avail_in = have;
+    return ret;
+}
+
+int ZEXPORT inflateBackEnd(strm)
+z_streamp strm;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inffast.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,318 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *in;      /* local strm->next_in */
+    unsigned char FAR *last;    /* while in < last, enough input available */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code this;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in - OFF;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out - OFF;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    write = state->write;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+        }
+        this = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(this.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(this.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", this.val));
+            PUP(out) = (unsigned char)(this.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(this.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+            }
+            this = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(this.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(this.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(this.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(PUP(in)) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+                    from = window - OFF;
+                    if (write == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (write < op) {      /* wrap around window */
+                        from += wsize + write - op;
+                        op -= write;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = window - OFF;
+                            if (write < len) {  /* some from start of window */
+                                op = write;
+                                len -= op;
+                                do {
+                                    PUP(out) = PUP(from);
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += write - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    }
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                this = dcode[this.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            this = lcode[this.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and write == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inffast.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inffixed.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,94 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications. It
+       is part of the implementation of the compression library and
+       is subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inflate.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1368 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+                              unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->wsize = 0;
+    state->whave = 0;
+    state->write = 0;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    if (windowBits < 0) {
+        state->wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+        if (windowBits < 48) windowBits &= 15;
+#endif
+    }
+    if (windowBits < 8 || windowBits > 15) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+        return Z_STREAM_ERROR;
+    }
+    state->wbits = (unsigned)windowBits;
+    state->window = Z_NULL;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+               state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+    struct inflate_state FAR *state;
+    unsigned copy, dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, 1U << state->wbits,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->write = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    copy = out - strm->avail_out;
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        state->write = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->write;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, strm->next_out - copy, copy);
+            state->write = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->write += dist;
+            if (state->write == state->wsize) state->write = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if (state->flags & 0x0200) CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if (state->flags & 0x0200) CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if (state->flags & 0x0200)
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if (hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = REVERSE(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                break;
+            }
+            for (;;) {
+                this = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            state->length = (unsigned)this.val;
+            if ((int)(this.op) == 0) {
+                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", this.val));
+                state->mode = LIT;
+                break;
+            }
+            if (this.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(this.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                this = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)this.val;
+            state->extra = (unsigned)(this.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            if (state->offset > state->whave + out - left) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->write) {
+                    copy -= state->write;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->write - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if (out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     REVERSE(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+        if (updatewindow(strm, out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if (state->wrap && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long id;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary id */
+    if (state->mode == DICT) {
+        id = adler32(0L, Z_NULL, 0);
+        id = adler32(id, dictionary, dictLength);
+        if (id != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window */
+    if (updatewindow(strm, strm->avail_out)) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    if (dictLength > state->wsize) {
+        zmemcpy(state->window, dictionary + dictLength - state->wsize,
+                state->wsize);
+        state->whave = state->wsize;
+    }
+    else {
+        zmemcpy(state->window + state->wsize - dictLength, dictionary,
+                dictLength);
+        state->whave = dictLength;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy(copy, state, sizeof(struct inflate_state));
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inflate.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,115 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip decoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN,        /* i: waiting for length/lit code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+        NAME -> COMMENT -> HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+    Read deflate blocks:
+            TYPE -> STORED or TABLE or LEN or CHECK
+            STORED -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN
+    Read deflate codes:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 7K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+    gz_headerp head;            /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inftrees.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,329 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+   " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code this;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        this.op = (unsigned char)64;    /* invalid code marker */
+        this.bits = (unsigned char)1;
+        this.val = (unsigned short)0;
+        *(*table)++ = this;             /* make a table to force an error */
+        *(*table)++ = this;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min <= MAXBITS; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked when a LENS table is being made
+       against the space in *table, ENOUGH, minus the maximum space needed by
+       the worst case distance code, MAXD.  This should never happen, but the
+       sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+       This assumes that when type == LENS, bits == 9.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if (type == LENS && used >= ENOUGH - MAXD)
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        this.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            this.op = (unsigned char)0;
+            this.val = work[sym];
+        }
+        else if ((int)(work[sym]) > end) {
+            this.op = (unsigned char)(extra[work[sym]]);
+            this.val = base[work[sym]];
+        }
+        else {
+            this.op = (unsigned char)(32 + 64);         /* end of block */
+            this.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = this;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if (type == LENS && used >= ENOUGH - MAXD)
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /*
+       Fill in rest of table for incomplete codes.  This loop is similar to the
+       loop above in incrementing huff for table indices.  It is assumed that
+       len is equal to curr + drop, so there is no loop needed to increment
+       through high index bits.  When the current sub-table is filled, the loop
+       drops back to the root table to fill in any remaining entries there.
+     */
+    this.op = (unsigned char)64;                /* invalid code marker */
+    this.bits = (unsigned char)(len - drop);
+    this.val = (unsigned short)0;
+    while (huff != 0) {
+        /* when done with sub-table, drop back to root table */
+        if (drop != 0 && (huff & mask) != low) {
+            drop = 0;
+            len = root;
+            next = *table;
+            this.bits = (unsigned char)len;
+        }
+
+        /* put invalid code marker in table */
+        next[huff >> drop] = this;
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/inftrees.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,55 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1444 code structures (852 for length/literals
+   and 592 for distances, the latter actually the result of an
+   exhaustive search).  The true maximum is not known, but the value
+   below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/trees.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1219 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2005 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id: trees.c 87 2008-08-15 19:03:36Z bok $ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+#  include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+                              ct_data *dtree));
+local void set_data_type  OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
+                              int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+    deflate_state *s;
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (value << s->bi_valid);
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = value;\
+    s->bi_buf |= (val << s->bi_valid);\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef DEBUG
+#    include <stdio.h>
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+            "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+        fprintf(header, "%2u%s", _dist_code[i],
+                SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+        fprintf(header, "%2u%s", _length_code[i],
+                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+        fprintf(header, "%1u%s", base_length[i],
+                SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "%5u%s", base_dist[i],
+                SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+    deflate_state *s;
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+    deflate_state *s;
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+    deflate_state *s;
+    ct_data *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(s, desc)
+    deflate_state *s;
+    tree_desc *desc;    /* the tree descriptor */
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (bits + xbits);
+        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if ((unsigned) tree[m].Len != (unsigned) bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((long)bits - (long)tree[m].Len)
+                              *(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+    ct_data *tree;             /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+    ushf *bl_count;            /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+                                s->depth[n] : s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree;   /* the tree to be scanned */
+    int max_code;    /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+    deflate_state *s;
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+    deflate_state *s;
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
+#ifdef DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+#endif
+    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+    deflate_state *s;
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+    /* Of the 10 bits for the empty block, we have already sent
+     * (10 - bi_valid) bits. The lookahead for the last real code (before
+     * the EOB of the previous block) was thus at least one plus the length
+     * of the EOB plus what we have just sent of the empty static block.
+     */
+    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+        send_bits(s, STATIC_TREES<<1, 3);
+        send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+        s->compressed_len += 10L;
+#endif
+        bi_flush(s);
+    }
+    s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+    deflate_state *s;
+    charf *buf;       /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+        /* Check if the file is binary or text */
+        if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+            set_data_type(s);
+
+        /* Construct the literal and distance trees */
+        build_tree(s, (tree_desc *)(&(s->l_desc)));
+        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+
+        build_tree(s, (tree_desc *)(&(s->d_desc)));
+        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+        /* At this point, opt_len and static_len are the total bit lengths of
+         * the compressed block data, excluding the tree representations.
+         */
+
+        /* Build the bit length tree for the above two trees, and get the index
+         * in bl_order of the last bit length code to send.
+         */
+        max_blindex = build_bl_tree(s);
+
+        /* Determine the best encoding. Compute the block lengths in bytes. */
+        opt_lenb = (s->opt_len+3+7)>>3;
+        static_lenb = (s->static_len+3+7)>>3;
+
+        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+                s->last_lit));
+
+        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+eof, 3);
+        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+eof, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (eof) {
+        bi_windup(s);
+#ifdef DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+    deflate_state *s;
+    unsigned dist;  /* distance of matched string */
+    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+    deflate_state *s;
+    ct_data *ltree; /* literal tree */
+    ct_data *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+               "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+    s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local void set_data_type(s)
+    deflate_state *s;
+{
+    int n;
+
+    for (n = 0; n < 9; n++)
+        if (s->dyn_ltree[n].Freq != 0)
+            break;
+    if (n == 9)
+        for (n = 14; n < 32; n++)
+            if (s->dyn_ltree[n].Freq != 0)
+                break;
+    s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+    deflate_state *s;
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+    deflate_state *s;
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+    deflate_state *s;
+    charf    *buf;    /* the input data */
+    unsigned len;     /* its length */
+    int      header;  /* true if block header must be written */
+{
+    bi_windup(s);        /* align on byte boundary */
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+
+    if (header) {
+        put_short(s, (ush)len);
+        put_short(s, (ush)~len);
+#ifdef DEBUG
+        s->bits_sent += 2*16;
+#endif
+    }
+#ifdef DEBUG
+    s->bits_sent += (ulg)len<<3;
+#endif
+    while (len--) {
+        put_byte(s, *buf++);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/trees.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zconf.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.h 87 2008-08-15 19:03:36Z bok $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_          z_deflateInit_
+#  define deflate               z_deflate
+#  define deflateEnd            z_deflateEnd
+#  define inflateInit_          z_inflateInit_
+#  define inflate               z_inflate
+#  define inflateEnd            z_inflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateCopy           z_deflateCopy
+#  define deflateReset          z_deflateReset
+#  define deflateParams         z_deflateParams
+#  define deflateBound          z_deflateBound
+#  define deflatePrime          z_deflatePrime
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateCopy           z_inflateCopy
+#  define inflateReset          z_inflateReset
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define uncompress            z_uncompress
+#  define adler32               z_adler32
+#  define crc32                 z_crc32
+#  define get_crc_table         z_get_crc_table
+#  define zError                z_zError
+
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
+#  define Byte                  z_Byte
+#  define uInt                  z_uInt
+#  define uLong                 z_uLong
+#  define Bytef                 z_Bytef
+#  define charf                 z_charf
+#  define intf                  z_intf
+#  define uIntf                 z_uIntf
+#  define uLongf                z_uLongf
+#  define voidpf                z_voidpf
+#  define voidp                 z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>   /* for off_t */
+#  endif
+#  define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#  ifdef FAR
+#    undef FAR
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(deflateBound,"DEBND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(compressBound,"CMBND")
+#   pragma map(inflate_table,"INTABL")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zconf.in.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.in.h 87 2008-08-15 19:03:36Z bok $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_          z_deflateInit_
+#  define deflate               z_deflate
+#  define deflateEnd            z_deflateEnd
+#  define inflateInit_          z_inflateInit_
+#  define inflate               z_inflate
+#  define inflateEnd            z_inflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateCopy           z_deflateCopy
+#  define deflateReset          z_deflateReset
+#  define deflateParams         z_deflateParams
+#  define deflateBound          z_deflateBound
+#  define deflatePrime          z_deflatePrime
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateCopy           z_inflateCopy
+#  define inflateReset          z_inflateReset
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define uncompress            z_uncompress
+#  define adler32               z_adler32
+#  define crc32                 z_crc32
+#  define get_crc_table         z_get_crc_table
+#  define zError                z_zError
+
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
+#  define Byte                  z_Byte
+#  define uInt                  z_uInt
+#  define uLong                 z_uLong
+#  define Bytef                 z_Bytef
+#  define charf                 z_charf
+#  define intf                  z_intf
+#  define uIntf                 z_uIntf
+#  define uLongf                z_uLongf
+#  define voidpf                z_voidpf
+#  define voidp                 z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>   /* for off_t */
+#  endif
+#  define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#  ifdef FAR
+#    undef FAR
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(deflateBound,"DEBND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(compressBound,"CMBND")
+#   pragma map(inflate_table,"INTABL")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zlib.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.3, July 18th, 2005
+
+  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+     This library can optionally read and write gzip streams in memory as well.
+
+     The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumualte before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  the value returned by deflateBound (see below). If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+  Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+  if and when it gets to the next deflate block boundary. When decoding the
+  zlib or gzip format, this will cause inflate() to return immediately after
+  the header and before the first block. When doing a raw inflate, inflate()
+  will go ahead and process the first block, and will return when it gets to
+  the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64
+  if inflate() is currently decoding the last block in the deflate stream,
+  plus 128 if inflate() returned immediately after decoding an end-of-block
+  code or decoding the complete header up to just before the first byte of the
+  deflate stream. The end-of-block will not be indicated until all of the
+  uncompressed data from that block has been written to strm->next_out.  The
+  number of unused bits may in general be greater than seven, except when
+  bit 7 of data_type is set, in which case the number of unused bits will be
+  less than eight.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster approach
+  may be used for the single inflate() call.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call. So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below. At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically.  Any information
+  contained in the gzip header is not retained, so applications that need that
+  information should instead use raw inflate, see inflateInit2() below, or
+  inflateBack() and perform their own processing of the gzip header and
+  trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing. If Z_DATA_ERROR is returned, the application may then
+  call inflateSync() to look for a good compression block if a partial recovery
+  of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer). It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+   determines the window size. deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding. Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper. The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero),
+   no header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding). Filtered data consists mostly of small values with a somewhat
+   random distribution. In this case, the compression algorithm is tuned to
+   compress them better. The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+   Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+   parameter only affects the compression ratio but not the correctness of the
+   compressed output even if it is not set appropriately.  Z_FIXED prevents the
+   use of dynamic Huffman codes, allowing for a simpler decoder for special
+   applications.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front. In addition, the
+   current implementation of deflate will use at most the window size minus
+   262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit()
+   or deflateInit2().  This would be used to allocate an output buffer
+   for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+  is that this function is used to start off the deflate output with the
+  bits leftover from a previous deflate stream when appending to it.  As such,
+  this function can only be used for raw deflate, and must be used before the
+  first deflate() call after a deflateInit2() or deflateReset().  bits must be
+  less than or equal to 16, and that many of the least significant bits of
+  value will be inserted in the output.
+
+      deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+      deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+      If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+      deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used. If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+   determines the window size. inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream. This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values. If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is. Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding. Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is
+   a crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+   is set to null if there is no error message.  inflateInit2 does not perform
+   any decompression apart from reading the zlib header if present: this will
+   be done by inflate(). (So next_in and avail_in may be modified, but next_out
+   and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called
+   immediately after inflateInit2() or inflateReset() and before any call of
+   inflate() to set the dictionary.  The application must insure that the
+   dictionary that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+  that this function is used to start inflating at a bit position in the
+  middle of a byte.  The provided bits will be used before any bytes are used
+  from next_in.  This function should only be used with raw inflate, and
+  should be used before the first inflate() call after inflateInit2() or
+  inflateReset().  bits must be less than or equal to 16, and that many of the
+  least significant bits of value will be inserted in the input.
+
+      inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+      inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK can be used to
+   force inflate() to return immediately after header processing is complete
+   and before any actual data is decompressed.
+
+      The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.)  If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When
+   any of extra, name, or comment are not Z_NULL and the respective field is
+   not present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+      If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+      inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+   be allocated, or Z_VERSION_ERROR if the version of the library does not
+   match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free
+   the allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects
+   only the raw deflate stream to decompress.  This is different from the
+   normal behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format
+   error in the deflate stream (in which case strm->msg is set to indicate the
+   nature of the error), or Z_STREAM_ERROR if the stream was not properly
+   initialized.  In the case of Z_BUF_ERROR, an input or output error can be
+   distinguished using strm->next_in which will be Z_NULL only if in() returned
+   an error.  If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+   out() returning non-zero.  (in() will always be called before out(), so
+   strm->next_in is assured to be defined if out() returns non-zero.)  Note
+   that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least the value returned
+   by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before
+   a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h", or 'R' for run-length encoding
+   as in "wb1R". (See the description of deflateInit2 for more information
+   about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file,
+                                   voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).  The number of
+   uncompressed bytes written is limited to 4095. The caller should assure that
+   this limit is not exceeded. If it is exceeded, then gzprintf() will return
+   return an error (0) with nothing written. In this case, there may also be a
+   buffer overflow with unpredictable consequences, which is possible only if
+   zlib was compiled with the insecure functions sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzungetc OF((int c, gzFile file));
+/*
+      Push one character back onto the stream to be read again later.
+   Only one character of push-back is allowed.  gzungetc() returns the
+   character pushed, or -1 on failure.  gzungetc() will fail if a
+   character has been pushed but not read yet, or if c is -1. The pushed
+   character will be discarded if the stream is repositioned with gzseek()
+   or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+                                      z_off_t offset, int whence));
+/*
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns 1 if file is being read directly without decompression, otherwise
+   zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file. This is analogous to the
+   clearerr() function in stdio. This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+/*
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32. If buf is NULL, this function returns the required initial
+   value for the for the crc. Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+        ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zutil.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,318 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zutil.c 87 2008-08-15 19:03:36Z bok $ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state      {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+    uLong flags;
+
+    flags = 0;
+    switch (sizeof(uInt)) {
+    case 2:     break;
+    case 4:     flags += 1;     break;
+    case 8:     flags += 2;     break;
+    default:    flags += 3;
+    }
+    switch (sizeof(uLong)) {
+    case 2:     break;
+    case 4:     flags += 1 << 2;        break;
+    case 8:     flags += 2 << 2;        break;
+    default:    flags += 3 << 2;
+    }
+    switch (sizeof(voidpf)) {
+    case 2:     break;
+    case 4:     flags += 1 << 4;        break;
+    case 8:     flags += 2 << 4;        break;
+    default:    flags += 3 << 4;
+    }
+    switch (sizeof(z_off_t)) {
+    case 2:     break;
+    case 4:     flags += 1 << 6;        break;
+    case 8:     flags += 2 << 6;        break;
+    default:    flags += 3 << 6;
+    }
+#ifdef DEBUG
+    flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+    flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+    flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+    flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+    flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+    flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+    flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+    flags += 1L << 20;
+#endif
+#ifdef FASTEST
+    flags += 1L << 21;
+#endif
+#ifdef STDC
+#  ifdef NO_vsnprintf
+        flags += 1L << 25;
+#    ifdef HAS_vsprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_vsnprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#else
+        flags += 1L << 24;
+#  ifdef NO_snprintf
+        flags += 1L << 25;
+#    ifdef HAS_sprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_snprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#endif
+    return flags;
+}
+
+#ifdef DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int z_verbose = verbose;
+
+void z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
+    int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void  zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+                              (voidpf)calloc(items, size);
+}
+
+void  zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/ThirdParty/Neptune/ThirdParty/zlib-1.2.3/zutil.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,269 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h 87 2008-08-15 19:03:36Z bok $ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+#  ifndef _WIN32_WCE
+#    include <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+#   ifdef _WIN32_WCE
+      /* The Microsoft C Run-Time Library for Windows CE doesn't have
+       * errno.  We define it as a global variable to simplify porting.
+       * Its value is always 0 and should not be used.  We rename it to
+       * avoid conflict with other libraries that use the same workaround.
+       */
+#     define errno z_errno
+#   endif
+    extern int errno;
+#else
+#  ifndef _WIN32_WCE
+#    include <errno.h>
+#  endif
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+#      include <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#    include <malloc.h>
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#  ifdef M_I86
+     #include <malloc.h>
+#  endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#    include <unix.h> /* for fdopen */
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#ifdef WIN32
+#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
+#    define OS_CODE  0x0b
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+#  if defined(_WIN32_WCE)
+#    define fdopen(fd,mode) NULL /* No fdopen() */
+#    ifndef _PTRDIFF_T_DEFINED
+       typedef int ptrdiff_t;
+#      define _PTRDIFF_T_DEFINED
+#    endif
+#  else
+#    define fdopen(fd,type)  _fdopen(fd,type)
+#  endif
+#endif
+
+        /* common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#if defined(__CYGWIN__)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#ifndef HAVE_VSNPRINTF
+#  ifdef MSDOS
+     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+        but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
+#      define vsnprintf _vsnprintf
+#    endif
+#  endif
+#  ifdef __SASC
+#    define NO_vsnprintf
+#  endif
+#endif
+#ifdef VMS
+#  define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
+   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
+   extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int z_verbose;
+   extern void z_error    OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void   zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
Binary file deps/libav/avcodec.lib has changed
Binary file deps/libav/avformat.lib has changed
Binary file deps/libav/avutil.lib has changed
Binary file deps/libav/gcc.lib has changed
Binary file deps/libav/swscale.lib has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ref/UPnP.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,2299 @@
+/*
+* UPnP Support for XBMC
+* Copyright (c) 2006 c0diq (Sylvain Rebaud)
+* Portions Copyright (c) by the authors of libPlatinum
+*
+* http://www.plutinosoft.com/blog/category/platinum/
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include "stdafx.h"
+#include "Util.h"
+#include "Application.h"
+
+#include "utils/Network.h"
+#include "UPnP.h"
+#include "FileSystem/UPnPVirtualPathDirectory.h"
+#include "FileSystem/MusicDatabaseDirectory.h"
+#include "FileSystem/VideoDatabaseDirectory.h"
+#include "MusicDatabase.h"
+#include "VideoDatabase.h"
+#include "FileSystem/VideoDatabaseDirectory/DirectoryNode.h"
+#include "FileSystem/VideoDatabaseDirectory/QueryParams.h"
+#include "File.h"
+#include "Platinum.h"
+#include "PltMediaConnect.h"
+#include "PltMediaRenderer.h"
+#include "PltSyncMediaBrowser.h"
+#include "PltDidl.h"
+#include "NptNetwork.h"
+#include "NptConsole.h"
+#include "MusicInfoTag.h"
+#include "FileSystem/Directory.h"
+#include "URL.h"
+#include "Settings.h"
+#include "FileItem.h"
+#include "GUIWindowManager.h"
+#include "GUIInfoManager.h"
+
+using namespace std;
+using namespace MUSIC_INFO;
+using namespace DIRECTORY;
+using namespace XFILE;
+
+extern CGUIInfoManager g_infoManager;
+
+NPT_SET_LOCAL_LOGGER("xbmc.upnp")
+
+#define UPNP_DEFAULT_MAX_RETURNED_ITEMS 200
+#define UPNP_DEFAULT_MIN_RETURNED_ITEMS 30
+
+typedef struct {
+  const char* extension;
+  const char* mimetype;
+} mimetype_extension_struct;
+
+static const mimetype_extension_struct mimetype_extension_map[] = {
+    {"mp3",  "audio/mpeg"},
+    {"m4a",  "audio/mp4"},
+    {"wma",  "audio/x-ms-wma"},
+    {"wav",  "audio/x-wav"},
+    {"wmv",  "video/x-ms-wmv"},
+    {"asf",  "video/x-ms-asf"},
+    {"vob",  "video/mpeg"},
+    {"mpg",  "video/mpeg"},
+    {"avi",  "video/avi"}, // PS3 needs this {"avi",  "video/x-msvideo"},
+    {"divx", "video/x-msvideo"},
+    {"xvid", "video/x-msvideo"},
+    {"mkv",  "video/x-matroska"},
+    {"gif",  "image/gif"},
+    {"jpg",  "image/jpeg"},
+    {"tbn",  "image/jpeg"},
+    {"tif",  "image/tiff"},
+    {NULL, NULL}
+};
+
+/*
+# Play speed
+#    1 normal
+#    0 invalid
+DLNA_ORG_PS = 'DLNA.ORG_PS'
+DLNA_ORG_PS_VAL = '1'
+
+# Convertion Indicator
+#    1 transcoded
+#    0 not transcoded
+DLNA_ORG_CI = 'DLNA.ORG_CI'
+DLNA_ORG_CI_VAL = '0'
+
+# Operations
+#    00 not time seek range, not range
+#    01 range supported
+#    10 time seek range supported
+#    11 both supported
+DLNA_ORG_OP = 'DLNA.ORG_OP'
+DLNA_ORG_OP_VAL = '01'
+
+# Flags
+#    senderPaced                      80000000  31
+#    lsopTimeBasedSeekSupported       40000000  30
+#    lsopByteBasedSeekSupported       20000000  29
+#    playcontainerSupported           10000000  28
+#    s0IncreasingSupported            08000000  27
+#    sNIncreasingSupported            04000000  26
+#    rtspPauseSupported               02000000  25
+#    streamingTransferModeSupported   01000000  24
+#    interactiveTransferModeSupported 00800000  23
+#    backgroundTransferModeSupported  00400000  22
+#    connectionStallingSupported      00200000  21
+#    dlnaVersion15Supported           00100000  20
+DLNA_ORG_FLAGS = 'DLNA.ORG_FLAGS'
+DLNA_ORG_FLAGS_VAL = '01500000000000000000000000000000'
+*/
+
+/*----------------------------------------------------------------------
+|   static
++---------------------------------------------------------------------*/
+CUPnP* CUPnP::upnp = NULL;
+// change to false for XBMC_PC if you want real UPnP functionality
+// otherwise keep to true for xbmc as it doesn't support multicast
+// don't change unless you know what you're doing!
+bool CUPnP::broadcast = true;
+
+namespace
+{
+  static const NPT_String JoinString(const NPT_List<NPT_String>& array, const NPT_String& delimiter)
+  {
+    NPT_String result;
+
+    for(NPT_List<NPT_String>::Iterator it = array.GetFirstItem(); it; it++ )
+        result += (*it) + delimiter;
+
+    if(result.IsEmpty())
+        return "";
+    else
+        return result.SubString(delimiter.GetLength());
+  }
+
+}
+
+
+/*----------------------------------------------------------------------
+|   NPT_Console::Output
++---------------------------------------------------------------------*/
+void
+NPT_Console::Output(const char* message)
+{
+    CLog::Log(LOGDEBUG, "%s", message);
+}
+
+/*----------------------------------------------------------------------
+|   CDeviceHostReferenceHolder class
++---------------------------------------------------------------------*/
+class CDeviceHostReferenceHolder
+{
+public:
+    PLT_DeviceHostReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   CCtrlPointReferenceHolder class
++---------------------------------------------------------------------*/
+class CCtrlPointReferenceHolder
+{
+public:
+    PLT_CtrlPointReference m_CtrlPoint;
+};
+
+/*----------------------------------------------------------------------
+|   CUPnPCleaner class
++---------------------------------------------------------------------*/
+class CUPnPCleaner : public NPT_Thread
+{
+public:
+    CUPnPCleaner(CUPnP* upnp) : NPT_Thread(true), m_UPnP(upnp) {}
+    void Run() {
+        delete m_UPnP;
+    }
+
+    CUPnP* m_UPnP;
+};
+
+/*----------------------------------------------------------------------
+|   CUPnP::CUPnP
++---------------------------------------------------------------------*/
+class CUPnPServer : public PLT_MediaConnect
+{
+public:
+    CUPnPServer(const char* friendly_name, const char* uuid = NULL, int port = 0) :
+        PLT_MediaConnect("", friendly_name, true, uuid, port) {
+        // hack: override path to make sure it's empty
+        // urls will contain full paths to local files
+        m_Path = "";
+    }
+
+    // PLT_MediaServer methods
+    virtual NPT_Result OnBrowseMetadata(PLT_ActionReference&          action,
+                                        const char*                   object_id,
+                                        const NPT_HttpRequestContext& context);
+
+    virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference&          action,
+                                              const char*                object_id,
+                                              const NPT_HttpRequestContext& context);
+
+    virtual NPT_Result OnSearch(PLT_ActionReference&          action,
+                                const NPT_String&             object_id,
+                                const NPT_String&             searchCriteria,
+                                const NPT_HttpRequestContext& context);
+
+    // PLT_FileMediaServer methods
+    virtual NPT_Result ServeFile(NPT_HttpRequest&              request,
+                                 const NPT_HttpRequestContext& context,
+                                 NPT_HttpResponse&             response,
+                                 const NPT_String&             uri_path,
+                                 const NPT_String&             file_path);
+
+    // class methods
+    static NPT_Result PopulateObjectFromTag(CMusicInfoTag&         tag,
+                                            PLT_MediaObject&       object,
+                                            NPT_String*            file_path = NULL,
+                                            PLT_MediaItemResource* resource = NULL);
+    static NPT_Result PopulateObjectFromTag(CVideoInfoTag&         tag,
+                                            PLT_MediaObject&       object,
+                                            NPT_String*            file_path = NULL,
+                                            PLT_MediaItemResource* resource = NULL);
+
+    static PLT_MediaObject* BuildObject(const CFileItem&              item,
+                                        NPT_String&                   file_path,
+                                        bool                          with_count,
+                                        const NPT_HttpRequestContext& context,
+                                        CUPnPServer*                  upnp_server = NULL);
+
+    static const char* GetContentTypeFromExtension(const char* extension);
+    static NPT_String  GetContentType(const CFileItem& item);
+    static NPT_String  GetContentType(const char* filename);
+    static const CStdString& CorrectAllItemsSortHack(const CStdString &item);
+
+private:
+    PLT_MediaObject* Build(CFileItemPtr                  item,
+                           bool                          with_count,
+                           const NPT_HttpRequestContext& context,
+                           const char*                   parent_id = NULL);
+    NPT_Result       BuildResponse(PLT_ActionReference&          action,
+                                   CFileItemList&                items,
+                                   const NPT_HttpRequestContext& context,
+                                   const char*                   parent_id);
+
+    static NPT_String GetParentFolder(NPT_String file_path) {
+        int index = file_path.ReverseFind("\\");
+        if (index == -1) return "";
+
+        return file_path.Left(index);
+    }
+    static NPT_String GetProtocolInfo(const CFileItem& item, const char* protocol);
+
+public:
+    static NPT_UInt32 m_MaxReturnedItems;
+};
+
+NPT_UInt32 CUPnPServer::m_MaxReturnedItems = 0;
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::GetContentTypeFromExtension
++---------------------------------------------------------------------*/
+const char*
+CUPnPServer::GetContentTypeFromExtension(const char* extension)
+{
+    const mimetype_extension_struct* mapping = mimetype_extension_map;
+    while (mapping->extension) {
+        if (NPT_StringsEqual(extension, mapping->extension)) {
+            return mapping->mimetype;
+        }
+        mapping++;
+    }
+
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::GetContentType
++---------------------------------------------------------------------*/
+NPT_String
+CUPnPServer::GetContentType(const char* filename)
+{
+    NPT_String ext = CUtil::GetExtension(filename).c_str();
+    ext.TrimLeft('.');
+    ext = ext.ToLowercase();
+
+    return GetContentTypeFromExtension(ext);
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::GetContentType
++---------------------------------------------------------------------*/
+NPT_String
+CUPnPServer::GetContentType(const CFileItem& item)
+{
+    NPT_String ext = CUtil::GetExtension(item.m_strPath).c_str();
+    if (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty()) {
+        ext = CUtil::GetExtension(item.GetVideoInfoTag()->m_strFileNameAndPath);
+    } else if (item.HasMusicInfoTag() && !item.GetMusicInfoTag()->GetURL().IsEmpty()) {
+        ext = CUtil::GetExtension(item.GetMusicInfoTag()->GetURL());
+    }
+    ext.TrimLeft('.');
+    ext = ext.ToLowercase();
+
+    /* we need a valid extension to retrieve the mimetype for the protocol info */
+    NPT_String content = item.GetContentType().c_str();
+    if (content == "application/octet-stream")
+        content = "";
+
+    if (content.IsEmpty())
+        content = GetContentTypeFromExtension(ext);
+
+    /* fallback to generic content type if not found */
+    if (content.IsEmpty()) {
+        if (item.IsVideo() || item.IsVideoDb() )
+            content = "video/" + ext;
+        else if (item.IsAudio() || item.IsMusicDb() )
+            content = "audio/" + ext;
+        else if (item.IsPicture() )
+            content = "image/" + ext;
+    }
+
+    /* nothing we can figure out */
+    if (content.IsEmpty()) {
+        content = "application/octet-stream";
+    }
+
+    return content;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::GetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_String
+CUPnPServer::GetProtocolInfo(const CFileItem& item, const char* protocol)
+{
+    NPT_String proto = protocol;
+
+    /* fixup the protocol just in case nothing was passed */
+    if (proto.IsEmpty()) {
+        proto = item.GetAsUrl().GetProtocol();
+    }
+
+    /*
+       map protocol to right prefix and use xbmc-get for
+       unsupported UPnP protocols for other xbmc clients
+       TODO: add rtsp ?
+    */
+    if (proto == "http") {
+        proto = "http-get";
+    } else {
+        proto = "xbmc-get";
+    }
+
+    /* we need a valid extension to retrieve the mimetype for the protocol info */
+    NPT_String content = GetContentType(item);
+
+    /* setup dlna strings, wish i knew what all of they mean */
+    NPT_String extra = "DLNA.ORG_OP=01;DLNA.ORG_CI=0";
+    if (content == "audio/mpeg")
+        extra.Insert("DLNA.ORG_PN=MP3;");
+    else if (content == "audio/mp4")
+        extra.Insert("DLNA.ORG_PN=AAC_ISO_320;");
+    else if (content == "audio/x-wav")
+        extra.Insert("DLNA.ORG_PN=WAV;");
+    else if (content == "audio/x-ms-wma")
+        extra.Insert("DLNA.ORG_PN=WMABASE;");
+    else if ((content == "image/jpeg") || (content == "image/jp2"))
+        extra.Insert("DLNA.ORG_PN=JPEG_LRG;");
+    else if (content == "image/png")
+        extra.Insert("DLNA.ORG_PN=PNG_LRG;");
+    else if (content == "image/bmp")
+        extra.Insert("DLNA.ORG_PN=BMP_LRG;");
+    else if (content == "image/tiff")
+        extra.Insert("DLNA.ORG_PN=TIFF_LRG;");
+    else if (content == "image/gif")
+        extra.Insert("DLNA.ORG_PN=GIF_LRG;");
+    else if (content == "video/avi")
+        extra.Insert("DLNA.ORG_PN=AVI;");
+    else if (content == "video/mpeg")
+        extra.Insert("DLNA.ORG_PN=MPEG_PS_PAL;");
+    else if (content == "video/mp4")
+        extra.Insert("DLNA.ORG_PN=MPEG4_P2_SP_AAC;");
+    else if (content == "video/x-ms-wmv")
+        extra.Insert("DLNA.ORG_PN=WMVMED_FULL;");
+    else if (content == "video/x-msvideo")
+        extra.Insert("DLNA.ORG_PN=AVI;");
+    else
+        extra = "*";
+
+    // TEST: override for 360
+    //extra = "*";
+
+    proto += ":*:" + content + ":" + extra;
+    return proto;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::PopulateObjectFromTag
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::PopulateObjectFromTag(CMusicInfoTag&         tag,
+                                   PLT_MediaObject&       object,
+                                   NPT_String*            file_path, /* = NULL */
+                                   PLT_MediaItemResource* resource   /* = NULL */)
+{
+    // some usefull buffers
+    CStdStringArray strings;
+
+    if (!tag.GetURL().IsEmpty() && file_path)
+      *file_path = tag.GetURL();
+
+    StringUtils::SplitString(tag.GetGenre(), " / ", strings);
+    for(CStdStringArray::iterator it = strings.begin(); it != strings.end(); it++) {
+        object.m_Affiliation.genre.Add((*it).c_str());
+    }
+
+    object.m_Title = tag.GetTitle();
+    object.m_Affiliation.album = tag.GetAlbum();
+    object.m_People.artists.Add(tag.GetArtist().c_str());
+    object.m_People.artists.Add(tag.GetArtist().c_str(), "Performer");
+    object.m_People.artists.Add(!tag.GetAlbumArtist().empty()?tag.GetAlbumArtist().c_str():tag.GetArtist().c_str(), "AlbumArtist");
+    object.m_Creator = tag.GetArtist();
+    object.m_MiscInfo.original_track_number = tag.GetTrackNumber();
+    if (resource) resource->m_Duration = tag.GetDuration();
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::PopulateObjectFromTag
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::PopulateObjectFromTag(CVideoInfoTag&         tag,
+                                   PLT_MediaObject&       object,
+                                   NPT_String*            file_path, /* = NULL */
+                                   PLT_MediaItemResource* resource   /* = NULL */)
+{
+    // some usefull buffers
+    CStdStringArray strings;
+
+    if (!tag.m_strFileNameAndPath.IsEmpty() && file_path)
+      *file_path = tag.m_strFileNameAndPath;
+
+    if (tag.m_iDbId != -1 ) {
+        if (tag.m_strShowTitle.IsEmpty()) {
+          object.m_ObjectClass.type = "object.item.videoItem"; // XBox 360 wants object.item.videoItem instead of object.item.videoItem.movie, is WMP happy?
+          object.m_Affiliation.album = "[Unknown Series]"; // required to make WMP to show title
+          object.m_Title = tag.m_strTitle;
+        } else {
+          object.m_ObjectClass.type = "object.item.videoItem.videoBroadcast";
+          object.m_Affiliation.album = tag.m_strShowTitle;
+          object.m_Title = tag.m_strShowTitle + " - ";
+          object.m_Title += "S" + ("0" + NPT_String::FromInteger(tag.m_iSeason)).Right(2);
+          object.m_Title += "E" + ("0" + NPT_String::FromInteger(tag.m_iEpisode)).Right(2);
+          object.m_Title += " : " + tag.m_strTitle;
+        }
+    }
+
+    StringUtils::SplitString(tag.m_strGenre, " / ", strings);
+    for(CStdStringArray::iterator it = strings.begin(); it != strings.end(); it++) {
+        object.m_Affiliation.genre.Add((*it).c_str());
+    }
+
+    for(CVideoInfoTag::iCast it = tag.m_cast.begin();it != tag.m_cast.end();it++) {
+        object.m_People.actors.Add(it->strName.c_str(), it->strRole.c_str());
+    }
+    object.m_People.director = tag.m_strDirector;
+
+    object.m_Description.description = tag.m_strTagLine;
+    object.m_Description.long_description = tag.m_strPlot;
+    if (resource) resource->m_Duration = StringUtils::TimeStringToSeconds(tag.m_strRuntime.c_str());
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::CorrectAllItemsSortHack
++---------------------------------------------------------------------*/
+const CStdString&
+CUPnPServer::CorrectAllItemsSortHack(const CStdString &item)
+{
+    // This is required as in order for the "* All Albums" etc. items to sort
+    // correctly, they must have fake artist/album etc. information generated.
+    // This looks nasty if we attempt to render it to the GUI, thus this (further)
+    // workaround
+    if ((item.size() == 1 && item[0] == 0x01) || (item.size() > 1 && ((unsigned char) item[1]) == 0xff))
+        return StringUtils::EmptyString;
+
+    return item;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::BuildObject
++---------------------------------------------------------------------*/
+PLT_MediaObject*
+CUPnPServer::BuildObject(const CFileItem&              item,
+                         NPT_String&                   file_path,
+                         bool                          with_count,
+                         const NPT_HttpRequestContext& context,
+                         CUPnPServer*                  upnp_server /* = NULL */)
+{
+    PLT_MediaItemResource resource;
+    PLT_MediaObject*      object = NULL;
+
+    CLog::Log(LOGDEBUG, "Building didl for object '%s'", (const char*)item.m_strPath);
+
+    // get list of ip addresses
+    NPT_List<NPT_String> ips;
+    NPT_CHECK_LABEL(PLT_UPnPMessageHelper::GetIPAddresses(ips), failure);
+
+    // if we're passed an interface where we received the request from
+    // move the ip to the top
+    if (context.GetLocalAddress().GetIpAddress().ToString() != "0.0.0.0") {
+        ips.Remove(context.GetLocalAddress().GetIpAddress().ToString());
+        ips.Insert(ips.GetFirstItem(), context.GetLocalAddress().GetIpAddress().ToString());
+    }
+
+    if (!item.m_bIsFolder) {
+        object = new PLT_MediaItem();
+        object->m_ObjectID = item.m_strPath;
+
+        /* Setup object type */
+        if (item.IsMusicDb() || item.IsAudio()) {
+            object->m_ObjectClass.type = "object.item.audioItem.musicTrack";
+
+            if (item.HasMusicInfoTag()) {
+                CMusicInfoTag *tag = (CMusicInfoTag*)item.GetMusicInfoTag();
+                PopulateObjectFromTag(*tag, *object, &file_path, &resource);
+            }
+        } else if (item.IsVideoDb() || item.IsVideo()) {
+            object->m_ObjectClass.type = "object.item.videoItem";
+            object->m_Affiliation.album = "[Unknown Series]"; // required to make WMP to show title
+
+            if (item.HasVideoInfoTag()) {
+                CVideoInfoTag *tag = (CVideoInfoTag*)item.GetVideoInfoTag();
+                PopulateObjectFromTag(*tag, *object, &file_path, &resource);
+            }
+        } else if (item.IsPicture()) {
+            object->m_ObjectClass.type = "object.item.imageItem.photo";
+        } else {
+            object->m_ObjectClass.type = "object.item";
+        }
+
+        // duration of zero is invalid
+        if (resource.m_Duration == 0) resource.m_Duration = -1;
+
+        // Set the resource file size
+        resource.m_Size = item.m_dwSize;
+        if (resource.m_Size == 0) {
+            struct __stat64 info;
+            if(CFile::Stat((const char*)file_path, &info) >= 0 && info.st_size >= 0) 
+              resource.m_Size = info.st_size;
+        }
+
+        // set date
+        if (item.m_dateTime.IsValid()) {
+            object->m_Date = item.m_dateTime.GetAsLocalizedDate();
+        }
+
+        if (upnp_server) {
+            // iterate through ip addresses and build list of resources
+            // through http file server
+            NPT_List<NPT_String>::Iterator ip = ips.GetFirstItem();
+            while (ip) {
+                resource.m_ProtocolInfo = GetProtocolInfo(item, "http");
+                resource.m_Uri = PLT_FileMediaServer::BuildResourceUri(upnp_server->m_FileBaseUri, *ip, file_path);
+                object->m_Resources.Add(resource);
+                ++ip;
+            }
+        }
+
+        // if the item is remote, add a direct link to the item
+        if (CUtil::IsRemote((const char*)file_path)) {
+            resource.m_ProtocolInfo = CUPnPServer::GetProtocolInfo(item, item.GetAsUrl().GetProtocol());
+            resource.m_Uri = file_path;
+
+            // if the direct link can be served directly using http, then push it in front
+            // otherwise keep the xbmc-get resource last and let a compatible client look for it
+            if (resource.m_ProtocolInfo.StartsWith("xbmc", true)) {
+                object->m_Resources.Add(resource);
+            } else {
+                object->m_Resources.Insert(object->m_Resources.GetFirstItem(), resource);
+            }
+        }
+
+        // Some upnp clients expect all audio items to have parent root id 4
+#ifdef WMP_ID_MAPPING
+        object->m_ParentID = "4";
+#endif
+    } else {
+        PLT_MediaContainer* container = new PLT_MediaContainer;
+        object = container;
+
+        /* Assign a title and id for this container */
+        container->m_ObjectID = item.m_strPath;
+        container->m_ObjectClass.type = "object.container";
+        container->m_ChildrenCount = -1;
+
+        /* this might be overkill, but hey */
+        if (item.IsMusicDb()) {
+            MUSICDATABASEDIRECTORY::NODE_TYPE node = CMusicDatabaseDirectory::GetDirectoryType(item.m_strPath);
+            switch(node) {
+                case MUSICDATABASEDIRECTORY::NODE_TYPE_ARTIST: {
+                      container->m_ObjectClass.type += ".person.musicArtist";
+                      CMusicInfoTag *tag = (CMusicInfoTag*)item.GetMusicInfoTag();
+                      if (tag) {
+                          container->m_People.artists.Add(
+                              CorrectAllItemsSortHack(tag->GetArtist()).c_str(), "Performer");
+                          container->m_People.artists.Add(
+                              CorrectAllItemsSortHack(!tag->GetAlbumArtist().empty()?tag->GetAlbumArtist():tag->GetArtist()).c_str(), "AlbumArtist");
+                      }
+#ifdef WMP_ID_MAPPING
+                      // Some upnp clients expect all artists to have parent root id 107
+                      container->m_ParentID = "107";
+#endif
+                  }
+                  break;
+                case MUSICDATABASEDIRECTORY::NODE_TYPE_ALBUM:
+                case MUSICDATABASEDIRECTORY::NODE_TYPE_ALBUM_COMPILATIONS:
+                case MUSICDATABASEDIRECTORY::NODE_TYPE_ALBUM_RECENTLY_ADDED:
+                case MUSICDATABASEDIRECTORY::NODE_TYPE_YEAR_ALBUM: {
+                      container->m_ObjectClass.type += ".album.musicAlbum";
+                      // for Sonos to be happy
+                      CMusicInfoTag *tag = (CMusicInfoTag*)item.GetMusicInfoTag();
+                      if (tag) {
+                          container->m_People.artists.Add(
+                              CorrectAllItemsSortHack(tag->GetArtist()).c_str(), "Performer");
+                          container->m_People.artists.Add(
+                              CorrectAllItemsSortHack(!tag->GetAlbumArtist().empty()?tag->GetAlbumArtist():tag->GetArtist()).c_str(), "AlbumArtist");
+                          container->m_Affiliation.album = CorrectAllItemsSortHack(tag->GetAlbum()).c_str();
+                      }
+#ifdef WMP_ID_MAPPING
+                      // Some upnp clients expect all albums to have parent root id 7
+                      container->m_ParentID = "7";
+#endif
+                  }
+                  break;
+                case MUSICDATABASEDIRECTORY::NODE_TYPE_GENRE:
+                  container->m_ObjectClass.type += ".genre.musicGenre";
+                  break;
+                default:
+                  break;
+            }
+        } else if (item.IsVideoDb()) {
+            VIDEODATABASEDIRECTORY::NODE_TYPE node = CVideoDatabaseDirectory::GetDirectoryType(item.m_strPath);
+            switch(node) {
+                case VIDEODATABASEDIRECTORY::NODE_TYPE_GENRE:
+                  container->m_ObjectClass.type += ".genre.movieGenre";
+                  break;
+                case VIDEODATABASEDIRECTORY::NODE_TYPE_MOVIES_OVERVIEW:
+                  container->m_ObjectClass.type += ".storageFolder";
+                  break;
+                default:
+                  container->m_ObjectClass.type += ".storageFolder";
+                  break;
+            }
+        } else if (item.IsPlayList()) {
+            container->m_ObjectClass.type += ".playlistContainer";
+        }
+
+        /* Get the number of children for this container */
+        if (with_count && upnp_server) {
+            if (object->m_ObjectID.StartsWith("virtualpath://")) {
+                NPT_Cardinal count = 0;
+                NPT_CHECK_LABEL(NPT_File::GetCount(file_path, count), failure);
+                container->m_ChildrenCount = count;
+            } else {
+                /* this should be a standard path */
+                // TODO - get file count of this directory
+            }
+        }
+    }
+
+    // set a title for the object
+    if (object->m_Title.IsEmpty()) {
+        if (!item.GetLabel().IsEmpty()) {
+            CStdString title = item.GetLabel();
+            if (item.IsPlayList() || !item.m_bIsFolder) CUtil::RemoveExtension(title);
+            object->m_Title = title;
+        } else {
+            CStdString title, volumeNumber;
+            CUtil::GetVolumeFromFileName(item.m_strPath, title, volumeNumber);
+            if (!item.m_bIsFolder) CUtil::RemoveExtension(title);
+            object->m_Title = title;
+        }
+    }
+    // set a thumbnail if we have one
+    if (item.HasThumbnail() && upnp_server) {
+        object->m_ExtraInfo.album_art_uri = PLT_FileMediaServer::BuildResourceUri(
+            upnp_server->m_FileBaseUri,
+            *ips.GetFirstItem(),
+            item.GetThumbnailImage());
+    }
+
+    return object;
+
+failure:
+    delete object;
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::Build
++---------------------------------------------------------------------*/
+PLT_MediaObject*
+CUPnPServer::Build(CFileItemPtr                  item,
+                   bool                          with_count,
+                   const NPT_HttpRequestContext& context,
+                   const char*                   parent_id /* = NULL */)
+{
+    PLT_MediaObject* object = NULL;
+    NPT_String       path = item->m_strPath.c_str();
+    NPT_String       share_name;
+    NPT_String       file_path;
+
+    //HACK: temporary disabling count as it thrashes HDD
+    with_count = false;
+
+    CLog::Log(LOGDEBUG, "Preparing upnp object for item '%s'", (const char*)path);
+
+    if (!CUPnPVirtualPathDirectory::SplitPath(path, share_name, file_path)) {
+        // db path handling
+
+        file_path = item->m_strPath;
+        share_name = "";
+
+        if (path.StartsWith("musicdb://")) {
+            CStdString label;
+            if (path == "musicdb://" ) {
+                item->SetLabel("Music Library");
+                item->SetLabelPreformated(true);
+            } else {
+                if (!item->HasMusicInfoTag() || !item->GetMusicInfoTag()->Loaded() )
+                    item->LoadMusicTag();
+
+                if (!item->HasThumbnail() )
+                    item->SetCachedMusicThumb();
+
+                if (item->GetLabel().IsEmpty()) {
+                    /* if no label try to grab it from node type */
+                    if (CMusicDatabaseDirectory::GetLabel((const char*)path, label)) {
+                        item->SetLabel(label);
+                        item->SetLabelPreformated(true);
+                    }
+                }
+            }
+        } else if (file_path.StartsWith("videodb://")) {
+            CStdString label;
+            if (path == "videodb://" ) {
+                item->SetLabel("Video Library");
+                item->SetLabelPreformated(true);
+            } else {
+                if (!item->HasVideoInfoTag()) {
+                    DIRECTORY::VIDEODATABASEDIRECTORY::CQueryParams params;
+                    DIRECTORY::VIDEODATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo((const char*)path, params);
+
+                    CVideoDatabase db;
+                    if (!db.Open() ) return NULL;
+
+                    if (params.GetMovieId() >= 0 )
+                        db.GetMovieInfo((const char*)path, *item->GetVideoInfoTag(), params.GetMovieId());
+                    else if (params.GetEpisodeId() >= 0 )
+                        db.GetEpisodeInfo((const char*)path, *item->GetVideoInfoTag(), params.GetEpisodeId());
+                    else if (params.GetTvShowId() >= 0 )
+                        db.GetTvShowInfo((const char*)path, *item->GetVideoInfoTag(), params.GetTvShowId());
+                }
+
+                // try to grab title from tag
+                if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_strTitle.IsEmpty()) {
+                    item->SetLabel(item->GetVideoInfoTag()->m_strTitle);
+                    item->SetLabelPreformated(true);
+                }
+
+                // try to grab it from the folder
+                if (item->GetLabel().IsEmpty()) {
+                    if (CVideoDatabaseDirectory::GetLabel((const char*)path, label)) {
+                        item->SetLabel(label);
+                        item->SetLabelPreformated(true);
+                    }
+                }
+
+                if (!item->HasThumbnail() )
+                    item->SetCachedVideoThumb();
+            }
+        }
+
+        // not a virtual path directory, new system
+        object = BuildObject(*item.get(), file_path, with_count, context, this);
+
+        // set parent id if passed, otherwise it should have been determined
+        if (object && parent_id) {
+            object->m_ParentID = parent_id;
+        }
+    } else {
+        // virtualpath:// handling
+
+        path.TrimRight("/");
+        if (file_path.GetLength()) {
+            // make sure the path starts with something that is shared given the share
+            if (!CUPnPVirtualPathDirectory::FindSourcePath(share_name, file_path, true)) goto failure;
+
+            // this is not a virtual directory
+            object = BuildObject(*item.get(), file_path, with_count, context, this);
+            if (!object) goto failure;
+
+            // override object id & change the class if it's an item
+            // and it's not been set previously
+            if (object->m_ObjectClass.type == "object.item") {
+                if (share_name == "virtualpath://upnpmusic")
+                    object->m_ObjectClass.type = "object.item.audioitem";
+                else if (share_name == "virtualpath://upnpvideo")
+                    object->m_ObjectClass.type = "object.item.videoitem";
+                else if (share_name == "virtualpath://upnppictures")
+                    object->m_ObjectClass.type = "object.item.imageitem";
+            }
+
+            if (parent_id) {
+                object->m_ParentID = parent_id;
+            } else {
+                // populate parentid manually
+                if (CUPnPVirtualPathDirectory::FindSourcePath(share_name, file_path)) {
+                    // found the file_path as one of the path of the share
+                    // this means the parent id is the share
+                    object->m_ParentID = share_name;
+                } else {
+                    // we didn't find the path, find the parent path
+                    NPT_String parent_path = GetParentFolder(file_path);
+                    if (parent_path.IsEmpty()) goto failure;
+
+                    // try again with parent
+                    if (CUPnPVirtualPathDirectory::FindSourcePath(share_name, parent_path)) {
+                        // found the file_path parent folder as one of the path of the share
+                        // this means the parent id is the share
+                        object->m_ParentID = share_name;
+                    } else {
+                        object->m_ParentID = share_name + "/" + parent_path;
+                    }
+                }
+            }
+
+            // old style, needs virtual path prefix
+            if (!object->m_ObjectID.StartsWith("virtualpath://"))
+                object->m_ObjectID = share_name + "/" + object->m_ObjectID;
+
+        } else {
+            object = new PLT_MediaContainer;
+            object->m_Title = item->GetLabel();
+            object->m_ObjectClass.type = "object.container";
+            object->m_ObjectID = path;
+
+            if (path == "virtualpath://upnproot") {
+                // root
+                object->m_ObjectID = "0";
+                object->m_ParentID = "-1";
+                // root has 5 children
+                if (with_count) {
+                    ((PLT_MediaContainer*)object)->m_ChildrenCount = 5;
+                }
+            } else if (share_name.GetLength() == 0) {
+                // no share_name means it's virtualpath://X where X=music, video or pictures
+                object->m_ParentID = "0";
+                if (with_count || true) { // we can always count these, it's quick
+                    ((PLT_MediaContainer*)object)->m_ChildrenCount = 0;
+
+                    // look up number of shares
+                    VECSOURCES *shares = NULL;
+                    if (path == "virtualpath://upnpmusic") {
+                        shares = g_settings.GetSourcesFromType("upnpmusic");
+                    } else if (path == "virtualpath://upnpvideo") {
+                        shares = g_settings.GetSourcesFromType("upnpvideo");
+                    } else if (path == "virtualpath://upnppictures") {
+                        shares = g_settings.GetSourcesFromType("upnppictures");
+                    }
+
+                    // use only shares that would some path with local files
+                    if (shares) {
+                        CUPnPVirtualPathDirectory dir;
+                        for (unsigned int i = 0; i < shares->size(); i++) {
+                            // Does this share contains any local paths?
+                            CMediaSource &share = shares->at(i);
+                            vector<CStdString> paths;
+
+                            // reconstruct share name as it could have been replaced by
+                            // a path if there was just one entry
+                            NPT_String share_name = path + "/";
+                            share_name += share.strName;
+                            if (dir.GetMatchingSource((const char*)share_name, share, paths) && paths.size()) {
+                                ((PLT_MediaContainer*)object)->m_ChildrenCount++;
+                            }
+                        }
+                    }
+                }
+            } else {
+                // this is a share name
+                CStdString mask;
+                if (share_name.StartsWith("virtualpath://upnpmusic")) {
+                    object->m_ParentID = "virtualpath://upnpmusic";
+                    mask = g_stSettings.m_musicExtensions;
+                } else if (share_name.StartsWith("virtualpath://upnpvideo")) {
+                    object->m_ParentID = "virtualpath://upnpvideo";
+                    mask = g_stSettings.m_videoExtensions;
+                } else if (share_name.StartsWith("virtualpath://upnppictures")) {
+                    object->m_ParentID = "virtualpath://upnppictures";
+                    mask = g_stSettings.m_pictureExtensions;
+                } else {
+                    // weird!
+                    goto failure;
+                }
+
+                if (with_count) {
+                    ((PLT_MediaContainer*)object)->m_ChildrenCount = 0;
+
+                    // get all the paths for a given share
+                    CMediaSource share;
+                    CUPnPVirtualPathDirectory dir;
+                    vector<CStdString> paths;
+                    if (!dir.GetMatchingSource((const char*)share_name, share, paths)) goto failure;
+                    for (unsigned int i=0; i<paths.size(); i++) {
+                        // FIXME: this is not efficient, we only need the number of items given a mask
+                        // and not the list of items
+
+                        // retrieve all the files for a given path
+                        CFileItemList items;
+                        if (CDirectory::GetDirectory(paths[i], items, mask)) {
+                            // update childcount
+                            ((PLT_MediaContainer*)object)->m_ChildrenCount += items.Size();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // remap Root virtualpath://upnproot/ to id "0"
+    if (object->m_ObjectID == "virtualpath://upnproot/")
+        object->m_ObjectID = "0";
+
+    // remap Parent Root virtualpath://upnproot/ to id "0"
+    if (object->m_ParentID == "virtualpath://upnproot/")
+        object->m_ParentID = "0";
+
+    return object;
+
+failure:
+    delete object;
+    return NULL;
+}
+
+/*----------------------------------------------------------------------
+|   TranslateWMPObjectId
++---------------------------------------------------------------------*/
+static NPT_String TranslateWMPObjectId(NPT_String id)
+{
+    if (id == "0") {
+        id = "virtualpath://upnproot/";
+    } else if (id == "15") {
+        // Xbox 360 asking for videos
+        id = "videodb://";
+    } else if (id == "16") {
+        // Xbox 360 asking for photos
+    } else if (id == "107") {
+        // Sonos uses 107 for artists root container id
+        id = "musicdb://2/";
+    } else if (id == "7") {
+        // Sonos uses 7 for albums root container id
+        id = "musicdb://3/";
+    } else if (id == "4") {
+        // Sonos uses 4 for tracks root container id
+        id = "musicdb://4/";
+    }
+
+    CLog::Log(LOGDEBUG, "UPnP Translated id to '%s'", (const char*)id);
+    return id;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::OnBrowseMetadata
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::OnBrowseMetadata(PLT_ActionReference&          action,
+                              const char*                   object_id,
+                              const NPT_HttpRequestContext& context)
+{
+    NPT_String                     didl;
+    NPT_Reference<PLT_MediaObject> object;
+    NPT_String                     id = TranslateWMPObjectId(object_id);
+    CMediaSource                   share;
+    CUPnPVirtualPathDirectory      dir;
+    vector<CStdString>             paths;
+    CFileItemPtr                   item;
+
+    CLog::Log(LOGINFO, "Received UPnP Browse Metadata request for object '%s'", (const char*)object_id);
+
+    if (id.StartsWith("virtualpath://")) {
+        id.TrimRight("/");
+        if (id == "virtualpath://upnproot") {
+            id += "/";
+            item.reset(new CFileItem((const char*)id, true));
+            item->SetLabel("Root");
+            item->SetLabelPreformated(true);
+            object = Build(item, true, context);
+        } else if (id == "virtualpath://upnpmusic") {
+            id += "/";
+            item.reset(new CFileItem((const char*)id, true));
+            item->SetLabel("Music Files");
+            item->SetLabelPreformated(true);
+            object = Build(item, true, context);
+        } else if (id == "virtualpath://upnpvideo") {
+            id += "/";
+            item.reset(new CFileItem((const char*)id, true));
+            item->SetLabel("Video Files");
+            item->SetLabelPreformated(true);
+            object = Build(item, true, context);
+        } else if (id == "virtualpath://upnppictures") {
+            id += "/";
+            item.reset(new CFileItem((const char*)id, true));
+            item->SetLabel("Picture Files");
+            item->SetLabelPreformated(true);
+            object = Build(item, true, context);
+        } else if (dir.GetMatchingSource((const char*)id, share, paths)) {
+            id += "/";
+            item.reset(new CFileItem((const char*)id, true));
+            item->SetLabel(share.strName);
+            item->SetLabelPreformated(true);
+            object = Build(item, true, context);
+        } else {
+            NPT_String share_name, file_path;
+            if (!CUPnPVirtualPathDirectory::SplitPath(id, share_name, file_path))
+                return NPT_FAILURE;
+
+            NPT_String parent_path = GetParentFolder(file_path);
+            if (parent_path.IsEmpty()) return NPT_FAILURE;
+
+            NPT_FileInfo info;
+            NPT_CHECK(NPT_File::GetInfo(file_path, &info));
+
+            item.reset(new CFileItem((const char*)id, (info.m_Type==NPT_FileInfo::FILE_TYPE_DIRECTORY)?true:false));
+            item->SetLabel((const char*)file_path.SubString(parent_path.GetLength()+1));
+            item->SetLabelPreformated(true);
+
+            // get file size
+            if (info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR) {
+                item->m_dwSize = info.m_Size;
+            }
+
+            object = Build(item, true, context);
+        }
+    } else {
+        // determine if it's a container by calling CDirectory::Exists
+        item.reset(new CFileItem((const char*)id, CDirectory::Exists((const char*)id)));
+
+        // determine parent id for shared paths only
+        // otherwise let db find out
+        CStdString parent;
+        if (!CUtil::GetParentPath((const char*)id, parent))
+          parent = "0";
+
+//#ifdef WMP_ID_MAPPING
+//        if (!id.StartsWith("musicdb://") && !id.StartsWith("videodb://")) {
+//            parent = "";
+//        }
+//#endif
+
+        object = Build(item, true, context, parent.empty()?NULL:parent.c_str());
+    }
+
+    if (object.IsNull()) return NPT_FAILURE;
+
+    NPT_String filter;
+    NPT_CHECK(action->GetArgumentValue("Filter", filter));
+
+    NPT_String tmp;
+    NPT_CHECK(PLT_Didl::ToDidl(*object.AsPointer(), filter, tmp));
+
+    /* add didl header and footer */
+    didl = didl_header + tmp + didl_footer;
+
+    NPT_CHECK(action->SetArgumentValue("Result", didl));
+    NPT_CHECK(action->SetArgumentValue("NumberReturned", "1"));
+    NPT_CHECK(action->SetArgumentValue("TotalMatches", "1"));
+
+    // update ID may be wrong here, it should be the one of the container?
+    NPT_CHECK(action->SetArgumentValue("UpdateId", "0"));
+
+    // TODO: We need to keep track of the overall SystemUpdateID of the CDS
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::OnBrowseDirectChildren
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::OnBrowseDirectChildren(PLT_ActionReference&          action,
+                                    const char*                   object_id,
+                                    const NPT_HttpRequestContext& context)
+{
+    CFileItemList items;
+    NPT_String    parent_id = TranslateWMPObjectId(object_id);
+
+    CLog::Log(LOGINFO, "Received UPnP Browse DirectChildren request for object '%s'", (const char*)object_id);
+
+    items.m_strPath = parent_id;
+    if (!items.Load()) {
+        // cache anything that takes more than a second to retrieve
+        DWORD time = GetTickCount() + 1000;
+
+        if (parent_id.StartsWith("virtualpath://")) {
+            CUPnPVirtualPathDirectory dir;
+            dir.GetDirectory((const char*)parent_id, items);
+        } else {
+            CDirectory::GetDirectory((const char*)parent_id, items);
+        }
+
+        if (items.CacheToDiscAlways() || (items.CacheToDiscIfSlow() && time < GetTickCount())) {
+            items.Save();
+        }
+    }
+
+    // Don't pass parent_id if action is Search not BrowseDirectChildren, as
+    // we want the engine to determine the best parent id, not necessarily the one
+    // passed
+    NPT_String action_name = action->GetActionDesc()->GetName();
+    return BuildResponse(action, items, context, (action_name.Compare("Search", true)==0)?NULL:parent_id.GetChars());
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::BuildResponse
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::BuildResponse(PLT_ActionReference&          action,
+                           CFileItemList&                items,
+                           const NPT_HttpRequestContext& context,
+                           const char*                   parent_id /* = NULL */)
+{
+    NPT_String filter;
+    NPT_String startingInd;
+    NPT_String reqCount;
+
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+    NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd));
+    NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount));
+
+    NPT_UInt32 start_index, stop_index, req_count, max_count;
+    NPT_CHECK_SEVERE(startingInd.ToInteger(start_index));
+    NPT_CHECK_SEVERE(reqCount.ToInteger(req_count));
+
+    CLog::Log(LOGDEBUG, "Building UPnP response with filter '%s', starting @ %d with %d requested",
+        (const char*)filter,
+        start_index,
+        req_count);
+
+    // won't return more than UPNP_MAX_RETURNED_ITEMS items at a time to keep things smooth
+    // 0 requested means as much as you can
+    max_count  = (req_count == 0)?m_MaxReturnedItems:min((unsigned long)req_count, (unsigned long)m_MaxReturnedItems);
+    stop_index = min((unsigned long)(start_index + max_count), (unsigned long)items.Size()); // don't return more than we can
+
+    NPT_Cardinal count = 0;
+    NPT_String didl = didl_header;
+    PLT_MediaObjectReference object;
+    for (unsigned long i=start_index; i<stop_index; ++i) {
+        object = Build(items[i], true, context, parent_id);
+        if (object.IsNull()) {
+            continue;
+        }
+
+        NPT_String tmp;
+        NPT_CHECK(PLT_Didl::ToDidl(*object.AsPointer(), filter, tmp));
+
+        // Neptunes string growing is dead slow for small additions
+        if (didl.GetCapacity() < tmp.GetLength() + didl.GetLength()) {
+            didl.Reserve((tmp.GetLength() + didl.GetLength())*2);
+        }
+        didl += tmp;
+        ++count;
+    }
+
+    didl += didl_footer;
+
+    CLog::Log(LOGDEBUG, "Returning UPnP response with %d items out of %d total matches",
+        count,
+        items.Size());
+
+    NPT_CHECK(action->SetArgumentValue("Result", didl));
+    NPT_CHECK(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(count)));
+    NPT_CHECK(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(items.Size())));
+    NPT_CHECK(action->SetArgumentValue("UpdateId", "0"));
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   FindSubCriteria
++---------------------------------------------------------------------*/
+static
+NPT_String FindSubCriteria(NPT_String criteria, const char* name)
+{
+    NPT_String result;
+    int search = criteria.Find(name);
+    if (search >= 0) {
+        criteria = criteria.Right(criteria.GetLength() - search - NPT_StringLength(name));
+        criteria.TrimLeft(" ");
+        if (criteria.GetLength()>0 && criteria[0] == '=') {
+            criteria.TrimLeft("= ");
+            if (criteria.GetLength()>0 && criteria[0] == '\"') {
+                search = criteria.Find("\"", 1);
+                if (search > 0) result = criteria.SubString(1, search-1);
+            }
+        }
+    }
+    return result;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::OnSearch
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::OnSearch(PLT_ActionReference&          action,
+                      const NPT_String&             object_id,
+                      const NPT_String&             searchCriteria,
+                      const NPT_HttpRequestContext& context)
+
+{
+    CLog::Log(LOGDEBUG, "Received Search request for object '%s'", (const char*)object_id);
+
+    if (object_id.StartsWith("musicdb://")) {
+        NPT_String id = object_id;
+        // we browse for all tracks given a genre, artist or album
+        if (searchCriteria.Find("object.item.audioItem") >= 0) {
+            if (!id.EndsWith("/")) id += "/";
+            NPT_Cardinal count = id.SubString(10).Split("/").GetItemCount();
+            // remove extra empty node count
+            count = count?count-1:0;
+
+            // genre
+            if (id.StartsWith("musicdb://1/")) {
+                // all tracks of all genres
+                if (count == 1)
+                    id += "-1/-1/-1/";
+                // all tracks of a specific genre
+                else if (count == 2)
+                    id += "-1/-1/";
+                // all tracks of a specific genre of a specfic artist
+                else if (count == 3)
+                    id += "-1/";
+            } else if (id.StartsWith("musicdb://2/")) {
+                // all tracks by all artists
+                if (count == 1)
+                    id += "-1/-1/";
+                // all tracks of a specific artist
+                else if (count == 2)
+                    id += "-1/";
+            } else if (id.StartsWith("musicdb://3/")) {
+                // all albums ?
+                if (count == 1) id += "-1/";
+            }
+        }
+        return OnBrowseDirectChildren(action, id, context);
+    } else if (searchCriteria.Find("object.item.audioItem") >= 0) {
+        // look for artist, album & genre filters
+        NPT_String genre = FindSubCriteria(searchCriteria, "upnp:genre");
+        NPT_String album = FindSubCriteria(searchCriteria, "upnp:album");
+        NPT_String artist = FindSubCriteria(searchCriteria, "upnp:artist");
+        // sonos looks for microsoft specific stuff
+        artist = artist.GetLength()?artist:FindSubCriteria(searchCriteria, "microsoft:artistPerformer");
+        artist = artist.GetLength()?artist:FindSubCriteria(searchCriteria, "microsoft:artistAlbumArtist");
+        artist = artist.GetLength()?artist:FindSubCriteria(searchCriteria, "microsoft:authorComposer");
+
+        CMusicDatabase database;
+        database.Open();
+
+        if (genre.GetLength() > 0) {
+            // all tracks by genre filtered by artist and/or album
+            CStdString strPath;
+            strPath.Format("musicdb://1/%ld/%ld/%ld/",
+                database.GetGenreByName((const char*)genre),
+                database.GetArtistByName((const char*)artist), // will return -1 if no artist
+                database.GetAlbumByName((const char*)album));  // will return -1 if no album
+
+            return OnBrowseDirectChildren(action, strPath.c_str(), context);
+        } else if (artist.GetLength() > 0) {
+            // all tracks by artist name filtered by album if passed
+            CStdString strPath;
+            strPath.Format("musicdb://2/%ld/%ld/",
+                database.GetArtistByName((const char*)artist),
+                database.GetAlbumByName((const char*)album)); // will return -1 if no album
+
+            return OnBrowseDirectChildren(action, strPath.c_str(), context);
+        } else if (album.GetLength() > 0) {
+            // all tracks by album name
+            CStdString strPath;
+            strPath.Format("musicdb://3/%ld/",
+                database.GetAlbumByName((const char*)album));
+
+            return OnBrowseDirectChildren(action, strPath.c_str(), context);
+        }
+
+        // browse all songs
+        return OnBrowseDirectChildren(action, "musicdb://4/", context);
+    } else if (searchCriteria.Find("object.container.album.musicAlbum") >= 0) {
+        // sonos filters by genre
+        NPT_String genre = FindSubCriteria(searchCriteria, "upnp:genre");
+
+        // 360 hack: artist/albums using search
+        NPT_String artist = FindSubCriteria(searchCriteria, "upnp:artist");
+        // sonos looks for microsoft specific stuff
+        artist = artist.GetLength()?artist:FindSubCriteria(searchCriteria, "microsoft:artistPerformer");
+        artist = artist.GetLength()?artist:FindSubCriteria(searchCriteria, "microsoft:artistAlbumArtist");
+        artist = artist.GetLength()?artist:FindSubCriteria(searchCriteria, "microsoft:authorComposer");
+
+        CMusicDatabase database;
+        database.Open();
+
+        if (genre.GetLength() > 0) {
+            CStdString strPath;
+            strPath.Format("musicdb://1/%ld/%ld/",
+                database.GetGenreByName((const char*)genre),
+                database.GetArtistByName((const char*)artist)); // no artist should return -1
+            return OnBrowseDirectChildren(action, strPath.c_str(), context);
+        } else if (artist.GetLength() > 0) {
+            CStdString strPath;
+            strPath.Format("musicdb://2/%ld/",
+                database.GetArtistByName((const char*)artist));
+            return OnBrowseDirectChildren(action, strPath.c_str(), context);
+        }
+
+        // all albums
+        return OnBrowseDirectChildren(action, "musicdb://3/", context);
+    } else if (searchCriteria.Find("object.container.person.musicArtist") >= 0) {
+        // Sonos filters by genre
+        NPT_String genre = FindSubCriteria(searchCriteria, "upnp:genre");
+        if (genre.GetLength() > 0) {
+            CMusicDatabase database;
+            database.Open();
+            CStdString strPath;
+            strPath.Format("musicdb://1/%ld/", database.GetGenreByName((const char*)genre));
+            return OnBrowseDirectChildren(action, strPath.c_str(), context);
+        }
+        return OnBrowseDirectChildren(action, "musicdb://2/", context);
+    }  else if (searchCriteria.Find("object.container.genre.musicGenre") >= 0) {
+        return OnBrowseDirectChildren(action, "musicdb://1/", context);
+    } else if (searchCriteria.Find("object.container.playlistContainer") >= 0) {
+        return OnBrowseDirectChildren(action, "special://musicplaylists/", context);
+    } else if (searchCriteria.Find("object.item.videoItem") >= 0) {
+      CFileItemList items, itemsall;
+
+      CVideoDatabase database;
+      if (!database.Open()) {
+        action->SetError(800, "Internal Error");
+        return NPT_SUCCESS;
+      }
+
+      if (!database.GetMoviesNav("videodb://1/2/", items)) {
+        action->SetError(800, "Internal Error");
+        return NPT_SUCCESS;
+      }
+      itemsall.Append(items);
+      items.Clear();
+
+      // TODO - set proper base url for this
+      if (!database.GetEpisodesNav("videodb://2/0/", items)) {
+        action->SetError(800, "Internal Error");
+        return NPT_SUCCESS;
+      }
+      itemsall.Append(items);
+      items.Clear();
+
+      return BuildResponse(action, itemsall, context, NULL);
+  }
+
+  return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPServer::ServeFile
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPServer::ServeFile(NPT_HttpRequest&              request,
+                       const NPT_HttpRequestContext& context,
+                       NPT_HttpResponse&             response,
+                       const NPT_String&             uri_path,
+                       const NPT_String&             file_path)
+{
+    CLog::Log(LOGDEBUG, "Received request to serve '%s'", (const char*)file_path);
+
+    // File requested
+    NPT_String path = m_FileBaseUri.GetPath();
+    if (path.Compare(uri_path.Left(path.GetLength()), true) == 0 &&
+        file_path.Left(8).Compare("stack://", true) == 0) {
+
+        NPT_List<NPT_String> files = file_path.SubString(8).Split(" , ");
+        if (files.GetItemCount() == 0) {
+            response.SetStatus(404, "File Not Found");
+            return NPT_SUCCESS;
+        }
+
+        NPT_String output;
+        output.Reserve(file_path.GetLength()*2);
+
+        NPT_List<NPT_String>::Iterator url = files.GetFirstItem();
+        for (;url;url++) {
+            NPT_HttpUrl uri = m_FileBaseUri;
+            NPT_HttpUrlQuery query;
+            query.AddField("path", *url);
+            uri.SetHost(context.GetLocalAddress().GetIpAddress().ToString());
+            uri.SetQuery(query.ToString());
+
+            output += uri.ToString();
+            output += "\n\r";
+        }
+
+        PLT_HttpHelper::SetContentType(response, "audio/x-mpegurl");
+        PLT_HttpHelper::SetBody(response, (const char*)output, output.GetLength());
+        return NPT_SUCCESS;
+    }
+
+    return PLT_MediaConnect::ServeFile(request,
+                                       context,
+                                       response,
+                                       uri_path,
+                                       file_path);
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer
++---------------------------------------------------------------------*/
+class CUPnPRenderer : public PLT_MediaRenderer
+{
+public:
+    CUPnPRenderer(const char*  friendly_name,
+                  bool         show_ip = false,
+                  const char*  uuid = NULL,
+                  unsigned int port = 0);
+
+    void UpdateState();
+
+    // Http server handler
+    virtual NPT_Result ProcessHttpRequest(NPT_HttpRequest&              request,
+                                          const NPT_HttpRequestContext& context,
+                                          NPT_HttpResponse&             response);
+
+    // AVTransport methods
+    virtual NPT_Result OnNext(PLT_ActionReference& action);
+    virtual NPT_Result OnPause(PLT_ActionReference& action);
+    virtual NPT_Result OnPlay(PLT_ActionReference& action);
+    virtual NPT_Result OnPrevious(PLT_ActionReference& action);
+    virtual NPT_Result OnStop(PLT_ActionReference& action);
+    virtual NPT_Result OnSeek(PLT_ActionReference& action);
+    virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action);
+
+    // RenderingControl methods
+    virtual NPT_Result OnSetVolume(PLT_ActionReference& action);
+    virtual NPT_Result OnSetMute(PLT_ActionReference& action);
+
+private:
+    NPT_Result SetupServices(PLT_DeviceData& data);
+    NPT_Result GetProtocolInfo(NPT_String& info,
+                                 NPT_String& proto,
+                                 NPT_String& mask,
+                                 NPT_String& content,
+                                 NPT_String& extra);
+    NPT_Result GetMetadata(NPT_String& meta);
+    NPT_Result PlayMedia(const char* uri,
+                         const char* metadata = NULL,
+                         PLT_Action* action = NULL);
+};
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::CUPnPRenderer
++---------------------------------------------------------------------*/
+CUPnPRenderer::CUPnPRenderer(const char*  friendly_name,
+                             bool         show_ip /* = false */,
+                             const char*  uuid /* = NULL */,
+                             unsigned int port /* = 0 */) :
+    PLT_MediaRenderer(friendly_name,
+                      show_ip,
+                      uuid,
+                      port)
+{
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::SetupServices(PLT_DeviceData& data)
+{
+    NPT_CHECK(PLT_MediaRenderer::SetupServices(data));
+    // update what we can play
+    PLT_Service* service = NULL;
+    NPT_CHECK_FATAL(FindServiceByType("urn:schemas-upnp-org:service:ConnectionManager:1", service));
+    service->SetStateVariable("SinkProtocolInfo",
+        "http-get:*:*:*,http-get:*:video/mpeg:*,http-get:*:audio/mpeg:*,xbmc-get:*:*:*");
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::ProcessHttpRequest
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::ProcessHttpRequest(NPT_HttpRequest&              request,
+                                  const NPT_HttpRequestContext& context,
+                                  NPT_HttpResponse&             response)
+{
+    // get the address of who sent us some data back
+    NPT_String  ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+    NPT_String  method     = request.GetMethod();
+    NPT_String  protocol   = request.GetProtocol();
+    NPT_HttpUrl url        = request.GetUrl();
+
+    if (url.GetPath() == "/thumb.jpg") {
+        NPT_HttpUrlQuery query(url.GetQuery());
+        NPT_String filepath = query.GetField("path");
+        if (!filepath.IsEmpty()) {
+            NPT_HttpEntity* entity = response.GetEntity();
+            if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+            // check the method
+            if (request.GetMethod() != NPT_HTTP_METHOD_GET &&
+                request.GetMethod() != NPT_HTTP_METHOD_HEAD) {
+                response.SetStatus(405, "Method Not Allowed");
+                return NPT_SUCCESS;
+            }
+
+            // ensure that the request's path is a valid thumb path
+            if (CUtil::IsRemote(filepath.GetChars()) ||
+                !filepath.StartsWith(g_settings.GetUserDataFolder())) {
+                response.SetStatus(404, "Not Found");
+                return NPT_SUCCESS;
+            }
+
+            // prevent hackers from accessing files outside of our root
+            if ((filepath.Find("/..") >= 0) || (filepath.Find("\\..") >=0)) {
+                return NPT_FAILURE;
+            }
+
+            // open the file
+            NPT_File file(filepath);
+            NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_READ);
+            if (NPT_FAILED(result)) {
+                response.SetStatus(404, "Not Found");
+                return NPT_SUCCESS;
+            }
+            NPT_InputStreamReference stream;
+            file.GetInputStream(stream);
+            entity->SetContentType(CUPnPServer::GetContentType(filepath));
+            entity->SetInputStream(stream, true);
+
+            return NPT_SUCCESS;
+        }
+    }
+
+    return PLT_MediaRenderer::ProcessHttpRequest(request, context, response);
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::UpdateState
++---------------------------------------------------------------------*/
+void
+CUPnPRenderer::UpdateState()
+{
+    PLT_Service *avt, *rct;
+    if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", avt)))
+        return;
+    if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:RenderingControl:1", rct)))
+        return;
+
+    CStdString buffer;
+    int volume;
+    if (g_stSettings.m_bMute) {
+        rct->SetStateVariable("Mute", "1");
+        volume = g_stSettings.m_iPreMuteVolumeLevel;
+    } else {
+        rct->SetStateVariable("Mute", "0");
+        volume = g_application.GetVolume();
+    }
+
+    buffer.Format("%d", volume);
+    rct->SetStateVariable("Volume", buffer.c_str());
+
+    buffer.Format("%d", 256 * (volume * 60 - 60) / 100);
+    rct->SetStateVariable("VolumeDb", buffer.c_str());
+
+    if (g_application.IsPlaying() || g_application.IsPaused()) {
+        if (g_application.IsPaused()) {
+            avt->SetStateVariable("TransportState", "PAUSED_PLAYBACK");
+        } else {
+            avt->SetStateVariable("TransportState", "PLAYING");
+        }
+
+        avt->SetStateVariable("TransportStatus", "OK");
+        avt->SetStateVariable("TransportPlaySpeed", (const char*)NPT_String::FromInteger(g_application.GetPlaySpeed()));
+        avt->SetStateVariable("NumberOfTracks", "1");
+        avt->SetStateVariable("CurrentTrack", "1");
+
+        buffer = g_infoManager.GetCurrentPlayTime(TIME_FORMAT_HH_MM_SS);
+        avt->SetStateVariable("RelativeTimePosition", buffer.c_str());
+        StringUtils::SecondsToTimeString((long)g_infoManager.GetTotalPlayTime(), buffer, TIME_FORMAT_HH_MM_SS);
+        avt->SetStateVariable("AbsoluteTimePosition", buffer.c_str());
+
+        buffer = g_infoManager.GetDuration(TIME_FORMAT_HH_MM_SS);
+        if (buffer.length() > 0) {
+          avt->SetStateVariable("CurrentTrackDuration", buffer.c_str());
+          avt->SetStateVariable("CurrentMediaDuration", buffer.c_str());
+        } else {
+          avt->SetStateVariable("CurrentTrackDuration", "00:00:00");
+          avt->SetStateVariable("CurrentMediaDuration", "00:00:00");
+        }
+
+        avt->SetStateVariable("AVTransportURI", g_application.CurrentFile().c_str());
+        avt->SetStateVariable("CurrentTrackURI", g_application.CurrentFile().c_str());
+
+        NPT_String metadata;
+        avt->GetStateVariableValue("AVTransportURIMetaData", metadata);
+        // try to recreate the didl dynamically if not set
+        if (metadata.IsEmpty()) {
+            GetMetadata(metadata);
+        }
+        avt->SetStateVariable("CurrentTrackMetadata", metadata);
+        avt->SetStateVariable("AVTransportURIMetaData", metadata);
+    } else {
+        avt->SetStateVariable("TransportState", "STOPPED");
+        avt->SetStateVariable("TransportPlaySpeed", "1");
+        avt->SetStateVariable("NumberOfTracks", "0");
+        avt->SetStateVariable("CurrentTrack", "0");
+        avt->SetStateVariable("RelativeTimePosition", "00:00:00");
+        avt->SetStateVariable("AbsoluteTimePosition", "00:00:00");
+        avt->SetStateVariable("CurrentTrackDuration", "00:00:00");
+        avt->SetStateVariable("CurrentMediaDuration", "00:00:00");
+    }
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::GetMetadata
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::GetMetadata(NPT_String& meta)
+{
+    NPT_Result res = NPT_FAILURE;
+    const CFileItem &item = g_application.CurrentFileItem();
+    NPT_String file_path;
+    PLT_MediaObject* object = CUPnPServer::BuildObject(item,
+                                                       file_path,
+                                                       false,
+                                                       NPT_HttpRequestContext());
+    if (object) {
+        // fetch the path to the thumbnail
+        CStdString thumb = g_infoManager.GetImage(MUSICPLAYER_COVER, (DWORD)-1); //TODO: Only audio for now
+
+#if defined(HAS_LINUX_NETWORK) || defined(HAS_WIN32_NETWORK)
+        NPT_String ip;
+        if (g_application.getNetwork().GetFirstConnectedInterface()) {
+            ip = g_application.getNetwork().GetFirstConnectedInterface()->GetCurrentIPAddress().c_str();
+        }
+#else
+        NPT_String ip = g_application.getNetwork().m_networkinfo.ip;
+#endif
+        // build url, use the internal device http server to serv the image
+        NPT_HttpUrlQuery query;
+        query.AddField("path", thumb.c_str());
+        object->m_ExtraInfo.album_art_uri = NPT_HttpUrl(
+            ip,
+            m_URLDescription.GetPort(),
+            "/thumb.jpg",
+            query.ToString()).ToString();
+
+        res = PLT_Didl::ToDidl(*object, "*", meta);
+        delete object;
+    }
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnNext
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnNext(PLT_ActionReference& action)
+{
+    g_application.getApplicationMessenger().PlayListPlayerNext();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnPause
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnPause(PLT_ActionReference& action)
+{
+    if (!g_application.IsPaused())
+      g_application.getApplicationMessenger().MediaPause();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnPlay
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnPlay(PLT_ActionReference& action)
+{
+    if (g_application.IsPaused()) {
+      g_application.getApplicationMessenger().MediaPause();
+    } else if (!g_application.IsPlaying()) {
+        NPT_String uri, meta;
+        PLT_Service* service;
+        // look for value set previously by SetAVTransportURI
+        NPT_CHECK_SEVERE(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service));
+        NPT_CHECK_SEVERE(service->GetStateVariableValue("AVTransportURI", uri));
+        NPT_CHECK_SEVERE(service->GetStateVariableValue("AVTransportURIMetaData", meta));
+
+        // if not set, use the current file being played
+        PlayMedia(uri, meta);
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnPrevious
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnPrevious(PLT_ActionReference& action)
+{
+    g_application.getApplicationMessenger().PlayListPlayerPrevious();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnStop
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnStop(PLT_ActionReference& action)
+{
+    g_application.getApplicationMessenger().MediaStop();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnSetAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnSetAVTransportURI(PLT_ActionReference& action)
+{
+    NPT_String uri, meta;
+    PLT_Service* service;
+    NPT_CHECK_SEVERE(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service));
+
+    NPT_CHECK_SEVERE(action->GetArgumentValue("CurrentURI", uri));
+    NPT_CHECK_SEVERE(action->GetArgumentValue("CurrentURIMetaData", meta));
+
+    // if not playing already, just keep around uri & metadata
+    // and wait for play command
+    if (!g_application.IsPlaying()) {
+        service->SetStateVariable("TransportState", "STOPPED");
+        service->SetStateVariable("TransportStatus", "OK");
+        service->SetStateVariable("TransportPlaySpeed", "1");
+        service->SetStateVariable("AVTransportURI", uri);
+        service->SetStateVariable("AVTransportURIMetaData", meta);
+
+        NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable());
+        return NPT_SUCCESS;
+    }
+
+    return PlayMedia(uri, meta, action.AsPointer());
+}
+
+NPT_Result
+CUPnPRenderer::GetProtocolInfo(NPT_String& info, NPT_String& proto, NPT_String& mask, NPT_String& content, NPT_String& extra)
+{
+  NPT_List<NPT_String> data = info.Split(":");
+  NPT_CHECK_FATAL(data.Get(0, proto));
+  NPT_CHECK      (data.Get(1, mask));
+  NPT_CHECK      (data.Get(2, content));
+  NPT_CHECK      (data.Get(3, extra));
+  return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::PlayMedia
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::PlayMedia(const char* uri, const char* meta, PLT_Action* action)
+{
+    PLT_Service* service;
+    NPT_CHECK_SEVERE(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service));
+
+    service->SetStateVariable("TransportState", "TRANSITIONING");
+    service->SetStateVariable("TransportStatus", "OK");
+    service->SetStateVariable("TransportPlaySpeed", "1");
+
+    PLT_MediaObjectListReference list;
+    PLT_MediaObject*             object = NULL;
+
+    if(meta && NPT_SUCCEEDED(PLT_Didl::FromDidl(meta, list)))
+      list->Get(0, object);
+
+    if(object) {
+        CFileItem item(uri, false);
+
+        PLT_MediaItemResource* res = object->m_Resources.GetFirstItem();
+        for(NPT_Cardinal i = 0; i < object->m_Resources.GetItemCount(); i++) {
+          if(object->m_Resources[i].m_Uri == uri) { 
+            res = &object->m_Resources[i];
+            break;
+          }
+        }
+        for(NPT_Cardinal i = 0; i < object->m_Resources.GetItemCount(); i++) {
+          if(object->m_Resources[i].m_ProtocolInfo.StartsWith("xbmc-get:")) {
+            res = &object->m_Resources[i];
+            item.m_strPath = res->m_Uri;
+            break;
+          }
+        }
+
+        NPT_String proto, mask, content, extra;
+        if(res) {
+          NPT_CHECK(GetProtocolInfo(res->m_ProtocolInfo, proto, mask, content, extra));
+          item.SetContentType((const char*)content);
+        }
+
+        item.m_dateTime.SetFromDateString((const char*)object->m_Date);
+        item.m_strTitle = (const char*)object->m_Title;
+        item.SetLabel((const char*)object->m_Title);
+        item.SetLabelPreformated(true);
+        item.SetThumbnailImage((const char*)object->m_ExtraInfo.album_art_uri);
+        if       (object->m_ObjectClass.type.StartsWith("object.item.audioItem")) {            
+            if(NPT_SUCCEEDED(CUPnP::PopulateTagFromObject(*item.GetMusicInfoTag(), *object, res)))
+                item.SetLabelPreformated(false);
+        } else if(object->m_ObjectClass.type.StartsWith("object.item.videoItem")) {
+            if(NPT_SUCCEEDED(CUPnP::PopulateTagFromObject(*item.GetVideoInfoTag(), *object, res)))
+                item.SetLabelPreformated(false);
+        } else if(object->m_ObjectClass.type.StartsWith("object.item.imageItem")) {
+        }
+        g_application.getApplicationMessenger().MediaPlay(item);
+    } else {
+        g_application.getApplicationMessenger().MediaPlay((const char*)uri);
+    }
+
+    if (!g_application.IsPlaying()) {
+        service->SetStateVariable("TransportState", "STOPPED");
+        service->SetStateVariable("TransportStatus", "ERROR_OCCURRED");
+    } else {
+        service->SetStateVariable("AVTransportURI", uri);
+        service->SetStateVariable("AVTransportURIMetaData", meta);
+    }
+
+    if (action) {
+        NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable());
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnSetVolume
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnSetVolume(PLT_ActionReference& action)
+{
+    NPT_String volume;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("DesiredVolume", volume));
+    g_application.SetVolume(atoi((const char*)volume));
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnSetMute
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnSetMute(PLT_ActionReference& action)
+{
+    NPT_String mute;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("DesiredMute",mute));
+    if((mute == "1") ^ g_stSettings.m_bMute)
+        g_application.Mute();
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnPRenderer::OnSeek
++---------------------------------------------------------------------*/
+NPT_Result
+CUPnPRenderer::OnSeek(PLT_ActionReference& action)
+{
+    if (!g_application.IsPlaying()) return NPT_ERROR_INVALID_STATE;
+
+    NPT_String unit, target;
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Unit", unit));
+    NPT_CHECK_SEVERE(action->GetArgumentValue("Target", target));
+
+    if (!unit.Compare("REL_TIME")) {
+        // converts target to seconds
+        NPT_UInt32 seconds;
+        NPT_CHECK_SEVERE(PLT_Didl::ParseTimeStamp(target, seconds));
+        g_application.SeekTime(seconds);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   CRendererReferenceHolder class
++---------------------------------------------------------------------*/
+class CRendererReferenceHolder
+{
+public:
+    PLT_DeviceHostReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+|   CMediaBrowser class
++---------------------------------------------------------------------*/
+class CMediaBrowser : public PLT_SyncMediaBrowser,
+                      public PLT_MediaContainerChangesListener
+{
+public:
+    CMediaBrowser(PLT_CtrlPointReference& ctrlPoint)
+        : PLT_SyncMediaBrowser(ctrlPoint, true)
+    {
+        SetContainerListener(this);
+    }
+
+    // PLT_MediaBrowser methods
+    virtual void OnMSAddedRemoved(PLT_DeviceDataReference& device, int added)
+    {
+        PLT_SyncMediaBrowser::OnMSAddedRemoved(device, added);
+
+        CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
+        message.SetStringParam("upnp://");
+        m_gWindowManager.SendThreadMessage(message);
+    }
+
+    // PLT_MediaContainerChangesListener methods
+    virtual void OnContainerChanged(PLT_DeviceDataReference& device,
+                                    const char*              item_id,
+                                    const char*              update_id)
+    {
+        NPT_String path = "upnp://"+device->GetUUID()+"/";
+        if (!NPT_StringsEqual(item_id, "0")) {
+            CStdString id = item_id;
+            CUtil::URLEncode(id);
+            path += id.c_str();
+            path += "/";
+        }
+
+        CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
+        message.SetStringParam(path.GetChars());
+        m_gWindowManager.SendThreadMessage(message);
+    }
+};
+
+
+/*----------------------------------------------------------------------
+|   CUPnP::CUPnP
++---------------------------------------------------------------------*/
+CUPnP::CUPnP() :
+    m_MediaBrowser(NULL),
+    m_ServerHolder(new CDeviceHostReferenceHolder()),
+    m_RendererHolder(new CRendererReferenceHolder()),
+    m_CtrlPointHolder(new CCtrlPointReferenceHolder())
+{
+//#ifdef HAS_XBOX_HARDWARE
+//    broadcast = true;
+//#else
+//    broadcast = false;
+//#endif
+    // xbox can't receive multicast, but it can send it
+    broadcast = false;
+
+    // initialize upnp in broadcast listening mode for xbmc
+    m_UPnP = new PLT_UPnP(1900, !broadcast);
+
+    // keep main IP around
+#if defined(HAS_LINUX_NETWORK) || defined(HAS_WIN32_NETWORK)
+    if (g_application.getNetwork().GetFirstConnectedInterface()) {
+        m_IP = g_application.getNetwork().GetFirstConnectedInterface()->GetCurrentIPAddress().c_str();
+    }
+#else
+    m_IP = g_application.getNetwork().m_networkinfo.ip;
+#endif
+    NPT_List<NPT_String> list;
+    if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetIPAddresses(list))) {
+        m_IP = *(list.GetFirstItem());
+    }
+
+    // start upnp monitoring
+    m_UPnP->Start();
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::~CUPnP
++---------------------------------------------------------------------*/
+CUPnP::~CUPnP()
+{
+    m_UPnP->Stop();
+    StopClient();
+    StopServer();
+
+    delete m_UPnP;
+    delete m_ServerHolder;
+    delete m_RendererHolder;
+    delete m_CtrlPointHolder;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::GetInstance
++---------------------------------------------------------------------*/
+CUPnP*
+CUPnP::GetInstance()
+{
+    if (!upnp) {
+        upnp = new CUPnP();
+    }
+
+    return upnp;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::ReleaseInstance
++---------------------------------------------------------------------*/
+void
+CUPnP::ReleaseInstance()
+{
+    if (upnp) {
+        CUPnP* _upnp = upnp;
+        upnp = NULL;
+
+        // since it takes a while to clean up
+        // starts a detached thread to do this
+        CUPnPCleaner* cleaner = new CUPnPCleaner(_upnp);
+        cleaner->Start();
+    }
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::StartClient
++---------------------------------------------------------------------*/
+void
+CUPnP::StartClient()
+{
+    if (!m_CtrlPointHolder->m_CtrlPoint.IsNull()) return;
+
+    // create controlpoint, pass NULL to avoid sending a multicast search
+    m_CtrlPointHolder->m_CtrlPoint = new PLT_CtrlPoint(broadcast?NULL:"upnp:rootdevice");
+
+    // ignore our own server
+    if (!m_ServerHolder->m_Device.IsNull()) {
+        m_CtrlPointHolder->m_CtrlPoint->IgnoreUUID(m_ServerHolder->m_Device->GetUUID());
+    }
+
+    // start it
+    m_UPnP->AddCtrlPoint(m_CtrlPointHolder->m_CtrlPoint);
+
+    // start browser
+    m_MediaBrowser = new CMediaBrowser(m_CtrlPointHolder->m_CtrlPoint);
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::StopClient
++---------------------------------------------------------------------*/
+void
+CUPnP::StopClient()
+{
+    if (m_CtrlPointHolder->m_CtrlPoint.IsNull()) return;
+
+    m_UPnP->RemoveCtrlPoint(m_CtrlPointHolder->m_CtrlPoint);
+    m_CtrlPointHolder->m_CtrlPoint = NULL;
+
+    delete m_MediaBrowser;
+    m_MediaBrowser = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::CreateServer
++---------------------------------------------------------------------*/
+CUPnPServer*
+CUPnP::CreateServer(int port /* = 0 */)
+{
+    CUPnPServer* device =
+        new CUPnPServer("XBMC: Media Server:",
+                        g_settings.m_UPnPUUIDServer.length()?g_settings.m_UPnPUUIDServer.c_str():NULL,
+                        port);
+
+    // trying to set optional upnp values for XP UPnP UI Icons to detect us
+    // but it doesn't work anyways as it requires multicast for XP to detect us
+    device->m_PresentationURL =
+        NPT_HttpUrl(m_IP,
+                    atoi(g_guiSettings.GetString("servers.webserverport")),
+                    "/").ToString();
+
+    device->m_ModelName        = "XBMC Media Center";
+    device->m_ModelNumber      = "1.0";
+    device->m_ModelDescription = "XBMC Media Center - Media Server";
+    device->m_ModelURL         = "http://www.xbmc.org/";
+    device->m_Manufacturer     = "Team XBMC";
+    device->m_ManufacturerURL  = "http://www.xbmc.org/";
+
+    return device;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::StartServer
++---------------------------------------------------------------------*/
+void
+CUPnP::StartServer()
+{
+    if (!m_ServerHolder->m_Device.IsNull()) return;
+
+    // load upnpserver.xml so that g_settings.m_vecUPnPMusiCMediaSources, etc.. are loaded
+    CStdString filename;
+    CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), "upnpserver.xml", filename);
+    g_settings.LoadUPnPXml(filename);
+
+    // create the server with a XBox compatible friendlyname and UUID from upnpserver.xml if found
+    m_ServerHolder->m_Device = CreateServer(g_settings.m_UPnPPortServer);
+
+    // tell controller to ignore ourselves from list of upnp servers
+    if (!m_CtrlPointHolder->m_CtrlPoint.IsNull()) {
+        m_CtrlPointHolder->m_CtrlPoint->IgnoreUUID(m_ServerHolder->m_Device->GetUUID());
+    }
+
+    // start server
+    NPT_Result res = m_UPnP->AddDevice(m_ServerHolder->m_Device);
+    if (NPT_FAILED(res)) {
+        // if the upnp device port was not 0, it could have failed because
+        // of port being in used, so restart with a random port
+        if (g_settings.m_UPnPPortServer > 0) m_ServerHolder->m_Device = CreateServer(0);
+
+        // tell controller to ignore ourselves from list of upnp servers
+        if (!m_CtrlPointHolder->m_CtrlPoint.IsNull()) {
+            m_CtrlPointHolder->m_CtrlPoint->IgnoreUUID(m_ServerHolder->m_Device->GetUUID());
+        }
+
+        res = m_UPnP->AddDevice(m_ServerHolder->m_Device);
+    }
+
+    // save port but don't overwrite saved settings if port was random
+    if (NPT_SUCCEEDED(res)) {
+        if (g_settings.m_UPnPPortServer == 0) {
+            g_settings.m_UPnPPortServer = m_ServerHolder->m_Device->GetPort();
+        }
+        CUPnPServer::m_MaxReturnedItems = UPNP_DEFAULT_MAX_RETURNED_ITEMS;
+        if (g_settings.m_UPnPMaxReturnedItems > 0) {
+            // must be > UPNP_DEFAULT_MIN_RETURNED_ITEMS
+            CUPnPServer::m_MaxReturnedItems = max(UPNP_DEFAULT_MIN_RETURNED_ITEMS, g_settings.m_UPnPMaxReturnedItems);
+        }
+        g_settings.m_UPnPMaxReturnedItems = CUPnPServer::m_MaxReturnedItems;
+    }
+
+    // save UUID
+    g_settings.m_UPnPUUIDServer = m_ServerHolder->m_Device->GetUUID();
+    g_settings.SaveUPnPXml(filename);
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::StopServer
++---------------------------------------------------------------------*/
+void
+CUPnP::StopServer()
+{
+    if (m_ServerHolder->m_Device.IsNull()) return;
+
+    m_UPnP->RemoveDevice(m_ServerHolder->m_Device);
+    m_ServerHolder->m_Device = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::CreateRenderer
++---------------------------------------------------------------------*/
+CUPnPRenderer*
+CUPnP::CreateRenderer(int port /* = 0 */)
+{
+    CUPnPRenderer* device =
+        new CUPnPRenderer("XBMC: Media Renderer",
+                          true,
+                          (g_settings.m_UPnPUUIDRenderer.length() ? g_settings.m_UPnPUUIDRenderer.c_str() : NULL),
+                          port);
+
+    device->m_PresentationURL =
+        NPT_HttpUrl(m_IP,
+                    atoi(g_guiSettings.GetString("servers.webserverport")),
+                    "/").ToString();
+    device->m_ModelName = "XBMC";
+    device->m_ModelNumber = "2.0";
+    device->m_ModelDescription = "XBMC Media Center - Media Renderer";
+    device->m_ModelURL = "http://www.xbmc.org/";
+    device->m_Manufacturer = "Team XBMC";
+    device->m_ManufacturerURL = "http://www.xbmc.org/";
+
+    return device;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::StartRenderer
++---------------------------------------------------------------------*/
+void CUPnP::StartRenderer()
+{
+    if (!m_RendererHolder->m_Device.IsNull()) return;
+
+    CStdString filename;
+    CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), "upnpserver.xml", filename);
+    g_settings.LoadUPnPXml(filename);
+
+    m_RendererHolder->m_Device = CreateRenderer(g_settings.m_UPnPPortRenderer);
+
+    // tell controller to ignore ourselves from list of upnp servers
+    if (!m_CtrlPointHolder->m_CtrlPoint.IsNull()) {
+        m_CtrlPointHolder->m_CtrlPoint->IgnoreUUID(m_RendererHolder->m_Device->GetUUID());
+    }
+
+    NPT_Result res = m_UPnP->AddDevice(m_RendererHolder->m_Device);
+
+    // failed most likely because port is in use, try again with random port now
+    if (NPT_FAILED(res) && g_settings.m_UPnPPortRenderer != 0) {
+        m_RendererHolder->m_Device = CreateRenderer(0);
+
+        // tell controller to ignore ourselves from list of upnp servers
+        if (!m_CtrlPointHolder->m_CtrlPoint.IsNull()) {
+            m_CtrlPointHolder->m_CtrlPoint->IgnoreUUID(m_RendererHolder->m_Device->GetUUID());
+        }
+
+        res = m_UPnP->AddDevice(m_RendererHolder->m_Device);
+    }
+
+    // save port but don't overwrite saved settings if random
+    if (NPT_SUCCEEDED(res) && g_settings.m_UPnPPortRenderer == 0) {
+        g_settings.m_UPnPPortRenderer = m_RendererHolder->m_Device->GetPort();
+    }
+
+    // save UUID
+    g_settings.m_UPnPUUIDRenderer = m_RendererHolder->m_Device->GetUUID();
+    g_settings.SaveUPnPXml(filename);
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::StopRenderer
++---------------------------------------------------------------------*/
+void CUPnP::StopRenderer()
+{
+    if (m_RendererHolder->m_Device.IsNull()) return;
+
+    m_UPnP->RemoveDevice(m_RendererHolder->m_Device);
+    m_RendererHolder->m_Device = NULL;
+}
+
+/*----------------------------------------------------------------------
+|   CUPnP::UpdateState
++---------------------------------------------------------------------*/
+void CUPnP::UpdateState()
+{
+  if (!m_RendererHolder->m_Device.IsNull())
+      ((CUPnPRenderer*)m_RendererHolder->m_Device.AsPointer())->UpdateState();
+}
+
+int CUPnP::PopulateTagFromObject(CMusicInfoTag&          tag,
+                                 PLT_MediaObject&       object,
+                                 PLT_MediaItemResource* resource /* = NULL */)
+{
+    tag.SetTitle((const char*)object.m_Title);
+    tag.SetArtist((const char*)object.m_Creator);
+    for(PLT_PersonRoles::Iterator it = object.m_People.artists.GetFirstItem(); it; it++) {
+        if     (it->role == "")            tag.SetArtist((const char*)it->name);
+        else if(it->role == "Performer")   tag.SetArtist((const char*)it->name);
+        else if(it->role == "AlbumArtist") tag.SetAlbumArtist((const char*)it->name);
+    }
+    tag.SetTrackNumber(object.m_MiscInfo.original_track_number);
+    tag.SetGenre((const char*)JoinString(object.m_Affiliation.genre, " / "));
+    if(resource)
+        tag.SetDuration(resource->m_Duration);
+    tag.SetLoaded();
+    return NPT_SUCCESS;
+}
+
+int CUPnP::PopulateTagFromObject(CVideoInfoTag&         tag,
+                                 PLT_MediaObject&       object,
+                                 PLT_MediaItemResource* resource /* = NULL */)
+{
+    tag.m_strTitle    = object.m_Title;
+    tag.m_strGenre    = JoinString(object.m_Affiliation.genre, " / ");
+    tag.m_strDirector = object.m_People.director;
+    tag.m_strTagLine  = object.m_Description.description;
+    tag.m_strPlot     = object.m_Description.long_description;
+    if(resource)
+      tag.m_strRuntime.Format("%d",resource->m_Duration);
+    return NPT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ref/ffmpeg.c	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,3938 @@
+/*
+ * FFmpeg main
+ * Copyright (c) 2000-2003 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* needed for usleep() */
+#define _XOPEN_SOURCE 600
+
+#include "config.h"
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <limits.h>
+#include <unistd.h>
+#include "libavformat/avformat.h"
+#include "libavdevice/avdevice.h"
+#include "libswscale/swscale.h"
+#include "libavcodec/opt.h"
+#include "libavcodec/audioconvert.h"
+#include "libavcodec/colorspace.h"
+#include "libavutil/fifo.h"
+#include "libavutil/avstring.h"
+#include "libavformat/os_support.h"
+
+#if HAVE_SYS_RESOURCE_H
+#include <sys/types.h>
+#include <sys/resource.h>
+#elif HAVE_GETPROCESSTIMES
+#include <windows.h>
+#endif
+
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#if HAVE_TERMIOS_H
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <termios.h>
+#elif HAVE_CONIO_H
+#include <conio.h>
+#endif
+#undef time //needed because HAVE_AV_CONFIG_H is defined on top
+#include <time.h>
+
+#include "cmdutils.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#undef exit
+
+const char program_name[] = "FFmpeg";
+const int program_birth_year = 2000;
+
+/* select an input stream for an output stream */
+typedef struct AVStreamMap {
+    int file_index;
+    int stream_index;
+    int sync_file_index;
+    int sync_stream_index;
+} AVStreamMap;
+
+/** select an input file for an output file */
+typedef struct AVMetaDataMap {
+    int out_file;
+    int in_file;
+} AVMetaDataMap;
+
+static const OptionDef options[];
+
+#define MAX_FILES 20
+
+static AVFormatContext *input_files[MAX_FILES];
+static int64_t input_files_ts_offset[MAX_FILES];
+static double input_files_ts_scale[MAX_FILES][MAX_STREAMS];
+static AVCodec *input_codecs[MAX_FILES*MAX_STREAMS];
+static int nb_input_files = 0;
+static int nb_icodecs;
+
+static AVFormatContext *output_files[MAX_FILES];
+static AVCodec *output_codecs[MAX_FILES*MAX_STREAMS];
+static int nb_output_files = 0;
+static int nb_ocodecs;
+
+static AVStreamMap stream_maps[MAX_FILES*MAX_STREAMS];
+static int nb_stream_maps;
+
+static AVMetaDataMap meta_data_maps[MAX_FILES];
+static int nb_meta_data_maps;
+
+static AVInputFormat *file_iformat;
+static AVOutputFormat *file_oformat;
+static int frame_width  = 0;
+static int frame_height = 0;
+static float frame_aspect_ratio = 0;
+static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
+static enum SampleFormat audio_sample_fmt = SAMPLE_FMT_NONE;
+static int frame_padtop  = 0;
+static int frame_padbottom = 0;
+static int frame_padleft  = 0;
+static int frame_padright = 0;
+static int padcolor[3] = {16,128,128}; /* default to black */
+static int frame_topBand  = 0;
+static int frame_bottomBand = 0;
+static int frame_leftBand  = 0;
+static int frame_rightBand = 0;
+static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};
+static AVRational frame_rate;
+static float video_qscale = 0;
+static uint16_t *intra_matrix = NULL;
+static uint16_t *inter_matrix = NULL;
+#if 0 //experimental, (can be removed)
+static float video_rc_qsquish=1.0;
+static float video_rc_qmod_amp=0;
+static int video_rc_qmod_freq=0;
+#endif
+static const char *video_rc_override_string=NULL;
+static int video_disable = 0;
+static int video_discard = 0;
+static char *video_codec_name = NULL;
+static int video_codec_tag = 0;
+static int same_quality = 0;
+static int do_deinterlace = 0;
+static int top_field_first = -1;
+static int me_threshold = 0;
+static int intra_dc_precision = 8;
+static int loop_input = 0;
+static int loop_output = AVFMT_NOOUTPUTLOOP;
+static int qp_hist = 0;
+
+static int intra_only = 0;
+static int audio_sample_rate = 44100;
+static int64_t channel_layout = 0;
+#define QSCALE_NONE -99999
+static float audio_qscale = QSCALE_NONE;
+static int audio_disable = 0;
+static int audio_channels = 1;
+static char  *audio_codec_name = NULL;
+static int audio_codec_tag = 0;
+static char *audio_language = NULL;
+
+static int subtitle_disable = 0;
+static char *subtitle_codec_name = NULL;
+static char *subtitle_language = NULL;
+static int subtitle_codec_tag = 0;
+
+static float mux_preload= 0.5;
+static float mux_max_delay= 0.7;
+
+static int64_t recording_time = INT64_MAX;
+static int64_t start_time = 0;
+static int64_t rec_timestamp = 0;
+static int64_t input_ts_offset = 0;
+static int file_overwrite = 0;
+static int metadata_count;
+static AVMetadataTag *metadata;
+static int do_benchmark = 0;
+static int do_hex_dump = 0;
+static int do_pkt_dump = 0;
+static int do_psnr = 0;
+static int do_pass = 0;
+static char *pass_logfilename_prefix = NULL;
+static int audio_stream_copy = 0;
+static int video_stream_copy = 0;
+static int subtitle_stream_copy = 0;
+static int video_sync_method= -1;
+static int audio_sync_method= 0;
+static float audio_drift_threshold= 0.1;
+static int copy_ts= 0;
+static int opt_shortest = 0;
+static int video_global_header = 0;
+static char *vstats_filename;
+static FILE *vstats_file;
+static int opt_programid = 0;
+static int copy_initial_nonkeyframes = 0;
+
+static int rate_emu = 0;
+
+static int  video_channel = 0;
+static char *video_standard;
+
+static int audio_volume = 256;
+
+static int exit_on_error = 0;
+static int using_stdin = 0;
+static int verbose = 1;
+static int thread_count= 1;
+static int q_pressed = 0;
+static int64_t video_size = 0;
+static int64_t audio_size = 0;
+static int64_t extra_size = 0;
+static int nb_frames_dup = 0;
+static int nb_frames_drop = 0;
+static int input_sync;
+static uint64_t limit_filesize = 0;
+static int force_fps = 0;
+
+static int pgmyuv_compatibility_hack=0;
+static float dts_delta_threshold = 10;
+
+static unsigned int sws_flags = SWS_BICUBIC;
+
+static int64_t timer_start;
+
+static uint8_t *audio_buf;
+static uint8_t *audio_out;
+static uint8_t *audio_out2;
+
+static short *samples;
+
+static AVBitStreamFilterContext *video_bitstream_filters=NULL;
+static AVBitStreamFilterContext *audio_bitstream_filters=NULL;
+static AVBitStreamFilterContext *subtitle_bitstream_filters=NULL;
+static AVBitStreamFilterContext *bitstream_filters[MAX_FILES][MAX_STREAMS];
+
+#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
+
+struct AVInputStream;
+
+typedef struct AVOutputStream {
+    int file_index;          /* file index */
+    int index;               /* stream index in the output file */
+    int source_index;        /* AVInputStream index */
+    AVStream *st;            /* stream in the output file */
+    int encoding_needed;     /* true if encoding needed for this stream */
+    int frame_number;
+    /* input pts and corresponding output pts
+       for A/V sync */
+    //double sync_ipts;        /* dts from the AVPacket of the demuxer in second units */
+    struct AVInputStream *sync_ist; /* input stream to sync against */
+    int64_t sync_opts;       /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
+    /* video only */
+    int video_resample;
+    AVFrame pict_tmp;      /* temporary image for resampling */
+    struct SwsContext *img_resample_ctx; /* for image resampling */
+    int resample_height;
+
+    int video_crop;
+    int topBand;             /* cropping area sizes */
+    int leftBand;
+
+    int video_pad;
+    int padtop;              /* padding area sizes */
+    int padbottom;
+    int padleft;
+    int padright;
+
+    /* audio only */
+    int audio_resample;
+    ReSampleContext *resample; /* for audio resampling */
+    int reformat_pair;
+    AVAudioConvert *reformat_ctx;
+    AVFifoBuffer *fifo;     /* for compression: one audio fifo per codec */
+    FILE *logfile;
+} AVOutputStream;
+
+typedef struct AVInputStream {
+    int file_index;
+    int index;
+    AVStream *st;
+    int discard;             /* true if stream data should be discarded */
+    int decoding_needed;     /* true if the packets must be decoded in 'raw_fifo' */
+    int64_t sample_index;      /* current sample */
+
+    int64_t       start;     /* time when read started */
+    int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
+                                is not defined */
+    int64_t       pts;       /* current pts */
+    int is_start;            /* is 1 at the start and after a discontinuity */
+} AVInputStream;
+
+typedef struct AVInputFile {
+    int eof_reached;      /* true if eof reached */
+    int ist_index;        /* index of first stream in ist_table */
+    int buffer_size;      /* current total buffer size */
+    int nb_streams;       /* nb streams we are aware of */
+} AVInputFile;
+
+#if HAVE_TERMIOS_H
+
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+#endif
+
+static void term_exit(void)
+{
+#if HAVE_TERMIOS_H
+    tcsetattr (0, TCSANOW, &oldtty);
+#endif
+}
+
+static volatile sig_atomic_t received_sigterm = 0;
+
+static void
+sigterm_handler(int sig)
+{
+    received_sigterm = sig;
+    term_exit();
+}
+
+static void term_init(void)
+{
+#if HAVE_TERMIOS_H
+    struct termios tty;
+
+    tcgetattr (0, &tty);
+    oldtty = tty;
+
+    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+                          |INLCR|IGNCR|ICRNL|IXON);
+    tty.c_oflag |= OPOST;
+    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+    tty.c_cflag &= ~(CSIZE|PARENB);
+    tty.c_cflag |= CS8;
+    tty.c_cc[VMIN] = 1;
+    tty.c_cc[VTIME] = 0;
+
+    tcsetattr (0, TCSANOW, &tty);
+    signal(SIGQUIT, sigterm_handler); /* Quit (POSIX).  */
+#endif
+
+    signal(SIGINT , sigterm_handler); /* Interrupt (ANSI).  */
+    signal(SIGTERM, sigterm_handler); /* Termination (ANSI).  */
+    /*
+    register a function to be called at normal program termination
+    */
+    atexit(term_exit);
+#if CONFIG_BEOS_NETSERVER
+    fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
+#endif
+}
+
+/* read a key without blocking */
+static int read_key(void)
+{
+#if HAVE_TERMIOS_H
+    int n = 1;
+    unsigned char ch;
+#if !CONFIG_BEOS_NETSERVER
+    struct timeval tv;
+    fd_set rfds;
+
+    FD_ZERO(&rfds);
+    FD_SET(0, &rfds);
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+    n = select(1, &rfds, NULL, NULL, &tv);
+#endif
+    if (n > 0) {
+        n = read(0, &ch, 1);
+        if (n == 1)
+            return ch;
+
+        return n;
+    }
+#elif HAVE_CONIO_H
+    if(kbhit())
+        return(getch());
+#endif
+    return -1;
+}
+
+static int decode_interrupt_cb(void)
+{
+    return q_pressed || (q_pressed = read_key() == 'q');
+}
+
+static int av_exit(int ret)
+{
+    int i;
+
+    /* close files */
+    for(i=0;i<nb_output_files;i++) {
+        /* maybe av_close_output_file ??? */
+        AVFormatContext *s = output_files[i];
+        int j;
+        if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+            url_fclose(s->pb);
+        for(j=0;j<s->nb_streams;j++) {
+            av_metadata_free(&s->streams[j]->metadata);
+            av_free(s->streams[j]->codec);
+            av_free(s->streams[j]);
+        }
+        for(j=0;j<s->nb_programs;j++) {
+            av_metadata_free(&s->programs[j]->metadata);
+        }
+        for(j=0;j<s->nb_chapters;j++) {
+            av_metadata_free(&s->chapters[j]->metadata);
+        }
+        av_metadata_free(&s->metadata);
+        av_free(s);
+    }
+    for(i=0;i<nb_input_files;i++)
+        av_close_input_file(input_files[i]);
+
+    av_free(intra_matrix);
+    av_free(inter_matrix);
+
+    if (vstats_file)
+        fclose(vstats_file);
+    av_free(vstats_filename);
+
+    av_free(opt_names);
+
+    av_free(video_codec_name);
+    av_free(audio_codec_name);
+    av_free(subtitle_codec_name);
+
+    av_free(video_standard);
+
+#if CONFIG_POWERPC_PERF
+    void powerpc_display_perf_report(void);
+    powerpc_display_perf_report();
+#endif /* CONFIG_POWERPC_PERF */
+
+    for (i=0;i<CODEC_TYPE_NB;i++)
+        av_free(avcodec_opts[i]);
+    av_free(avformat_opts);
+    av_free(sws_opts);
+    av_free(audio_buf);
+    av_free(audio_out);
+    av_free(audio_out2);
+    av_free(samples);
+
+    if (received_sigterm) {
+        fprintf(stderr,
+            "Received signal %d: terminating.\n",
+            (int) received_sigterm);
+        exit (255);
+    }
+
+    exit(ret); /* not all OS-es handle main() return value */
+    return ret;
+}
+
+static int read_ffserver_streams(AVFormatContext *s, const char *filename)
+{
+    int i, err;
+    AVFormatContext *ic;
+    int nopts = 0;
+
+    err = av_open_input_file(&ic, filename, NULL, FFM_PACKET_SIZE, NULL);
+    if (err < 0)
+        return err;
+    /* copy stream format */
+    s->nb_streams = ic->nb_streams;
+    for(i=0;i<ic->nb_streams;i++) {
+        AVStream *st;
+
+        // FIXME: a more elegant solution is needed
+        st = av_mallocz(sizeof(AVStream));
+        memcpy(st, ic->streams[i], sizeof(AVStream));
+        st->codec = avcodec_alloc_context();
+        memcpy(st->codec, ic->streams[i]->codec, sizeof(AVCodecContext));
+        s->streams[i] = st;
+
+        if (st->codec->codec_type == CODEC_TYPE_AUDIO && audio_stream_copy)
+            st->stream_copy = 1;
+        else if (st->codec->codec_type == CODEC_TYPE_VIDEO && video_stream_copy)
+            st->stream_copy = 1;
+
+        if(!st->codec->thread_count)
+            st->codec->thread_count = 1;
+        if(st->codec->thread_count>1)
+            avcodec_thread_init(st->codec, st->codec->thread_count);
+
+        if(st->codec->flags & CODEC_FLAG_BITEXACT)
+            nopts = 1;
+    }
+
+    if (!nopts)
+        s->timestamp = av_gettime();
+
+    av_close_input_file(ic);
+    return 0;
+}
+
+static double
+get_sync_ipts(const AVOutputStream *ost)
+{
+    const AVInputStream *ist = ost->sync_ist;
+    return (double)(ist->pts - start_time)/AV_TIME_BASE;
+}
+
+static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
+    int ret;
+
+    while(bsfc){
+        AVPacket new_pkt= *pkt;
+        int a= av_bitstream_filter_filter(bsfc, avctx, NULL,
+                                          &new_pkt.data, &new_pkt.size,
+                                          pkt->data, pkt->size,
+                                          pkt->flags & PKT_FLAG_KEY);
+        if(a>0){
+            av_free_packet(pkt);
+            new_pkt.destruct= av_destruct_packet;
+        } else if(a<0){
+            fprintf(stderr, "%s failed for stream %d, codec %s",
+                    bsfc->filter->name, pkt->stream_index,
+                    avctx->codec ? avctx->codec->name : "copy");
+            print_error("", a);
+            if (exit_on_error)
+                av_exit(1);
+        }
+        *pkt= new_pkt;
+
+        bsfc= bsfc->next;
+    }
+
+    ret= av_interleaved_write_frame(s, pkt);
+    if(ret < 0){
+        print_error("av_interleaved_write_frame()", ret);
+        av_exit(1);
+    }
+}
+
+#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
+
+static void do_audio_out(AVFormatContext *s,
+                         AVOutputStream *ost,
+                         AVInputStream *ist,
+                         unsigned char *buf, int size)
+{
+    uint8_t *buftmp;
+    const int audio_out_size= 4*MAX_AUDIO_PACKET_SIZE;
+
+    int size_out, frame_bytes, ret;
+    AVCodecContext *enc= ost->st->codec;
+    AVCodecContext *dec= ist->st->codec;
+    int osize= av_get_bits_per_sample_format(enc->sample_fmt)/8;
+    int isize= av_get_bits_per_sample_format(dec->sample_fmt)/8;
+
+    /* SC: dynamic allocation of buffers */
+    if (!audio_buf)
+        audio_buf = av_malloc(2*MAX_AUDIO_PACKET_SIZE);
+    if (!audio_out)
+        audio_out = av_malloc(audio_out_size);
+    if (!audio_buf || !audio_out)
+        return;               /* Should signal an error ! */
+
+    if (enc->channels != dec->channels)
+        ost->audio_resample = 1;
+
+    if (ost->audio_resample && !ost->resample) {
+        if (dec->sample_fmt != SAMPLE_FMT_S16)
+            fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n");
+        ost->resample = av_audio_resample_init(enc->channels,    dec->channels,
+                                               enc->sample_rate, dec->sample_rate,
+                                               enc->sample_fmt,  dec->sample_fmt,
+                                               16, 10, 0, 0.8);
+        if (!ost->resample) {
+            fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n",
+                    dec->channels, dec->sample_rate,
+                    enc->channels, enc->sample_rate);
+            av_exit(1);
+        }
+    }
+
+#define MAKE_SFMT_PAIR(a,b) ((a)+SAMPLE_FMT_NB*(b))
+    if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt &&
+        MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) {
+        if (!audio_out2)
+            audio_out2 = av_malloc(audio_out_size);
+        if (!audio_out2)
+            av_exit(1);
+        if (ost->reformat_ctx)
+            av_audio_convert_free(ost->reformat_ctx);
+        ost->reformat_ctx = av_audio_convert_alloc(enc->sample_fmt, 1,
+                                                   dec->sample_fmt, 1, NULL, 0);
+        if (!ost->reformat_ctx) {
+            fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
+                avcodec_get_sample_fmt_name(dec->sample_fmt),
+                avcodec_get_sample_fmt_name(enc->sample_fmt));
+            av_exit(1);
+        }
+        ost->reformat_pair=MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt);
+    }
+
+    if(audio_sync_method){
+        double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
+                - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2);
+        double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate;
+        int byte_delta= ((int)idelta)*2*ist->st->codec->channels;
+
+        //FIXME resample delay
+        if(fabs(delta) > 50){
+            if(ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate){
+                if(byte_delta < 0){
+                    byte_delta= FFMAX(byte_delta, -size);
+                    size += byte_delta;
+                    buf  -= byte_delta;
+                    if(verbose > 2)
+                        fprintf(stderr, "discarding %d audio samples\n", (int)-delta);
+                    if(!size)
+                        return;
+                    ist->is_start=0;
+                }else{
+                    static uint8_t *input_tmp= NULL;
+                    input_tmp= av_realloc(input_tmp, byte_delta + size);
+
+                    if(byte_delta + size <= MAX_AUDIO_PACKET_SIZE)
+                        ist->is_start=0;
+                    else
+                        byte_delta= MAX_AUDIO_PACKET_SIZE - size;
+
+                    memset(input_tmp, 0, byte_delta);
+                    memcpy(input_tmp + byte_delta, buf, size);
+                    buf= input_tmp;
+                    size += byte_delta;
+                    if(verbose > 2)
+                        fprintf(stderr, "adding %d audio samples of silence\n", (int)delta);
+                }
+            }else if(audio_sync_method>1){
+                int comp= av_clip(delta, -audio_sync_method, audio_sync_method);
+                assert(ost->audio_resample);
+                if(verbose > 2)
+                    fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate);
+//                fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
+                av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate);
+            }
+        }
+    }else
+        ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
+                        - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong
+
+    if (ost->audio_resample) {
+        buftmp = audio_buf;
+        size_out = audio_resample(ost->resample,
+                                  (short *)buftmp, (short *)buf,
+                                  size / (ist->st->codec->channels * isize));
+        size_out = size_out * enc->channels * osize;
+    } else {
+        buftmp = buf;
+        size_out = size;
+    }
+
+    if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt) {
+        const void *ibuf[6]= {buftmp};
+        void *obuf[6]= {audio_out2};
+        int istride[6]= {isize};
+        int ostride[6]= {osize};
+        int len= size_out/istride[0];
+        if (av_audio_convert(ost->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
+            printf("av_audio_convert() failed\n");
+            if (exit_on_error)
+                av_exit(1);
+            return;
+        }
+        buftmp = audio_out2;
+        size_out = len*osize;
+    }
+
+    /* now encode as many frames as possible */
+    if (enc->frame_size > 1) {
+        /* output resampled raw samples */
+        if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
+            fprintf(stderr, "av_fifo_realloc2() failed\n");
+            av_exit(1);
+        }
+        av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL);
+
+        frame_bytes = enc->frame_size * osize * enc->channels;
+
+        while (av_fifo_size(ost->fifo) >= frame_bytes) {
+            AVPacket pkt;
+            av_init_packet(&pkt);
+
+            av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
+
+            //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
+
+            ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
+                                       (short *)audio_buf);
+            if (ret < 0) {
+                fprintf(stderr, "Audio encoding failed\n");
+                av_exit(1);
+            }
+            audio_size += ret;
+            pkt.stream_index= ost->index;
+            pkt.data= audio_out;
+            pkt.size= ret;
+            if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+                pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+            pkt.flags |= PKT_FLAG_KEY;
+            write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+
+            ost->sync_opts += enc->frame_size;
+        }
+    } else {
+        AVPacket pkt;
+        int coded_bps = av_get_bits_per_sample(enc->codec->id)/8;
+        av_init_packet(&pkt);
+
+        ost->sync_opts += size_out / (osize * enc->channels);
+
+        /* output a pcm frame */
+        /* determine the size of the coded buffer */
+        size_out /= osize;
+        if (coded_bps)
+            size_out *= coded_bps;
+
+        //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
+        ret = avcodec_encode_audio(enc, audio_out, size_out,
+                                   (short *)buftmp);
+        if (ret < 0) {
+            fprintf(stderr, "Audio encoding failed\n");
+            av_exit(1);
+        }
+        audio_size += ret;
+        pkt.stream_index= ost->index;
+        pkt.data= audio_out;
+        pkt.size= ret;
+        if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+            pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+        pkt.flags |= PKT_FLAG_KEY;
+        write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+    }
+}
+
+static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void **bufp)
+{
+    AVCodecContext *dec;
+    AVPicture *picture2;
+    AVPicture picture_tmp;
+    uint8_t *buf = 0;
+
+    dec = ist->st->codec;
+
+    /* deinterlace : must be done before any resize */
+    if (do_deinterlace) {
+        int size;
+
+        /* create temporary picture */
+        size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
+        buf = av_malloc(size);
+        if (!buf)
+            return;
+
+        picture2 = &picture_tmp;
+        avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
+
+        if(avpicture_deinterlace(picture2, picture,
+                                 dec->pix_fmt, dec->width, dec->height) < 0) {
+            /* if error, do not deinterlace */
+            fprintf(stderr, "Deinterlacing failed\n");
+            av_free(buf);
+            buf = NULL;
+            picture2 = picture;
+        }
+    } else {
+        picture2 = picture;
+    }
+
+    if (picture != picture2)
+        *picture = *picture2;
+    *bufp = buf;
+}
+
+/* we begin to correct av delay at this threshold */
+#define AV_DELAY_MAX 0.100
+
+static void do_subtitle_out(AVFormatContext *s,
+                            AVOutputStream *ost,
+                            AVInputStream *ist,
+                            AVSubtitle *sub,
+                            int64_t pts)
+{
+    static uint8_t *subtitle_out = NULL;
+    int subtitle_out_max_size = 65536;
+    int subtitle_out_size, nb, i;
+    AVCodecContext *enc;
+    AVPacket pkt;
+
+    if (pts == AV_NOPTS_VALUE) {
+        fprintf(stderr, "Subtitle packets must have a pts\n");
+        if (exit_on_error)
+            av_exit(1);
+        return;
+    }
+
+    enc = ost->st->codec;
+
+    if (!subtitle_out) {
+        subtitle_out = av_malloc(subtitle_out_max_size);
+    }
+
+    /* Note: DVB subtitle need one packet to draw them and one other
+       packet to clear them */
+    /* XXX: signal it in the codec context ? */
+    if (enc->codec_id == CODEC_ID_DVB_SUBTITLE)
+        nb = 2;
+    else
+        nb = 1;
+
+    for(i = 0; i < nb; i++) {
+        subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out,
+                                                    subtitle_out_max_size, sub);
+
+        av_init_packet(&pkt);
+        pkt.stream_index = ost->index;
+        pkt.data = subtitle_out;
+        pkt.size = subtitle_out_size;
+        pkt.pts = av_rescale_q(pts, ist->st->time_base, ost->st->time_base);
+        if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
+            /* XXX: the pts correction is handled here. Maybe handling
+               it in the codec would be better */
+            if (i == 0)
+                pkt.pts += 90 * sub->start_display_time;
+            else
+                pkt.pts += 90 * sub->end_display_time;
+        }
+        write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+    }
+}
+
+static int bit_buffer_size= 1024*256;
+static uint8_t *bit_buffer= NULL;
+
+static void do_video_out(AVFormatContext *s,
+                         AVOutputStream *ost,
+                         AVInputStream *ist,
+                         AVFrame *in_picture,
+                         int *frame_size)
+{
+    int nb_frames, i, ret;
+    AVFrame *final_picture, *formatted_picture, *resampling_dst, *padding_src;
+    AVFrame picture_crop_temp, picture_pad_temp;
+    AVCodecContext *enc, *dec;
+
+    avcodec_get_frame_defaults(&picture_crop_temp);
+    avcodec_get_frame_defaults(&picture_pad_temp);
+
+    enc = ost->st->codec;
+    dec = ist->st->codec;
+
+    /* by default, we output a single frame */
+    nb_frames = 1;
+
+    *frame_size = 0;
+
+    if(video_sync_method>0 || (video_sync_method && av_q2d(enc->time_base) > 0.001)){
+        double vdelta;
+        vdelta = get_sync_ipts(ost) / av_q2d(enc->time_base) - ost->sync_opts;
+        //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
+        if (vdelta < -1.1)
+            nb_frames = 0;
+        else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){
+            if(vdelta<=-0.6){
+                nb_frames=0;
+            }else if(vdelta>0.6)
+            ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
+        }else if (vdelta > 1.1)
+            nb_frames = lrintf(vdelta);
+//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames);
+        if (nb_frames == 0){
+            ++nb_frames_drop;
+            if (verbose>2)
+                fprintf(stderr, "*** drop!\n");
+        }else if (nb_frames > 1) {
+            nb_frames_dup += nb_frames;
+            if (verbose>2)
+                fprintf(stderr, "*** %d dup!\n", nb_frames-1);
+        }
+    }else
+        ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
+
+    nb_frames= FFMIN(nb_frames, max_frames[CODEC_TYPE_VIDEO] - ost->frame_number);
+    if (nb_frames <= 0)
+        return;
+
+    if (ost->video_crop) {
+        if (av_picture_crop((AVPicture *)&picture_crop_temp, (AVPicture *)in_picture, dec->pix_fmt, ost->topBand, ost->leftBand) < 0) {
+            fprintf(stderr, "error cropping picture\n");
+            if (exit_on_error)
+                av_exit(1);
+            return;
+        }
+        formatted_picture = &picture_crop_temp;
+    } else {
+        formatted_picture = in_picture;
+    }
+
+    final_picture = formatted_picture;
+    padding_src = formatted_picture;
+    resampling_dst = &ost->pict_tmp;
+    if (ost->video_pad) {
+        final_picture = &ost->pict_tmp;
+        if (ost->video_resample) {
+            if (av_picture_crop((AVPicture *)&picture_pad_temp, (AVPicture *)final_picture, enc->pix_fmt, ost->padtop, ost->padleft) < 0) {
+                fprintf(stderr, "error padding picture\n");
+                if (exit_on_error)
+                    av_exit(1);
+                return;
+            }
+            resampling_dst = &picture_pad_temp;
+        }
+    }
+
+    if (ost->video_resample) {
+        padding_src = NULL;
+        final_picture = &ost->pict_tmp;
+        sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize,
+              0, ost->resample_height, resampling_dst->data, resampling_dst->linesize);
+    }
+
+    if (ost->video_pad) {
+        av_picture_pad((AVPicture*)final_picture, (AVPicture *)padding_src,
+                enc->height, enc->width, enc->pix_fmt,
+                ost->padtop, ost->padbottom, ost->padleft, ost->padright, padcolor);
+    }
+
+    /* duplicates frame if needed */
+    for(i=0;i<nb_frames;i++) {
+        AVPacket pkt;
+        av_init_packet(&pkt);
+        pkt.stream_index= ost->index;
+
+        if (s->oformat->flags & AVFMT_RAWPICTURE) {
+            /* raw pictures are written as AVPicture structure to
+               avoid any copies. We support temorarily the older
+               method. */
+            AVFrame* old_frame = enc->coded_frame;
+            enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack
+            pkt.data= (uint8_t *)final_picture;
+            pkt.size=  sizeof(AVPicture);
+            pkt.pts= av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);
+            pkt.flags |= PKT_FLAG_KEY;
+
+            write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+            enc->coded_frame = old_frame;
+        } else {
+            AVFrame big_picture;
+
+            big_picture= *final_picture;
+            /* better than nothing: use input picture interlaced
+               settings */
+            big_picture.interlaced_frame = in_picture->interlaced_frame;
+            if(avcodec_opts[CODEC_TYPE_VIDEO]->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){
+                if(top_field_first == -1)
+                    big_picture.top_field_first = in_picture->top_field_first;
+                else
+                    big_picture.top_field_first = top_field_first;
+            }
+
+            /* handles sameq here. This is not correct because it may
+               not be a global option */
+            if (same_quality) {
+                big_picture.quality = ist->st->quality;
+            }else
+                big_picture.quality = ost->st->quality;
+            if(!me_threshold)
+                big_picture.pict_type = 0;
+//            big_picture.pts = AV_NOPTS_VALUE;
+            big_picture.pts= ost->sync_opts;
+//            big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
+//av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
+            ret = avcodec_encode_video(enc,
+                                       bit_buffer, bit_buffer_size,
+                                       &big_picture);
+            if (ret < 0) {
+                fprintf(stderr, "Video encoding failed\n");
+                av_exit(1);
+            }
+
+            if(ret>0){
+                pkt.data= bit_buffer;
+                pkt.size= ret;
+                if(enc->coded_frame->pts != AV_NOPTS_VALUE)
+                    pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",
+   pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,
+   pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/
+
+                if(enc->coded_frame->key_frame)
+                    pkt.flags |= PKT_FLAG_KEY;
+                write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+                *frame_size = ret;
+                video_size += ret;
+                //fprintf(stderr,"\nFrame: %3d size: %5d type: %d",
+                //        enc->frame_number-1, ret, enc->pict_type);
+                /* if two pass, output log */
+                if (ost->logfile && enc->stats_out) {
+                    fprintf(ost->logfile, "%s", enc->stats_out);
+                }
+            }
+        }
+        ost->sync_opts++;
+        ost->frame_number++;
+    }
+}
+
+static double psnr(double d){
+    return -10.0*log(d)/log(10.0);
+}
+
+static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
+                           int frame_size)
+{
+    AVCodecContext *enc;
+    int frame_number;
+    double ti1, bitrate, avg_bitrate;
+
+    /* this is executed just the first time do_video_stats is called */
+    if (!vstats_file) {
+        vstats_file = fopen(vstats_filename, "w");
+        if (!vstats_file) {
+            perror("fopen");
+            av_exit(1);
+        }
+    }
+
+    enc = ost->st->codec;
+    if (enc->codec_type == CODEC_TYPE_VIDEO) {
+        frame_number = ost->frame_number;
+        fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+        if (enc->flags&CODEC_FLAG_PSNR)
+            fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0]/(enc->width*enc->height*255.0*255.0)));
+
+        fprintf(vstats_file,"f_size= %6d ", frame_size);
+        /* compute pts value */
+        ti1 = ost->sync_opts * av_q2d(enc->time_base);
+        if (ti1 < 0.01)
+            ti1 = 0.01;
+
+        bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
+        avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0;
+        fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
+            (double)video_size / 1024, ti1, bitrate, avg_bitrate);
+        fprintf(vstats_file,"type= %c\n", av_get_pict_type_char(enc->coded_frame->pict_type));
+    }
+}
+
+static void print_report(AVFormatContext **output_files,
+                         AVOutputStream **ost_table, int nb_ostreams,
+                         int is_last_report)
+{
+    char buf[1024];
+    AVOutputStream *ost;
+    AVFormatContext *oc;
+    int64_t total_size;
+    AVCodecContext *enc;
+    int frame_number, vid, i;
+    double bitrate, ti1, pts;
+    static int64_t last_time = -1;
+    static int qp_histogram[52];
+
+    if (!is_last_report) {
+        int64_t cur_time;
+        /* display the report every 0.5 seconds */
+        cur_time = av_gettime();
+        if (last_time == -1) {
+            last_time = cur_time;
+            return;
+        }
+        if ((cur_time - last_time) < 500000)
+            return;
+        last_time = cur_time;
+    }
+
+
+    oc = output_files[0];
+
+    total_size = url_fsize(oc->pb);
+    if(total_size<0) // FIXME improve url_fsize() so it works with non seekable output too
+        total_size= url_ftell(oc->pb);
+
+    buf[0] = '\0';
+    ti1 = 1e10;
+    vid = 0;
+    for(i=0;i<nb_ostreams;i++) {
+        ost = ost_table[i];
+        enc = ost->st->codec;
+        if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {
+            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",
+                     !ost->st->stream_copy ?
+                     enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
+        }
+        if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
+            float t = (av_gettime()-timer_start) / 1000000.0;
+
+            frame_number = ost->frame_number;
+            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
+                     frame_number, (t>1)?(int)(frame_number/t+0.5) : 0,
+                     !ost->st->stream_copy ?
+                     enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
+            if(is_last_report)
+                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
+            if(qp_hist){
+                int j;
+                int qp= lrintf(enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+                if(qp>=0 && qp<FF_ARRAY_ELEMS(qp_histogram))
+                    qp_histogram[qp]++;
+                for(j=0; j<32; j++)
+                    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log(qp_histogram[j]+1)/log(2)));
+            }
+            if (enc->flags&CODEC_FLAG_PSNR){
+                int j;
+                double error, error_sum=0;
+                double scale, scale_sum=0;
+                char type[3]= {'Y','U','V'};
+                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");
+                for(j=0; j<3; j++){
+                    if(is_last_report){
+                        error= enc->error[j];
+                        scale= enc->width*enc->height*255.0*255.0*frame_number;
+                    }else{
+                        error= enc->coded_frame->error[j];
+                        scale= enc->width*enc->height*255.0*255.0;
+                    }
+                    if(j) scale/=4;
+                    error_sum += error;
+                    scale_sum += scale;
+                    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
+                }
+                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
+            }
+            vid = 1;
+        }
+        /* compute min output value */
+        pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
+        if ((pts < ti1) && (pts > 0))
+            ti1 = pts;
+    }
+    if (ti1 < 0.01)
+        ti1 = 0.01;
+
+    if (verbose || is_last_report) {
+        bitrate = (double)(total_size * 8) / ti1 / 1000.0;
+
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+            "size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
+            (double)total_size / 1024, ti1, bitrate);
+
+        if (verbose > 1)
+          snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
+                  nb_frames_dup, nb_frames_drop);
+
+        if (verbose >= 0)
+            fprintf(stderr, "%s    \r", buf);
+
+        fflush(stderr);
+    }
+
+    if (is_last_report && verbose >= 0){
+        int64_t raw= audio_size + video_size + extra_size;
+        fprintf(stderr, "\n");
+        fprintf(stderr, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n",
+                video_size/1024.0,
+                audio_size/1024.0,
+                extra_size/1024.0,
+                100.0*(total_size - raw)/raw
+        );
+    }
+}
+
+/* pkt = NULL means EOF (needed to flush decoder buffers) */
+static int output_packet(AVInputStream *ist, int ist_index,
+                         AVOutputStream **ost_table, int nb_ostreams,
+                         const AVPacket *pkt)
+{
+    AVFormatContext *os;
+    AVOutputStream *ost;
+    int ret, i;
+    uint8_t *data_buf;
+    int data_size, got_picture;
+    AVFrame picture;
+    void *buffer_to_free;
+    static unsigned int samples_size= 0;
+    AVSubtitle subtitle, *subtitle_to_free;
+    int got_subtitle;
+    AVPacket avpkt;
+
+    if(ist->next_pts == AV_NOPTS_VALUE)
+        ist->next_pts= ist->pts;
+
+    if (pkt == NULL) {
+        /* EOF handling */
+        av_init_packet(&avpkt);
+        avpkt.data = NULL;
+        avpkt.size = 0;
+        goto handle_eof;
+    } else {
+        avpkt = *pkt;
+    }
+
+    if(pkt->dts != AV_NOPTS_VALUE)
+        ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
+
+    //while we have more to decode or while the decoder did output something on EOF
+    while (avpkt.size > 0 || (!pkt && ist->next_pts != ist->pts)) {
+    handle_eof:
+        ist->pts= ist->next_pts;
+
+        if(avpkt.size && avpkt.size != pkt->size && verbose>0)
+            fprintf(stderr, "Multiple frames in a packet from stream %d\n", pkt->stream_index);
+
+        /* decode the packet if needed */
+        data_buf = NULL; /* fail safe */
+        data_size = 0;
+        subtitle_to_free = NULL;
+        if (ist->decoding_needed) {
+            switch(ist->st->codec->codec_type) {
+            case CODEC_TYPE_AUDIO:{
+                if(pkt && samples_size < FFMAX(pkt->size*sizeof(*samples), AVCODEC_MAX_AUDIO_FRAME_SIZE)) {
+                    samples_size = FFMAX(pkt->size*sizeof(*samples), AVCODEC_MAX_AUDIO_FRAME_SIZE);
+                    av_free(samples);
+                    samples= av_malloc(samples_size);
+                }
+                data_size= samples_size;
+                    /* XXX: could avoid copy if PCM 16 bits with same
+                       endianness as CPU */
+                ret = avcodec_decode_audio3(ist->st->codec, samples, &data_size,
+                                            &avpkt);
+                if (ret < 0)
+                    goto fail_decode;
+                avpkt.data += ret;
+                avpkt.size -= ret;
+                /* Some bug in mpeg audio decoder gives */
+                /* data_size < 0, it seems they are overflows */
+                if (data_size <= 0) {
+                    /* no audio frame */
+                    continue;
+                }
+                data_buf = (uint8_t *)samples;
+                ist->next_pts += ((int64_t)AV_TIME_BASE/2 * data_size) /
+                    (ist->st->codec->sample_rate * ist->st->codec->channels);
+                break;}
+            case CODEC_TYPE_VIDEO:
+                    data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
+                    /* XXX: allocate picture correctly */
+                    avcodec_get_frame_defaults(&picture);
+
+                    ret = avcodec_decode_video2(ist->st->codec,
+                                                &picture, &got_picture, &avpkt);
+                    ist->st->quality= picture.quality;
+                    if (ret < 0)
+                        goto fail_decode;
+                    if (!got_picture) {
+                        /* no picture yet */
+                        goto discard_packet;
+                    }
+                    if (ist->st->codec->time_base.num != 0) {
+                        int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
+                        ist->next_pts += ((int64_t)AV_TIME_BASE *
+                                          ist->st->codec->time_base.num * ticks) /
+                            ist->st->codec->time_base.den;
+                    }
+                    avpkt.size = 0;
+                    break;
+            case CODEC_TYPE_SUBTITLE:
+                ret = avcodec_decode_subtitle2(ist->st->codec,
+                                               &subtitle, &got_subtitle, &avpkt);
+                if (ret < 0)
+                    goto fail_decode;
+                if (!got_subtitle) {
+                    goto discard_packet;
+                }
+                subtitle_to_free = &subtitle;
+                avpkt.size = 0;
+                break;
+            default:
+                goto fail_decode;
+            }
+        } else {
+            switch(ist->st->codec->codec_type) {
+            case CODEC_TYPE_AUDIO:
+                ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
+                    ist->st->codec->sample_rate;
+                break;
+            case CODEC_TYPE_VIDEO:
+                if (ist->st->codec->time_base.num != 0) {
+                    int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
+                    ist->next_pts += ((int64_t)AV_TIME_BASE *
+                                      ist->st->codec->time_base.num * ticks) /
+                        ist->st->codec->time_base.den;
+                }
+                break;
+            }
+            data_buf = avpkt.data;
+            data_size = avpkt.size;
+            ret = avpkt.size;
+            avpkt.size = 0;
+        }
+
+        buffer_to_free = NULL;
+        if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO) {
+            pre_process_video_frame(ist, (AVPicture *)&picture,
+                                    &buffer_to_free);
+        }
+
+        // preprocess audio (volume)
+        if (ist->st->codec->codec_type == CODEC_TYPE_AUDIO) {
+            if (audio_volume != 256) {
+                short *volp;
+                volp = samples;
+                for(i=0;i<(data_size / sizeof(short));i++) {
+                    int v = ((*volp) * audio_volume + 128) >> 8;
+                    if (v < -32768) v = -32768;
+                    if (v >  32767) v = 32767;
+                    *volp++ = v;
+                }
+            }
+        }
+
+        /* frame rate emulation */
+        if (rate_emu) {
+            int64_t pts = av_rescale(ist->pts, 1000000, AV_TIME_BASE);
+            int64_t now = av_gettime() - ist->start;
+            if (pts > now)
+                usleep(pts - now);
+        }
+
+        /* if output time reached then transcode raw format,
+           encode packets and output them */
+        if (start_time == 0 || ist->pts >= start_time)
+            for(i=0;i<nb_ostreams;i++) {
+                int frame_size;
+
+                ost = ost_table[i];
+                if (ost->source_index == ist_index) {
+                    os = output_files[ost->file_index];
+
+#if 0
+                    printf("%d: got pts=%0.3f %0.3f\n", i,
+                           (double)pkt->pts / AV_TIME_BASE,
+                           ((double)ist->pts / AV_TIME_BASE) -
+                           ((double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den));
+#endif
+                    /* set the input output pts pairs */
+                    //ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE;
+
+                    if (ost->encoding_needed) {
+                        switch(ost->st->codec->codec_type) {
+                        case CODEC_TYPE_AUDIO:
+                            do_audio_out(os, ost, ist, data_buf, data_size);
+                            break;
+                        case CODEC_TYPE_VIDEO:
+                            do_video_out(os, ost, ist, &picture, &frame_size);
+                            if (vstats_filename && frame_size)
+                                do_video_stats(os, ost, frame_size);
+                            break;
+                        case CODEC_TYPE_SUBTITLE:
+                            do_subtitle_out(os, ost, ist, &subtitle,
+                                            pkt->pts);
+                            break;
+                        default:
+                            abort();
+                        }
+                    } else {
+                        AVFrame avframe; //FIXME/XXX remove this
+                        AVPacket opkt;
+                        int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base);
+
+                        av_init_packet(&opkt);
+
+                        if ((!ost->frame_number && !(pkt->flags & PKT_FLAG_KEY)) && !copy_initial_nonkeyframes)
+                            continue;
+
+                        /* no reencoding needed : output the packet directly */
+                        /* force the input stream PTS */
+
+                        avcodec_get_frame_defaults(&avframe);
+                        ost->st->codec->coded_frame= &avframe;
+                        avframe.key_frame = pkt->flags & PKT_FLAG_KEY;
+
+                        if(ost->st->codec->codec_type == CODEC_TYPE_AUDIO)
+                            audio_size += data_size;
+                        else if (ost->st->codec->codec_type == CODEC_TYPE_VIDEO) {
+                            video_size += data_size;
+                            ost->sync_opts++;
+                        }
+
+                        opkt.stream_index= ost->index;
+                        if(pkt->pts != AV_NOPTS_VALUE)
+                            opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
+                        else
+                            opkt.pts= AV_NOPTS_VALUE;
+
+                        if (pkt->dts == AV_NOPTS_VALUE)
+                            opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
+                        else
+                            opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
+                        opkt.dts -= ost_tb_start_time;
+
+                        opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
+                        opkt.flags= pkt->flags;
+
+                        //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
+                        if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY))
+                            opkt.destruct= av_destruct_packet;
+
+                        write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][opkt.stream_index]);
+                        ost->st->codec->frame_number++;
+                        ost->frame_number++;
+                        av_free_packet(&opkt);
+                    }
+                }
+            }
+        av_free(buffer_to_free);
+        /* XXX: allocate the subtitles in the codec ? */
+        if (subtitle_to_free) {
+            if (subtitle_to_free->rects != NULL) {
+                for (i = 0; i < subtitle_to_free->num_rects; i++) {
+                    av_freep(&subtitle_to_free->rects[i]->pict.data[0]);
+                    av_freep(&subtitle_to_free->rects[i]->pict.data[1]);
+                    av_freep(&subtitle_to_free->rects[i]);
+                }
+                av_freep(&subtitle_to_free->rects);
+            }
+            subtitle_to_free->num_rects = 0;
+            subtitle_to_free = NULL;
+        }
+    }
+ discard_packet:
+    if (pkt == NULL) {
+        /* EOF handling */
+
+        for(i=0;i<nb_ostreams;i++) {
+            ost = ost_table[i];
+            if (ost->source_index == ist_index) {
+                AVCodecContext *enc= ost->st->codec;
+                os = output_files[ost->file_index];
+
+                if(ost->st->codec->codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1)
+                    continue;
+                if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE))
+                    continue;
+
+                if (ost->encoding_needed) {
+                    for(;;) {
+                        AVPacket pkt;
+                        int fifo_bytes;
+                        av_init_packet(&pkt);
+                        pkt.stream_index= ost->index;
+
+                        switch(ost->st->codec->codec_type) {
+                        case CODEC_TYPE_AUDIO:
+                            fifo_bytes = av_fifo_size(ost->fifo);
+                            ret = 0;
+                            /* encode any samples remaining in fifo */
+                            if (fifo_bytes > 0) {
+                                int osize = av_get_bits_per_sample_format(enc->sample_fmt) >> 3;
+                                int fs_tmp = enc->frame_size;
+
+                                av_fifo_generic_read(ost->fifo, samples, fifo_bytes, NULL);
+                                if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
+                                    enc->frame_size = fifo_bytes / (osize * enc->channels);
+                                } else { /* pad */
+                                    int frame_bytes = enc->frame_size*osize*enc->channels;
+                                    if (samples_size < frame_bytes)
+                                        av_exit(1);
+                                    memset((uint8_t*)samples+fifo_bytes, 0, frame_bytes - fifo_bytes);
+                                }
+
+                                ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples);
+                                pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den,
+                                                          ost->st->time_base.num, enc->sample_rate);
+                                enc->frame_size = fs_tmp;
+                            }
+                            if(ret <= 0) {
+                                ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
+                            }
+                            if (ret < 0) {
+                                fprintf(stderr, "Audio encoding failed\n");
+                                av_exit(1);
+                            }
+                            audio_size += ret;
+                            pkt.flags |= PKT_FLAG_KEY;
+                            break;
+                        case CODEC_TYPE_VIDEO:
+                            ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
+                            if (ret < 0) {
+                                fprintf(stderr, "Video encoding failed\n");
+                                av_exit(1);
+                            }
+                            video_size += ret;
+                            if(enc->coded_frame && enc->coded_frame->key_frame)
+                                pkt.flags |= PKT_FLAG_KEY;
+                            if (ost->logfile && enc->stats_out) {
+                                fprintf(ost->logfile, "%s", enc->stats_out);
+                            }
+                            break;
+                        default:
+                            ret=-1;
+                        }
+
+                        if(ret<=0)
+                            break;
+                        pkt.data= bit_buffer;
+                        pkt.size= ret;
+                        if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+                            pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+                        write_frame(os, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+ fail_decode:
+    return -1;
+}
+
+static void print_sdp(AVFormatContext **avc, int n)
+{
+    char sdp[2048];
+
+    avf_sdp_create(avc, n, sdp, sizeof(sdp));
+    printf("SDP:\n%s\n", sdp);
+    fflush(stdout);
+}
+
+static int stream_index_from_inputs(AVFormatContext **input_files,
+                                    int nb_input_files,
+                                    AVInputFile *file_table,
+                                    AVInputStream **ist_table,
+                                    enum CodecType type,
+                                    int programid)
+{
+    int p, q, z;
+    for(z=0; z<nb_input_files; z++) {
+        AVFormatContext *ic = input_files[z];
+        for(p=0; p<ic->nb_programs; p++) {
+            AVProgram *program = ic->programs[p];
+            if(program->id != programid)
+                continue;
+            for(q=0; q<program->nb_stream_indexes; q++) {
+                int sidx = program->stream_index[q];
+                int ris = file_table[z].ist_index + sidx;
+                if(ist_table[ris]->discard && ic->streams[sidx]->codec->codec_type == type)
+                    return ris;
+            }
+        }
+    }
+
+    return -1;
+}
+
+/*
+ * The following code is the main loop of the file converter
+ */
+static int av_encode(AVFormatContext **output_files,
+                     int nb_output_files,
+                     AVFormatContext **input_files,
+                     int nb_input_files,
+                     AVStreamMap *stream_maps, int nb_stream_maps)
+{
+    int ret = 0, i, j, k, n, nb_istreams = 0, nb_ostreams = 0;
+    AVFormatContext *is, *os;
+    AVCodecContext *codec, *icodec;
+    AVOutputStream *ost, **ost_table = NULL;
+    AVInputStream *ist, **ist_table = NULL;
+    AVInputFile *file_table;
+    char error[1024];
+    int key;
+    int want_sdp = 1;
+    uint8_t no_packet[MAX_FILES]={0};
+    int no_packet_count=0;
+
+    file_table= av_mallocz(nb_input_files * sizeof(AVInputFile));
+    if (!file_table)
+        goto fail;
+
+    /* input stream init */
+    j = 0;
+    for(i=0;i<nb_input_files;i++) {
+        is = input_files[i];
+        file_table[i].ist_index = j;
+        file_table[i].nb_streams = is->nb_streams;
+        j += is->nb_streams;
+    }
+    nb_istreams = j;
+
+    ist_table = av_mallocz(nb_istreams * sizeof(AVInputStream *));
+    if (!ist_table)
+        goto fail;
+
+    for(i=0;i<nb_istreams;i++) {
+        ist = av_mallocz(sizeof(AVInputStream));
+        if (!ist)
+            goto fail;
+        ist_table[i] = ist;
+    }
+    j = 0;
+    for(i=0;i<nb_input_files;i++) {
+        is = input_files[i];
+        for(k=0;k<is->nb_streams;k++) {
+            ist = ist_table[j++];
+            ist->st = is->streams[k];
+            ist->file_index = i;
+            ist->index = k;
+            ist->discard = 1; /* the stream is discarded by default
+                                 (changed later) */
+
+            if (rate_emu) {
+                ist->start = av_gettime();
+            }
+        }
+    }
+
+    /* output stream init */
+    nb_ostreams = 0;
+    for(i=0;i<nb_output_files;i++) {
+        os = output_files[i];
+        if (!os->nb_streams) {
+            dump_format(output_files[i], i, output_files[i]->filename, 1);
+            fprintf(stderr, "Output file #%d does not contain any stream\n", i);
+            av_exit(1);
+        }
+        nb_ostreams += os->nb_streams;
+    }
+    if (nb_stream_maps > 0 && nb_stream_maps != nb_ostreams) {
+        fprintf(stderr, "Number of stream maps must match number of output streams\n");
+        av_exit(1);
+    }
+
+    /* Sanity check the mapping args -- do the input files & streams exist? */
+    for(i=0;i<nb_stream_maps;i++) {
+        int fi = stream_maps[i].file_index;
+        int si = stream_maps[i].stream_index;
+
+        if (fi < 0 || fi > nb_input_files - 1 ||
+            si < 0 || si > file_table[fi].nb_streams - 1) {
+            fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si);
+            av_exit(1);
+        }
+        fi = stream_maps[i].sync_file_index;
+        si = stream_maps[i].sync_stream_index;
+        if (fi < 0 || fi > nb_input_files - 1 ||
+            si < 0 || si > file_table[fi].nb_streams - 1) {
+            fprintf(stderr,"Could not find sync stream #%d.%d\n", fi, si);
+            av_exit(1);
+        }
+    }
+
+    ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams);
+    if (!ost_table)
+        goto fail;
+    for(i=0;i<nb_ostreams;i++) {
+        ost = av_mallocz(sizeof(AVOutputStream));
+        if (!ost)
+            goto fail;
+        ost_table[i] = ost;
+    }
+
+    n = 0;
+    for(k=0;k<nb_output_files;k++) {
+        os = output_files[k];
+        for(i=0;i<os->nb_streams;i++,n++) {
+            int found;
+            ost = ost_table[n];
+            ost->file_index = k;
+            ost->index = i;
+            ost->st = os->streams[i];
+            if (nb_stream_maps > 0) {
+                ost->source_index = file_table[stream_maps[n].file_index].ist_index +
+                    stream_maps[n].stream_index;
+
+                /* Sanity check that the stream types match */
+                if (ist_table[ost->source_index]->st->codec->codec_type != ost->st->codec->codec_type) {
+                    int i= ost->file_index;
+                    dump_format(output_files[i], i, output_files[i]->filename, 1);
+                    fprintf(stderr, "Codec type mismatch for mapping #%d.%d -> #%d.%d\n",
+                        stream_maps[n].file_index, stream_maps[n].stream_index,
+                        ost->file_index, ost->index);
+                    av_exit(1);
+                }
+
+            } else {
+                if(opt_programid) {
+                    found = 0;
+                    j = stream_index_from_inputs(input_files, nb_input_files, file_table, ist_table, ost->st->codec->codec_type, opt_programid);
+                    if(j != -1) {
+                        ost->source_index = j;
+                        found = 1;
+                    }
+                } else {
+                    /* get corresponding input stream index : we select the first one with the right type */
+                    found = 0;
+                    for(j=0;j<nb_istreams;j++) {
+                        ist = ist_table[j];
+                        if (ist->discard &&
+                            ist->st->codec->codec_type == ost->st->codec->codec_type) {
+                            ost->source_index = j;
+                            found = 1;
+                            break;
+                        }
+                    }
+                }
+
+                if (!found) {
+                    if(! opt_programid) {
+                        /* try again and reuse existing stream */
+                        for(j=0;j<nb_istreams;j++) {
+                            ist = ist_table[j];
+                            if (ist->st->codec->codec_type == ost->st->codec->codec_type) {
+                                ost->source_index = j;
+                                found = 1;
+                            }
+                        }
+                    }
+                    if (!found) {
+                        int i= ost->file_index;
+                        dump_format(output_files[i], i, output_files[i]->filename, 1);
+                        fprintf(stderr, "Could not find input stream matching output stream #%d.%d\n",
+                                ost->file_index, ost->index);
+                        av_exit(1);
+                    }
+                }
+            }
+            ist = ist_table[ost->source_index];
+            ist->discard = 0;
+            ost->sync_ist = (nb_stream_maps > 0) ?
+                ist_table[file_table[stream_maps[n].sync_file_index].ist_index +
+                         stream_maps[n].sync_stream_index] : ist;
+        }
+    }
+
+    /* for each output stream, we compute the right encoding parameters */
+    for(i=0;i<nb_ostreams;i++) {
+        AVMetadataTag *lang;
+        ost = ost_table[i];
+        os = output_files[ost->file_index];
+        ist = ist_table[ost->source_index];
+
+        codec = ost->st->codec;
+        icodec = ist->st->codec;
+
+        if ((lang=av_metadata_get(ist->st->metadata, "language", NULL, 0))
+            &&   !av_metadata_get(ost->st->metadata, "language", NULL, 0))
+            av_metadata_set(&ost->st->metadata, "language", lang->value);
+
+        ost->st->disposition = ist->st->disposition;
+        codec->bits_per_raw_sample= icodec->bits_per_raw_sample;
+        codec->chroma_sample_location = icodec->chroma_sample_location;
+
+        if (ost->st->stream_copy) {
+            /* if stream_copy is selected, no need to decode or encode */
+            codec->codec_id = icodec->codec_id;
+            codec->codec_type = icodec->codec_type;
+
+            if(!codec->codec_tag){
+                if(   !os->oformat->codec_tag
+                   || av_codec_get_id (os->oformat->codec_tag, icodec->codec_tag) > 0
+                   || av_codec_get_tag(os->oformat->codec_tag, icodec->codec_id) <= 0)
+                    codec->codec_tag = icodec->codec_tag;
+            }
+
+            codec->bit_rate = icodec->bit_rate;
+            codec->extradata= icodec->extradata;
+            codec->extradata_size= icodec->extradata_size;
+            if(av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000){
+                codec->time_base = icodec->time_base;
+                codec->time_base.num *= icodec->ticks_per_frame;
+            }else
+                codec->time_base = ist->st->time_base;
+            switch(codec->codec_type) {
+            case CODEC_TYPE_AUDIO:
+                if(audio_volume != 256) {
+                    fprintf(stderr,"-acodec copy and -vol are incompatible (frames are not decoded)\n");
+                    av_exit(1);
+                }
+                codec->channel_layout = icodec->channel_layout;
+                codec->sample_rate = icodec->sample_rate;
+                codec->channels = icodec->channels;
+                codec->frame_size = icodec->frame_size;
+                codec->block_align= icodec->block_align;
+                if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3)
+                    codec->block_align= 0;
+                if(codec->codec_id == CODEC_ID_AC3)
+                    codec->block_align= 0;
+                break;
+            case CODEC_TYPE_VIDEO:
+                codec->pix_fmt = icodec->pix_fmt;
+                codec->width = icodec->width;
+                codec->height = icodec->height;
+                codec->has_b_frames = icodec->has_b_frames;
+                break;
+            case CODEC_TYPE_SUBTITLE:
+                codec->width = icodec->width;
+                codec->height = icodec->height;
+                break;
+            default:
+                abort();
+            }
+        } else {
+            switch(codec->codec_type) {
+            case CODEC_TYPE_AUDIO:
+                ost->fifo= av_fifo_alloc(1024);
+                if(!ost->fifo)
+                    goto fail;
+                ost->reformat_pair = MAKE_SFMT_PAIR(SAMPLE_FMT_NONE,SAMPLE_FMT_NONE);
+                ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
+                icodec->request_channels = codec->channels;
+                ist->decoding_needed = 1;
+                ost->encoding_needed = 1;
+                break;
+            case CODEC_TYPE_VIDEO:
+                if (ost->st->codec->pix_fmt == PIX_FMT_NONE) {
+                    fprintf(stderr, "Video pixel format is unknown, stream cannot be decoded\n");
+                    av_exit(1);
+                }
+                ost->video_crop = ((frame_leftBand + frame_rightBand + frame_topBand + frame_bottomBand) != 0);
+                ost->video_pad = ((frame_padleft + frame_padright + frame_padtop + frame_padbottom) != 0);
+                ost->video_resample = ((codec->width != icodec->width -
+                                (frame_leftBand + frame_rightBand) +
+                                (frame_padleft + frame_padright)) ||
+                        (codec->height != icodec->height -
+                                (frame_topBand  + frame_bottomBand) +
+                                (frame_padtop + frame_padbottom)) ||
+                        (codec->pix_fmt != icodec->pix_fmt));
+                if (ost->video_crop) {
+                    ost->topBand = frame_topBand;
+                    ost->leftBand = frame_leftBand;
+                }
+                if (ost->video_pad) {
+                    ost->padtop = frame_padtop;
+                    ost->padleft = frame_padleft;
+                    ost->padbottom = frame_padbottom;
+                    ost->padright = frame_padright;
+                    if (!ost->video_resample) {
+                        avcodec_get_frame_defaults(&ost->pict_tmp);
+                        if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt,
+                                         codec->width, codec->height))
+                            goto fail;
+                    }
+                }
+                if (ost->video_resample) {
+                    avcodec_get_frame_defaults(&ost->pict_tmp);
+                    if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt,
+                                         codec->width, codec->height)) {
+                        fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");
+                        av_exit(1);
+                    }
+                    sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
+                    ost->img_resample_ctx = sws_getContext(
+                            icodec->width - (frame_leftBand + frame_rightBand),
+                            icodec->height - (frame_topBand + frame_bottomBand),
+                            icodec->pix_fmt,
+                            codec->width - (frame_padleft + frame_padright),
+                            codec->height - (frame_padtop + frame_padbottom),
+                            codec->pix_fmt,
+                            sws_flags, NULL, NULL, NULL);
+                    if (ost->img_resample_ctx == NULL) {
+                        fprintf(stderr, "Cannot get resampling context\n");
+                        av_exit(1);
+                    }
+                    ost->resample_height = icodec->height - (frame_topBand + frame_bottomBand);
+                    codec->bits_per_raw_sample= 0;
+                }
+                ost->encoding_needed = 1;
+                ist->decoding_needed = 1;
+                break;
+            case CODEC_TYPE_SUBTITLE:
+                ost->encoding_needed = 1;
+                ist->decoding_needed = 1;
+                break;
+            default:
+                abort();
+                break;
+            }
+            /* two pass mode */
+            if (ost->encoding_needed &&
+                (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
+                char logfilename[1024];
+                FILE *f;
+                int size;
+                char *logbuffer;
+
+                snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
+                         pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX,
+                         i);
+                if (codec->flags & CODEC_FLAG_PASS1) {
+                    f = fopen(logfilename, "w");
+                    if (!f) {
+                        fprintf(stderr, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno));
+                        av_exit(1);
+                    }
+                    ost->logfile = f;
+                } else {
+                    /* read the log file */
+                    f = fopen(logfilename, "r");
+                    if (!f) {
+                        fprintf(stderr, "Cannot read log file '%s' for pass-2 encoding: %s\n", logfilename, strerror(errno));
+                        av_exit(1);
+                    }
+                    fseek(f, 0, SEEK_END);
+                    size = ftell(f);
+                    fseek(f, 0, SEEK_SET);
+                    logbuffer = av_malloc(size + 1);
+                    if (!logbuffer) {
+                        fprintf(stderr, "Could not allocate log buffer\n");
+                        av_exit(1);
+                    }
+                    size = fread(logbuffer, 1, size, f);
+                    fclose(f);
+                    logbuffer[size] = '\0';
+                    codec->stats_in = logbuffer;
+                }
+            }
+        }
+        if(codec->codec_type == CODEC_TYPE_VIDEO){
+            int size= codec->width * codec->height;
+            bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 200);
+        }
+    }
+
+    if (!bit_buffer)
+        bit_buffer = av_malloc(bit_buffer_size);
+    if (!bit_buffer) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    /* open each encoder */
+    for(i=0;i<nb_ostreams;i++) {
+        ost = ost_table[i];
+        if (ost->encoding_needed) {
+            AVCodec *codec = output_codecs[i];
+            if (!codec)
+                codec = avcodec_find_encoder(ost->st->codec->codec_id);
+            if (!codec) {
+                snprintf(error, sizeof(error), "Unsupported codec for output stream #%d.%d",
+                        ost->file_index, ost->index);
+                ret = AVERROR(EINVAL);
+                goto dump_format;
+            }
+            if (avcodec_open(ost->st->codec, codec) < 0) {
+                snprintf(error, sizeof(error), "Error while opening codec for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height",
+                        ost->file_index, ost->index);
+                ret = AVERROR(EINVAL);
+                goto dump_format;
+            }
+            extra_size += ost->st->codec->extradata_size;
+        }
+    }
+
+    /* open each decoder */
+    for(i=0;i<nb_istreams;i++) {
+        ist = ist_table[i];
+        if (ist->decoding_needed) {
+            AVCodec *codec = input_codecs[i];
+            if (!codec)
+                codec = avcodec_find_decoder(ist->st->codec->codec_id);
+            if (!codec) {
+                snprintf(error, sizeof(error), "Unsupported codec (id=%d) for input stream #%d.%d",
+                        ist->st->codec->codec_id, ist->file_index, ist->index);
+                ret = AVERROR(EINVAL);
+                goto dump_format;
+            }
+            if (avcodec_open(ist->st->codec, codec) < 0) {
+                snprintf(error, sizeof(error), "Error while opening codec for input stream #%d.%d",
+                        ist->file_index, ist->index);
+                ret = AVERROR(EINVAL);
+                goto dump_format;
+            }
+            //if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO)
+            //    ist->st->codec->flags |= CODEC_FLAG_REPEAT_FIELD;
+        }
+    }
+
+    /* init pts */
+    for(i=0;i<nb_istreams;i++) {
+        ist = ist_table[i];
+        ist->pts = 0;
+        ist->next_pts = AV_NOPTS_VALUE;
+        ist->is_start = 1;
+    }
+
+    /* set meta data information from input file if required */
+    for (i=0;i<nb_meta_data_maps;i++) {
+        AVFormatContext *out_file;
+        AVFormatContext *in_file;
+        AVMetadataTag *mtag;
+
+        int out_file_index = meta_data_maps[i].out_file;
+        int in_file_index = meta_data_maps[i].in_file;
+        if (out_file_index < 0 || out_file_index >= nb_output_files) {
+            snprintf(error, sizeof(error), "Invalid output file index %d map_meta_data(%d,%d)",
+                     out_file_index, out_file_index, in_file_index);
+            ret = AVERROR(EINVAL);
+            goto dump_format;
+        }
+        if (in_file_index < 0 || in_file_index >= nb_input_files) {
+            snprintf(error, sizeof(error), "Invalid input file index %d map_meta_data(%d,%d)",
+                     in_file_index, out_file_index, in_file_index);
+            ret = AVERROR(EINVAL);
+            goto dump_format;
+        }
+
+        out_file = output_files[out_file_index];
+        in_file = input_files[in_file_index];
+
+
+        mtag=NULL;
+        while((mtag=av_metadata_get(in_file->metadata, "", mtag, AV_METADATA_IGNORE_SUFFIX)))
+            av_metadata_set(&out_file->metadata, mtag->key, mtag->value);
+        av_metadata_conv(out_file, out_file->oformat->metadata_conv,
+                                    in_file->iformat->metadata_conv);
+    }
+
+    /* open files and write file headers */
+    for(i=0;i<nb_output_files;i++) {
+        os = output_files[i];
+        if (av_write_header(os) < 0) {
+            snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
+            ret = AVERROR(EINVAL);
+            goto dump_format;
+        }
+        if (strcmp(output_files[i]->oformat->name, "rtp")) {
+            want_sdp = 0;
+        }
+    }
+
+ dump_format:
+    /* dump the file output parameters - cannot be done before in case
+       of stream copy */
+    for(i=0;i<nb_output_files;i++) {
+        dump_format(output_files[i], i, output_files[i]->filename, 1);
+    }
+
+    /* dump the stream mapping */
+    if (verbose >= 0) {
+        fprintf(stderr, "Stream mapping:\n");
+        for(i=0;i<nb_ostreams;i++) {
+            ost = ost_table[i];
+            fprintf(stderr, "  Stream #%d.%d -> #%d.%d",
+                    ist_table[ost->source_index]->file_index,
+                    ist_table[ost->source_index]->index,
+                    ost->file_index,
+                    ost->index);
+            if (ost->sync_ist != ist_table[ost->source_index])
+                fprintf(stderr, " [sync #%d.%d]",
+                        ost->sync_ist->file_index,
+                        ost->sync_ist->index);
+            fprintf(stderr, "\n");
+        }
+    }
+
+    if (ret) {
+        fprintf(stderr, "%s\n", error);
+        goto fail;
+    }
+
+    if (want_sdp) {
+        print_sdp(output_files, nb_output_files);
+    }
+
+    if (!using_stdin && verbose >= 0) {
+        fprintf(stderr, "Press [q] to stop encoding\n");
+        url_set_interrupt_cb(decode_interrupt_cb);
+    }
+    term_init();
+
+    timer_start = av_gettime();
+
+    for(; received_sigterm == 0;) {
+        int file_index, ist_index;
+        AVPacket pkt;
+        double ipts_min;
+        double opts_min;
+
+    redo:
+        ipts_min= 1e100;
+        opts_min= 1e100;
+        /* if 'q' pressed, exits */
+        if (!using_stdin) {
+            if (q_pressed)
+                break;
+            /* read_key() returns 0 on EOF */
+            key = read_key();
+            if (key == 'q')
+                break;
+        }
+
+        /* select the stream that we must read now by looking at the
+           smallest output pts */
+        file_index = -1;
+        for(i=0;i<nb_ostreams;i++) {
+            double ipts, opts;
+            ost = ost_table[i];
+            os = output_files[ost->file_index];
+            ist = ist_table[ost->source_index];
+            if(no_packet[ist->file_index])
+                continue;
+            if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO)
+                opts = ost->sync_opts * av_q2d(ost->st->codec->time_base);
+            else
+                opts = ost->st->pts.val * av_q2d(ost->st->time_base);
+            ipts = (double)ist->pts;
+            if (!file_table[ist->file_index].eof_reached){
+                if(ipts < ipts_min) {
+                    ipts_min = ipts;
+                    if(input_sync ) file_index = ist->file_index;
+                }
+                if(opts < opts_min) {
+                    opts_min = opts;
+                    if(!input_sync) file_index = ist->file_index;
+                }
+            }
+            if(ost->frame_number >= max_frames[ost->st->codec->codec_type]){
+                file_index= -1;
+                break;
+            }
+        }
+        /* if none, if is finished */
+        if (file_index < 0) {
+            if(no_packet_count){
+                no_packet_count=0;
+                memset(no_packet, 0, sizeof(no_packet));
+                usleep(10000);
+                continue;
+            }
+            break;
+        }
+
+        /* finish if recording time exhausted */
+        if (opts_min >= (recording_time / 1000000.0))
+            break;
+
+        /* finish if limit size exhausted */
+        if (limit_filesize != 0 && limit_filesize < url_ftell(output_files[0]->pb))
+            break;
+
+        /* read a frame from it and output it in the fifo */
+        is = input_files[file_index];
+        ret= av_read_frame(is, &pkt);
+        if(ret == AVERROR(EAGAIN)){
+            no_packet[file_index]=1;
+            no_packet_count++;
+            continue;
+        }
+        if (ret < 0) {
+            file_table[file_index].eof_reached = 1;
+            if (opt_shortest)
+                break;
+            else
+                continue;
+        }
+
+        no_packet_count=0;
+        memset(no_packet, 0, sizeof(no_packet));
+
+        if (do_pkt_dump) {
+            av_pkt_dump_log(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump);
+        }
+        /* the following test is needed in case new streams appear
+           dynamically in stream : we ignore them */
+        if (pkt.stream_index >= file_table[file_index].nb_streams)
+            goto discard_packet;
+        ist_index = file_table[file_index].ist_index + pkt.stream_index;
+        ist = ist_table[ist_index];
+        if (ist->discard)
+            goto discard_packet;
+
+        if (pkt.dts != AV_NOPTS_VALUE)
+            pkt.dts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
+        if (pkt.pts != AV_NOPTS_VALUE)
+            pkt.pts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
+
+        if(input_files_ts_scale[file_index][pkt.stream_index]){
+            if(pkt.pts != AV_NOPTS_VALUE)
+                pkt.pts *= input_files_ts_scale[file_index][pkt.stream_index];
+            if(pkt.dts != AV_NOPTS_VALUE)
+                pkt.dts *= input_files_ts_scale[file_index][pkt.stream_index];
+        }
+
+//        fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type);
+        if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE
+            && (is->iformat->flags & AVFMT_TS_DISCONT)) {
+            int64_t pkt_dts= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
+            int64_t delta= pkt_dts - ist->next_pts;
+            if((FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE || pkt_dts+1<ist->pts)&& !copy_ts){
+                input_files_ts_offset[ist->file_index]-= delta;
+                if (verbose > 2)
+                    fprintf(stderr, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, input_files_ts_offset[ist->file_index]);
+                pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
+                if(pkt.pts != AV_NOPTS_VALUE)
+                    pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
+            }
+        }
+
+        //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
+        if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
+
+            if (verbose >= 0)
+                fprintf(stderr, "Error while decoding stream #%d.%d\n",
+                        ist->file_index, ist->index);
+            if (exit_on_error)
+                av_exit(1);
+            av_free_packet(&pkt);
+            goto redo;
+        }
+
+    discard_packet:
+        av_free_packet(&pkt);
+
+        /* dump report by using the output first video and audio streams */
+        print_report(output_files, ost_table, nb_ostreams, 0);
+    }
+
+    /* at the end of stream, we must flush the decoder buffers */
+    for(i=0;i<nb_istreams;i++) {
+        ist = ist_table[i];
+        if (ist->decoding_needed) {
+            output_packet(ist, i, ost_table, nb_ostreams, NULL);
+        }
+    }
+
+    term_exit();
+
+    /* write the trailer if needed and close file */
+    for(i=0;i<nb_output_files;i++) {
+        os = output_files[i];
+        av_write_trailer(os);
+    }
+
+    /* dump report by using the first video and audio streams */
+    print_report(output_files, ost_table, nb_ostreams, 1);
+
+    /* close each encoder */
+    for(i=0;i<nb_ostreams;i++) {
+        ost = ost_table[i];
+        if (ost->encoding_needed) {
+            av_freep(&ost->st->codec->stats_in);
+            avcodec_close(ost->st->codec);
+        }
+    }
+
+    /* close each decoder */
+    for(i=0;i<nb_istreams;i++) {
+        ist = ist_table[i];
+        if (ist->decoding_needed) {
+            avcodec_close(ist->st->codec);
+        }
+    }
+
+    /* finished ! */
+    ret = 0;
+
+ fail:
+    av_freep(&bit_buffer);
+    av_free(file_table);
+
+    if (ist_table) {
+        for(i=0;i<nb_istreams;i++) {
+            ist = ist_table[i];
+            av_free(ist);
+        }
+        av_free(ist_table);
+    }
+    if (ost_table) {
+        for(i=0;i<nb_ostreams;i++) {
+            ost = ost_table[i];
+            if (ost) {
+                if (ost->logfile) {
+                    fclose(ost->logfile);
+                    ost->logfile = NULL;
+                }
+                av_fifo_free(ost->fifo); /* works even if fifo is not
+                                             initialized but set to zero */
+                av_free(ost->pict_tmp.data[0]);
+                if (ost->video_resample)
+                    sws_freeContext(ost->img_resample_ctx);
+                if (ost->resample)
+                    audio_resample_close(ost->resample);
+                if (ost->reformat_ctx)
+                    av_audio_convert_free(ost->reformat_ctx);
+                av_free(ost);
+            }
+        }
+        av_free(ost_table);
+    }
+    return ret;
+}
+
+#if 0
+int file_read(const char *filename)
+{
+    URLContext *h;
+    unsigned char buffer[1024];
+    int len, i;
+
+    if (url_open(&h, filename, O_RDONLY) < 0) {
+        printf("could not open '%s'\n", filename);
+        return -1;
+    }
+    for(;;) {
+        len = url_read(h, buffer, sizeof(buffer));
+        if (len <= 0)
+            break;
+        for(i=0;i<len;i++) putchar(buffer[i]);
+    }
+    url_close(h);
+    return 0;
+}
+#endif
+
+static void opt_format(const char *arg)
+{
+    /* compatibility stuff for pgmyuv */
+    if (!strcmp(arg, "pgmyuv")) {
+        pgmyuv_compatibility_hack=1;
+//        opt_image_format(arg);
+        arg = "image2";
+        fprintf(stderr, "pgmyuv format is deprecated, use image2\n");
+    }
+
+    file_iformat = av_find_input_format(arg);
+    file_oformat = guess_format(arg, NULL, NULL);
+    if (!file_iformat && !file_oformat) {
+        fprintf(stderr, "Unknown input or output format: %s\n", arg);
+        av_exit(1);
+    }
+}
+
+static void opt_video_rc_override_string(const char *arg)
+{
+    video_rc_override_string = arg;
+}
+
+static int opt_me_threshold(const char *opt, const char *arg)
+{
+    me_threshold = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
+    return 0;
+}
+
+static int opt_loglevel(const char *opt, const char *arg)
+{
+    int level = parse_number_or_die(opt, arg, OPT_INT, INT_MIN, INT_MAX);
+    av_log_set_level(level);
+    return 0;
+}
+
+static int opt_verbose(const char *opt, const char *arg)
+{
+    verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10);
+    return 0;
+}
+
+static int opt_frame_rate(const char *opt, const char *arg)
+{
+    if (av_parse_video_frame_rate(&frame_rate, arg) < 0) {
+        fprintf(stderr, "Incorrect value for %s: %s\n", opt, arg);
+        av_exit(1);
+    }
+    return 0;
+}
+
+static int opt_bitrate(const char *opt, const char *arg)
+{
+    int codec_type = opt[0]=='a' ? CODEC_TYPE_AUDIO : CODEC_TYPE_VIDEO;
+
+    opt_default(opt, arg);
+
+    if (av_get_int(avcodec_opts[codec_type], "b", NULL) < 1000)
+        fprintf(stderr, "WARNING: The bitrate parameter is set too low. It takes bits/s as argument, not kbits/s\n");
+
+    return 0;
+}
+
+static void opt_frame_crop_top(const char *arg)
+{
+    frame_topBand = atoi(arg);
+    if (frame_topBand < 0) {
+        fprintf(stderr, "Incorrect top crop size\n");
+        av_exit(1);
+    }
+    if ((frame_topBand) >= frame_height){
+        fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+        av_exit(1);
+    }
+    frame_height -= frame_topBand;
+}
+
+static void opt_frame_crop_bottom(const char *arg)
+{
+    frame_bottomBand = atoi(arg);
+    if (frame_bottomBand < 0) {
+        fprintf(stderr, "Incorrect bottom crop size\n");
+        av_exit(1);
+    }
+    if ((frame_bottomBand) >= frame_height){
+        fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+        av_exit(1);
+    }
+    frame_height -= frame_bottomBand;
+}
+
+static void opt_frame_crop_left(const char *arg)
+{
+    frame_leftBand = atoi(arg);
+    if (frame_leftBand < 0) {
+        fprintf(stderr, "Incorrect left crop size\n");
+        av_exit(1);
+    }
+    if ((frame_leftBand) >= frame_width){
+        fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+        av_exit(1);
+    }
+    frame_width -= frame_leftBand;
+}
+
+static void opt_frame_crop_right(const char *arg)
+{
+    frame_rightBand = atoi(arg);
+    if (frame_rightBand < 0) {
+        fprintf(stderr, "Incorrect right crop size\n");
+        av_exit(1);
+    }
+    if ((frame_rightBand) >= frame_width){
+        fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+        av_exit(1);
+    }
+    frame_width -= frame_rightBand;
+}
+
+static void opt_frame_size(const char *arg)
+{
+    if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
+        fprintf(stderr, "Incorrect frame size\n");
+        av_exit(1);
+    }
+    if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
+        fprintf(stderr, "Frame size must be a multiple of 2\n");
+        av_exit(1);
+    }
+}
+
+static void opt_pad_color(const char *arg) {
+    /* Input is expected to be six hex digits similar to
+       how colors are expressed in html tags (but without the #) */
+    int rgb = strtol(arg, NULL, 16);
+    int r,g,b;
+
+    r = (rgb >> 16);
+    g = ((rgb >> 8) & 255);
+    b = (rgb & 255);
+
+    padcolor[0] = RGB_TO_Y(r,g,b);
+    padcolor[1] = RGB_TO_U(r,g,b,0);
+    padcolor[2] = RGB_TO_V(r,g,b,0);
+}
+
+static void opt_frame_pad_top(const char *arg)
+{
+    frame_padtop = atoi(arg);
+    if (frame_padtop < 0) {
+        fprintf(stderr, "Incorrect top pad size\n");
+        av_exit(1);
+    }
+}
+
+static void opt_frame_pad_bottom(const char *arg)
+{
+    frame_padbottom = atoi(arg);
+    if (frame_padbottom < 0) {
+        fprintf(stderr, "Incorrect bottom pad size\n");
+        av_exit(1);
+    }
+}
+
+
+static void opt_frame_pad_left(const char *arg)
+{
+    frame_padleft = atoi(arg);
+    if (frame_padleft < 0) {
+        fprintf(stderr, "Incorrect left pad size\n");
+        av_exit(1);
+    }
+}
+
+
+static void opt_frame_pad_right(const char *arg)
+{
+    frame_padright = atoi(arg);
+    if (frame_padright < 0) {
+        fprintf(stderr, "Incorrect right pad size\n");
+        av_exit(1);
+    }
+}
+
+static void list_fmts(void (*get_fmt_string)(char *buf, int buf_size, int fmt), int nb_fmts)
+{
+    int i;
+    char fmt_str[128];
+    for (i=-1; i < nb_fmts; i++) {
+        get_fmt_string (fmt_str, sizeof(fmt_str), i);
+        fprintf(stdout, "%s\n", fmt_str);
+    }
+}
+
+static void opt_frame_pix_fmt(const char *arg)
+{
+    if (strcmp(arg, "list")) {
+        frame_pix_fmt = avcodec_get_pix_fmt(arg);
+        if (frame_pix_fmt == PIX_FMT_NONE) {
+            fprintf(stderr, "Unknown pixel format requested: %s\n", arg);
+            av_exit(1);
+        }
+    } else {
+        list_fmts(avcodec_pix_fmt_string, PIX_FMT_NB);
+        av_exit(0);
+    }
+}
+
+static void opt_frame_aspect_ratio(const char *arg)
+{
+    int x = 0, y = 0;
+    double ar = 0;
+    const char *p;
+    char *end;
+
+    p = strchr(arg, ':');
+    if (p) {
+        x = strtol(arg, &end, 10);
+        if (end == p)
+            y = strtol(end+1, &end, 10);
+        if (x > 0 && y > 0)
+            ar = (double)x / (double)y;
+    } else
+        ar = strtod(arg, NULL);
+
+    if (!ar) {
+        fprintf(stderr, "Incorrect aspect ratio specification.\n");
+        av_exit(1);
+    }
+    frame_aspect_ratio = ar;
+}
+
+static int opt_metadata(const char *opt, const char *arg)
+{
+    char *mid= strchr(arg, '=');
+
+    if(!mid){
+        fprintf(stderr, "Missing =\n");
+        av_exit(1);
+    }
+    *mid++= 0;
+
+    metadata_count++;
+    metadata= av_realloc(metadata, sizeof(*metadata)*metadata_count);
+    metadata[metadata_count-1].key  = av_strdup(arg);
+    metadata[metadata_count-1].value= av_strdup(mid);
+
+    return 0;
+}
+
+static void opt_qscale(const char *arg)
+{
+    video_qscale = atof(arg);
+    if (video_qscale <= 0 ||
+        video_qscale > 255) {
+        fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
+        av_exit(1);
+    }
+}
+
+static void opt_top_field_first(const char *arg)
+{
+    top_field_first= atoi(arg);
+}
+
+static int opt_thread_count(const char *opt, const char *arg)
+{
+    thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
+#if !HAVE_THREADS
+    if (verbose >= 0)
+        fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
+#endif
+    return 0;
+}
+
+static void opt_audio_sample_fmt(const char *arg)
+{
+    if (strcmp(arg, "list"))
+        audio_sample_fmt = avcodec_get_sample_fmt(arg);
+    else {
+        list_fmts(avcodec_sample_fmt_string, SAMPLE_FMT_NB);
+        av_exit(0);
+    }
+}
+
+static int opt_audio_rate(const char *opt, const char *arg)
+{
+    audio_sample_rate = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
+    return 0;
+}
+
+static int opt_audio_channels(const char *opt, const char *arg)
+{
+    audio_channels = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
+    return 0;
+}
+
+static void opt_video_channel(const char *arg)
+{
+    video_channel = strtol(arg, NULL, 0);
+}
+
+static void opt_video_standard(const char *arg)
+{
+    video_standard = av_strdup(arg);
+}
+
+static void opt_codec(int *pstream_copy, char **pcodec_name,
+                      int codec_type, const char *arg)
+{
+    av_freep(pcodec_name);
+    if (!strcmp(arg, "copy")) {
+        *pstream_copy = 1;
+    } else {
+        *pcodec_name = av_strdup(arg);
+    }
+}
+
+static void opt_audio_codec(const char *arg)
+{
+    opt_codec(&audio_stream_copy, &audio_codec_name, CODEC_TYPE_AUDIO, arg);
+}
+
+static void opt_audio_tag(const char *arg)
+{
+    char *tail;
+    audio_codec_tag= strtol(arg, &tail, 0);
+
+    if(!tail || *tail)
+        audio_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
+}
+
+static void opt_video_tag(const char *arg)
+{
+    char *tail;
+    video_codec_tag= strtol(arg, &tail, 0);
+
+    if(!tail || *tail)
+        video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
+}
+
+static void opt_video_codec(const char *arg)
+{
+    opt_codec(&video_stream_copy, &video_codec_name, CODEC_TYPE_VIDEO, arg);
+}
+
+static void opt_subtitle_codec(const char *arg)
+{
+    opt_codec(&subtitle_stream_copy, &subtitle_codec_name, CODEC_TYPE_SUBTITLE, arg);
+}
+
+static void opt_subtitle_tag(const char *arg)
+{
+    char *tail;
+    subtitle_codec_tag= strtol(arg, &tail, 0);
+
+    if(!tail || *tail)
+        subtitle_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
+}
+
+static void opt_map(const char *arg)
+{
+    AVStreamMap *m;
+    char *p;
+
+    m = &stream_maps[nb_stream_maps++];
+
+    m->file_index = strtol(arg, &p, 0);
+    if (*p)
+        p++;
+
+    m->stream_index = strtol(p, &p, 0);
+    if (*p) {
+        p++;
+        m->sync_file_index = strtol(p, &p, 0);
+        if (*p)
+            p++;
+        m->sync_stream_index = strtol(p, &p, 0);
+    } else {
+        m->sync_file_index = m->file_index;
+        m->sync_stream_index = m->stream_index;
+    }
+}
+
+static void opt_map_meta_data(const char *arg)
+{
+    AVMetaDataMap *m;
+    char *p;
+
+    m = &meta_data_maps[nb_meta_data_maps++];
+
+    m->out_file = strtol(arg, &p, 0);
+    if (*p)
+        p++;
+
+    m->in_file = strtol(p, &p, 0);
+}
+
+static void opt_input_ts_scale(const char *arg)
+{
+    unsigned int stream;
+    double scale;
+    char *p;
+
+    stream = strtol(arg, &p, 0);
+    if (*p)
+        p++;
+    scale= strtod(p, &p);
+
+    if(stream >= MAX_STREAMS)
+        av_exit(1);
+
+    input_files_ts_scale[nb_input_files][stream]= scale;
+}
+
+static int opt_recording_time(const char *opt, const char *arg)
+{
+    recording_time = parse_time_or_die(opt, arg, 1);
+    return 0;
+}
+
+static int opt_start_time(const char *opt, const char *arg)
+{
+    start_time = parse_time_or_die(opt, arg, 1);
+    return 0;
+}
+
+static int opt_rec_timestamp(const char *opt, const char *arg)
+{
+    rec_timestamp = parse_time_or_die(opt, arg, 0) / 1000000;
+    return 0;
+}
+
+static int opt_input_ts_offset(const char *opt, const char *arg)
+{
+    input_ts_offset = parse_time_or_die(opt, arg, 1);
+    return 0;
+}
+
+static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
+{
+    const char *codec_string = encoder ? "encoder" : "decoder";
+    AVCodec *codec;
+
+    if(!name)
+        return CODEC_ID_NONE;
+    codec = encoder ?
+        avcodec_find_encoder_by_name(name) :
+        avcodec_find_decoder_by_name(name);
+    if(!codec) {
+        fprintf(stderr, "Unknown %s '%s'\n", codec_string, name);
+        av_exit(1);
+    }
+    if(codec->type != type) {
+        fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name);
+        av_exit(1);
+    }
+    return codec->id;
+}
+
+static void opt_input_file(const char *filename)
+{
+    AVFormatContext *ic;
+    AVFormatParameters params, *ap = &params;
+    int err, i, ret, rfps, rfps_base;
+    int64_t timestamp;
+
+    if (!strcmp(filename, "-"))
+        filename = "pipe:";
+
+    using_stdin |= !strncmp(filename, "pipe:", 5) ||
+                    !strcmp(filename, "/dev/stdin");
+
+    /* get default parameters from command line */
+    ic = avformat_alloc_context();
+
+    memset(ap, 0, sizeof(*ap));
+    ap->prealloced_context = 1;
+    ap->sample_rate = audio_sample_rate;
+    ap->channels = audio_channels;
+    ap->time_base.den = frame_rate.num;
+    ap->time_base.num = frame_rate.den;
+    ap->width = frame_width + frame_padleft + frame_padright;
+    ap->height = frame_height + frame_padtop + frame_padbottom;
+    ap->pix_fmt = frame_pix_fmt;
+   // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat
+    ap->channel = video_channel;
+    ap->standard = video_standard;
+    ap->video_codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 0);
+    ap->audio_codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 0);
+    if(pgmyuv_compatibility_hack)
+        ap->video_codec_id= CODEC_ID_PGMYUV;
+
+    set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM);
+
+    ic->video_codec_id   = find_codec_or_die(video_codec_name   , CODEC_TYPE_VIDEO   , 0);
+    ic->audio_codec_id   = find_codec_or_die(audio_codec_name   , CODEC_TYPE_AUDIO   , 0);
+    ic->subtitle_codec_id= find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 0);
+    ic->flags |= AVFMT_FLAG_NONBLOCK;
+
+    /* open the input file with generic libav function */
+    err = av_open_input_file(&ic, filename, file_iformat, 0, ap);
+    if (err < 0) {
+        print_error(filename, err);
+        av_exit(1);
+    }
+    if(opt_programid) {
+        int i;
+        for(i=0; i<ic->nb_programs; i++)
+            if(ic->programs[i]->id != opt_programid)
+                ic->programs[i]->discard = AVDISCARD_ALL;
+    }
+
+    ic->loop_input = loop_input;
+
+    /* If not enough info to get the stream parameters, we decode the
+       first frames to get it. (used in mpeg case for example) */
+    ret = av_find_stream_info(ic);
+    if (ret < 0 && verbose >= 0) {
+        fprintf(stderr, "%s: could not find codec parameters\n", filename);
+        av_exit(1);
+    }
+
+    timestamp = start_time;
+    /* add the stream start time */
+    if (ic->start_time != AV_NOPTS_VALUE)
+        timestamp += ic->start_time;
+
+    /* if seeking requested, we execute it */
+    if (start_time != 0) {
+        ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
+        if (ret < 0) {
+            fprintf(stderr, "%s: could not seek to position %0.3f\n",
+                    filename, (double)timestamp / AV_TIME_BASE);
+        }
+        /* reset seek info */
+        start_time = 0;
+    }
+
+    /* update the current parameters so that they match the one of the input stream */
+    for(i=0;i<ic->nb_streams;i++) {
+        AVCodecContext *enc = ic->streams[i]->codec;
+        if(thread_count>1)
+            avcodec_thread_init(enc, thread_count);
+        enc->thread_count= thread_count;
+        switch(enc->codec_type) {
+        case CODEC_TYPE_AUDIO:
+            set_context_opts(enc, avcodec_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM);
+            //fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
+            channel_layout = enc->channel_layout;
+            audio_channels = enc->channels;
+            audio_sample_rate = enc->sample_rate;
+            audio_sample_fmt = enc->sample_fmt;
+            input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(audio_codec_name);
+            if(audio_disable)
+                ic->streams[i]->discard= AVDISCARD_ALL;
+            break;
+        case CODEC_TYPE_VIDEO:
+            set_context_opts(enc, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM);
+            frame_height = enc->height;
+            frame_width = enc->width;
+            if(ic->streams[i]->sample_aspect_ratio.num)
+                frame_aspect_ratio=av_q2d(ic->streams[i]->sample_aspect_ratio);
+            else
+                frame_aspect_ratio=av_q2d(enc->sample_aspect_ratio);
+            frame_aspect_ratio *= (float) enc->width / enc->height;
+            frame_pix_fmt = enc->pix_fmt;
+            rfps      = ic->streams[i]->r_frame_rate.num;
+            rfps_base = ic->streams[i]->r_frame_rate.den;
+            if(enc->lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
+            if(me_threshold)
+                enc->debug |= FF_DEBUG_MV;
+
+            if (enc->time_base.den != rfps || enc->time_base.num != rfps_base) {
+
+                if (verbose >= 0)
+                    fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
+                            i, (float)enc->time_base.den / enc->time_base.num, enc->time_base.den, enc->time_base.num,
+
+                    (float)rfps / rfps_base, rfps, rfps_base);
+            }
+            /* update the current frame rate to match the stream frame rate */
+            frame_rate.num = rfps;
+            frame_rate.den = rfps_base;
+
+            input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(video_codec_name);
+            if(video_disable)
+                ic->streams[i]->discard= AVDISCARD_ALL;
+            else if(video_discard)
+                ic->streams[i]->discard= video_discard;
+            break;
+        case CODEC_TYPE_DATA:
+            break;
+        case CODEC_TYPE_SUBTITLE:
+            input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(subtitle_codec_name);
+            if(subtitle_disable)
+                ic->streams[i]->discard = AVDISCARD_ALL;
+            break;
+        case CODEC_TYPE_ATTACHMENT:
+        case CODEC_TYPE_UNKNOWN:
+            nb_icodecs++;
+            break;
+        default:
+            abort();
+        }
+    }
+
+    input_files[nb_input_files] = ic;
+    input_files_ts_offset[nb_input_files] = input_ts_offset - (copy_ts ? 0 : timestamp);
+    /* dump the file content */
+    if (verbose >= 0)
+        dump_format(ic, nb_input_files, filename, 0);
+
+    nb_input_files++;
+    file_iformat = NULL;
+    file_oformat = NULL;
+
+    video_channel = 0;
+
+    av_freep(&video_codec_name);
+    av_freep(&audio_codec_name);
+    av_freep(&subtitle_codec_name);
+}
+
+static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
+                                         int *has_subtitle_ptr)
+{
+    int has_video, has_audio, has_subtitle, i, j;
+    AVFormatContext *ic;
+
+    has_video = 0;
+    has_audio = 0;
+    has_subtitle = 0;
+    for(j=0;j<nb_input_files;j++) {
+        ic = input_files[j];
+        for(i=0;i<ic->nb_streams;i++) {
+            AVCodecContext *enc = ic->streams[i]->codec;
+            switch(enc->codec_type) {
+            case CODEC_TYPE_AUDIO:
+                has_audio = 1;
+                break;
+            case CODEC_TYPE_VIDEO:
+                has_video = 1;
+                break;
+            case CODEC_TYPE_SUBTITLE:
+                has_subtitle = 1;
+                break;
+            case CODEC_TYPE_DATA:
+            case CODEC_TYPE_ATTACHMENT:
+            case CODEC_TYPE_UNKNOWN:
+                break;
+            default:
+                abort();
+            }
+        }
+    }
+    *has_video_ptr = has_video;
+    *has_audio_ptr = has_audio;
+    *has_subtitle_ptr = has_subtitle;
+}
+
+static void new_video_stream(AVFormatContext *oc)
+{
+    AVStream *st;
+    AVCodecContext *video_enc;
+    int codec_id;
+
+    st = av_new_stream(oc, oc->nb_streams);
+    if (!st) {
+        fprintf(stderr, "Could not alloc stream\n");
+        av_exit(1);
+    }
+    avcodec_get_context_defaults2(st->codec, CODEC_TYPE_VIDEO);
+    bitstream_filters[nb_output_files][oc->nb_streams - 1]= video_bitstream_filters;
+    video_bitstream_filters= NULL;
+
+    if(thread_count>1)
+        avcodec_thread_init(st->codec, thread_count);
+
+    video_enc = st->codec;
+
+    if(video_codec_tag)
+        video_enc->codec_tag= video_codec_tag;
+
+    if(   (video_global_header&1)
+       || (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER))){
+        video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
+        avcodec_opts[CODEC_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
+    }
+    if(video_global_header&2){
+        video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
+        avcodec_opts[CODEC_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER;
+    }
+
+    if (video_stream_copy) {
+        st->stream_copy = 1;
+        video_enc->codec_type = CODEC_TYPE_VIDEO;
+        video_enc->sample_aspect_ratio =
+        st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
+    } else {
+        const char *p;
+        int i;
+        AVCodec *codec;
+        AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1};
+
+        if (video_codec_name) {
+            codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 1);
+            codec = avcodec_find_encoder_by_name(video_codec_name);
+            output_codecs[nb_ocodecs] = codec;
+        } else {
+            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
+            codec = avcodec_find_encoder(codec_id);
+        }
+
+        video_enc->codec_id = codec_id;
+
+        set_context_opts(video_enc, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
+
+        if (codec && codec->supported_framerates && !force_fps)
+            fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)];
+        video_enc->time_base.den = fps.num;
+        video_enc->time_base.num = fps.den;
+
+        video_enc->width = frame_width + frame_padright + frame_padleft;
+        video_enc->height = frame_height + frame_padtop + frame_padbottom;
+        video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255);
+        video_enc->pix_fmt = frame_pix_fmt;
+        st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
+
+        if(codec && codec->pix_fmts){
+            const enum PixelFormat *p= codec->pix_fmts;
+            for(; *p!=-1; p++){
+                if(*p == video_enc->pix_fmt)
+                    break;
+            }
+            if(*p == -1)
+                video_enc->pix_fmt = codec->pix_fmts[0];
+        }
+
+        if (intra_only)
+            video_enc->gop_size = 0;
+        if (video_qscale || same_quality) {
+            video_enc->flags |= CODEC_FLAG_QSCALE;
+            video_enc->global_quality=
+                st->quality = FF_QP2LAMBDA * video_qscale;
+        }
+
+        if(intra_matrix)
+            video_enc->intra_matrix = intra_matrix;
+        if(inter_matrix)
+            video_enc->inter_matrix = inter_matrix;
+
+        video_enc->thread_count = thread_count;
+        p= video_rc_override_string;
+        for(i=0; p; i++){
+            int start, end, q;
+            int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
+            if(e!=3){
+                fprintf(stderr, "error parsing rc_override\n");
+                av_exit(1);
+            }
+            video_enc->rc_override=
+                av_realloc(video_enc->rc_override,
+                           sizeof(RcOverride)*(i+1));
+            video_enc->rc_override[i].start_frame= start;
+            video_enc->rc_override[i].end_frame  = end;
+            if(q>0){
+                video_enc->rc_override[i].qscale= q;
+                video_enc->rc_override[i].quality_factor= 1.0;
+            }
+            else{
+                video_enc->rc_override[i].qscale= 0;
+                video_enc->rc_override[i].quality_factor= -q/100.0;
+            }
+            p= strchr(p, '/');
+            if(p) p++;
+        }
+        video_enc->rc_override_count=i;
+        if (!video_enc->rc_initial_buffer_occupancy)
+            video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4;
+        video_enc->me_threshold= me_threshold;
+        video_enc->intra_dc_precision= intra_dc_precision - 8;
+
+        if (do_psnr)
+            video_enc->flags|= CODEC_FLAG_PSNR;
+
+        /* two pass mode */
+        if (do_pass) {
+            if (do_pass == 1) {
+                video_enc->flags |= CODEC_FLAG_PASS1;
+            } else {
+                video_enc->flags |= CODEC_FLAG_PASS2;
+            }
+        }
+    }
+    nb_ocodecs++;
+
+    /* reset some key parameters */
+    video_disable = 0;
+    av_freep(&video_codec_name);
+    video_stream_copy = 0;
+}
+
+static void new_audio_stream(AVFormatContext *oc)
+{
+    AVStream *st;
+    AVCodecContext *audio_enc;
+    int codec_id;
+
+    st = av_new_stream(oc, oc->nb_streams);
+    if (!st) {
+        fprintf(stderr, "Could not alloc stream\n");
+        av_exit(1);
+    }
+    avcodec_get_context_defaults2(st->codec, CODEC_TYPE_AUDIO);
+
+    bitstream_filters[nb_output_files][oc->nb_streams - 1]= audio_bitstream_filters;
+    audio_bitstream_filters= NULL;
+
+    if(thread_count>1)
+        avcodec_thread_init(st->codec, thread_count);
+
+    audio_enc = st->codec;
+    audio_enc->codec_type = CODEC_TYPE_AUDIO;
+
+    if(audio_codec_tag)
+        audio_enc->codec_tag= audio_codec_tag;
+
+    if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
+        audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
+        avcodec_opts[CODEC_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
+    }
+    if (audio_stream_copy) {
+        st->stream_copy = 1;
+        audio_enc->channels = audio_channels;
+    } else {
+        AVCodec *codec;
+
+        set_context_opts(audio_enc, avcodec_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
+
+        if (audio_codec_name) {
+            codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1);
+            codec = avcodec_find_encoder_by_name(audio_codec_name);
+            output_codecs[nb_ocodecs] = codec;
+        } else {
+            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_AUDIO);
+            codec = avcodec_find_encoder(codec_id);
+        }
+        audio_enc->codec_id = codec_id;
+
+        if (audio_qscale > QSCALE_NONE) {
+            audio_enc->flags |= CODEC_FLAG_QSCALE;
+            audio_enc->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
+        }
+        audio_enc->thread_count = thread_count;
+        audio_enc->channels = audio_channels;
+        audio_enc->sample_fmt = audio_sample_fmt;
+        audio_enc->channel_layout = channel_layout;
+        if (avcodec_channel_layout_num_channels(channel_layout) != audio_channels)
+            audio_enc->channel_layout = 0;
+
+        if(codec && codec->sample_fmts){
+            const enum SampleFormat *p= codec->sample_fmts;
+            for(; *p!=-1; p++){
+                if(*p == audio_enc->sample_fmt)
+                    break;
+            }
+            if(*p == -1)
+                audio_enc->sample_fmt = codec->sample_fmts[0];
+        }
+    }
+    nb_ocodecs++;
+    audio_enc->sample_rate = audio_sample_rate;
+    audio_enc->time_base= (AVRational){1, audio_sample_rate};
+    if (audio_language) {
+        av_metadata_set(&st->metadata, "language", audio_language);
+        av_free(audio_language);
+        audio_language = NULL;
+    }
+
+    /* reset some key parameters */
+    audio_disable = 0;
+    av_freep(&audio_codec_name);
+    audio_stream_copy = 0;
+}
+
+static void new_subtitle_stream(AVFormatContext *oc)
+{
+    AVStream *st;
+    AVCodecContext *subtitle_enc;
+
+    st = av_new_stream(oc, oc->nb_streams);
+    if (!st) {
+        fprintf(stderr, "Could not alloc stream\n");
+        av_exit(1);
+    }
+    avcodec_get_context_defaults2(st->codec, CODEC_TYPE_SUBTITLE);
+
+    bitstream_filters[nb_output_files][oc->nb_streams - 1]= subtitle_bitstream_filters;
+    subtitle_bitstream_filters= NULL;
+
+    subtitle_enc = st->codec;
+    subtitle_enc->codec_type = CODEC_TYPE_SUBTITLE;
+
+    if(subtitle_codec_tag)
+        subtitle_enc->codec_tag= subtitle_codec_tag;
+
+    if (subtitle_stream_copy) {
+        st->stream_copy = 1;
+    } else {
+        set_context_opts(avcodec_opts[CODEC_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
+        subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 1);
+        output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name);
+    }
+    nb_ocodecs++;
+
+    if (subtitle_language) {
+        av_metadata_set(&st->metadata, "language", subtitle_language);
+        av_free(subtitle_language);
+        subtitle_language = NULL;
+    }
+
+    subtitle_disable = 0;
+    av_freep(&subtitle_codec_name);
+    subtitle_stream_copy = 0;
+}
+
+static void opt_new_audio_stream(void)
+{
+    AVFormatContext *oc;
+    if (nb_output_files <= 0) {
+        fprintf(stderr, "At least one output file must be specified\n");
+        av_exit(1);
+    }
+    oc = output_files[nb_output_files - 1];
+    new_audio_stream(oc);
+}
+
+static void opt_new_video_stream(void)
+{
+    AVFormatContext *oc;
+    if (nb_output_files <= 0) {
+        fprintf(stderr, "At least one output file must be specified\n");
+        av_exit(1);
+    }
+    oc = output_files[nb_output_files - 1];
+    new_video_stream(oc);
+}
+
+static void opt_new_subtitle_stream(void)
+{
+    AVFormatContext *oc;
+    if (nb_output_files <= 0) {
+        fprintf(stderr, "At least one output file must be specified\n");
+        av_exit(1);
+    }
+    oc = output_files[nb_output_files - 1];
+    new_subtitle_stream(oc);
+}
+
+static void opt_output_file(const char *filename)
+{
+    AVFormatContext *oc;
+    int use_video, use_audio, use_subtitle;
+    int input_has_video, input_has_audio, input_has_subtitle;
+    AVFormatParameters params, *ap = &params;
+
+    if (!strcmp(filename, "-"))
+        filename = "pipe:";
+
+    oc = avformat_alloc_context();
+
+    if (!file_oformat) {
+        file_oformat = guess_format(NULL, filename, NULL);
+        if (!file_oformat) {
+            fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
+                    filename);
+            av_exit(1);
+        }
+    }
+
+    oc->oformat = file_oformat;
+    av_strlcpy(oc->filename, filename, sizeof(oc->filename));
+
+    if (!strcmp(file_oformat->name, "ffm") &&
+        av_strstart(filename, "http:", NULL)) {
+        /* special case for files sent to ffserver: we get the stream
+           parameters from ffserver */
+        int err = read_ffserver_streams(oc, filename);
+        if (err < 0) {
+            print_error(filename, err);
+            av_exit(1);
+        }
+    } else {
+        use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
+        use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
+        use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
+
+        /* disable if no corresponding type found and at least one
+           input file */
+        if (nb_input_files > 0) {
+            check_audio_video_sub_inputs(&input_has_video, &input_has_audio,
+                                         &input_has_subtitle);
+            if (!input_has_video)
+                use_video = 0;
+            if (!input_has_audio)
+                use_audio = 0;
+            if (!input_has_subtitle)
+                use_subtitle = 0;
+        }
+
+        /* manual disable */
+        if (audio_disable) {
+            use_audio = 0;
+        }
+        if (video_disable) {
+            use_video = 0;
+        }
+        if (subtitle_disable) {
+            use_subtitle = 0;
+        }
+
+        if (use_video) {
+            new_video_stream(oc);
+        }
+
+        if (use_audio) {
+            new_audio_stream(oc);
+        }
+
+        if (use_subtitle) {
+            new_subtitle_stream(oc);
+        }
+
+        oc->timestamp = rec_timestamp;
+
+        for(; metadata_count>0; metadata_count--){
+            av_metadata_set(&oc->metadata, metadata[metadata_count-1].key,
+                                           metadata[metadata_count-1].value);
+        }
+        av_metadata_conv(oc, oc->oformat->metadata_conv, NULL);
+    }
+
+    output_files[nb_output_files++] = oc;
+
+    /* check filename in case of an image number is expected */
+    if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
+        if (!av_filename_number_test(oc->filename)) {
+            print_error(oc->filename, AVERROR_NUMEXPECTED);
+            av_exit(1);
+        }
+    }
+
+    if (!(oc->oformat->flags & AVFMT_NOFILE)) {
+        /* test if it already exists to avoid loosing precious files */
+        if (!file_overwrite &&
+            (strchr(filename, ':') == NULL ||
+             filename[1] == ':' ||
+             av_strstart(filename, "file:", NULL))) {
+            if (url_exist(filename)) {
+                if (!using_stdin) {
+                    fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
+                    fflush(stderr);
+                    if (!read_yesno()) {
+                        fprintf(stderr, "Not overwriting - exiting\n");
+                        av_exit(1);
+                    }
+                }
+                else {
+                    fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
+                    av_exit(1);
+                }
+            }
+        }
+
+        /* open the file */
+        if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
+            fprintf(stderr, "Could not open '%s'\n", filename);
+            av_exit(1);
+        }
+    }
+
+    memset(ap, 0, sizeof(*ap));
+    if (av_set_parameters(oc, ap) < 0) {
+        fprintf(stderr, "%s: Invalid encoding parameters\n",
+                oc->filename);
+        av_exit(1);
+    }
+
+    oc->preload= (int)(mux_preload*AV_TIME_BASE);
+    oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
+    oc->loop_output = loop_output;
+    oc->flags |= AVFMT_FLAG_NONBLOCK;
+
+    set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM);
+
+    /* reset some options */
+    file_oformat = NULL;
+    file_iformat = NULL;
+}
+
+/* same option as mencoder */
+static void opt_pass(const char *pass_str)
+{
+    int pass;
+    pass = atoi(pass_str);
+    if (pass != 1 && pass != 2) {
+        fprintf(stderr, "pass number can be only 1 or 2\n");
+        av_exit(1);
+    }
+    do_pass = pass;
+}
+
+static int64_t getutime(void)
+{
+#if HAVE_GETRUSAGE
+    struct rusage rusage;
+
+    getrusage(RUSAGE_SELF, &rusage);
+    return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
+#elif HAVE_GETPROCESSTIMES
+    HANDLE proc;
+    FILETIME c, e, k, u;
+    proc = GetCurrentProcess();
+    GetProcessTimes(proc, &c, &e, &k, &u);
+    return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
+#else
+    return av_gettime();
+#endif
+}
+
+static void parse_matrix_coeffs(uint16_t *dest, const char *str)
+{
+    int i;
+    const char *p = str;
+    for(i = 0;; i++) {
+        dest[i] = atoi(p);
+        if(i == 63)
+            break;
+        p = strchr(p, ',');
+        if(!p) {
+            fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
+            av_exit(1);
+        }
+        p++;
+    }
+}
+
+static void opt_inter_matrix(const char *arg)
+{
+    inter_matrix = av_mallocz(sizeof(uint16_t) * 64);
+    parse_matrix_coeffs(inter_matrix, arg);
+}
+
+static void opt_intra_matrix(const char *arg)
+{
+    intra_matrix = av_mallocz(sizeof(uint16_t) * 64);
+    parse_matrix_coeffs(intra_matrix, arg);
+}
+
+/**
+ * Trivial log callback.
+ * Only suitable for show_help and similar since it lacks prefix handling.
+ */
+static void log_callback_help(void* ptr, int level, const char* fmt, va_list vl)
+{
+    vfprintf(stdout, fmt, vl);
+}
+
+static void show_help(void)
+{
+    av_log_set_callback(log_callback_help);
+    printf("usage: ffmpeg [[infile options] -i infile]... {[outfile options] outfile}...\n"
+           "Hyper fast Audio and Video encoder\n");
+    printf("\n");
+    show_help_options(options, "Main options:\n",
+                      OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, 0);
+    show_help_options(options, "\nAdvanced options:\n",
+                      OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB,
+                      OPT_EXPERT);
+    show_help_options(options, "\nVideo options:\n",
+                      OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+                      OPT_VIDEO);
+    show_help_options(options, "\nAdvanced Video options:\n",
+                      OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+                      OPT_VIDEO | OPT_EXPERT);
+    show_help_options(options, "\nAudio options:\n",
+                      OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+                      OPT_AUDIO);
+    show_help_options(options, "\nAdvanced Audio options:\n",
+                      OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+                      OPT_AUDIO | OPT_EXPERT);
+    show_help_options(options, "\nSubtitle options:\n",
+                      OPT_SUBTITLE | OPT_GRAB,
+                      OPT_SUBTITLE);
+    show_help_options(options, "\nAudio/Video grab options:\n",
+                      OPT_GRAB,
+                      OPT_GRAB);
+    printf("\n");
+    av_opt_show(avcodec_opts[0], NULL);
+    printf("\n");
+    av_opt_show(avformat_opts, NULL);
+    printf("\n");
+    av_opt_show(sws_opts, NULL);
+}
+
+static void opt_target(const char *arg)
+{
+    int norm = -1;
+    static const char *const frame_rates[] = {"25", "30000/1001", "24000/1001"};
+
+    if(!strncmp(arg, "pal-", 4)) {
+        norm = 0;
+        arg += 4;
+    } else if(!strncmp(arg, "ntsc-", 5)) {
+        norm = 1;
+        arg += 5;
+    } else if(!strncmp(arg, "film-", 5)) {
+        norm = 2;
+        arg += 5;
+    } else {
+        int fr;
+        /* Calculate FR via float to avoid int overflow */
+        fr = (int)(frame_rate.num * 1000.0 / frame_rate.den);
+        if(fr == 25000) {
+            norm = 0;
+        } else if((fr == 29970) || (fr == 23976)) {
+            norm = 1;
+        } else {
+            /* Try to determine PAL/NTSC by peeking in the input files */
+            if(nb_input_files) {
+                int i, j;
+                for(j = 0; j < nb_input_files; j++) {
+                    for(i = 0; i < input_files[j]->nb_streams; i++) {
+                        AVCodecContext *c = input_files[j]->streams[i]->codec;
+                        if(c->codec_type != CODEC_TYPE_VIDEO)
+                            continue;
+                        fr = c->time_base.den * 1000 / c->time_base.num;
+                        if(fr == 25000) {
+                            norm = 0;
+                            break;
+                        } else if((fr == 29970) || (fr == 23976)) {
+                            norm = 1;
+                            break;
+                        }
+                    }
+                    if(norm >= 0)
+                        break;
+                }
+            }
+        }
+        if(verbose && norm >= 0)
+            fprintf(stderr, "Assuming %s for target.\n", norm ? "NTSC" : "PAL");
+    }
+
+    if(norm < 0) {
+        fprintf(stderr, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
+        fprintf(stderr, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
+        fprintf(stderr, "or set a framerate with \"-r xxx\".\n");
+        av_exit(1);
+    }
+
+    if(!strcmp(arg, "vcd")) {
+
+        opt_video_codec("mpeg1video");
+        opt_audio_codec("mp2");
+        opt_format("vcd");
+
+        opt_frame_size(norm ? "352x240" : "352x288");
+        opt_frame_rate(NULL, frame_rates[norm]);
+        opt_default("gop", norm ? "18" : "15");
+
+        opt_default("b", "1150000");
+        opt_default("maxrate", "1150000");
+        opt_default("minrate", "1150000");
+        opt_default("bufsize", "327680"); // 40*1024*8;
+
+        opt_default("ab", "224000");
+        audio_sample_rate = 44100;
+        audio_channels = 2;
+
+        opt_default("packetsize", "2324");
+        opt_default("muxrate", "1411200"); // 2352 * 75 * 8;
+
+        /* We have to offset the PTS, so that it is consistent with the SCR.
+           SCR starts at 36000, but the first two packs contain only padding
+           and the first pack from the other stream, respectively, may also have
+           been written before.
+           So the real data starts at SCR 36000+3*1200. */
+        mux_preload= (36000+3*1200) / 90000.0; //0.44
+    } else if(!strcmp(arg, "svcd")) {
+
+        opt_video_codec("mpeg2video");
+        opt_audio_codec("mp2");
+        opt_format("svcd");
+
+        opt_frame_size(norm ? "480x480" : "480x576");
+        opt_frame_rate(NULL, frame_rates[norm]);
+        opt_default("gop", norm ? "18" : "15");
+
+        opt_default("b", "2040000");
+        opt_default("maxrate", "2516000");
+        opt_default("minrate", "0"); //1145000;
+        opt_default("bufsize", "1835008"); //224*1024*8;
+        opt_default("flags", "+scan_offset");
+
+
+        opt_default("ab", "224000");
+        audio_sample_rate = 44100;
+
+        opt_default("packetsize", "2324");
+
+    } else if(!strcmp(arg, "dvd")) {
+
+        opt_video_codec("mpeg2video");
+        opt_audio_codec("ac3");
+        opt_format("dvd");
+
+        opt_frame_size(norm ? "720x480" : "720x576");
+        opt_frame_rate(NULL, frame_rates[norm]);
+        opt_default("gop", norm ? "18" : "15");
+
+        opt_default("b", "6000000");
+        opt_default("maxrate", "9000000");
+        opt_default("minrate", "0"); //1500000;
+        opt_default("bufsize", "1835008"); //224*1024*8;
+
+        opt_default("packetsize", "2048");  // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
+        opt_default("muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
+
+        opt_default("ab", "448000");
+        audio_sample_rate = 48000;
+
+    } else if(!strncmp(arg, "dv", 2)) {
+
+        opt_format("dv");
+
+        opt_frame_size(norm ? "720x480" : "720x576");
+        opt_frame_pix_fmt(!strncmp(arg, "dv50", 4) ? "yuv422p" :
+                                             (norm ? "yuv411p" : "yuv420p"));
+        opt_frame_rate(NULL, frame_rates[norm]);
+
+        audio_sample_rate = 48000;
+        audio_channels = 2;
+
+    } else {
+        fprintf(stderr, "Unknown target: %s\n", arg);
+        av_exit(1);
+    }
+}
+
+static void opt_vstats_file (const char *arg)
+{
+    av_free (vstats_filename);
+    vstats_filename=av_strdup (arg);
+}
+
+static void opt_vstats (void)
+{
+    char filename[40];
+    time_t today2 = time(NULL);
+    struct tm *today = localtime(&today2);
+
+    snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min,
+             today->tm_sec);
+    opt_vstats_file(filename);
+}
+
+static int opt_bsf(const char *opt, const char *arg)
+{
+    AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
+    AVBitStreamFilterContext **bsfp;
+
+    if(!bsfc){
+        fprintf(stderr, "Unknown bitstream filter %s\n", arg);
+        av_exit(1);
+    }
+
+    bsfp= *opt == 'v' ? &video_bitstream_filters :
+          *opt == 'a' ? &audio_bitstream_filters :
+                        &subtitle_bitstream_filters;
+    while(*bsfp)
+        bsfp= &(*bsfp)->next;
+
+    *bsfp= bsfc;
+
+    return 0;
+}
+
+static int opt_preset(const char *opt, const char *arg)
+{
+    FILE *f=NULL;
+    char filename[1000], tmp[1000], tmp2[1000], line[1000];
+    int i;
+    const char *base[2]= { getenv("HOME"),
+                           FFMPEG_DATADIR,
+                         };
+
+    for(i=!base[0]; i<2 && !f; i++){
+        snprintf(filename, sizeof(filename), "%s%s/%s.ffpreset", base[i], i ? "" : "/.ffmpeg", arg);
+        f= fopen(filename, "r");
+        if(!f){
+            char *codec_name= *opt == 'v' ? video_codec_name :
+                              *opt == 'a' ? audio_codec_name :
+                                            subtitle_codec_name;
+            snprintf(filename, sizeof(filename), "%s%s/%s-%s.ffpreset", base[i],  i ? "" : "/.ffmpeg", codec_name, arg);
+            f= fopen(filename, "r");
+        }
+    }
+    if(!f && ((arg[0]=='.' && arg[1]=='/') || arg[0]=='/' ||
+              is_dos_path(arg))){
+        av_strlcpy(filename, arg, sizeof(filename));
+        f= fopen(filename, "r");
+    }
+
+    if(!f){
+        fprintf(stderr, "File for preset '%s' not found\n", arg);
+        av_exit(1);
+    }
+
+    while(!feof(f)){
+        int e= fscanf(f, "%999[^\n]\n", line) - 1;
+        if(line[0] == '#' && !e)
+            continue;
+        e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
+        if(e){
+            fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
+            av_exit(1);
+        }
+        if(!strcmp(tmp, "acodec")){
+            opt_audio_codec(tmp2);
+        }else if(!strcmp(tmp, "vcodec")){
+            opt_video_codec(tmp2);
+        }else if(!strcmp(tmp, "scodec")){
+            opt_subtitle_codec(tmp2);
+        }else if(opt_default(tmp, tmp2) < 0){
+            fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
+            av_exit(1);
+        }
+    }
+
+    fclose(f);
+
+    return 0;
+}
+
+static const OptionDef options[] = {
+    /* main options */
+    { "L", OPT_EXIT, {(void*)show_license}, "show license" },
+    { "h", OPT_EXIT, {(void*)show_help}, "show help" },
+    { "version", OPT_EXIT, {(void*)show_version}, "show version" },
+    { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
+    { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
+    { "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
+    { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
+    { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
+    { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
+    { "t", OPT_FUNC2 | HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" },
+    { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, //
+    { "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
+    { "itsoffset", OPT_FUNC2 | HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" },
+    { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" },
+    { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)opt_rec_timestamp}, "set the timestamp ('now' to set the current time)", "time" },
+    { "metadata", OPT_FUNC2 | HAS_ARG, {(void*)opt_metadata}, "add metadata", "string=string" },
+    { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" },
+    { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
+      "add timings for benchmarking" },
+    { "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump},
+      "dump each input packet" },
+    { "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
+      "when dumping packets, also dump the payload" },
+    { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" },
+    { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" },
+    { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "number of times to loop output in formats that support looping (0 loops forever)", "" },
+    { "v", HAS_ARG | OPT_FUNC2, {(void*)opt_verbose}, "set ffmpeg verbosity level", "number" },
+    { "loglevel", HAS_ARG | OPT_FUNC2, {(void*)opt_loglevel}, "set libav* logging level", "number" },
+    { "target", HAS_ARG, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
+    { "threads", OPT_FUNC2 | HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
+    { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
+    { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
+    { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" },
+    { "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_global_header}, "video global header storage type", "" },
+    { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" },
+    { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
+    { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" },
+    { "programid", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&opt_programid}, "desired program number", "" },
+    { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" },
+    { "copyinkf", OPT_BOOL | OPT_EXPERT, {(void*)&copy_initial_nonkeyframes}, "copy initial non-keyframes" },
+
+    /* video options */
+    { "b", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
+    { "vb", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
+    { "vframes", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&max_frames[CODEC_TYPE_VIDEO]}, "set the number of video frames to record", "number" },
+    { "r", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_rate}, "set frame rate (Hz value, fraction or abbreviation)", "rate" },
+    { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
+    { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
+    { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format, 'list' as argument shows all the pixel formats supported", "format" },
+    { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_top}, "set top crop band size (in pixels)", "size" },
+    { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" },
+    { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" },
+    { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" },
+    { "padtop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_top}, "set top pad band size (in pixels)", "size" },
+    { "padbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_bottom}, "set bottom pad band size (in pixels)", "size" },
+    { "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_left}, "set left pad band size (in pixels)", "size" },
+    { "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_right}, "set right pad band size (in pixels)", "size" },
+    { "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad_color}, "set color of pad bands (Hex 000000 thru FFFFFF)", "color" },
+    { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"},
+    { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" },
+    { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
+    { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" },
+    { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" },
+    { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
+    { "me_threshold", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold",  "threshold" },
+    { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality},
+      "use same video quality as source (implies VBR)" },
+    { "pass", HAS_ARG | OPT_VIDEO, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" },
+    { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" },
+    { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace},
+      "deinterlace pictures" },
+    { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
+    { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
+    { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
+    { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
+    { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
+    { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
+    { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" },
+    { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
+    { "newvideo", OPT_VIDEO, {(void*)opt_new_video_stream}, "add a new video stream to the current output stream" },
+    { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
+    { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&force_fps}, "force the selected framerate, disable the best supported framerate selection" },
+
+    /* audio options */
+    { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
+    { "aframes", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&max_frames[CODEC_TYPE_AUDIO]}, "set the number of audio frames to record", "number" },
+    { "aq", OPT_FLOAT | HAS_ARG | OPT_AUDIO, {(void*)&audio_qscale}, "set audio quality (codec-specific)", "quality", },
+    { "ar", HAS_ARG | OPT_FUNC2 | OPT_AUDIO, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" },
+    { "ac", HAS_ARG | OPT_FUNC2 | OPT_AUDIO, {(void*)opt_audio_channels}, "set number of audio channels", "channels" },
+    { "an", OPT_BOOL | OPT_AUDIO, {(void*)&audio_disable}, "disable audio" },
+    { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
+    { "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_tag}, "force audio tag/fourcc", "fourcc/tag" },
+    { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
+    { "newaudio", OPT_AUDIO, {(void*)opt_new_audio_stream}, "add a new audio stream to the current output stream" },
+    { "alang", HAS_ARG | OPT_STRING | OPT_AUDIO, {(void *)&audio_language}, "set the ISO 639 language code (3 letters) of the current audio stream" , "code" },
+    { "sample_fmt", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_sample_fmt}, "set sample format, 'list' as argument shows all the sample formats supported", "format" },
+
+    /* subtitle options */
+    { "sn", OPT_BOOL | OPT_SUBTITLE, {(void*)&subtitle_disable}, "disable subtitle" },
+    { "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
+    { "newsubtitle", OPT_SUBTITLE, {(void*)opt_new_subtitle_stream}, "add a new subtitle stream to the current output stream" },
+    { "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" },
+    { "stag", HAS_ARG | OPT_EXPERT | OPT_SUBTITLE, {(void*)opt_subtitle_tag}, "force subtitle tag/fourcc", "fourcc/tag" },
+
+    /* grab options */
+    { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" },
+    { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" },
+    { "isync", OPT_BOOL | OPT_EXPERT | OPT_GRAB, {(void*)&input_sync}, "sync read on input", "" },
+
+    /* muxer options */
+    { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_max_delay}, "set the maximum demux-decode delay", "seconds" },
+    { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_preload}, "set the initial demux-decode delay", "seconds" },
+
+    { "absf", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream_filter" },
+    { "vbsf", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream_filter" },
+    { "sbsf", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream_filter" },
+
+    { "apre", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_preset}, "set the audio options to the indicated preset", "preset" },
+    { "vpre", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_preset}, "set the video options to the indicated preset", "preset" },
+    { "spre", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_preset}, "set the subtitle options to the indicated preset", "preset" },
+
+    { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
+    { NULL, },
+};
+
+int main(int argc, char **argv)
+{
+    int i;
+    int64_t ti;
+
+    avcodec_register_all();
+    avdevice_register_all();
+    av_register_all();
+
+    if(isatty(STDIN_FILENO))
+        url_set_interrupt_cb(decode_interrupt_cb);
+
+    for(i=0; i<CODEC_TYPE_NB; i++){
+        avcodec_opts[i]= avcodec_alloc_context2(i);
+    }
+    avformat_opts = avformat_alloc_context();
+    sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
+
+    show_banner();
+
+    /* parse options */
+    parse_options(argc, argv, options, opt_output_file);
+
+    /* file converter / grab */
+    if (nb_output_files <= 0) {
+        fprintf(stderr, "At least one output file must be specified\n");
+        av_exit(1);
+    }
+
+    if (nb_input_files == 0) {
+        fprintf(stderr, "At least one input file must be specified\n");
+        av_exit(1);
+    }
+
+    ti = getutime();
+    if (av_encode(output_files, nb_output_files, input_files, nb_input_files,
+                  stream_maps, nb_stream_maps) < 0)
+        av_exit(1);
+    ti = getutime() - ti;
+    if (do_benchmark) {
+        printf("bench: utime=%0.3fs\n", ti / 1000000.0);
+    }
+
+    return av_exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ref/opts	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1 @@
+./configure --enable-gpl --disable-debug --disable-ffmpeg --disable-ffplay --disable-ffserver --disable-network --disable-ipv6 --enable-runtime-cpudetect --enable-memalign-hack --extra-cflags="-fno-common"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ref/output_example.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,575 @@
+/**
+* Mime on Fire (mime) -- Simple UPnP server for XBOX360
+* Copyright (C) 2009 Robert Fraser
+* 
+* This program is free software; you can redistribute it andor
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+module mime.app.main;
+
+// Imports for whole program (just link to them)
+import tango.stdc.stdarg; // Must be linked in to prevent strange linker errors
+debug import tango.core.stacktrace.TraceExceptions;
+import NONE = mime.codec.libav.mingw;
+
+import Math = tango.math.Math;
+import tango.stdc.stdlib;
+import tango.stdc.stdio;
+import tango.stdc.stringz;
+import tango.core.Array;
+
+import mime.codec.libav.avutil;
+import mime.codec.libav.avcodec;
+import mime.codec.libav.avformat;
+import mime.codec.libav.swscale;
+
+/* 5 seconds stream duration */
+const STREAM_DURATION = 5.0;
+const STREAM_FRAME_RATE = 25; /* 25 images/s */
+const STREAM_NB_FRAMES = (cast(int)(STREAM_DURATION * STREAM_FRAME_RATE));
+const STREAM_PIX_FMT = PIX_FMT_YUV420P; /* default pix_fmt */
+static int sws_flags = SWS_BICUBIC;
+
+
+private bool containsString(char* haystack, char[] needle)
+{
+	char[] sHaystack = fromStringz(haystack);
+	return sHaystack.find(needle) < sHaystack.length;
+}
+
+/**************************************************************/
+/* audio output */
+
+
+float t, tincr, tincr2;
+short *samples;
+char *audio_outbuf;
+int audio_outbuf_size;
+int audio_input_frame_size;
+
+/*
+ * add an audio output stream
+ */
+static AVStream *add_audio_stream(AVFormatContext *oc, int codec_id)
+{
+    AVCodecContext *c;
+    AVStream *st;
+
+    st = av_new_stream(oc, 1);
+    if (!st) {
+        fprintf(stderr, "Could not alloc stream\n");
+        exit(1);
+    }
+
+    c = st.codec;
+    c.codec_id = codec_id;
+    c.codec_type = CODEC_TYPE_AUDIO;
+
+    /* put sample parameters */
+    c.bit_rate = 64000;
+    c.sample_rate = 44100;
+    c.channels = 2;
+    return st;
+}
+
+static void open_audio(AVFormatContext *oc, AVStream *st)
+{
+    AVCodecContext *c;
+    AVCodec *codec;
+
+    c = st.codec;
+
+    /* find the audio encoder */
+    codec = avcodec_find_encoder(c.codec_id);
+    if (!codec) {
+        fprintf(stderr, "codec not found\n");
+        exit(1);
+    }
+
+    /* open it */
+    if (avcodec_open(c, codec) < 0) {
+        fprintf(stderr, "could not open codec\n");
+        exit(1);
+    }
+
+    /* init signal generator */
+    t = 0;
+    tincr = 2 * Math.PI * 110.0 / c.sample_rate;
+    /* increment frequency by 110 Hz per second */
+    tincr2 = 2 * Math.PI * 110.0 / c.sample_rate / c.sample_rate;
+
+    audio_outbuf_size = 10000;
+    audio_outbuf = cast(char*) av_malloc(audio_outbuf_size);
+
+    /* ugly hack for PCM codecs (will be removed ASAP with new PCM
+       support to compute the input frame size in samples */
+    if (c.frame_size <= 1) {
+        audio_input_frame_size = audio_outbuf_size / c.channels;
+        switch(st.codec.codec_id) {
+        case CODEC_ID_PCM_S16LE:
+        case CODEC_ID_PCM_S16BE:
+        case CODEC_ID_PCM_U16LE:
+        case CODEC_ID_PCM_U16BE:
+            audio_input_frame_size >>= 1;
+            break;
+        default:
+            break;
+        }
+    } else {
+        audio_input_frame_size = c.frame_size;
+    }
+    
+    if(containsString(oc.oformat.name, "asf"))
+        c.flags |= CODEC_FLAG_GLOBAL_HEADER;
+    
+    samples = cast(short*) av_malloc(audio_input_frame_size * 2 * c.channels);
+}
+
+/* prepare a 16 bit dummy audio frame of 'frame_size' samples and
+   'nb_channels' channels */
+static void get_audio_frame(short *samples, int frame_size, int nb_channels)
+{
+    int j, i, v;
+    short *q;
+
+    q = samples;
+    for(j=0;j<frame_size;j++) {
+        v = cast(int)(Math.sin(t) * 10000);
+        for(i = 0; i < nb_channels; i++)
+            *q++ = v;
+        t += tincr;
+        tincr += tincr2;
+    }
+}
+
+static void write_audio_frame(AVFormatContext *oc, AVStream *st)
+{
+    AVCodecContext *c;
+    AVPacket pkt;
+    av_init_packet(&pkt);
+
+    c = st.codec;
+
+    get_audio_frame(samples, audio_input_frame_size, c.channels);
+
+    pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
+
+    pkt.pts= av_rescale_q(c.coded_frame.pts, c.time_base, st.time_base);
+    pkt.flags |= PKT_FLAG_KEY;
+    pkt.stream_index= st.index;
+    pkt.data= audio_outbuf;
+
+    /* write the compressed frame in the media file */
+    if (av_write_frame(oc, &pkt) != 0) {
+        fprintf(stderr, "Error while writing audio frame\n");
+        exit(1);
+    }
+}
+
+static void close_audio(AVFormatContext *oc, AVStream *st)
+{
+    avcodec_close(st.codec);
+
+    av_free(samples);
+    av_free(audio_outbuf);
+}
+
+/**************************************************************/
+/* video output */
+
+AVFrame *picture, tmp_picture;
+char *video_outbuf;
+int frame_count, video_outbuf_size;
+
+/* add a video output stream */
+static AVStream *add_video_stream(AVFormatContext *oc, int codec_id)
+{
+    AVCodecContext *c;
+    AVStream *st;
+
+    st = av_new_stream(oc, 0);
+    if (!st) {
+        fprintf(stderr, "Could not alloc stream\n");
+        exit(1);
+    }
+
+    c = st.codec;
+    c.codec_id = codec_id;
+    c.codec_type = CODEC_TYPE_VIDEO;
+
+    /* put sample parameters */
+    c.bit_rate = 400000;
+    /* resolution must be a multiple of two */
+    c.width = 352;
+    c.height = 288;
+    /* time base: this is the fundamental unit of time (in seconds) in terms
+       of which frame timestamps are represented. for fixed-fps content,
+       timebase should be 1/framerate and timestamp increments should be
+       identically 1. */
+    c.time_base.den = STREAM_FRAME_RATE;
+    c.time_base.num = 1;
+    c.gop_size = 12; /* emit one intra frame every twelve frames at most */
+    c.pix_fmt = STREAM_PIX_FMT;
+    if (c.codec_id == CODEC_ID_MPEG2VIDEO) {
+        /* just for testing, we also add B frames */
+        c.max_b_frames = 2;
+    }
+    if (c.codec_id == CODEC_ID_MPEG1VIDEO){
+        /* needed to avoid using macroblocks in which some coeffs overflow
+           this doesnt happen with normal video, it just happens here as the
+           motion of the chroma plane doesnt match the luma plane */
+        c.mb_decision=2;
+    }
+    // some formats want stream headers to be separate
+    if(containsString(oc.oformat.name, "mp4") || 
+       containsString(oc.oformat.name, "mpeg4") ||
+       containsString(oc.oformat.name, "asf") ||
+       containsString(oc.oformat.name, "mov") || 
+       containsString(oc.oformat.name, "3gp"))
+        c.flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+    return st;
+}
+
+static AVFrame *alloc_picture(int pix_fmt, int width, int height)
+{
+    AVFrame *picture;
+    char *picture_buf;
+    int size;
+
+    picture = avcodec_alloc_frame();
+    if (!picture)
+        return null;
+    size = avpicture_get_size(pix_fmt, width, height);
+    picture_buf = cast(char*) av_malloc(size);
+    if (!picture_buf) {
+        av_free(picture);
+        return null;
+    }
+    avpicture_fill(cast(AVPicture *)picture, picture_buf,
+                   pix_fmt, width, height);
+    return picture;
+}
+
+static void open_video(AVFormatContext *oc, AVStream *st)
+{
+    AVCodec *codec;
+    AVCodecContext *c;
+
+    c = st.codec;
+
+    /* find the video encoder */
+    codec = avcodec_find_encoder(c.codec_id);
+    if (!codec) {
+        fprintf(stderr, "codec not found\n");
+        exit(1);
+    }
+
+    /* open the codec */
+    if (avcodec_open(c, codec) < 0) {
+        fprintf(stderr, "could not open codec\n");
+        exit(1);
+    }
+
+    video_outbuf = null;
+    if (!(oc.oformat.flags & AVFMT_RAWPICTURE)) {
+        /* allocate output buffer */
+        /* XXX: API change will be done */
+        /* buffers passed into lav* can be allocated any way you prefer,
+           as long as they're aligned enough for the architecture, and
+           they're freed appropriately (such as using av_free for buffers
+           allocated with av_malloc) */
+        video_outbuf_size = 200000;
+        video_outbuf = cast(char*) av_malloc(video_outbuf_size);
+    }
+
+    /* allocate the encoded raw picture */
+    picture = alloc_picture(c.pix_fmt, c.width, c.height);
+    if (!picture) {
+        fprintf(stderr, "Could not allocate picture\n");
+        exit(1);
+    }
+
+    /* if the output format is not YUV420P, then a temporary YUV420P
+       picture is needed too. It is then converted to the required
+       output format */
+    tmp_picture = null;
+    if (c.pix_fmt != PIX_FMT_YUV420P) {
+        tmp_picture = alloc_picture(PIX_FMT_YUV420P, c.width, c.height);
+        if (!tmp_picture) {
+            fprintf(stderr, "Could not allocate temporary picture\n");
+            exit(1);
+        }
+    }
+}
+
+/* prepare a dummy image */
+static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
+{
+    int x, y, i;
+
+    i = frame_index;
+
+    /* Y */
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            pict.data[0][y * pict.linesize[0] + x] = x + y + i * 3;
+        }
+    }
+
+    /* Cb and Cr */
+    for(y=0;y<height/2;y++) {
+        for(x=0;x<width/2;x++) {
+            pict.data[1][y * pict.linesize[1] + x] = 128 + y + i * 2;
+            pict.data[2][y * pict.linesize[2] + x] = 64 + x + i * 5;
+        }
+    }
+}
+
+static void write_video_frame(AVFormatContext *oc, AVStream *st)
+{
+    int out_size, ret;
+    AVCodecContext *c;
+    static SwsContext *img_convert_ctx;
+
+    c = st.codec;
+
+    if (frame_count >= STREAM_NB_FRAMES) {
+        /* no more frame to compress. The codec has a latency of a few
+           frames if using B frames, so we get the last frames by
+           passing the same picture again */
+    } else {
+        if (c.pix_fmt != PIX_FMT_YUV420P) {
+            /* as we only generate a YUV420P picture, we must convert it
+               to the codec pixel format if needed */
+            if (img_convert_ctx == null) {
+                img_convert_ctx = sws_getContext(c.width, c.height,
+                                                 PIX_FMT_YUV420P,
+                                                 c.width, c.height,
+                                                 c.pix_fmt,
+                                                 sws_flags, null, null, null);
+                if (img_convert_ctx == null) {
+                    fprintf(stderr, "Cannot initialize the conversion context\n");
+                    exit(1);
+                }
+            }
+            fill_yuv_image(tmp_picture, frame_count, c.width, c.height);
+            sws_scale(img_convert_ctx, tmp_picture.data.ptr, tmp_picture.linesize.ptr,
+                      0, c.height, picture.data.ptr, picture.linesize.ptr);
+        } else {
+            fill_yuv_image(picture, frame_count, c.width, c.height);
+        }
+    }
+
+
+    if (oc.oformat.flags & AVFMT_RAWPICTURE) {
+        /* raw video case. The API will change slightly in the near
+           futur for that */
+        AVPacket pkt;
+        av_init_packet(&pkt);
+
+        pkt.flags |= PKT_FLAG_KEY;
+        pkt.stream_index= st.index;
+        pkt.data= cast(char *)picture;
+        pkt.size= AVPicture.sizeof;
+
+        ret = av_write_frame(oc, &pkt);
+    } else {
+        /* encode the image */
+        out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
+        /* if zero size, it means the image was buffered */
+        if (out_size > 0) {
+            AVPacket pkt;
+            av_init_packet(&pkt);
+
+            pkt.pts= av_rescale_q(c.coded_frame.pts, c.time_base, st.time_base);
+            if(c.coded_frame.key_frame)
+                pkt.flags |= PKT_FLAG_KEY;
+            pkt.stream_index= st.index;
+            pkt.data= video_outbuf;
+            pkt.size= out_size;
+
+            /* write the compressed frame in the media file */
+            ret = av_write_frame(oc, &pkt);
+        } else {
+            ret = 0;
+        }
+    }
+    if (ret != 0) {
+        fprintf(stderr, "Error while writing video frame\n");
+        exit(1);
+    }
+    frame_count++;
+}
+
+static void close_video(AVFormatContext *oc, AVStream *st)
+{
+    avcodec_close(st.codec);
+    av_free(picture.data[0]);
+    av_free(picture);
+    if (tmp_picture) {
+        av_free(tmp_picture.data[0]);
+        av_free(tmp_picture);
+    }
+    av_free(video_outbuf);
+}
+
+/**************************************************************/
+/* media file output */
+
+int main(char[][] args)
+{	
+    char *filename;
+    AVOutputFormat *fmt;
+    AVFormatContext *oc;
+    AVStream *audio_st, video_st;
+    double audio_pts, video_pts;
+    int i;
+
+    /* initialize libavcodec, and register all codecs and formats */
+    av_register_all();
+    
+    version(none)
+    {
+    	char* codecName(int codec_id)
+    	{
+    		auto codec = avcodec_find_encoder(codec_id);
+    		return codec ? codec.name : toStringz("NONE");
+    		
+    	}
+    	
+    	AVOutputFormat* fmt2 = first_oformat;
+    	printf("format (extension, video codec, audio codec)\n");
+    	while(fmt2)
+    	{
+    		printf("%s (.%s, %s, %s)\n", fmt2.name, fmt2.extensions, codecName(fmt2.video_codec), codecName(fmt2.audio_codec));
+    		fmt2 = fmt2.next;
+    	}
+    }
+    
+    version(none)
+    {
+    	// List codecs
+	    AVCodec* codec = av_codec_next(null); // Get first
+		while(codec)
+		{
+			if(codec.type == CODEC_TYPE_VIDEO)
+			{
+				printf("%d - %s (%s)\n", codec.id, codec.name, codec.long_name);
+			}
+			Lnext: codec = av_codec_next(codec);
+		}
+    }
+
+    filename = toStringz("biff_happy.m4v");
+    
+    fmt = guess_format(toStringz("m4v"), null, null);
+    if (!fmt) {
+        fprintf(stderr, "Could not find suitable output format\n");
+        exit(1);
+    }
+
+    /* allocate the output media context */
+    oc = av_alloc_format_context();
+    if (!oc) {
+        fprintf(stderr, "Memory error\n");
+        exit(1);
+    }
+    oc.oformat = fmt;
+    snprintf(oc.filename.ptr, oc.filename.sizeof, "%s", filename);
+
+    /* add the audio and video streams using the default format codecs
+       and initialize the codecs */
+    video_st = null;
+    audio_st = null;
+    // WORKAREA use the right profile for mpeg4 encoding (MP4 2 Advanced Simple)
+    if (fmt.video_codec != CODEC_ID_NONE) {
+        video_st = add_video_stream(oc, fmt.video_codec);
+    }
+    // WORKAREA -- we want to be doing this with AAC - http://blogs.msdn.com/xboxteam/archive/2007/11/30/december-2007-video-playback-faq.aspx
+    /* if (fmt.audio_codec != CODEC_ID_NONE) {
+        audio_st = add_audio_stream(oc, fmt.audio_codec);
+    } */
+
+    /* set the output parameters (must be done even if no
+       parameters). */
+    if (av_set_parameters(oc, null) < 0) {
+        fprintf(stderr, "Invalid output format parameters\n");
+        exit(1);
+    }
+
+    dump_format(oc, 0, filename, 1);
+
+    /* now that all the parameters are set, we can open the audio and
+       video codecs and allocate the necessary encode buffers */
+    if (video_st)
+        open_video(oc, video_st);
+    if (audio_st)
+        open_audio(oc, audio_st);
+
+    /* open the output file, if needed */
+    if (!(fmt.flags & AVFMT_NOFILE)) {
+        if (url_fopen(&oc.pb, filename, URL_WRONLY) < 0) {
+            fprintf(stderr, "Could not open '%s'\n", filename);
+            exit(1);
+        }
+    }
+
+    /* write the stream header, if any */
+    av_write_header(oc);
+
+    for(;;) {
+        /* compute current audio and video time */
+        if (audio_st)
+            audio_pts = cast(double)audio_st.pts.val * audio_st.time_base.num / audio_st.time_base.den;
+        else
+            audio_pts = 0.0;
+
+        if (video_st)
+            video_pts = cast(double)video_st.pts.val * video_st.time_base.num / video_st.time_base.den;
+        else
+            video_pts = 0.0;
+
+        if ((!audio_st || audio_pts >= STREAM_DURATION) &&
+            (!video_st || video_pts >= STREAM_DURATION))
+            break;
+
+        /* write interleaved audio and video frames */
+        if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
+            write_audio_frame(oc, audio_st);
+        } else {
+            write_video_frame(oc, video_st);
+        }
+    }
+
+    /* close each codec */
+    if (video_st)
+        close_video(oc, video_st);
+    if (audio_st)
+        close_audio(oc, audio_st);
+
+    /* write the trailer, if any */
+    av_write_trailer(oc);
+
+    /* free the streams */
+    for(i = 0; i < oc.nb_streams; i++) {
+        av_freep(&oc.streams[i].codec);
+        av_freep(&oc.streams[i]);
+    }
+
+    if (!(fmt.flags & AVFMT_NOFILE)) {
+        /* close the output file */
+    }
+
+    /* free the stream */
+    av_free(oc);
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/build/frankenbuild.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,229 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module frankenbuild;
+
+import tango.io.Stdout;
+import tango.sys.Process;
+import tango.io.vfs.model.Vfs;
+import tango.io.vfs.FileFolder;
+import Path = tango.io.Path;
+
+version(Windows) {} else static assert(false, "Build system only works for Windows");
+
+const char[] rebuildPath = "build/rebuild.exe";
+const char[] touchPath = "build/touch.exe";
+const char[] upxPath = "build/upx.exe";
+const char[] mcppPath = "build/mcpp.exe";
+
+//TODO get these paths from registry
+const char[] devenvPath = `"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.com"`;
+
+int main(char[][] args)
+{   
+    Stdout.flush(true);
+    
+	if(args.length < 2)
+	{
+		Stdout("ERROR: Must specify a target");
+		return 1;
+	}
+	
+	char[] target = args[1];
+	char[][] extraArgs = args[2..$];
+	
+	char[] cbase;
+	cbase = " -I../src/impl";
+	cbase ~= " -w";
+	cbase ~= " ../deps/libav/gcc.lib ../deps/libav/avutil.lib ../deps/libav/avcodec.lib ../deps/libav/avformat.lib ../deps/libav/swscale.lib";
+    foreach(arg; extraArgs)
+	    cbase ~= " " ~ arg;
+    
+    bool targetFound = false;
+    char[][] cats = [target];
+    bool delegate()[] commands = [];
+    
+    if(cats.contains("all"))
+    {
+        cats ~= "debug";
+        cats ~= "release";
+    }
+	
+	if(cats.contains("debug"))
+	{
+	    targetFound = true;
+	    cats ~= "platif-debug";
+	    char[] cargs = cbase.dup;
+	    cargs ~= " -g";
+	    cargs ~= " -debug -debug=AVBuffer";
+	    cargs ~= " -ofhoofbaby-d/hoofbaby.exe";
+	    cargs ~= " -oqobjs/debug";
+	    cargs ~= " ../src/impl/hoofbaby/app/main.d";
+	    commands ~= { return cpp("../src/platif/platif.h", "../src/impl/hoofbaby/platinum/platif.d"); };
+	    commands ~= { return rebuild(cargs); };
+	}
+	
+	if(cats.contains("release"))
+    {
+        targetFound = true;
+	    cats ~= "platif-release";
+	    char[] cargs = cbase.dup;
+	    cargs ~= " -O -inline";
+	    cargs ~= " -ofhoofbaby/hoofbaby.exe";
+	    cargs ~= " -oqobjs/release";
+	    cargs ~= " ../src/impl/hoofbaby/app/main.d";
+	    commands ~= { return cpp("../src/platif/platif.h", "../src/impl/hoofbaby/platinum/platif.d"); };
+	    commands ~= { return rebuild(cargs); };
+	    commands ~= { return upx("hoofbaby/hoofbaby.exe"); };// D executables are enormous
+    }
+	
+	if(cats.contains("platif-debug"))
+	{
+	    targetFound = true;
+	    char[] cargs = `..\deps\Platinum\Build\Targets\x86-microsoft-win32-vs2008\Platinum.sln /build "Debug|Win32" /project platif`;
+	    commands ~= { return devenv(cargs); };
+	    commands ~= { return rm("./hoofbaby-d", ["*.exp", "*.lib"]); };
+	}
+	
+	if(cats.contains("platif-release"))
+	{
+	    targetFound = true;
+	    char[] cargs = `..\deps\Platinum\Build\Targets\x86-microsoft-win32-vs2008\Platinum.sln /build "Release|Win32" /project platif`;
+	    commands ~= { return devenv(cargs); };
+	    commands ~= { return rm("./hoofbaby", ["*.exp", "*.lib"]); };
+	}
+	
+	if(!targetFound)
+	{
+		Stdout.format("Unknown or invalid target {0}", target).newline;
+		return 1;
+	}
+	
+	commands ~= { return rm(".", ["*.map"]); }; // The builder itself may have created a .map, so run this every time
+    foreach(cmd; commands)
+        if(!cmd())
+            return 1;
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+
+bool contains(T)(T[] a, T b)
+{
+    foreach(c; a)
+        if(b == c)
+            return true;
+    return false;
+}
+
+bool isNewerThan(char[] f1, char[] f2)
+{
+    return Path.exists(f1) && Path.exists(f2) && Path.modified(f1) > Path.modified(f2);
+}
+
+//------------------------------------------------------------------------------
+
+bool exec(char[] program, char[] args, bool print)
+{
+    char[] cmd = program ~ " " ~ args;
+    if(print) Stdout("=> " ~ cmd).newline;
+    if((new Process(true, cmd)).setRedirect(Redirect.None).execute().wait().status)
+        return false;
+    if(print) Stdout.newline;
+    return true;
+}
+
+bool rebuild(char[] args) { return exec(rebuildPath, args, true);     }
+bool devenv(char[] args)  { return exec(devenvPath, args, true);      }
+bool touch(char[] file)   { return exec(touchPath, file, false);      }
+bool upx(char[] file)     { return exec(upxPath, "-9 " ~ file, true); }
+
+bool rm(char[] path, char[][] globs)
+{
+    Stdout.format("=> rm {0} {1}", path, globs).newline;
+    FileFolder folder = new FileFolder(path);
+    foreach(glob; globs)
+    {
+        VfsFiles files = folder.tree.catalog(glob);
+        foreach(file; files)
+            try { file.remove(); } catch(Exception e) { Stdout(e.toString()).newline(); }
+    }
+    Stdout.newline;
+    return true; // Even if we failed to delete stuff, it's okay
+}
+
+bool cp(char[] isrc, char[] idst)
+{
+    bool didCopy = false;
+    
+    void copyFile(char[] src, char[] dst)
+    {
+        if(Path.exists(dst))
+        {
+            if(dst.isNewerThan(src))
+                return;
+            Path.remove(dst);
+        }
+        Path.copy(src, dst);
+        version(Windows) touch(dst); // Windows doesn't change the modification date unless this is done
+        didCopy = true;
+    }
+    
+    void cpr(char[] src, char[] dst)
+    {
+        if(!Path.exists(dst))
+        {
+            Path.createFolder(dst);
+            didCopy = true;
+        }
+        foreach(info; Path.children(src))
+        {
+            char[] srcPath = src ~ "/" ~ info.name;
+            char[] dstPath = dst ~ "/" ~ info.name;
+            if(info.folder)
+                cpr(srcPath, dstPath);
+            else
+                copyFile(srcPath, dstPath);
+        }
+    }
+    
+    try
+    {
+        isrc = Path.standard(isrc);
+        idst = Path.standard(idst);
+        if(Path.isFolder(isrc))
+            cpr(isrc, idst);
+        else
+            copyFile(isrc, idst);
+        if(didCopy)
+            Stdout.format("=> cp {0} {1}", isrc, idst).newline.newline;
+    }
+    catch(Exception e)
+    {
+        Stdout.format("=> cp {0} {1}", isrc, idst).newline;
+        Stdout(e.toString()).newline.newline;
+        return false;
+    }
+    
+    return true;
+}
+
+bool cpp(char[] src, char[] dst, char[] extraParams = "")
+{
+    if(dst.isNewerThan(src))
+        return true;
+    char[] cmd = src ~ " -o " ~ dst ~ " -I../src -D__D -e utf8" ~ extraParams;
+    return exec(mcppPath, cmd, true);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dtypes.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,75 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DTYPES_H
+#define _DTYPES_H
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4098) // void function returning a value
+#endif
+
+//------------------------------------------------------------------------------
+// D Types
+#ifdef __D
+#define D_CONST
+#define D_LINT int
+#define D_LUINT uint
+#define D_LONG long
+#define D_ULONG ulong
+
+// C/C++ Types
+#else
+#define D_CONST const
+#define D_LINT  long          // int masquerading as a long
+#define D_LUINT unsigned long // unsigned int masquerading as an unsigned long
+#define D_LONG  __int64
+#define D_ULONG unsigned __int64
+#endif
+
+//------------------------------------------------------------------------------
+// Defintitions for exposing functions via a DLL
+// Use "FUN(name, return type, parameters)" to export a function defined elesewhere from your DLL
+// Try to expose only what's needed, since only exposed stuff will be linked in
+
+#define UNDERSCORE(__X__) _##__X__
+
+#ifdef __D
+#define __STRINGIFY(__X__) __STRINGIFY2(__X__)
+#define __STRINGIFY2(__X__) #__X__
+#define FP_TYPE(__RV__, __PARAMS__) __RV__ function __PARAMS__
+#define FUN(__NAME__, __RV__, __PARAMS__) __STRINGIFY(FP_TYPE(__RV__, __PARAMS__)), #__NAME__,
+#define EXPORT(__NAME__, __RV__, __PARAMS__, __PNAMES__) FUN(UNDERSCORE(__NAME__), __RV__, __PARAMS__)
+#define BEGIN_DFUNCTIONS(__LIBNAME__) mixin(shared_mixin(__LIBNAME__, [
+#define END_DFUNCTIONS "", ""]));
+#define D_ENUM(__NAME__) alias int __NAME__; \
+	enum : __NAME__
+
+#else
+#ifdef __cplusplus
+#define _EXTERN extern "C"
+#else
+#define _EXTERN
+#endif
+#define _DLLEXPORT _EXTERN __declspec(dllexport)
+#define FUN(__NAME__, __RV__, __PARAMS__) _DLLEXPORT __RV__ __NAME__ __PARAMS__;
+#define EXPORT(__NAME__, __RV__, __PARAMS__, __PNAMES__) \
+	_EXTERN __RV__ __NAME__ __PARAMS__; \
+	_DLLEXPORT __RV__ UNDERSCORE(__NAME__) __PARAMS__ { return __NAME__ __PNAMES__; }
+#define BEGIN_DFUNCTIONS(__LIBNAME__)
+#define END_DFUNCTIONS
+#define D_ENUM(__NAME__) enum
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/app/codec_adhoc.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,305 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+module hoofbaby.app.codec_adhoc;
+
+import hoofbaby.util.buffer;
+import tango.stdc.stdio;
+import tango.stdc.stringz;
+import Math = tango.math.Math;
+import tango.io.device.File;
+import tango.time.StopWatch;
+
+import hoofbaby.codec.libav.avutil;
+import hoofbaby.codec.libav.avcodec;
+import hoofbaby.codec.libav.avformat;
+import hoofbaby.codec.libav.avbuffer;
+
+private const int STREAM_FRAME_RATE = 25;
+private const double STREAM_DURATION = 5.0;
+private const int STREAM_NB_FRAMES = (cast(int) (STREAM_DURATION * STREAM_FRAME_RATE));
+private const int OUTBUF_SIZE = 100000;
+
+int codec_main()
+{
+	StopWatch sw;
+	int frameCount = 0;
+	double audioCount, audioIncr, audioIncr2;
+	char* voutbuf, aoutbuf;
+	int res;
+
+	AVFrame* allocFrame(int pix_fmt, int width, int height)
+	{
+		AVFrame* picture;
+		char* buf;
+		int size;
+
+		picture = avcodec_alloc_frame();
+		if(!picture)
+			return null;
+		size = avpicture_get_size(pix_fmt, width, height);
+		buf = cast(char*) av_malloc(size);
+		if(!buf)
+		{
+			av_free(picture);
+			return null;
+		}
+		avpicture_fill(cast(AVPicture*) picture, buf, pix_fmt, width, height);
+		return picture;
+	}
+
+	void generatePicture(AVFrame* pict, int width, int height)
+	{
+		int x, y, i;
+		i = frameCount;
+
+		/* Y */
+		for(y = 0; y < height; y++)
+		{
+			for(x = 0; x < width; x++)
+			{
+				pict.data[0][y * pict.linesize[0] + x] = x + y + i * 3;
+			}
+		}
+
+		/* Cb and Cr */
+		for(y = 0; y < height / 2; y++)
+		{
+			for(x = 0; x < width / 2; x++)
+			{
+				pict.data[1][y * pict.linesize[1] + x] = 128 + y + i * 2;
+				pict.data[2][y * pict.linesize[2] + x] = 64 + x + i * 5;
+			}
+		}
+	}
+
+	int writeVideoFrame(AVFormatContext* ctx, AVStream* stream, AVFrame* picture)
+	{
+		AVCodecContext* vcodec = stream.codec;
+		int ret = 0;
+
+		if(frameCount >= STREAM_NB_FRAMES)
+		{
+			// no more frame to compress. The codec has a latency of a few
+			// frames if using B frames, so we get the last frames by
+			// passing the same picture again
+		}
+		else
+		{
+			generatePicture(picture, vcodec.width, vcodec.height);
+		}
+
+		// Encode it!
+		int outSize = avcodec_encode_video(vcodec, voutbuf, OUTBUF_SIZE, picture);
+		// if zero size, it means the image was buffered.. if not, write that ****!
+		if(outSize > 0)
+		{
+			AVPacket pkt;
+			av_init_packet(&pkt);
+
+			pkt.pts = av_rescale_q(vcodec.coded_frame.pts, vcodec.time_base, stream.time_base);
+			if(vcodec.coded_frame.key_frame)
+				pkt.flags |= PKT_FLAG_KEY;
+			pkt.stream_index = stream.index;
+			pkt.data = voutbuf;
+			pkt.size = outSize;
+
+			// oh yeah!
+			ret = av_write_frame(ctx, &pkt);
+		}
+		else
+		{
+			ret = 0;
+		}
+		
+		frameCount++;
+		assert(!ret, "Error writing video frame");
+		return ret;
+	}
+	
+	int writeAudioFrame(AVFormatContext* ctx, AVStream* stream, short* samples)
+	{
+		AVCodecContext* acodec = stream.codec;
+
+		{
+			int j, i, v;
+		    short *q;
+
+		    q = samples;
+		    for(j = 0; j < acodec.frame_size; j++)
+		    {
+		        v = cast(int)(Math.sin(audioCount) * 10000);
+		        for(i = 0; i < 2; i++) // 2 is number of channels
+		            *q++ = v;
+		        audioCount += audioIncr;
+		        audioIncr += audioIncr2;
+		    }
+		}
+		
+		AVPacket pkt;
+		av_init_packet(&pkt);
+		pkt.size = avcodec_encode_audio(acodec, aoutbuf, OUTBUF_SIZE, samples);
+		//pkt.pts = av_rescale_q(acodec.coded_frame.pts, acodec.time_base, acodec.time_base);
+		pkt.flags |= PKT_FLAG_KEY;
+		pkt.stream_index = stream.index;
+		pkt.data = aoutbuf;
+		
+		int res = av_write_frame(ctx, &pkt) != 0;
+		assert(res == 0, "Error writing audio frame");
+		return res;
+	}
+	
+	//--------------------------------------------------------------------------
+	// Container format
+	
+	sw.start();
+	
+	AVOutputFormat* fmt = guess_format("asf", null, null);
+	assert(fmt !is null, "Could not find format");
+	
+	AVFormatContext* ctx = av_alloc_format_context();
+	assert(ctx !is null, "Could not allocate format context");
+	scope(exit) if(ctx) av_free(ctx);
+	ctx.oformat = fmt;
+	//ctx.preload = cast(int) (0.5 * AV_TIME_BASE);
+	ctx.max_delay = cast(int) (0.7 * AV_TIME_BASE);
+	ctx.loop_output = AVFMT_NOOUTPUTLOOP;
+	ctx.flags |= AVFMT_FLAG_NONBLOCK;
+	
+	AVFormatParameters params;
+	params.prealloced_context = 1;
+	params.video_codec_id = CODEC_ID_WMV2;
+	params.audio_codec_id = CODEC_ID_WMAV2;
+	params.width = 352;
+	params.height = 288;
+	params.time_base.num = 1;
+	params.time_base.den = STREAM_FRAME_RATE;
+	params.pix_fmt = PIX_FMT_YUV420P;
+	params.channels = 2;
+	params.sample_rate = 44100;
+	res = av_set_parameters(ctx, null);
+	assert(res >= 0, "Could not set parameters");
+	
+	//--------------------------------------------------------------------------
+	// Video stream
+	
+	AVStream* vstream = av_new_stream(ctx, 0);
+	assert(vstream !is null, "Could not allocate video stream");
+	ctx.streams[0] = vstream;
+	
+	AVCodec* vcodecName = avcodec_find_encoder(CODEC_ID_WMV2);
+	assert(vcodecName, "Could not find video codec");
+	AVCodecContext* vcodec = vstream.codec;
+	vcodec.codec_id = CODEC_ID_WMV2;
+	vcodec.codec_type = CODEC_TYPE_VIDEO;
+	vcodec.bit_rate = 400000;
+	vcodec.width = 352;
+	vcodec.height = 288;
+	vcodec.gop_size = 12;
+	vcodec.qmin = 3;
+	vcodec.time_base.den = STREAM_FRAME_RATE;
+	vcodec.time_base.num = 1;
+	vcodec.pix_fmt = PIX_FMT_YUV420P;
+	vcodec.flags |= CODEC_FLAG_GLOBAL_HEADER;
+	res = avcodec_open(vcodec, vcodecName);
+	assert(res >= 0, "Could not open video codec");
+	
+	//--------------------------------------------------------------------------
+	// Audio stream
+	
+	AVStream* astream = av_new_stream(ctx, 0);
+	assert(astream !is null, "Could not allocate audio stream");
+	ctx.streams[1] = astream;
+	
+	AVCodec* acodecName = avcodec_find_encoder(CODEC_ID_WMAV2);
+	assert(acodecName, "Could not find audio codec");
+	AVCodecContext* acodec = astream.codec;
+	acodec.codec_id = CODEC_ID_WMAV2;
+	acodec.codec_type = CODEC_TYPE_AUDIO;
+	acodec.bit_rate = 64000;
+	acodec.sample_rate = 44100;
+	acodec.channels = 2;
+	acodec.flags |= CODEC_FLAG_GLOBAL_HEADER;
+	audioCount = 0.0;
+	audioIncr = 2 * Math.PI * 110.0 / acodec.sample_rate;
+	audioIncr2 = 2 * Math.PI * 110.0 / acodec.sample_rate / acodec.sample_rate;
+	res = avcodec_open(acodec, acodecName);
+	assert(res >= 0, "Could not open audio codec");
+	
+	//--------------------------------------------------------------------------
+	// Actually doing stuff
+	
+	// Open output file
+	RingBuffer ringBuf = RingBuffer(1 << 24); // 16 MB
+	scope(exit) ringBuf.free();
+	ctx.pb = getBioContext(&ringBuf, 1 << 24);
+	assert(ctx.pb !is null);
+	assert(ctx.pb.opaque !is null);
+
+	// Allocate a video frame and audio buffer to store stuff
+	AVFrame* frame = allocFrame(PIX_FMT_YUV420P, vcodec.width, vcodec.height);
+	assert(frame !is null, "Could not allocate frame");
+	scope(exit) if(frame) av_free(frame);
+	short* samples = cast(short*) av_malloc(acodec.frame_size * 2 * acodec.channels);
+	assert(frame !is null, "Could not allocate samples");
+	scope(exit) if(samples) av_free(samples);
+	
+	// Allocate some output buffers
+	voutbuf = cast(char*) av_malloc(OUTBUF_SIZE);
+	assert(voutbuf !is null, "Could not allocate video output buffer");
+	scope(exit) if(voutbuf) av_free(voutbuf);
+	aoutbuf = cast(char*) av_malloc(OUTBUF_SIZE);
+	assert(aoutbuf !is null, "Could not allocate audio output buffer");
+	scope(exit) if(aoutbuf) av_free(voutbuf);
+	
+	printf("Setup time %f\n", sw.stop());
+	sw.start();
+	
+	// Write the header
+	res = av_write_header(ctx);
+	assert(res >= 0, "Could not write header for output file (incorrect codec paramters?)");
+	
+    while(true)
+	{
+		double audio_pts = cast(double) astream.pts.val * astream.time_base.num / astream.time_base.den;
+		double video_pts = cast(double) vstream.pts.val * vstream.time_base.num / vstream.time_base.den;
+
+		if(audio_pts >= STREAM_DURATION && video_pts >= STREAM_DURATION)
+			break;
+
+		// Write interleaved audio & video
+		if(audio_pts < video_pts)
+			writeAudioFrame(ctx, astream, samples);
+		else
+			writeVideoFrame(ctx, vstream, frame);
+	}
+    
+	res = av_write_trailer(ctx);
+	assert(res >= 0, "Could not write trailer for output file");
+	
+	printf("Encoding time %f\n", sw.stop());
+	sw.start();
+	
+	scope File file = new File("biff_happy.wmv", File.WriteCreate);
+	uint available = ringBuf.available;
+	ringBuf.beginRead(available);
+	file.write(ringBuf.addr[0 .. ringBuf.available()]);
+	ringBuf.endRead(available);
+	file.close();
+	
+	printf("IO time %f\n", sw.stop());
+	sw.start();
+	
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/app/libs.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,36 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.app.libs;
+
+import tango.io.Stdout;
+
+import platif = hoofbaby.platinum.platif;
+import libav = hoofbaby.codec.libav.avformat;
+
+public bool initLibs()
+{
+	try
+	{
+		platif._loadLib();
+		libav.av_register_all();
+	}
+	catch(Exception e)
+	{
+		debug Stdout("Error initializing shared libraries: " ~ e.toString());
+		return false;
+	}
+	return true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/app/main.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,36 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.app.main;
+
+// Imports for whole program (just link to them)
+import tango.stdc.stdarg; // Must be linked in to prevent strange linker errors
+debug import tango.core.stacktrace.TraceExceptions;
+import NONE = hoofbaby.codec.libav.mingw;
+
+import hoofbaby.app.libs;
+
+version = Codec_Adhoc;
+version(Codec_Adhoc)       import hoofbaby.app.codec_adhoc;
+else version(Server_Adhoc) import Platinum = hoofbaby.platinum.platif;
+else                       static assert(false);
+
+
+public int main(char[][] args)
+{
+	initLibs();
+	version(Codec_Adhoc) return codec_main();
+	else                 return Platinum.mimeOnFire(`D:\Media\Videos`);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/libav/avbuffer.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,41 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.codec.libav.avbuffer;
+
+import hoofbaby.codec.libav.avformat;
+import hoofbaby.util.buffer;
+import tango.stdc.stdlib;
+import tango.stdc.string;
+import tango.stdc.stdio;
+
+ByteIOContext* getBioContext(RingBuffer* buf, int maxPacketSize)
+{
+	ByteIOContext* bio = av_alloc_put_byte(cast(char*) malloc(1 << 16), 1 << 16, 1, buf, null, &hoofbaby_avbuffer_write, null);
+	if(bio)
+		bio.is_streamed = true;
+	return bio;
+}
+
+extern(C) int hoofbaby_avbuffer_write(void* _buf, char* data, int size)
+{
+	RingBuffer* buf = cast(RingBuffer*) _buf;
+	assert(buf);
+	void* p = buf.beginWrite(size);
+	assert(p);
+	memcpy(p, data, size);
+	buf.endWrite(size);
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/libav/avcodec.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1204 @@
+/* THIS FILE GENERATED BY bcd.gen */
+module hoofbaby.codec.libav.avcodec;
+
+import hoofbaby.codec.libav.avutil;
+
+enum
+{
+	LIBAVCODEC_VERSION_MAJOR = 52,
+	LIBAVCODEC_VERSION_MINOR = 31,
+	LIBAVCODEC_VERSION_MICRO = 2,
+	AV_TIME_BASE = 1000000,
+	CH_FRONT_LEFT = 0x00000001,
+	CH_FRONT_RIGHT = 0x00000002,
+	CH_FRONT_CENTER = 0x00000004,
+	CH_LOW_FREQUENCY = 0x00000008,
+	CH_BACK_LEFT = 0x00000010,
+	CH_BACK_RIGHT = 0x00000020,
+	CH_FRONT_LEFT_OF_CENTER = 0x00000040,
+	CH_FRONT_RIGHT_OF_CENTER = 0x00000080,
+	CH_BACK_CENTER = 0x00000100,
+	CH_SIDE_LEFT = 0x00000200,
+	CH_SIDE_RIGHT = 0x00000400,
+	CH_TOP_CENTER = 0x00000800,
+	CH_TOP_FRONT_LEFT = 0x00001000,
+	CH_TOP_FRONT_CENTER = 0x00002000,
+	CH_TOP_FRONT_RIGHT = 0x00004000,
+	CH_TOP_BACK_LEFT = 0x00008000,
+	CH_TOP_BACK_CENTER = 0x00010000,
+	CH_TOP_BACK_RIGHT = 0x00020000,
+	CH_STEREO_LEFT = 0x20000000,
+	CH_STEREO_RIGHT = 0x40000000,
+	AVCODEC_MAX_AUDIO_FRAME_SIZE = 192000,
+	FF_INPUT_BUFFER_PADDING_SIZE = 8,
+	FF_MIN_BUFFER_SIZE = 16384,
+	FF_MAX_B_FRAMES = 16,
+	CODEC_FLAG_QSCALE = 0x0002,
+	CODEC_FLAG_4MV = 0x0004,
+	CODEC_FLAG_QPEL = 0x0010,
+	CODEC_FLAG_GMC = 0x0020,
+	CODEC_FLAG_MV0 = 0x0040,
+	CODEC_FLAG_PART = 0x0080,
+	CODEC_FLAG_INPUT_PRESERVED = 0x0100,
+	CODEC_FLAG_PASS1 = 0x0200,
+	CODEC_FLAG_PASS2 = 0x0400,
+	CODEC_FLAG_EXTERN_HUFF = 0x1000,
+	CODEC_FLAG_GRAY = 0x2000,
+	CODEC_FLAG_EMU_EDGE = 0x4000,
+	CODEC_FLAG_PSNR = 0x8000,
+	CODEC_FLAG_TRUNCATED = 0x00010000,
+	CODEC_FLAG_NORMALIZE_AQP = 0x00020000,
+	CODEC_FLAG_INTERLACED_DCT = 0x00040000,
+	CODEC_FLAG_LOW_DELAY = 0x00080000,
+	CODEC_FLAG_ALT_SCAN = 0x00100000,
+	CODEC_FLAG_GLOBAL_HEADER = 0x00400000,
+	CODEC_FLAG_BITEXACT = 0x00800000,
+	CODEC_FLAG_AC_PRED = 0x01000000,
+	CODEC_FLAG_H263P_UMV = 0x02000000,
+	CODEC_FLAG_CBP_RD = 0x04000000,
+	CODEC_FLAG_QP_RD = 0x08000000,
+	CODEC_FLAG_H263P_AIV = 0x00000008,
+	CODEC_FLAG_OBMC = 0x00000001,
+	CODEC_FLAG_LOOP_FILTER = 0x00000800,
+	CODEC_FLAG_H263P_SLICE_STRUCT = 0x10000000,
+	CODEC_FLAG_INTERLACED_ME = 0x20000000,
+	CODEC_FLAG_SVCD_SCAN_OFFSET = 0x40000000,
+	CODEC_FLAG_CLOSED_GOP = 0x80000000,
+	CODEC_FLAG2_FAST = 0x00000001,
+	CODEC_FLAG2_STRICT_GOP = 0x00000002,
+	CODEC_FLAG2_NO_OUTPUT = 0x00000004,
+	CODEC_FLAG2_LOCAL_HEADER = 0x00000008,
+	CODEC_FLAG2_BPYRAMID = 0x00000010,
+	CODEC_FLAG2_WPRED = 0x00000020,
+	CODEC_FLAG2_MIXED_REFS = 0x00000040,
+	CODEC_FLAG2_8X8DCT = 0x00000080,
+	CODEC_FLAG2_FASTPSKIP = 0x00000100,
+	CODEC_FLAG2_AUD = 0x00000200,
+	CODEC_FLAG2_BRDO = 0x00000400,
+	CODEC_FLAG2_INTRA_VLC = 0x00000800,
+	CODEC_FLAG2_MEMC_ONLY = 0x00001000,
+	CODEC_FLAG2_DROP_FRAME_TIMECODE = 0x00002000,
+	CODEC_FLAG2_SKIP_RD = 0x00004000,
+	CODEC_FLAG2_CHUNKS = 0x00008000,
+	CODEC_FLAG2_NON_LINEAR_QUANT = 0x00010000,
+	CODEC_FLAG2_BIT_RESERVOIR = 0x00020000,
+	CODEC_CAP_DRAW_HORIZ_BAND = 0x0001,
+	CODEC_CAP_DR1 = 0x0002,
+	CODEC_CAP_PARSE_ONLY = 0x0004,
+	CODEC_CAP_TRUNCATED = 0x0008,
+	CODEC_CAP_HWACCEL = 0x0010,
+	CODEC_CAP_DELAY = 0x0020,
+	CODEC_CAP_SMALL_LAST_FRAME = 0x0040,
+	CODEC_CAP_HWACCEL_VDPAU = 0x0080,
+	MB_TYPE_INTRA4x4 = 0x0001,
+	MB_TYPE_INTRA16x16 = 0x0002,
+	MB_TYPE_INTRA_PCM = 0x0004,
+	MB_TYPE_16x16 = 0x0008,
+	MB_TYPE_16x8 = 0x0010,
+	MB_TYPE_8x16 = 0x0020,
+	MB_TYPE_8x8 = 0x0040,
+	MB_TYPE_INTERLACED = 0x0080,
+	MB_TYPE_DIRECT2 = 0x0100,
+	MB_TYPE_ACPRED = 0x0200,
+	MB_TYPE_GMC = 0x0400,
+	MB_TYPE_SKIP = 0x0800,
+	MB_TYPE_P0L0 = 0x1000,
+	MB_TYPE_P1L0 = 0x2000,
+	MB_TYPE_P0L1 = 0x4000,
+	MB_TYPE_P1L1 = 0x8000,
+	MB_TYPE_QUANT = 0x00010000,
+	MB_TYPE_CBP = 0x00020000,
+	FF_QSCALE_TYPE_MPEG1 = 0,
+	FF_QSCALE_TYPE_MPEG2 = 1,
+	FF_QSCALE_TYPE_H264 = 2,
+	FF_BUFFER_TYPE_INTERNAL = 1,
+	FF_BUFFER_TYPE_USER = 2,
+	FF_BUFFER_TYPE_SHARED = 4,
+	FF_BUFFER_TYPE_COPY = 8,
+	FF_I_TYPE = 1,
+	FF_P_TYPE = 2,
+	FF_B_TYPE = 3,
+	FF_S_TYPE = 4,
+	FF_SI_TYPE = 5,
+	FF_SP_TYPE = 6,
+	FF_BI_TYPE = 7,
+	FF_BUFFER_HINTS_VALID = 0x01,
+	FF_BUFFER_HINTS_READABLE = 0x02,
+	FF_BUFFER_HINTS_PRESERVE = 0x04,
+	FF_BUFFER_HINTS_REUSABLE = 0x08,
+	AV_PKT_FLAG_KEY = 0x0001,
+	FF_ASPECT_EXTENDED = 15,
+	FF_RC_STRATEGY_XVID = 1,
+	FF_BUG_AUTODETECT = 1,
+	FF_BUG_OLD_MSMPEG4 = 2,
+	FF_BUG_XVID_ILACE = 4,
+	FF_BUG_UMP4 = 8,
+	FF_BUG_NO_PADDING = 16,
+	FF_BUG_AMV = 32,
+	FF_BUG_AC_VLC = 0,
+	FF_BUG_QPEL_CHROMA = 64,
+	FF_BUG_STD_QPEL = 128,
+	FF_BUG_QPEL_CHROMA2 = 256,
+	FF_BUG_DIRECT_BLOCKSIZE = 512,
+	FF_BUG_EDGE = 1024,
+	FF_BUG_HPEL_CHROMA = 2048,
+	FF_BUG_DC_CLIP = 4096,
+	FF_BUG_MS = 8192,
+	FF_COMPLIANCE_VERY_STRICT = 2,
+	FF_COMPLIANCE_STRICT = 1,
+	FF_COMPLIANCE_NORMAL = 0,
+	FF_COMPLIANCE_INOFFICIAL = -1,
+	FF_COMPLIANCE_EXPERIMENTAL = -2,
+	FF_ER_CAREFUL = 1,
+	FF_ER_COMPLIANT = 2,
+	FF_ER_AGGRESSIVE = 3,
+	FF_ER_VERY_AGGRESSIVE = 4,
+	FF_DCT_AUTO = 0,
+	FF_DCT_FASTINT = 1,
+	FF_DCT_INT = 2,
+	FF_DCT_MMX = 3,
+	FF_DCT_MLIB = 4,
+	FF_DCT_ALTIVEC = 5,
+	FF_DCT_FAAN = 6,
+	FF_IDCT_AUTO = 0,
+	FF_IDCT_INT = 1,
+	FF_IDCT_SIMPLE = 2,
+	FF_IDCT_SIMPLEMMX = 3,
+	FF_IDCT_LIBMPEG2MMX = 4,
+	FF_IDCT_PS2 = 5,
+	FF_IDCT_MLIB = 6,
+	FF_IDCT_ARM = 7,
+	FF_IDCT_ALTIVEC = 8,
+	FF_IDCT_SH4 = 9,
+	FF_IDCT_SIMPLEARM = 10,
+	FF_IDCT_H264 = 11,
+	FF_IDCT_VP3 = 12,
+	FF_IDCT_IPP = 13,
+	FF_IDCT_XVIDMMX = 14,
+	FF_IDCT_CAVS = 15,
+	FF_IDCT_SIMPLEARMV5TE = 16,
+	FF_IDCT_SIMPLEARMV6 = 17,
+	FF_IDCT_SIMPLEVIS = 18,
+	FF_IDCT_WMV2 = 19,
+	FF_IDCT_FAAN = 20,
+	FF_IDCT_EA = 21,
+	FF_IDCT_SIMPLENEON = 22,
+	FF_IDCT_SIMPLEALPHA = 23,
+	FF_EC_GUESS_MVS = 1,
+	FF_EC_DEBLOCK = 2,
+	FF_MM_FORCE = 0x80000000,
+	FF_MM_MMX = 0x0001,
+	FF_MM_3DNOW = 0x0004,
+	FF_MM_MMXEXT = 0x0002,
+	FF_MM_MMX2 = 0x0002,
+	FF_MM_SSE = 0x0008,
+	FF_MM_SSE2 = 0x0010,
+	FF_MM_3DNOWEXT = 0x0020,
+	FF_MM_SSE3 = 0x0040,
+	FF_MM_SSSE3 = 0x0080,
+	FF_MM_SSE4 = 0x0100,
+	FF_MM_SSE42 = 0x0200,
+	FF_MM_IWMMXT = 0x0100,
+	FF_MM_ALTIVEC = 0x0001,
+	FF_PRED_LEFT = 0,
+	FF_PRED_PLANE = 1,
+	FF_PRED_MEDIAN = 2,
+	FF_DEBUG_PICT_INFO = 1,
+	FF_DEBUG_RC = 2,
+	FF_DEBUG_BITSTREAM = 4,
+	FF_DEBUG_MB_TYPE = 8,
+	FF_DEBUG_QP = 16,
+	FF_DEBUG_MV = 32,
+	FF_DEBUG_DCT_COEFF = 0x00000040,
+	FF_DEBUG_SKIP = 0x00000080,
+	FF_DEBUG_STARTCODE = 0x00000100,
+	FF_DEBUG_PTS = 0x00000200,
+	FF_DEBUG_ER = 0x00000400,
+	FF_DEBUG_MMCO = 0x00000800,
+	FF_DEBUG_BUGS = 0x00001000,
+	FF_DEBUG_VIS_QP = 0x00002000,
+	FF_DEBUG_VIS_MB_TYPE = 0x00004000,
+	FF_DEBUG_BUFFERS = 0x00008000,
+	FF_DEBUG_VIS_MV_P_FOR = 0x00000001,
+	FF_DEBUG_VIS_MV_B_FOR = 0x00000002,
+	FF_DEBUG_VIS_MV_B_BACK = 0x00000004,
+	FF_CMP_SAD = 0,
+	FF_CMP_SSE = 1,
+	FF_CMP_SATD = 2,
+	FF_CMP_DCT = 3,
+	FF_CMP_PSNR = 4,
+	FF_CMP_BIT = 5,
+	FF_CMP_RD = 6,
+	FF_CMP_ZERO = 7,
+	FF_CMP_VSAD = 8,
+	FF_CMP_VSSE = 9,
+	FF_CMP_NSSE = 10,
+	FF_CMP_W53 = 11,
+	FF_CMP_W97 = 12,
+	FF_CMP_DCTMAX = 13,
+	FF_CMP_DCT264 = 14,
+	FF_CMP_CHROMA = 256,
+	FF_DTG_AFD_SAME = 8,
+	FF_DTG_AFD_4_3 = 9,
+	FF_DTG_AFD_16_9 = 10,
+	FF_DTG_AFD_14_9 = 11,
+	FF_DTG_AFD_4_3_SP_14_9 = 13,
+	FF_DTG_AFD_16_9_SP_14_9 = 14,
+	FF_DTG_AFD_SP_4_3 = 15,
+	FF_DEFAULT_QUANT_BIAS = 999999,
+	FF_LAMBDA_SHIFT = 7,
+	FF_QP2LAMBDA = 118,
+	FF_CODER_TYPE_VLC = 0,
+	FF_CODER_TYPE_AC = 1,
+	FF_CODER_TYPE_RAW = 2,
+	FF_CODER_TYPE_RLE = 3,
+	FF_CODER_TYPE_DEFLATE = 4,
+	SLICE_FLAG_CODED_ORDER = 0x0001,
+	SLICE_FLAG_ALLOW_FIELD = 0x0002,
+	SLICE_FLAG_ALLOW_PLANE = 0x0004,
+	FF_MB_DECISION_SIMPLE = 0,
+	FF_MB_DECISION_BITS = 1,
+	FF_MB_DECISION_RD = 2,
+	FF_AA_AUTO = 0,
+	FF_AA_FASTINT = 1,
+	FF_AA_INT = 2,
+	FF_AA_FLOAT = 3,
+	FF_PROFILE_UNKNOWN = -99,
+	FF_PROFILE_AAC_MAIN = 0,
+	FF_PROFILE_AAC_LOW = 1,
+	FF_PROFILE_AAC_SSR = 2,
+	FF_PROFILE_AAC_LTP = 3,
+	FF_LEVEL_UNKNOWN = -99,
+	X264_PART_I4X4 = 0x001,
+	X264_PART_I8X8 = 0x002,
+	X264_PART_P8X8 = 0x010,
+	X264_PART_P4X4 = 0x020,
+	X264_PART_B8X8 = 0x100,
+	FF_COMPRESSION_DEFAULT = -1,
+	AVPALETTE_SIZE = 1024,
+	AVPALETTE_COUNT = 256,
+	FF_LOSS_RESOLUTION = 0x0001,
+	FF_LOSS_DEPTH = 0x0002,
+	FF_LOSS_COLORSPACE = 0x0004,
+	FF_LOSS_ALPHA = 0x0008,
+	FF_LOSS_COLORQUANT = 0x0010,
+	FF_LOSS_CHROMA = 0x0020,
+	FF_ALPHA_TRANSP = 0x0001,
+	FF_ALPHA_SEMI_TRANSP = 0x0002,
+	AV_PARSER_PTS_NB = 4,
+	PARSER_FLAG_COMPLETE_FRAMES = 0x0001,
+	PKT_FLAG_KEY = 0x0001,
+}
+
+alias int AVLockOp;
+enum : AVLockOp
+{
+	AV_LOCK_CREATE = 0,
+	AV_LOCK_OBTAIN = 1,
+	AV_LOCK_RELEASE = 2,
+	AV_LOCK_DESTROY = 3,
+}
+
+alias int function(AVBitStreamFilterContext*, AVCodecContext*, char*, char**, int*, char*, int, int) _BCD_func__1510;
+alias void function(AVBitStreamFilterContext*) _BCD_func__1511;
+alias int function(AVCodecParserContext*) _BCD_func__1514;
+alias int function(AVCodecParserContext*, AVCodecContext*, char**, int*, char*, int) _BCD_func__1515;
+alias void function(AVCodecParserContext*) _BCD_func__1516;
+alias int function(AVCodecContext*, char*, int) _BCD_func__1517;
+alias int function(AVCodecContext*, char*, uint) _BCD_func__1525;
+alias int function(AVCodecContext*) _BCD_func__1526;
+alias int function(AVCodecContext*, char*, int, void*) _BCD_func__1528;
+alias int function(AVCodecContext*, void*, int*, AVPacket*) _BCD_func__1529;
+alias void function(AVCodecContext*) _BCD_func__1530;
+alias void function(AVCodecContext*, AVFrame*, int*, int, int, int) _BCD_func__1536;
+alias void function(AVCodecContext*, void*, int, int) _BCD_func__1537;
+alias int function(AVCodecContext*, AVFrame*) _BCD_func__1538;
+alias void function(AVCodecContext*, AVFrame*) _BCD_func__1539;
+alias int function(AVCodecContext*, int*) _BCD_func__1540;
+alias int function(AVCodecContext*, void*) _BCD_func__1566;
+alias int function(AVCodecContext*, _BCD_func__1566, void*, int*, int, int) _BCD_func__1541;
+alias void function(AVPacket*) _BCD_func__1545;
+alias int function(void**, int) _BCD_func__1421;
+alias int function(AVCodecContext*, void*) _BCD_func__1443;
+alias int function() _BCD_func__1366;
+
+alias void ReSampleContext;
+
+alias int AVSubtitleType;
+enum : AVSubtitleType
+{
+	SUBTITLE_NONE = 0,
+	SUBTITLE_BITMAP = 1,
+	SUBTITLE_TEXT = 2,
+	SUBTITLE_ASS = 3,
+}
+
+alias int CodecType;
+enum : CodecType
+{
+	CODEC_TYPE_UNKNOWN = -1,
+	CODEC_TYPE_VIDEO = 0,
+	CODEC_TYPE_AUDIO = 1,
+	CODEC_TYPE_DATA = 2,
+	CODEC_TYPE_SUBTITLE = 3,
+	CODEC_TYPE_ATTACHMENT = 4,
+	CODEC_TYPE_NB = 5,
+}
+
+alias int CodecID;
+enum : CodecID
+{
+	CODEC_ID_NONE = 0,
+	CODEC_ID_MPEG1VIDEO = 1,
+	CODEC_ID_MPEG2VIDEO = 2,
+	CODEC_ID_MPEG2VIDEO_XVMC = 3,
+	CODEC_ID_H261 = 4,
+	CODEC_ID_H263 = 5,
+	CODEC_ID_RV10 = 6,
+	CODEC_ID_RV20 = 7,
+	CODEC_ID_MJPEG = 8,
+	CODEC_ID_MJPEGB = 9,
+	CODEC_ID_LJPEG = 10,
+	CODEC_ID_SP5X = 11,
+	CODEC_ID_JPEGLS = 12,
+	CODEC_ID_MPEG4 = 13,
+	CODEC_ID_RAWVIDEO = 14,
+	CODEC_ID_MSMPEG4V1 = 15,
+	CODEC_ID_MSMPEG4V2 = 16,
+	CODEC_ID_MSMPEG4V3 = 17,
+	CODEC_ID_WMV1 = 18,
+	CODEC_ID_WMV2 = 19,
+	CODEC_ID_H263P = 20,
+	CODEC_ID_H263I = 21,
+	CODEC_ID_FLV1 = 22,
+	CODEC_ID_SVQ1 = 23,
+	CODEC_ID_SVQ3 = 24,
+	CODEC_ID_DVVIDEO = 25,
+	CODEC_ID_HUFFYUV = 26,
+	CODEC_ID_CYUV = 27,
+	CODEC_ID_H264 = 28,
+	CODEC_ID_INDEO3 = 29,
+	CODEC_ID_VP3 = 30,
+	CODEC_ID_THEORA = 31,
+	CODEC_ID_ASV1 = 32,
+	CODEC_ID_ASV2 = 33,
+	CODEC_ID_FFV1 = 34,
+	CODEC_ID_4XM = 35,
+	CODEC_ID_VCR1 = 36,
+	CODEC_ID_CLJR = 37,
+	CODEC_ID_MDEC = 38,
+	CODEC_ID_ROQ = 39,
+	CODEC_ID_INTERPLAY_VIDEO = 40,
+	CODEC_ID_XAN_WC3 = 41,
+	CODEC_ID_XAN_WC4 = 42,
+	CODEC_ID_RPZA = 43,
+	CODEC_ID_CINEPAK = 44,
+	CODEC_ID_WS_VQA = 45,
+	CODEC_ID_MSRLE = 46,
+	CODEC_ID_MSVIDEO1 = 47,
+	CODEC_ID_IDCIN = 48,
+	CODEC_ID_8BPS = 49,
+	CODEC_ID_SMC = 50,
+	CODEC_ID_FLIC = 51,
+	CODEC_ID_TRUEMOTION1 = 52,
+	CODEC_ID_VMDVIDEO = 53,
+	CODEC_ID_MSZH = 54,
+	CODEC_ID_ZLIB = 55,
+	CODEC_ID_QTRLE = 56,
+	CODEC_ID_SNOW = 57,
+	CODEC_ID_TSCC = 58,
+	CODEC_ID_ULTI = 59,
+	CODEC_ID_QDRAW = 60,
+	CODEC_ID_VIXL = 61,
+	CODEC_ID_QPEG = 62,
+	CODEC_ID_XVID = 63,
+	CODEC_ID_PNG = 64,
+	CODEC_ID_PPM = 65,
+	CODEC_ID_PBM = 66,
+	CODEC_ID_PGM = 67,
+	CODEC_ID_PGMYUV = 68,
+	CODEC_ID_PAM = 69,
+	CODEC_ID_FFVHUFF = 70,
+	CODEC_ID_RV30 = 71,
+	CODEC_ID_RV40 = 72,
+	CODEC_ID_VC1 = 73,
+	CODEC_ID_WMV3 = 74,
+	CODEC_ID_LOCO = 75,
+	CODEC_ID_WNV1 = 76,
+	CODEC_ID_AASC = 77,
+	CODEC_ID_INDEO2 = 78,
+	CODEC_ID_FRAPS = 79,
+	CODEC_ID_TRUEMOTION2 = 80,
+	CODEC_ID_BMP = 81,
+	CODEC_ID_CSCD = 82,
+	CODEC_ID_MMVIDEO = 83,
+	CODEC_ID_ZMBV = 84,
+	CODEC_ID_AVS = 85,
+	CODEC_ID_SMACKVIDEO = 86,
+	CODEC_ID_NUV = 87,
+	CODEC_ID_KMVC = 88,
+	CODEC_ID_FLASHSV = 89,
+	CODEC_ID_CAVS = 90,
+	CODEC_ID_JPEG2000 = 91,
+	CODEC_ID_VMNC = 92,
+	CODEC_ID_VP5 = 93,
+	CODEC_ID_VP6 = 94,
+	CODEC_ID_VP6F = 95,
+	CODEC_ID_TARGA = 96,
+	CODEC_ID_DSICINVIDEO = 97,
+	CODEC_ID_TIERTEXSEQVIDEO = 98,
+	CODEC_ID_TIFF = 99,
+	CODEC_ID_GIF = 100,
+	CODEC_ID_FFH264 = 101,
+	CODEC_ID_DXA = 102,
+	CODEC_ID_DNXHD = 103,
+	CODEC_ID_THP = 104,
+	CODEC_ID_SGI = 105,
+	CODEC_ID_C93 = 106,
+	CODEC_ID_BETHSOFTVID = 107,
+	CODEC_ID_PTX = 108,
+	CODEC_ID_TXD = 109,
+	CODEC_ID_VP6A = 110,
+	CODEC_ID_AMV = 111,
+	CODEC_ID_VB = 112,
+	CODEC_ID_PCX = 113,
+	CODEC_ID_SUNRAST = 114,
+	CODEC_ID_INDEO4 = 115,
+	CODEC_ID_INDEO5 = 116,
+	CODEC_ID_MIMIC = 117,
+	CODEC_ID_RL2 = 118,
+	CODEC_ID_8SVX_EXP = 119,
+	CODEC_ID_8SVX_FIB = 120,
+	CODEC_ID_ESCAPE124 = 121,
+	CODEC_ID_DIRAC = 122,
+	CODEC_ID_BFI = 123,
+	CODEC_ID_CMV = 124,
+	CODEC_ID_MOTIONPIXELS = 125,
+	CODEC_ID_TGV = 126,
+	CODEC_ID_TGQ = 127,
+	CODEC_ID_TQI = 128,
+	CODEC_ID_AURA = 129,
+	CODEC_ID_AURA2 = 130,
+	CODEC_ID_V210X = 131,
+	CODEC_ID_TMV = 132,
+	CODEC_ID_V210 = 133,
+	CODEC_ID_DPX = 134,
+	CODEC_ID_MAD = 135,
+	CODEC_ID_PCM_S16LE = 65536,
+	CODEC_ID_PCM_S16BE = 65537,
+	CODEC_ID_PCM_U16LE = 65538,
+	CODEC_ID_PCM_U16BE = 65539,
+	CODEC_ID_PCM_S8 = 65540,
+	CODEC_ID_PCM_U8 = 65541,
+	CODEC_ID_PCM_MULAW = 65542,
+	CODEC_ID_PCM_ALAW = 65543,
+	CODEC_ID_PCM_S32LE = 65544,
+	CODEC_ID_PCM_S32BE = 65545,
+	CODEC_ID_PCM_U32LE = 65546,
+	CODEC_ID_PCM_U32BE = 65547,
+	CODEC_ID_PCM_S24LE = 65548,
+	CODEC_ID_PCM_S24BE = 65549,
+	CODEC_ID_PCM_U24LE = 65550,
+	CODEC_ID_PCM_U24BE = 65551,
+	CODEC_ID_PCM_S24DAUD = 65552,
+	CODEC_ID_PCM_ZORK = 65553,
+	CODEC_ID_PCM_S16LE_PLANAR = 65554,
+	CODEC_ID_PCM_DVD = 65555,
+	CODEC_ID_PCM_F32BE = 65556,
+	CODEC_ID_PCM_F32LE = 65557,
+	CODEC_ID_PCM_F64BE = 65558,
+	CODEC_ID_PCM_F64LE = 65559,
+	CODEC_ID_ADPCM_IMA_QT = 69632,
+	CODEC_ID_ADPCM_IMA_WAV = 69633,
+	CODEC_ID_ADPCM_IMA_DK3 = 69634,
+	CODEC_ID_ADPCM_IMA_DK4 = 69635,
+	CODEC_ID_ADPCM_IMA_WS = 69636,
+	CODEC_ID_ADPCM_IMA_SMJPEG = 69637,
+	CODEC_ID_ADPCM_MS = 69638,
+	CODEC_ID_ADPCM_4XM = 69639,
+	CODEC_ID_ADPCM_XA = 69640,
+	CODEC_ID_ADPCM_ADX = 69641,
+	CODEC_ID_ADPCM_EA = 69642,
+	CODEC_ID_ADPCM_G726 = 69643,
+	CODEC_ID_ADPCM_CT = 69644,
+	CODEC_ID_ADPCM_SWF = 69645,
+	CODEC_ID_ADPCM_YAMAHA = 69646,
+	CODEC_ID_ADPCM_SBPRO_4 = 69647,
+	CODEC_ID_ADPCM_SBPRO_3 = 69648,
+	CODEC_ID_ADPCM_SBPRO_2 = 69649,
+	CODEC_ID_ADPCM_THP = 69650,
+	CODEC_ID_ADPCM_IMA_AMV = 69651,
+	CODEC_ID_ADPCM_EA_R1 = 69652,
+	CODEC_ID_ADPCM_EA_R3 = 69653,
+	CODEC_ID_ADPCM_EA_R2 = 69654,
+	CODEC_ID_ADPCM_IMA_EA_SEAD = 69655,
+	CODEC_ID_ADPCM_IMA_EA_EACS = 69656,
+	CODEC_ID_ADPCM_EA_XAS = 69657,
+	CODEC_ID_ADPCM_EA_MAXIS_XA = 69658,
+	CODEC_ID_ADPCM_IMA_ISS = 69659,
+	CODEC_ID_AMR_NB = 73728,
+	CODEC_ID_AMR_WB = 73729,
+	CODEC_ID_RA_144 = 77824,
+	CODEC_ID_RA_288 = 77825,
+	CODEC_ID_ROQ_DPCM = 81920,
+	CODEC_ID_INTERPLAY_DPCM = 81921,
+	CODEC_ID_XAN_DPCM = 81922,
+	CODEC_ID_SOL_DPCM = 81923,
+	CODEC_ID_MP2 = 86016,
+	CODEC_ID_MP3 = 86017,
+	CODEC_ID_AAC = 86018,
+	CODEC_ID_AC3 = 86019,
+	CODEC_ID_DTS = 86020,
+	CODEC_ID_VORBIS = 86021,
+	CODEC_ID_DVAUDIO = 86022,
+	CODEC_ID_WMAV1 = 86023,
+	CODEC_ID_WMAV2 = 86024,
+	CODEC_ID_MACE3 = 86025,
+	CODEC_ID_MACE6 = 86026,
+	CODEC_ID_VMDAUDIO = 86027,
+	CODEC_ID_SONIC = 86028,
+	CODEC_ID_SONIC_LS = 86029,
+	CODEC_ID_FLAC = 86030,
+	CODEC_ID_MP3ADU = 86031,
+	CODEC_ID_MP3ON4 = 86032,
+	CODEC_ID_SHORTEN = 86033,
+	CODEC_ID_ALAC = 86034,
+	CODEC_ID_WESTWOOD_SND1 = 86035,
+	CODEC_ID_GSM = 86036,
+	CODEC_ID_QDM2 = 86037,
+	CODEC_ID_COOK = 86038,
+	CODEC_ID_TRUESPEECH = 86039,
+	CODEC_ID_TTA = 86040,
+	CODEC_ID_SMACKAUDIO = 86041,
+	CODEC_ID_QCELP = 86042,
+	CODEC_ID_WAVPACK = 86043,
+	CODEC_ID_DSICINAUDIO = 86044,
+	CODEC_ID_IMC = 86045,
+	CODEC_ID_MUSEPACK7 = 86046,
+	CODEC_ID_MLP = 86047,
+	CODEC_ID_GSM_MS = 86048,
+	CODEC_ID_ATRAC3 = 86049,
+	CODEC_ID_VOXWARE = 86050,
+	CODEC_ID_APE = 86051,
+	CODEC_ID_NELLYMOSER = 86052,
+	CODEC_ID_MUSEPACK8 = 86053,
+	CODEC_ID_SPEEX = 86054,
+	CODEC_ID_WMAVOICE = 86055,
+	CODEC_ID_WMAPRO = 86056,
+	CODEC_ID_WMALOSSLESS = 86057,
+	CODEC_ID_ATRAC3P = 86058,
+	CODEC_ID_EAC3 = 86059,
+	CODEC_ID_SIPR = 86060,
+	CODEC_ID_MP1 = 86061,
+	CODEC_ID_TWINVQ = 86062,
+	CODEC_ID_TRUEHD = 86063,
+	CODEC_ID_MP4ALS = 86064,
+	CODEC_ID_DVD_SUBTITLE = 94208,
+	CODEC_ID_DVB_SUBTITLE = 94209,
+	CODEC_ID_TEXT = 94210,
+	CODEC_ID_XSUB = 94211,
+	CODEC_ID_SSA = 94212,
+	CODEC_ID_MOV_TEXT = 94213,
+	CODEC_ID_TTF = 98304,
+	CODEC_ID_PROBE = 102400,
+	CODEC_ID_MPEG2TS = 131072,
+}
+
+alias int SampleFormat;
+enum : SampleFormat
+{
+	SAMPLE_FMT_NONE = -1,
+	SAMPLE_FMT_U8 = 0,
+	SAMPLE_FMT_S16 = 1,
+	SAMPLE_FMT_S32 = 2,
+	SAMPLE_FMT_FLT = 3,
+	SAMPLE_FMT_DBL = 4,
+	SAMPLE_FMT_NB = 5,
+}
+
+alias int AVDiscard;
+enum : AVDiscard
+{
+	AVDISCARD_NONE = -16,
+	AVDISCARD_DEFAULT = 0,
+	AVDISCARD_NONREF = 8,
+	AVDISCARD_BIDIR = 16,
+	AVDISCARD_NONKEY = 32,
+	AVDISCARD_ALL = 48,
+}
+
+alias int AVColorPrimaries;
+enum : AVColorPrimaries
+{
+	AVCOL_PRI_BT709 = 1,
+	AVCOL_PRI_UNSPECIFIED = 2,
+	AVCOL_PRI_BT470M = 4,
+	AVCOL_PRI_BT470BG = 5,
+	AVCOL_PRI_SMPTE170M = 6,
+	AVCOL_PRI_SMPTE240M = 7,
+	AVCOL_PRI_FILM = 8,
+	AVCOL_PRI_NB = 9,
+}
+
+alias int AVColorTransferCharacteristic;
+enum : AVColorTransferCharacteristic
+{
+	AVCOL_TRC_BT709 = 1,
+	AVCOL_TRC_UNSPECIFIED = 2,
+	AVCOL_TRC_GAMMA22 = 4,
+	AVCOL_TRC_GAMMA28 = 5,
+	AVCOL_TRC_NB = 6,
+}
+
+alias int AVColorSpace;
+enum : AVColorSpace
+{
+	AVCOL_SPC_RGB = 0,
+	AVCOL_SPC_BT709 = 1,
+	AVCOL_SPC_UNSPECIFIED = 2,
+	AVCOL_SPC_FCC = 4,
+	AVCOL_SPC_BT470BG = 5,
+	AVCOL_SPC_SMPTE170M = 6,
+	AVCOL_SPC_SMPTE240M = 7,
+	AVCOL_SPC_NB = 8,
+}
+
+alias int AVColorRange;
+enum : AVColorRange
+{
+	AVCOL_RANGE_UNSPECIFIED = 0,
+	AVCOL_RANGE_MPEG = 1,
+	AVCOL_RANGE_JPEG = 2,
+	AVCOL_RANGE_NB = 3,
+}
+
+alias int AVChromaLocation;
+enum : AVChromaLocation
+{
+	AVCHROMA_LOC_UNSPECIFIED = 0,
+	AVCHROMA_LOC_LEFT = 1,
+	AVCHROMA_LOC_CENTER = 2,
+	AVCHROMA_LOC_TOPLEFT = 3,
+	AVCHROMA_LOC_TOP = 4,
+	AVCHROMA_LOC_BOTTOMLEFT = 5,
+	AVCHROMA_LOC_BOTTOM = 6,
+	AVCHROMA_LOC_NB = 7,
+}
+
+alias int Motion_Est_ID;
+enum : Motion_Est_ID
+{
+	ME_ZERO = 1,
+	ME_FULL = 2,
+	ME_LOG = 3,
+	ME_PHODS = 4,
+	ME_EPZS = 5,
+	ME_X1 = 6,
+	ME_HEX = 7,
+	ME_UMH = 8,
+	ME_ITER = 9,
+	ME_TESA = 10,
+}
+
+struct AVBitStreamFilter
+{
+	char* name;
+	int priv_data_size;
+	_BCD_func__1510 filter;
+	_BCD_func__1511 close;
+	AVBitStreamFilter* next;
+}
+
+struct AVBitStreamFilterContext
+{
+	void* priv_data;
+	AVBitStreamFilter* filter;
+	AVCodecParserContext* parser;
+	AVBitStreamFilterContext* next;
+}
+
+struct AVCodecParser
+{
+	int[5] codec_ids;
+	int priv_data_size;
+	_BCD_func__1514 parser_init;
+	_BCD_func__1515 parser_parse;
+	_BCD_func__1516 parser_close;
+	_BCD_func__1517 split;
+	AVCodecParser* next;
+}
+
+struct AVCodecParserContext
+{
+	void* priv_data;
+	AVCodecParser* parser;
+	long frame_offset;
+	long cur_offset;
+	long next_frame_offset;
+	int pict_type;
+	int repeat_pict;
+	long pts;
+	long dts;
+	long last_pts;
+	long last_dts;
+	int fetch_timestamp;
+	int cur_frame_start_index;
+	long[4] cur_frame_offset;
+	long[4] cur_frame_pts;
+	long[4] cur_frame_dts;
+	int flags;
+	long offset;
+	long[4] cur_frame_end;
+	int key_frame;
+	long convergence_duration;
+	int dts_sync_point;
+	int dts_ref_dts_delta;
+	int pts_dts_delta;
+	long[4] cur_frame_pos;
+	long pos;
+	long last_pos;
+}
+
+struct AVSubtitle
+{
+	ushort format;
+	uint start_display_time;
+	uint end_display_time;
+	uint num_rects;
+	AVSubtitleRect** rects;
+}
+
+struct AVSubtitleRect
+{
+	int x;
+	int y;
+	int w;
+	int h;
+	int nb_colors;
+	AVPicture pict;
+	int type;
+	char* text;
+	char* ass;
+}
+
+struct AVPicture
+{
+	char*[4] data;
+	int[4] linesize;
+}
+
+struct AVHWAccel
+{
+	char* name;
+	int type;
+	int id;
+	int pix_fmt;
+	int capabilities;
+	AVHWAccel* next;
+	_BCD_func__1525 start_frame;
+	_BCD_func__1525 decode_slice;
+	_BCD_func__1526 end_frame;
+	int priv_data_size;
+}
+
+struct AVPaletteControl
+{
+	int palette_changed;
+	uint[256] palette;
+}
+
+struct AVCodec
+{
+	char* name;
+	int type;
+	int id;
+	int priv_data_size;
+	_BCD_func__1526 init;
+	_BCD_func__1528 encode;
+	_BCD_func__1526 close;
+	_BCD_func__1529 decode;
+	int capabilities;
+	AVCodec* next;
+	_BCD_func__1530 flush;
+	AVRational* supported_framerates;
+	int* pix_fmts;
+	char* long_name;
+	int* supported_samplerates;
+	int* sample_fmts;
+	long* channel_layouts;
+}
+
+struct AVCodecContext
+{
+	AVClass* av_class;
+	int bit_rate;
+	int bit_rate_tolerance;
+	int flags;
+	int sub_id;
+	int me_method;
+	char* extradata;
+	int extradata_size;
+	AVRational time_base;
+	int width;
+	int height;
+	int gop_size;
+	int pix_fmt;
+	int rate_emu;
+	_BCD_func__1536 draw_horiz_band;
+	int sample_rate;
+	int channels;
+	int sample_fmt;
+	int frame_size;
+	int frame_number;
+	int real_pict_num;
+	int delay;
+	float qcompress;
+	float qblur;
+	int qmin;
+	int qmax;
+	int max_qdiff;
+	int max_b_frames;
+	float b_quant_factor;
+	int rc_strategy;
+	int b_frame_strategy;
+	int hurry_up;
+	AVCodec* codec;
+	void* priv_data;
+	int rtp_payload_size;
+	_BCD_func__1537 rtp_callback;
+	int mv_bits;
+	int header_bits;
+	int i_tex_bits;
+	int p_tex_bits;
+	int i_count;
+	int p_count;
+	int skip_count;
+	int misc_bits;
+	int frame_bits;
+	void* opaque;
+	char[32] codec_name;
+	int codec_type;
+	int codec_id;
+	uint codec_tag;
+	int workaround_bugs;
+	int luma_elim_threshold;
+	int chroma_elim_threshold;
+	int strict_std_compliance;
+	float b_quant_offset;
+	int error_recognition;
+	_BCD_func__1538 get_buffer;
+	_BCD_func__1539 release_buffer;
+	int has_b_frames;
+	int block_align;
+	int parse_only;
+	int mpeg_quant;
+	char* stats_out;
+	char* stats_in;
+	float rc_qsquish;
+	float rc_qmod_amp;
+	int rc_qmod_freq;
+	RcOverride* rc_override;
+	int rc_override_count;
+	char* rc_eq;
+	int rc_max_rate;
+	int rc_min_rate;
+	int rc_buffer_size;
+	float rc_buffer_aggressivity;
+	float i_quant_factor;
+	float i_quant_offset;
+	float rc_initial_cplx;
+	int dct_algo;
+	float lumi_masking;
+	float temporal_cplx_masking;
+	float spatial_cplx_masking;
+	float p_masking;
+	float dark_masking;
+	int idct_algo;
+	int slice_count;
+	int* slice_offset;
+	int error_concealment;
+	uint dsp_mask;
+	int bits_per_coded_sample;
+	int prediction_method;
+	AVRational sample_aspect_ratio;
+	AVFrame* coded_frame;
+	int debug_;
+	int debug_mv;
+	ulong[4] error;
+	int mb_qmin;
+	int mb_qmax;
+	int me_cmp;
+	int me_sub_cmp;
+	int mb_cmp;
+	int ildct_cmp;
+	int dia_size;
+	int last_predictor_count;
+	int pre_me;
+	int me_pre_cmp;
+	int pre_dia_size;
+	int me_subpel_quality;
+	_BCD_func__1540 get_format;
+	int dtg_active_format;
+	int me_range;
+	int intra_quant_bias;
+	int inter_quant_bias;
+	int color_table_id;
+	int internal_buffer_count;
+	void* internal_buffer;
+	int global_quality;
+	int coder_type;
+	int context_model;
+	int slice_flags;
+	int xvmc_acceleration;
+	int mb_decision;
+	ushort* intra_matrix;
+	ushort* inter_matrix;
+	uint stream_codec_tag;
+	int scenechange_threshold;
+	int lmin;
+	int lmax;
+	AVPaletteControl* palctrl;
+	int noise_reduction;
+	_BCD_func__1538 reget_buffer;
+	int rc_initial_buffer_occupancy;
+	int inter_threshold;
+	int flags2;
+	int error_rate;
+	int antialias_algo;
+	int quantizer_noise_shaping;
+	int thread_count;
+	_BCD_func__1541 execute;
+	void* thread_opaque;
+	int me_threshold;
+	int mb_threshold;
+	int intra_dc_precision;
+	int nsse_weight;
+	int skip_top;
+	int skip_bottom;
+	int profile;
+	int level;
+	int lowres;
+	int coded_width;
+	int coded_height;
+	int frame_skip_threshold;
+	int frame_skip_factor;
+	int frame_skip_exp;
+	int frame_skip_cmp;
+	float border_masking;
+	int mb_lmin;
+	int mb_lmax;
+	int me_penalty_compensation;
+	int skip_loop_filter;
+	int skip_idct;
+	int skip_frame;
+	int bidir_refine;
+	int brd_scale;
+	float crf;
+	int cqp;
+	int keyint_min;
+	int refs;
+	int chromaoffset;
+	int bframebias;
+	int trellis;
+	float complexityblur;
+	int deblockalpha;
+	int deblockbeta;
+	int partitions;
+	int directpred;
+	int cutoff;
+	int scenechange_factor;
+	int mv0_threshold;
+	int b_sensitivity;
+	int compression_level;
+	int use_lpc;
+	int lpc_coeff_precision;
+	int min_prediction_order;
+	int max_prediction_order;
+	int prediction_order_method;
+	int min_partition_order;
+	int max_partition_order;
+	long timecode_frame_start;
+	int request_channels;
+	float drc_scale;
+	long reordered_opaque;
+	int bits_per_raw_sample;
+	long channel_layout;
+	long request_channel_layout;
+	float rc_max_available_vbv_use;
+	float rc_min_vbv_overflow_use;
+	AVHWAccel* hwaccel;
+	int ticks_per_frame;
+	void* hwaccel_context;
+	int color_primaries;
+	int color_trc;
+	int colorspace;
+	int color_range;
+	int chroma_sample_location;
+}
+
+struct AVFrame
+{
+	char*[4] data;
+	int[4] linesize;
+	char*[4] base;
+	int key_frame;
+	int pict_type;
+	long pts;
+	int coded_picture_number;
+	int display_picture_number;
+	int quality;
+	int age;
+	int reference;
+	char* qscale_table;
+	int qstride;
+	char* mbskip_table;
+	short[2]*[2] motion_val;
+	uint* mb_type;
+	char motion_subsample_log2;
+	void* opaque;
+	ulong[4] error;
+	int type;
+	int repeat_pict;
+	int qscale_type;
+	int interlaced_frame;
+	int top_field_first;
+	AVPanScan* pan_scan;
+	int palette_has_changed;
+	int buffer_hints;
+	short* dct_coeff;
+	char*[2] ref_index;
+	long reordered_opaque;
+	void* hwaccel_picture_private;
+}
+
+struct AVPacket
+{
+	long pts;
+	long dts;
+	char* data;
+	int size;
+	int stream_index;
+	int flags;
+	int duration;
+	_BCD_func__1545 destruct;
+	void* priv;
+	long pos;
+	long convergence_duration;
+}
+
+struct AVPanScan
+{
+	int id;
+	int width;
+	int height;
+	short[2][3] position;
+}
+
+struct RcOverride
+{
+	int start_frame;
+	int end_frame;
+	int qscale;
+	float quality_factor;
+}
+
+extern(C)
+{
+	int av_lockmgr_register(_BCD_func__1421);
+	AVHWAccel* av_hwaccel_next(AVHWAccel*);
+	void av_register_hwaccel(AVHWAccel*);
+	int av_parse_video_frame_rate(AVRational*, char*);
+	int av_parse_video_frame_size(int*, int*, char*);
+	uint av_xiphlacing(char*, uint);
+	int av_picture_pad(AVPicture*, AVPicture*, int, int, int, int, int, int, int, int*);
+	int av_picture_crop(AVPicture*, AVPicture*, int, int, int);
+	void av_picture_copy(AVPicture*, AVPicture*, int, int, int);
+	void av_fast_malloc(void*, uint*, uint);
+	void* av_fast_realloc(void*, uint*, uint);
+	AVBitStreamFilter* av_bitstream_filter_next(AVBitStreamFilter*);
+	void av_bitstream_filter_close(AVBitStreamFilterContext*);
+	int av_bitstream_filter_filter(AVBitStreamFilterContext*, AVCodecContext*, char*, char**, int*, char*, int, int);
+	AVBitStreamFilterContext* av_bitstream_filter_init(char*);
+	void av_register_bitstream_filter(AVBitStreamFilter*);
+	void av_parser_close(AVCodecParserContext*);
+	int av_parser_change(AVCodecParserContext*, AVCodecContext*, char**, int*, char*, int, int);
+	int av_parser_parse2(AVCodecParserContext*, AVCodecContext*, char**, int*, char*, int, long, long, long);
+	int av_parser_parse(AVCodecParserContext*, AVCodecContext*, char**, int*, char*, int, long, long);
+	AVCodecParserContext* av_parser_init(int);
+	void av_register_codec_parser(AVCodecParser*);
+	AVCodecParser* av_parser_next(AVCodecParser*);
+	int av_get_bits_per_sample_format(int);
+	int av_get_bits_per_sample(int);
+	char av_get_pict_type_char(int);
+	void avcodec_default_free_buffers(AVCodecContext*);
+	void avcodec_flush_buffers(AVCodecContext*);
+	void avcodec_register_all();
+	int avcodec_close(AVCodecContext*);
+	int avcodec_encode_subtitle(AVCodecContext*, char*, int, AVSubtitle*);
+	int avcodec_encode_video(AVCodecContext*, char*, int, AVFrame*);
+	int avcodec_encode_audio(AVCodecContext*, char*, int, short*);
+	int avcodec_parse_frame(AVCodecContext*, char**, int*, char*, int);
+	int avcodec_decode_subtitle2(AVCodecContext*, AVSubtitle*, int*, AVPacket*);
+	int avcodec_decode_subtitle(AVCodecContext*, AVSubtitle*, int*, char*, int);
+	int avcodec_decode_video2(AVCodecContext*, AVFrame*, int*, AVPacket*);
+	int avcodec_decode_video(AVCodecContext*, AVFrame*, int*, char*, int);
+	int avcodec_decode_audio3(AVCodecContext*, short*, int*, AVPacket*);
+	int avcodec_decode_audio2(AVCodecContext*, short*, int*, char*, int);
+	int avcodec_open(AVCodecContext*, AVCodec*);
+	int avcodec_default_execute(AVCodecContext*, _BCD_func__1443, void*, int*, int, int);
+	int avcodec_thread_execute(AVCodecContext*, _BCD_func__1443, void*, int*, int, int);
+	void avcodec_thread_free(AVCodecContext*);
+	int avcodec_thread_init(AVCodecContext*, int);
+	int avcodec_default_get_format(AVCodecContext*, int*);
+	int avcodec_check_dimensions(void*, uint, uint);
+	void avcodec_align_dimensions(AVCodecContext*, int*, int*);
+	int avcodec_default_reget_buffer(AVCodecContext*, AVFrame*);
+	void avcodec_default_release_buffer(AVCodecContext*, AVFrame*);
+	int avcodec_default_get_buffer(AVCodecContext*, AVFrame*);
+	AVFrame* avcodec_alloc_frame();
+	void avcodec_get_frame_defaults(AVFrame*);
+	AVCodecContext* avcodec_alloc_context2(int);
+	AVCodecContext* avcodec_alloc_context();
+	void avcodec_get_context_defaults2(AVCodecContext*, int);
+	void avcodec_get_context_defaults(AVCodecContext*);
+	void avcodec_string(char*, int, AVCodecContext*, int);
+	AVCodec* avcodec_find_decoder_by_name(char*);
+	AVCodec* avcodec_find_decoder(int);
+	AVCodec* avcodec_find_encoder_by_name(char*);
+	AVCodec* avcodec_find_encoder(int);
+	void avcodec_register(AVCodec*);
+	void register_avcodec(AVCodec*);
+	void avcodec_init();
+	uint avcodec_version();
+	AVCodec* av_codec_next(AVCodec*);
+	int avpicture_deinterlace(AVPicture*, AVPicture*, int, int, int);
+	int img_get_alpha_info(AVPicture*, int, int, int);
+	void avcodec_pix_fmt_string(char*, int, int);
+	int avcodec_find_best_pix_fmt(long, int, int, int*);
+	int avcodec_get_pix_fmt_loss(int, int, int);
+	uint avcodec_pix_fmt_to_codec_tag(int);
+	int avcodec_get_pix_fmt(char*);
+	void avcodec_set_dimensions(AVCodecContext*, int, int);
+	char* avcodec_get_pix_fmt_name(int);
+	void avcodec_get_chroma_sub_sample(int, int*, int*);
+	int avpicture_get_size(int, int, int);
+	int avpicture_layout(AVPicture*, int, int, int, char*, int);
+	int avpicture_fill(AVPicture*, char*, int, int, int);
+	void avpicture_free(AVPicture*);
+	int avpicture_alloc(AVPicture*, int, int, int);
+	void av_resample_close(void*);
+	void av_resample_compensate(void*, int, int);
+	int av_resample(void*, short*, short*, int*, int, int, int);
+	void* av_resample_init(int, int, int, int, int, double);
+	void audio_resample_close(void*);
+	int audio_resample(void*, short*, short*, int);
+	void* av_audio_resample_init(int, int, int, int, int, int, int, int, int, double);
+	void* audio_resample_init(int, int, int, int);
+	void av_free_packet(AVPacket*);
+	int av_dup_packet(AVPacket*);
+	void av_shrink_packet(AVPacket*, int);
+	int av_new_packet(AVPacket*, int);
+	void av_init_packet(AVPacket*);
+	void av_destruct_packet(AVPacket*);
+	void av_destruct_packet_nofree(AVPacket*);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/libav/avformat.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,497 @@
+/* THIS FILE GENERATED BY bcd.gen */
+module hoofbaby.codec.libav.avformat;
+
+import hoofbaby.codec.libav.avutil;
+import hoofbaby.codec.libav.avcodec;
+import tango.stdc.stdio;
+
+
+enum
+{
+	LIBAVFORMAT_VERSION_MAJOR = 52,
+	LIBAVFORMAT_VERSION_MINOR = 34,
+	LIBAVFORMAT_VERSION_MICRO = 0,
+	URL_RDONLY = 0,
+	URL_WRONLY = 1,
+	URL_RDWR = 2,
+	AVSEEK_SIZE = 0x10000,
+	AV_METADATA_MATCH_CASE = 1,
+	AV_METADATA_IGNORE_SUFFIX = 2,
+	AVPROBE_SCORE_MAX = 100,
+	AVPROBE_PADDING_SIZE = 32,
+	AVFMT_NOFILE = 0x0001,
+	AVFMT_NEEDNUMBER = 0x0002,
+	AVFMT_SHOW_IDS = 0x0008,
+	AVFMT_RAWPICTURE = 0x0020,
+	AVFMT_GLOBALHEADER = 0x0040,
+	AVFMT_NOTIMESTAMPS = 0x0080,
+	AVFMT_GENERIC_INDEX = 0x0100,
+	AVFMT_TS_DISCONT = 0x0200,
+	AVFMT_VARIABLE_FPS = 0x0400,
+	AVINDEX_KEYFRAME = 0x0001,
+	AV_DISPOSITION_DEFAULT = 0x0001,
+	AV_DISPOSITION_DUB = 0x0002,
+	AV_DISPOSITION_ORIGINAL = 0x0004,
+	AV_DISPOSITION_COMMENT = 0x0008,
+	AV_DISPOSITION_LYRICS = 0x0010,
+	AV_DISPOSITION_KARAOKE = 0x0020,
+	MAX_REORDER_DELAY = 16,
+	MAX_PROBE_PACKETS = 100,
+	AV_PROGRAM_RUNNING = 1,
+	AVFMTCTX_NOHEADER = 0x0001,
+	MAX_STREAMS = 20,
+	AVFMT_NOOUTPUTLOOP = -1,
+	AVFMT_INFINITEOUTPUTLOOP = 0,
+	AVFMT_FLAG_GENPTS = 0x0001,
+	AVFMT_FLAG_IGNIDX = 0x0002,
+	AVFMT_FLAG_NONBLOCK = 0x0004,
+	FF_FDEBUG_TS = 0x0001,
+	AVSEEK_FLAG_BACKWARD = 1,
+	AVSEEK_FLAG_BYTE = 2,
+	AVSEEK_FLAG_ANY = 4,
+	FFM_PACKET_SIZE = 4096,
+}
+
+alias int AVStreamParseType;
+enum : AVStreamParseType
+{
+	AVSTREAM_PARSE_NONE = 0,
+	AVSTREAM_PARSE_FULL = 1,
+	AVSTREAM_PARSE_HEADERS = 2,
+	AVSTREAM_PARSE_TIMESTAMPS = 3,
+}
+
+alias void AVMetadata;
+alias void AVMetadataConv;
+
+struct AVPacketList
+{
+	AVPacket pkt;
+	AVPacketList* next;
+}
+
+struct AVChapter
+{
+	int id;
+	AVRational time_base;
+	long start;
+	long end;
+	char* title;
+	void* metadata;
+}
+
+struct AVProgram
+{
+	int id;
+	char* provider_name;
+	char* name;
+	int flags;
+	int discard;
+	uint* stream_index;
+	uint nb_stream_indexes;
+	void* metadata;
+}
+
+struct AVStream
+{
+	int index;
+	int id;
+	AVCodecContext* codec;
+	AVRational r_frame_rate;
+	void* priv_data;
+	long first_dts;
+	AVFrac pts;
+	AVRational time_base;
+	int pts_wrap_bits;
+	int stream_copy;
+	int discard;
+	float quality;
+	long start_time;
+	long duration;
+	char[4] language;
+	int need_parsing;
+	AVCodecParserContext* parser;
+	long cur_dts;
+	int last_IP_duration;
+	long last_IP_pts;
+	AVIndexEntry* index_entries;
+	int nb_index_entries;
+	uint index_entries_allocated_size;
+	long nb_frames;
+	long[5] unused;
+	char* filename;
+	int disposition;
+	AVProbeData probe_data;
+	long[17] pts_buffer;
+	AVRational sample_aspect_ratio;
+	void* metadata;
+	char* cur_ptr;
+	int cur_len;
+	AVPacket cur_pkt;
+	long reference_dts;
+	int probe_packets;
+}
+
+struct AVIndexEntry
+{
+	long pos;
+	long timestamp;
+	int min_distance;
+	
+	int __bitfield1;
+	int flags() { return (__bitfield1 << 30) >> 30; }
+	int flags(int value) { __bitfield1 = (__bitfield1 & 0xfffffffffffffffc) | ((value & 0x3) << 0); return value; }
+	int size() { return (__bitfield1 << 0) >> 2; }
+	int size(int value) { __bitfield1 = (__bitfield1 & 0xffffffff00000003) | ((value & 0x3fffffff) << 2); return value; }
+}
+
+struct AVInputFormat
+{
+	char* name;
+	char* long_name;
+	int priv_data_size;
+	int function(AVProbeData*) read_probe;
+	int function(AVFormatContext*, AVFormatParameters*) read_header;
+	int function(AVFormatContext*, AVPacket*) read_packet;
+	int function(AVFormatContext*) read_close;
+	int function(AVFormatContext*, int, long, int) read_seek;
+	long function(AVFormatContext*, int, long*, long) read_timestamp;
+	int flags;
+	char* extensions;
+	int value;
+	int function(AVFormatContext*) read_play;
+	int function(AVFormatContext*) read_pause;
+	void** codec_tag;
+	int function(AVFormatContext*, int, long, long, long, int) read_seek2;
+	void* metadata_conv;
+	AVInputFormat* next;
+}
+
+struct AVOutputFormat
+{
+	char* name;
+	char* long_name;
+	char* mime_type;
+	char* extensions;
+	int priv_data_size;
+	int audio_codec;
+	int video_codec;
+	int function(AVFormatContext*) write_header;
+	int function(AVFormatContext*, AVPacket*) write_packet;
+	int function(AVFormatContext*) write_trailer;
+	int flags;
+	int function(AVFormatContext*, AVFormatParameters*) set_parameters;
+	int function(AVFormatContext*, AVPacket*, AVPacket*, int) interleave_packet;
+	void** codec_tag;
+	int subtitle_codec;
+	void* metadata_conv;
+	AVOutputFormat* next;
+}
+
+struct AVFormatParameters
+{
+	AVRational time_base;
+	int sample_rate;
+	int channels;
+	int width;
+	int height;
+	PixelFormat pix_fmt;
+	int channel;
+	char* standard;
+	CodecID video_codec_id;
+	CodecID audio_codec_id;
+	
+	uint __bitfield1;
+	uint mpeg2ts_raw() { return (__bitfield1 >> 0) & 0x1; }
+	uint mpeg2ts_raw(uint value) { __bitfield1 = (__bitfield1 & 0xfffffffffffffffe) | (value << 0); return value; }
+	uint mpeg2ts_compute_pcr() { return (__bitfield1 >> 1) & 0x1; }
+	uint mpeg2ts_compute_pcr(uint value) { __bitfield1 = (__bitfield1 & 0xfffffffffffffffd) | (value << 1); return value; }
+	uint initial_pause() { return (__bitfield1 >> 2) & 0x1; }
+	uint initial_pause(uint value) { __bitfield1 = (__bitfield1 & 0xfffffffffffffffb) | (value << 2); return value; }
+	uint prealloced_context() { return (__bitfield1 >> 3) & 0x1; }
+	uint prealloced_context(uint value) { __bitfield1 = (__bitfield1 & 0xfffffffffffffff7) | (value << 3); return value; }
+}
+
+struct AVProbeData
+{
+	char* filename;
+	char* buf;
+	int buf_size;
+}
+
+struct AVFrac
+{
+	long val;
+	long num;
+	long den;
+}
+
+struct AVMetadataTag
+{
+	char* key;
+	char* value;
+}
+
+struct AVFormatContext
+{
+	AVClass* av_class;
+	AVInputFormat* iformat;
+	AVOutputFormat* oformat;
+	void* priv_data;
+	ByteIOContext* pb;
+	uint nb_streams;
+	AVStream*[20] streams;
+	char[1024] filename;
+	long timestamp;
+	char[512] title;
+	char[512] author;
+	char[512] copyright;
+	char[512] comment;
+	char[512] album;
+	int year;
+	int track;
+	char[32] genre;
+	int ctx_flags;
+	AVPacketList* packet_buffer;
+	long start_time;
+	long duration;
+	long file_size;
+	int bit_rate;
+	AVStream* cur_st;
+	char* cur_ptr_deprecated;
+	int cur_len_deprecated;
+	AVPacket cur_pkt_deprecated;
+	long data_offset;
+	int index_built;
+	int mux_rate;
+	int packet_size;
+	int preload;
+	int max_delay;
+	int loop_output;
+	int flags;
+	int loop_input;
+	uint probesize;
+	int max_analyze_duration;
+	char* key;
+	int keylen;
+	uint nb_programs;
+	AVProgram** programs;
+	int video_codec_id;
+	int audio_codec_id;
+	int subtitle_codec_id;
+	uint max_index_size;
+	uint max_picture_buffer;
+	uint nb_chapters;
+	AVChapter** chapters;
+	int debug_;
+	AVPacketList* raw_packet_buffer;
+	AVPacketList* raw_packet_buffer_end;
+	AVPacketList* packet_buffer_end;
+	void* metadata;
+}
+
+struct ByteIOContext
+{
+	char* buffer;
+	int buffer_size;
+	char* buf_ptr;
+	char* buf_end;
+	void* opaque;
+	int function(void*, char*, int) read_packet;
+	int function(void*, char*, int) write_packet;
+	long function(void*, long, int) seek;
+	long pos;
+	int must_flush;
+	int eof_reached;
+	int write_flag;
+	int is_streamed;
+	int max_packet_size;
+	uint checksum;
+	char* checksum_ptr;
+	uint function(uint, char*, uint) update_checksum;
+	int error;
+	int function(void*, int) read_pause;
+	long function(void*, int, long, int) read_seek;
+}
+
+struct URLPollEntry
+{
+	URLContext* handle;
+	int events;
+	int revents;
+}
+
+struct URLProtocol
+{
+	char* name;
+	int function(URLContext*, char*, int) url_open;
+	int function(URLContext*, char*, int) url_read;
+	int function(URLContext*, char*, int) url_write;
+	long function(URLContext*, long, int) url_seek;
+	int function(URLContext*) url_close;
+	URLProtocol* next;
+	int function(URLContext*, int) url_read_pause;
+	long function(URLContext*, int, long, int) url_read_seek;
+	int function(URLContext*) url_get_file_handle;
+}
+
+struct URLContext
+{
+	URLProtocol* prot;
+	int flags;
+	int is_streamed;
+	int max_packet_size;
+	void* priv_data;
+	char* filename;
+}
+
+extern(C)
+{
+	int avf_sdp_create(AVFormatContext**, int, char*, int);
+	int av_filename_number_test(char*);
+	int av_get_frame_filename(char*, int, char*, int);
+	int find_info_tag(char*, int, char*, char*);
+	void ffm_set_write_index(AVFormatContext*, long, long);
+	int ffm_write_write_index(int, long);
+	long ffm_read_write_index(int);
+	long av_gettime();
+	long parse_date(char*, int);
+	int parse_frame_rate(int*, int*, char*);
+	int parse_image_size(int*, int*, char*);
+	void dump_format(AVFormatContext*, int, char*, int);
+	int av_write_trailer(AVFormatContext*);
+	int av_interleave_packet_per_dts(AVFormatContext*, AVPacket*, AVPacket*, int);
+	int av_interleaved_write_frame(AVFormatContext*, AVPacket*);
+	int av_write_frame(AVFormatContext*, AVPacket*);
+	int av_write_header(AVFormatContext*);
+	int av_set_parameters(AVFormatContext*, AVFormatParameters*);
+	long av_gen_search(AVFormatContext*, int, long, long, long, long, long, long, int, long*, long function(AVFormatContext*, int, long*, long));
+	void av_update_cur_dts(AVFormatContext*, AVStream*, long);
+	int av_seek_frame_binary(AVFormatContext*, int, long, int);
+	int av_add_index_entry(AVStream*, long, long, int, int, int);
+	void ff_reduce_index(AVFormatContext*, int);
+	int av_index_search_timestamp(AVStream*, long, int);
+	int av_find_default_stream_index(AVFormatContext*);
+	void av_set_pts_info(AVStream*, int, int, int);
+	AVChapter* ff_new_chapter(AVFormatContext*, int, AVRational, long, long, char*);
+	AVProgram* av_new_program(AVFormatContext*, int);
+	AVStream* av_new_stream(AVFormatContext*, int);
+	void av_close_input_file(AVFormatContext*);
+	void av_close_input_stream(AVFormatContext*);
+	int av_read_pause(AVFormatContext*);
+	int av_read_play(AVFormatContext*);
+	int avformat_seek_file(AVFormatContext*, int, long, long, long, int);
+	int av_seek_frame(AVFormatContext*, int, long, int);
+	int av_read_frame(AVFormatContext*, AVPacket*);
+	int av_read_packet(AVFormatContext*, AVPacket*);
+	int av_find_stream_info(AVFormatContext*);
+	AVFormatContext* avformat_alloc_context();
+	AVFormatContext* av_alloc_format_context();
+	int av_open_input_file(AVFormatContext**, char*, AVInputFormat*, int, AVFormatParameters*);
+	int av_open_input_stream(AVFormatContext**, ByteIOContext*, char*, AVInputFormat*, AVFormatParameters*);
+	AVInputFormat* av_probe_input_format(AVProbeData*, int);
+	AVInputFormat* av_find_input_format(char*);
+	uint av_codec_get_tag(void**, int);
+	int av_codec_get_id(void**, uint);
+	void av_register_all();
+	void av_pkt_dump_log(void*, int, AVPacket*, int);
+	void av_pkt_dump(_iobuf*, AVPacket*, int);
+	void av_hex_dump_log(void*, int, char*, int);
+	void av_hex_dump(_iobuf*, char*, int);
+	int av_guess_codec(AVOutputFormat*, char*, char*, char*, int);
+	AVOutputFormat* guess_format(char*, char*, char*);
+	AVOutputFormat* guess_stream_format(char*, char*, char*);
+	void av_register_output_format(AVOutputFormat*);
+	void av_register_input_format(AVInputFormat*);
+	int av_guess_image2_codec(char*);
+	AVOutputFormat* av_oformat_next(AVOutputFormat*);
+	AVInputFormat* av_iformat_next(AVInputFormat*);
+	int av_get_packet(ByteIOContext*, AVPacket*, int);
+	void av_metadata_free(void**);
+	void av_metadata_conv(AVFormatContext*, void*, void*);
+	int av_metadata_set(void**, char*, char*);
+	AVMetadataTag* av_metadata_get(void*, char*, AVMetadataTag*, int);
+	int udp_get_file_handle(URLContext*);
+	int udp_get_local_port(URLContext*);
+	int udp_set_remote_url(URLContext*, char*);
+	void init_checksum(ByteIOContext*, uint function(uint, char*, uint), uint);
+	uint get_checksum(ByteIOContext*);
+	uint ff_crc04C11DB7_update(uint, char*, uint);
+	int url_close_dyn_buf(ByteIOContext*, char**);
+	int url_open_dyn_packet_buf(ByteIOContext**, int);
+	int url_open_dyn_buf(ByteIOContext**);
+	int url_close_buf(ByteIOContext*);
+	int url_open_buf(ByteIOContext**, char*, int, int);
+	int url_fget_max_packet_size(ByteIOContext*);
+	URLContext* url_fileno(ByteIOContext*);
+	int url_fclose(ByteIOContext*);
+	int url_fopen(ByteIOContext**, char*, int);
+	int url_resetbuf(ByteIOContext*, int);
+	int url_setbufsize(ByteIOContext*, int);
+	int url_fdopen(ByteIOContext**, URLContext*);
+	int url_is_streamed(ByteIOContext*);
+	ulong ff_get_v(ByteIOContext*);
+	ulong get_be64(ByteIOContext*);
+	uint get_be32(ByteIOContext*);
+	uint get_be24(ByteIOContext*);
+	uint get_be16(ByteIOContext*);
+	char* get_strz(ByteIOContext*, char*, int);
+	uint get_le16(ByteIOContext*);
+	ulong get_le64(ByteIOContext*);
+	uint get_le32(ByteIOContext*);
+	uint get_le24(ByteIOContext*);
+	int get_byte(ByteIOContext*);
+	int get_partial_buffer(ByteIOContext*, char*, int);
+	int get_buffer(ByteIOContext*, char*, int);
+	void put_flush_packet(ByteIOContext*);
+	char* url_fgets(ByteIOContext*, char*, int);
+	int url_fprintf(ByteIOContext*, char*, ...);
+	int url_fgetc(ByteIOContext*);
+	long av_url_read_fseek(ByteIOContext*, int, long, int);
+	int av_url_read_fpause(ByteIOContext*, int);
+	int url_ferror(ByteIOContext*);
+	int url_feof(ByteIOContext*);
+	long url_fsize(ByteIOContext*);
+	long url_ftell(ByteIOContext*);
+	void url_fskip(ByteIOContext*, long);
+	long url_fseek(ByteIOContext*, long, int);
+	void put_strz(ByteIOContext*, char*);
+	void put_tag(ByteIOContext*, char*);
+	void put_be16(ByteIOContext*, uint);
+	void put_le16(ByteIOContext*, uint);
+	void put_be24(ByteIOContext*, uint);
+	void put_le24(ByteIOContext*, uint);
+	void put_be32(ByteIOContext*, uint);
+	void put_le32(ByteIOContext*, uint);
+	void put_be64(ByteIOContext*, ulong);
+	void put_le64(ByteIOContext*, ulong);
+	void put_buffer(ByteIOContext*, char*, int);
+	void put_byte(ByteIOContext*, int);
+	ByteIOContext* av_alloc_put_byte(char*, int, int, void*, int function(void*, char*, int), int function(void*, char*, int), long function(void*, long, int));
+	int init_put_byte(ByteIOContext*, char*, int, int, void*, int function(void*, char*, int), int function(void*, char*, int), long function(void*, long, int));
+	int av_register_protocol(URLProtocol*);
+	int register_protocol(URLProtocol*);
+	URLProtocol* av_protocol_next(URLProtocol*);
+	long av_url_read_seek(URLContext*, int, long, int);
+	int av_url_read_pause(URLContext*, int);
+	int url_poll(URLPollEntry*, int, int);
+	void url_set_interrupt_cb(int function());
+	void url_get_filename(URLContext*, char*, int);
+	int url_get_max_packet_size(URLContext*);
+	int url_get_file_handle(URLContext*);
+	long url_filesize(URLContext*);
+	int url_exist(char*);
+	int url_close(URLContext*);
+	long url_seek(URLContext*, long, int);
+	int url_write(URLContext*, char*, int);
+	int url_read_complete(URLContext*, char*, int);
+	int url_read(URLContext*, char*, int);
+	int url_open(URLContext**, char*, int);
+	int url_open_protocol(URLContext**, URLProtocol*, char*, int);
+	uint avformat_version();
+	
+	extern AVOutputFormat* first_oformat;
+	extern AVInputFormat* first_iformat;
+	extern int function() url_interrupt_cb;
+	extern URLProtocol* first_protocol;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/libav/avutil.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,160 @@
+/* THIS FILE GENERATED BY bcd.gen */
+module hoofbaby.codec.libav.avutil;
+
+enum
+{
+	LIBAVUTIL_VERSION_MAJOR = 50,
+	LIBAVUTIL_VERSION_MINOR = 3,
+	LIBAVUTIL_VERSION_MICRO = 0,
+	AV_LOG_QUIET = -8,
+	AV_LOG_PANIC = 0,
+	AV_LOG_FATAL = 8,
+	AV_LOG_ERROR = 16,
+	AV_LOG_WARNING = 24,
+	AV_LOG_INFO = 32,
+	AV_LOG_VERBOSE = 40,
+	AV_LOG_DEBUG = 48,
+}
+
+alias int PixelFormat;
+enum : PixelFormat
+{
+	PIX_FMT_NONE = -1,
+	PIX_FMT_YUV420P = 0,
+	PIX_FMT_YUYV422 = 1,
+	PIX_FMT_RGB24 = 2,
+	PIX_FMT_BGR24 = 3,
+	PIX_FMT_YUV422P = 4,
+	PIX_FMT_YUV444P = 5,
+	PIX_FMT_YUV410P = 6,
+	PIX_FMT_YUV411P = 7,
+	PIX_FMT_GRAY8 = 8,
+	PIX_FMT_MONOWHITE = 9,
+	PIX_FMT_MONOBLACK = 10,
+	PIX_FMT_PAL8 = 11,
+	PIX_FMT_YUVJ420P = 12,
+	PIX_FMT_YUVJ422P = 13,
+	PIX_FMT_YUVJ444P = 14,
+	PIX_FMT_XVMC_MPEG2_MC = 15,
+	PIX_FMT_XVMC_MPEG2_IDCT = 16,
+	PIX_FMT_UYVY422 = 17,
+	PIX_FMT_UYYVYY411 = 18,
+	PIX_FMT_BGR8 = 19,
+	PIX_FMT_BGR4 = 20,
+	PIX_FMT_BGR4_BYTE = 21,
+	PIX_FMT_RGB8 = 22,
+	PIX_FMT_RGB4 = 23,
+	PIX_FMT_RGB4_BYTE = 24,
+	PIX_FMT_NV12 = 25,
+	PIX_FMT_NV21 = 26,
+	PIX_FMT_ARGB = 27,
+	PIX_FMT_RGBA = 28,
+	PIX_FMT_ABGR = 29,
+	PIX_FMT_BGRA = 30,
+	PIX_FMT_GRAY16BE = 31,
+	PIX_FMT_GRAY16LE = 32,
+	PIX_FMT_YUV440P = 33,
+	PIX_FMT_YUVJ440P = 34,
+	PIX_FMT_YUVA420P = 35,
+	PIX_FMT_VDPAU_H264 = 36,
+	PIX_FMT_VDPAU_MPEG1 = 37,
+	PIX_FMT_VDPAU_MPEG2 = 38,
+	PIX_FMT_VDPAU_WMV3 = 39,
+	PIX_FMT_VDPAU_VC1 = 40,
+	PIX_FMT_RGB48BE = 41,
+	PIX_FMT_RGB48LE = 42,
+	PIX_FMT_RGB565BE = 43,
+	PIX_FMT_RGB565LE = 44,
+	PIX_FMT_RGB555BE = 45,
+	PIX_FMT_RGB555LE = 46,
+	PIX_FMT_BGR565BE = 47,
+	PIX_FMT_BGR565LE = 48,
+	PIX_FMT_BGR555BE = 49,
+	PIX_FMT_BGR555LE = 50,
+	PIX_FMT_VAAPI_MOCO = 51,
+	PIX_FMT_VAAPI_IDCT = 52,
+	PIX_FMT_VAAPI_VLD = 53,
+	PIX_FMT_YUV420PLE = 54,
+	PIX_FMT_YUV420PBE = 55,
+	PIX_FMT_YUV422PLE = 56,
+	PIX_FMT_YUV422PBE = 57,
+	PIX_FMT_YUV444PLE = 58,
+	PIX_FMT_YUV444PBE = 59,
+	PIX_FMT_NB = 60,
+}
+
+alias char* function(void*) _BCD_func__901;
+alias void function(void*, int, char*, char*) _BCD_func__880;
+alias int function() _BCD_func__823;
+
+alias int AVRounding;
+enum : AVRounding
+{
+	AV_ROUND_ZERO = 0,
+	AV_ROUND_INF = 1,
+	AV_ROUND_DOWN = 2,
+	AV_ROUND_UP = 3,
+	AV_ROUND_NEAR_INF = 5,
+}
+
+struct AVClass
+{
+	char* class_name;
+	_BCD_func__901 item_name;
+	void* option;
+}
+
+struct AVExtFloat
+{
+	char[2] exponent;
+	char[8] mantissa;
+}
+
+struct AVRational
+{
+	int num;
+	int den;
+}
+
+extern(C)
+{
+	void av_log_default_callback(void*, int, char*, char*);
+	void av_log_set_callback(_BCD_func__880);
+	void av_log_set_level(int);
+	int av_log_get_level();
+	void av_vlog(void*, int, char*, char*);
+	void av_log(void*, int, char*, ...);
+	AVExtFloat av_dbl2ext(double);
+	int av_flt2int(float);
+	long av_dbl2int(double);
+	double av_ext2dbl(AVExtFloat);
+	float av_int2flt(int);
+	double av_int2dbl(long);
+	long av_rescale_q(long, AVRational, AVRational);
+	long av_rescale_rnd(long, long, long, int);
+	long av_rescale(long, long, long);
+	long av_gcd(long, long);
+	int av_find_nearest_q_idx(AVRational, AVRational*);
+	int av_nearer_q(AVRational, AVRational, AVRational);
+	AVRational av_d2q(double, int);
+	AVRational av_sub_q(AVRational, AVRational);
+	AVRational av_add_q(AVRational, AVRational);
+	AVRational av_div_q(AVRational, AVRational);
+	AVRational av_mul_q(AVRational, AVRational);
+	int av_reduce(int*, int*, long, long, long);
+	double av_q2d(AVRational);
+	int av_cmp_q(AVRational, AVRational);
+	void av_freep(void*);
+	char* av_strdup(char*);
+	void* av_mallocz(uint);
+	void av_free(void*);
+	void* av_realloc(void*, uint);
+	void* av_malloc(uint);
+	float av_clipf(float, float, float);
+	short av_clip_int16(int);
+	char av_clip_uint8(int);
+	int av_clip(int, int, int);
+	int av_log2_16bit(uint);
+	int av_log2(uint);
+	uint avutil_version();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/libav/mingw.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,68 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.codec.libav.mingw;
+
+import tango.stdc.stdlib;
+import tango.stdc.math;
+import tango.stdc.ctype;
+import tango.stdc.stdio;
+import tango.stdc.stdarg;
+import tango.sys.win32.UserGdi;
+
+// Some implementations of MinGW/libc functions required to link with libav*
+
+extern(C) double __strtod(in char* nptr, char** endptr) { return strtod(nptr, endptr); }
+extern(C) uint __fpclassifyf(float x) { return __fpclassify_f(x); }
+extern(C) int __mingw_vfprintf(FILE* stream, char* format, va_list va) { return vfprintf(stream, format, va); }
+extern(C) long _lseeki64(HFILE handle, long offset, int whence) { return _llseek(handle, offset, whence); }
+
+extern(C) int strcasecmp(char* s1, char* s2)
+{
+	while(toupper(*s1) == toupper(*s2))
+	{
+		if(*s1 == '\0')
+			return 0;
+		s1++;
+		s2++;
+	}
+	return toupper(*s1) - toupper(*s2);
+}
+
+extern(C) int strncasecmp(char* s1, char* s2, size_t n)
+{
+	while(toupper(*s1) == toupper(*s2))
+	{
+		if(--n == 0 || *s1 == '\0')
+			return 0;
+		s1++;
+		s2++;
+	}
+	return toupper(*s1) - toupper(*s2);
+}
+
+// This isn't extern(C) in Tango for some odd reason
+extern(C) int snprintf(char* s, size_t n, char* fmt, ...)
+{
+	va_list va;
+	va_start(va, fmt);
+	return _vsnprintf(s, n, fmt, va);
+	va_end(va);
+}
+
+// TODO -- too lazy to implement these until I'm sure they're needed
+extern(C) int gettimeofday(void* tp, void* tz) { assert(false); }
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/libav/swscale.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,89 @@
+/* THIS FILE GENERATED BY bcd.gen */
+module hoofbaby.codec.libav.swscale;
+
+import hoofbaby.codec.libav.avutil;
+
+enum
+{
+	LIBSWSCALE_VERSION_MAJOR = 0,
+	LIBSWSCALE_VERSION_MINOR = 7,
+	LIBSWSCALE_VERSION_MICRO = 1,
+	SWS_FAST_BILINEAR = 1,
+	SWS_BILINEAR = 2,
+	SWS_BICUBIC = 4,
+	SWS_X = 8,
+	SWS_POINT = 0x10,
+	SWS_AREA = 0x20,
+	SWS_BICUBLIN = 0x40,
+	SWS_GAUSS = 0x80,
+	SWS_SINC = 0x100,
+	SWS_LANCZOS = 0x200,
+	SWS_SPLINE = 0x400,
+	SWS_SRC_V_CHR_DROP_MASK = 0x30000,
+	SWS_SRC_V_CHR_DROP_SHIFT = 16,
+	SWS_PARAM_DEFAULT = 123456,
+	SWS_PRINT_INFO = 0x1000,
+	SWS_FULL_CHR_H_INT = 0x2000,
+	SWS_FULL_CHR_H_INP = 0x4000,
+	SWS_DIRECT_BGR = 0x8000,
+	SWS_ACCURATE_RND = 0x40000,
+	SWS_BITEXACT = 0x80000,
+	SWS_CPU_CAPS_MMX = 0x80000000,
+	SWS_CPU_CAPS_MMX2 = 0x20000000,
+	SWS_CPU_CAPS_3DNOW = 0x40000000,
+	SWS_CPU_CAPS_ALTIVEC = 0x10000000,
+	SWS_CPU_CAPS_BFIN = 0x01000000,
+	SWS_CS_ITU709 = 1,
+	SWS_CS_FCC = 4,
+	SWS_CS_ITU601 = 5,
+	SWS_CS_ITU624 = 5,
+	SWS_CS_SMPTE170M = 5,
+	SWS_CS_SMPTE240M = 7,
+	SWS_CS_DEFAULT = 5,
+}
+
+const double SWS_MAX_REDUCE_CUTOFF = 0.002;
+typedef void SwsContext;
+
+alias int function() _BCD_func__867;
+
+struct SwsFilter
+{
+	SwsVector* lumH;
+	SwsVector* lumV;
+	SwsVector* chrH;
+	SwsVector* chrV;
+}
+
+struct SwsVector
+{
+	double* coeff;
+	int length;
+}
+
+extern(C)
+{
+	SwsContext* sws_getCachedContext(SwsContext*, int, int, int, int, int, int, int, SwsFilter*, SwsFilter*, double*);
+	void sws_freeFilter(SwsFilter*);
+	SwsFilter* sws_getDefaultFilter(float, float, float, float, float, float, int);
+	void sws_freeVec(SwsVector*);
+	void sws_printVec2(SwsVector*, AVCLASS*, int);
+	void sws_printVec(SwsVector*);
+	SwsVector* sws_cloneVec(SwsVector*);
+	void sws_shiftVec(SwsVector*, int);
+	void sws_subVec(SwsVector*, SwsVector*);
+	void sws_addVec(SwsVector*, SwsVector*);
+	void sws_convVec(SwsVector*, SwsVector*);
+	void sws_normalizeVec(SwsVector*, double);
+	void sws_scaleVec(SwsVector*, double);
+	SwsVector* sws_getIdentityVec();
+	SwsVector* sws_getConstVec(double, int);
+	SwsVector* sws_getGaussianVec(double, double);
+	int sws_getColorspaceDetails(SwsContext*, int**, int*, int**, int*, int*, int*, int*);
+	int sws_setColorspaceDetails(SwsContext*, int*, int, int*, int, int, int, int);
+	int sws_scale_ordered(SwsContext*, char**, int*, int, int, char**, int*);
+	int sws_scale(SwsContext*, char**, int*, int, int, char**, int*);
+	SwsContext* sws_getContext(int, int, int, int, int, int, int, SwsFilter*, SwsFilter*, double*);
+	void sws_freeContext(SwsContext*);
+	uint swscale_version();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/platinum/platif.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,24 @@
+#line 1 "C:/d/workspace/hoofbaby/src/platif/platif.h"
+#line 18 "C:/d/workspace/hoofbaby/src/platif/platif.h"
+#line 1 "../dtypes.h"
+#line 19 "C:/d/workspace/hoofbaby/src/platif/platif.h"
+
+
+module hoofbaby.platinum.platif;
+import hoofbaby.util.sharedlib;
+
+
+struct Hoofbaby
+{
+	int (*Stream_New)(void**);
+	int (*Stream_Read)(void*, void*,  uint ,  uint *);
+	int (*Stream_Seek)(void*,  ulong );
+	int (*Stream_Tell)(void*,  ulong *);
+	int (*Stream_GetSize)(void*,  ulong *);
+	int (*Stream_GetAvailable)(void*,  ulong *);
+};
+
+mixin(shared_mixin("platif", [
+	"void function (Hoofbaby* interf)" , "initHoofbaby",
+	"int function ( char* path)" , "startServer",
+"", ""]));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/array.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,232 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.array;
+
+import tango.core.BitManip : bsr;
+import tango.core.Traits : isReferenceType;
+import tango.core.Memory : GC;
+import tango.stdc.string : memcpy, memset;
+
+
+public struct Array(T, size_t START_SIZE = 16, bool doScan = isReferenceType!(T),
+                    alias Realloc = GC.realloc, alias Free = GC.free)
+{
+	T* arr = null;
+	size_t len = 0;
+	size_t cap = 0;
+	
+	public void opCatAssign(T v)
+	{
+		len++;
+		if(len >= cap)
+			grow(cap ? cap * 2 : START_SIZE);
+		arr[len - 1] = v;
+	}
+	
+	public void opCatAssign(T[] v)
+	{
+		int newlen = len + v.length;
+		if(newlen > cap)
+		{
+			if(newlen < START_SIZE)
+				grow(START_SIZE);
+			else
+				grow(2 << bsr(newlen + 1)); // Next power of 2
+		}
+		memcpy(arr + len, v.ptr, (newlen - len) * T.sizeof);
+		len = newlen;
+	}
+	
+	public void opCatAssign(Array!(T) v)
+	{
+		opCatAssign(v.toArray());
+	}
+	
+	public T[] toArray()
+	{
+		return arr[0 .. len];
+	}
+	
+	public size_t length()
+	{
+		return len;
+	}
+	
+	public T opIndex(size_t n)
+	{
+		assert(n < len);
+		return arr[n];
+	}
+
+	public void opIndexAssign(T v, size_t n)
+	{
+		assert(n < len);
+		arr[n] = v;
+	}
+	
+	public T[] opSlice()
+	{
+		return toArray();
+	}
+	
+	public T[] opSlice(size_t low, size_t high)
+	{
+		assert(low <= high);
+		assert(high < len);
+		return arr[low .. high];
+	}
+	
+	public void opSliceAssign(T v)
+	{
+		arr[0 .. len] = v;
+	}
+	
+	public void opSliceAssign(T v, size_t low, size_t high)
+	{
+		assert(low <= high);
+		assert(high < len);
+		arr[low .. high] = v;
+	}
+	
+	public void opSliceAssign(T[] v, size_t low, size_t high)
+	{
+		assert(low <= high);
+		assert(high < len);
+		assert(v.length == high - low);
+		memcpy(arr + low, v.ptr, v.length * T.sizeof);
+	}
+	
+	public void opSliceAssign(Array!(T) v, size_t low, size_t high)
+	{
+		opSliceAssign(v.toArray(), low, high);
+	}
+	
+	public bool isEmpty()
+	{
+		return len == 0;
+	}
+	
+	public void clear()
+	{
+		len = 0;
+	}
+	
+	public void free()
+	{
+		if(arr)
+		{
+			Free(arr);
+			arr = null;
+		}
+		len = 0;
+	}
+	
+	public void zero()
+	{
+		if(arr)
+		{
+			memset(arr, 0, cap * T.sizeof);
+			Free(arr);
+			arr = null;
+		}
+		len = 0;
+	}
+	
+	public void addNull()
+	{
+		len++;
+		if(len >= cap)
+			grow(cap ? cap * 2 : START_SIZE);
+	}
+	
+	public bool contains(T elem)
+	{
+		for(int i = 0; i < len; i++)
+			if(arr[i] == elem)
+				return true;
+		return false;
+	}
+	
+	static if(doScan)
+		private static const BlkAttr = 0;
+	else
+		private static const BlkAttr = GC.BlkAttr.NO_SCAN;
+	
+	private void grow(size_t sz)
+	{
+		arr = cast(T*) Realloc(arr, sz * T.sizeof, BlkAttr);
+		static if(doScan)
+		{
+			memset(arr + cap, 0, (sz - cap) * T.sizeof); 
+		}
+		cap = sz;
+	}
+}
+
+public struct Stack(T, size_t START_SIZE = 16, bool doScan = true, bool zeroOnPop = false,
+                    alias ArrayType = Array, ArrayArgs...)
+{
+	private ArrayType!(T, START_SIZE, doScan, ArrayArgs) arr;
+	
+	public void pushNull()
+	{
+		arr.addNull();
+	}
+	
+	public void push(T v)
+	{
+		arr ~= v;
+	}
+
+	public T pop()
+	{
+		assert(arr.len > 0);
+		T ret = arr.arr[arr.len - 1];
+		static if(zeroOnPop)
+			arr.arr[arr.len - 1] = T.init;
+		arr.len--;
+		return ret;
+	}
+	
+	public T peek()
+	{
+		assert(arr.len > 0);
+		return arr.arr[arr.len - 1];
+	}
+	
+	public bool isEmpty()
+	{
+		return arr.isEmpty();
+	}
+	
+	public void clear()
+	{
+		static if(zeroOnPop)
+			arr.zero();
+		else
+			arr.clear();
+	}
+	
+	public bool contains(T elem)
+	{
+		return arr.contains(elem);
+	}
+	
+	public T[] toArray()
+	{
+		return arr.toArray();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/buffer.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,244 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.buffer;
+
+import tango.time.StopWatch;
+import tango.core.sync.Condition;
+import tango.core.sync.Mutex;
+
+version(Windows)
+{
+	import tango.stdc.stringz;
+	import tango.text.convert.Format;
+	import tango.sys.win32.UserGdi;
+	
+	import hoofbaby.util.exception;
+
+	private extern(Windows)
+	{
+		HANDLE CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCTSTR);
+		LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD);
+		LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress);
+		BOOL UnmapViewOfFile(LPCVOID);
+	}
+	
+	private uint bufNum = 0;
+	
+	/**
+	 * Allocates a buffer of the given size. ALl accesses up to buf + (size * 2)
+	 * are valid; those over buf + size will reach around
+	 * 
+	 * Params:
+	 *     size = The size of the buffer (must be multiple of page size; use large powers of two)
+	 * Returns: A pointer to the beginning of that memory
+	 */
+	private void* _allocBuffer(uint size)
+	{
+		// Ensure page file is the right size
+		SYSTEM_INFO info;
+		GetSystemInfo(&info);
+		uint pageSize = info.dwAllocationGranularity;
+		if(size % pageSize) // PERHAPS next multiple of instead of error?
+			throw new IllegalOperationException(Format("Memory map pagefile mismatch -- "
+					"requested {0}, but page size is {1}", size, pageSize));
+		
+		// Try to allocate the buffer
+		HANDLE mmap = CreateFileMappingA(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, size, null);
+		if(!mmap) throw new UnrecoverableException("Could not create memory mapping for buffer");
+		void* buf = MapViewOfFile(mmap, FILE_MAP_ALL_ACCESS, 0, 0, size);
+		if(!buf) throw new UnrecoverableException("Could not map view of buffer");
+		void* buf2 = MapViewOfFileEx(mmap, FILE_MAP_ALL_ACCESS, 0, 0, size, buf + size);
+		if(!buf2) throw new UnrecoverableException("Could not map second view of buffer");
+		if(buf2 != buf + size) throw new UnrecoverableException("Memory mapped buffers are not contiguous");
+		return buf;
+	}
+	
+	private void _freeBuffer(void* buffer, uint size)
+	{
+		UnmapViewOfFile(buffer);
+		UnmapViewOfFile(buffer + size);
+	}
+}
+else
+{
+	static assert(false, "Unsupported operating system");
+}
+
+// IMPORTANT synchronization!!!!
+public struct RingBuffer
+{
+	private const double WAIT_TIME = 0.01; // 10 ms
+	private static Condition NULL_CONDITION;
+	
+	private uint size;
+	private void* addr;
+	
+	private uint readOfs;
+	private uint writeOfs;
+	
+	/**
+	 * The callback function to be called upon an overflow or underflow.
+	 * 
+	 * Params:
+	 *     buffer = The RIngBuffer instance with the issue
+	 *     sizeRequested = the size the operation requested
+	 *     sizeAvailable = how much is actually there
+	 * Returns: true if the function should return null, false if the buffer should still
+	 *          return the requested pointer (i.e. if the function waited until something
+	 *          was available)
+	 */
+	public alias bool delegate(RingBuffer* buffer, uint sizeRequested, uint sizeAvialbale) BufferCallback;
+	public BufferCallback onUnderflow;
+	public BufferCallback onOverflow;
+	
+	debug(AVBuffer)
+	{
+		private uint readRequested = 0;
+		private uint writeRequested = 0;
+	}
+	
+	public static RingBuffer opCall(uint size)
+	{
+		// Not really a singleton; who cares if more than one is constructed?
+		if(!NULL_CONDITION)
+			NULL_CONDITION = new Condition(new Mutex());
+		
+		RingBuffer r;
+		assert(size > 0);
+		r.size = size;
+		r.addr = _allocBuffer(size);
+		return r;
+	}
+	
+	public void free()
+	{
+		_freeBuffer(addr, size);
+		addr = null;
+	}
+	
+	public void* beginRead(uint requested)
+	{
+		debug(AVBuffer)
+		{
+			assert(readRequested == 0);
+			readRequested = requested;
+		}
+		
+		if(requested > available)
+		{
+			if(!onUnderflow || onUnderflow(this, requested, available))
+			{
+				debug(AVBuffer) readRequested = 0;
+				return null;
+			}
+		}
+		
+		return addr + readOfs;
+	}
+	
+	public void endRead(uint bytes)
+	{
+		debug(AVBuffer)
+		{
+			assert(bytes == readRequested);
+			readRequested = 0;
+		}
+		
+		readOfs += bytes;
+		if(readOfs > size)
+		{
+			readOfs -= bytes;
+			writeOfs -= bytes;
+		}
+	}
+	
+	public void* beginWrite(uint requested)
+	{
+		debug(AVBuffer)
+		{
+			assert(writeRequested == 0);
+			writeRequested = requested;
+		}
+		
+		if(requested > freeSpace)
+		{
+			if(!onOverflow || onOverflow(this, requested, available))
+			{
+				return null;
+			}
+		}
+		
+		return addr + writeOfs;
+	}
+
+	public void endWrite(uint bytes)
+	{
+		debug(AVBuffer)
+		{
+			assert(bytes == writeRequested);
+			writeRequested = 0;
+		}
+		
+		writeOfs += bytes;
+	}
+	
+	public uint available()
+	{
+		return writeOfs - readOfs;
+	}
+	
+	public uint freeSpace()
+	{
+		return size - available();
+	}
+	
+	public uint totalSize()
+	{
+		return size;
+	}
+	
+	public void clear()
+	{
+		readOfs = 0;
+		writeOfs = 0;
+	}
+	
+	public void isEmpty()
+	{
+		return readOfs == writeOfs;
+	}
+	
+	private bool _waitFor(char[] exp)(uint bytes, uint timeoutMs, Condition cond = null)
+	{
+		if(!cond)
+			cond = NULL_CONDITION;
+		
+		ulong microsecs = timeoutMs * 1000;
+		StopWatch sw;
+		sw.start();
+		do
+		{
+			if(mixin(exp) >= bytes)
+				return true;
+			if(cond.wait(WAIT_TIME))
+				return false;
+		} while(sw.microsec() < microsecs);
+		return false;
+	}
+	
+	public alias _waitFor!("available") waitAvailable;
+	public alias _waitFor!("freeSpace") waitFreeSpace;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/conv.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,46 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.conv;
+
+//------------------------------------------------------------------------------
+// Fast casting
+
+/**
+ * Cast without a typecheck. Use only if you're certain T is actually a U.
+ * 
+ * Params:
+ *     v = The value to cast from
+ * Returns: v as a T
+ */
+public T as(T, U)(U v)
+{
+	static assert(is(T : U));
+	return cast(T) (cast(void*) v);
+}
+
+public T checkedCast(T, U)(U v)
+{
+	static assert(is(T : U));
+	if(v is null)
+		return null;
+	T ret = cast(T) v;
+	assert(ret !is null, "Expected " ~ T.stringof ~ ", but got " ~ v.classinfo.name);
+	return ret;
+}
+
+//------------------------------------------------------------------------------
+// Mixin generation
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/exception.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,52 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.exception;
+
+import tango.core.Exception;
+
+public class NotImplementedException : Exception
+{
+	public this(char[] msg)
+	{
+		super(msg);
+	}
+	
+	public this()
+	{
+		this("Not implemented");
+	}
+}
+
+public class IllegalOperationException : Exception
+{
+	public this(char[] msg)
+	{
+		super(msg);
+	}
+	
+	public this()
+	{
+		this("Illegal operation");
+	}
+}
+
+public class UnrecoverableException : Exception
+{
+	public this(char[] msg)
+	{
+		super(msg);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/memory.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,96 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.memory;
+
+import tango.core.Memory : GC;
+import candy.util.array;
+
+/**
+ * Provides a pool of GCed memory to allocate things from a block.
+ * This maintains cache coherency for related types (i.e. tree nodes).
+ * It doesn't garuntee any ordering, though, the array struct should be
+ * used for that. Also, everything has to be freed at once, freeing one
+ * portion of this has no effect.
+ * 
+ * Based on a similar concept posted by bearophile at: 
+ * http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=88227
+ */
+public struct MemPool(size_t BLOCK_SIZE = 1 << 14)
+{
+    private void* next; // Next available block
+    private void* end;  // End of the current block
+    private void*[] blocks;
+    
+    public void* alloc(size_t sz)
+    {
+    	sz = ((sz + 7) & ~7); // Next multiple of 8 if this isn't a multiple of 8
+    	if (this.next + sz >= this.end)
+    	{
+    		void* blk = GC.calloc(BLOCK_SIZE);
+    		this.blocks.length = this.blocks.length + 1;
+    		this.blocks[$ - 1] = blk;
+    		this.next = blk;
+    		this.end = blk + BLOCK_SIZE;
+        }
+        
+        void* ret = this.next;
+        this.next += sz;
+        return ret;
+    }
+    
+    public void free()
+    {
+    	foreach(blk; this.blocks)
+    		GC.free(blk);
+    	this.blocks = null;
+    	this.blocks.length = 0;
+    	this.next = null;
+    	this.end = null;
+    }
+}
+
+/**
+ * Wrapper for MemPool that allocates the given struct
+ */
+public struct StructPool(T)
+{
+	private MemPool!() pool;
+	public T* alloc()  { return cast(T*) pool.alloc(T.sizeof); }
+}
+
+public struct MemStack(size_t BLOCK_SIZE = 1 << 14)
+{
+	private Stack!(MemPool!(BLOCK_SIZE)*, 16, true, true) stack;
+	public static const size_t MAX_ALLOC = BLOCK_SIZE;
+	
+	public void* alloc(size_t sz) { return stack.peek().alloc(sz);          }
+	public void  push()           { stack.push(new MemPool!(BLOCK_SIZE));   }
+	public void  pop()            { stack.pop().free();                     }
+}
+
+/**
+ * Placement new mixin for allocating from a memory pool. Benchmarks show this
+ * as faster than the D new in real usage (i.e. the parser runs about 1.2x
+ * faster using this).
+ */
+public template MemPoolNew(alias Pool)
+{
+	version(NoMemPool) { } else
+	{
+		public final new(uint sz)    { return Pool.alloc(sz); }
+		public final delete(void *p) {                        }
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/meta.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,64 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.meta;
+
+public char[] ctfeItoa(int n)
+{
+	bool neg = false;
+	char[] r;
+	if (n < 0)
+	{
+		n = -n;
+		neg = true;
+	}
+	do
+	{
+		r = cast(char)('0' + (n % 10)) ~ r;
+	} while ((n /= 10) > 0);
+	if(neg)
+		r = '-' ~ r;
+	return r;
+}
+
+public bool ctfeStartsWith(char[] haystack, char[] needle)
+{
+	for(int i = 0; i < needle.length; i++)
+	{
+		if(i >= haystack.length || haystack[i] != needle[i])
+			return false;
+	}
+	return true;
+}
+
+public char[] ctfeReplace(char[] text, char[] search, char[] rep)
+{
+	char[] r;
+	int slen = search.length;
+	int tlen = text.length - slen + 1;
+	int lendiff = rep.length - slen;
+	int i = 0;
+	int j = 0;
+	for(i = 0; i < tlen; i++)
+	{
+		if(text[i .. i + slen] == search)
+		{
+			r ~= text[j .. i] ~ rep;
+			i = j = i + slen;
+		}
+	}
+	r ~= text[j .. $];
+	return r;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/redblack.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,937 @@
+/*******************************************************************************
+		
+		(this module taken from tango.util.container.RedBlack, since that
+		 module is package-protected)
+		
+        copyright:      Copyright (c) 2008 Kris Bell. All rights reserved
+
+        license:        BSD style: $(LICENSE)
+
+        version:        Apr 2008: Initial release
+
+        authors:        Kris, tsalm
+
+        Since:          0.99.7
+
+        Based upon Doug Lea's Java collection package
+
+*******************************************************************************/
+
+module candy.util.redblack;
+
+template Compare (V) { alias int function (ref V a, ref V b) Compare; }
+
+private typedef int AttributeDummy;
+
+/*******************************************************************************
+
+        RedBlack implements basic capabilities of Red-Black trees,
+        an efficient kind of balanced binary tree. The particular
+        algorithms used are adaptations of those in Corman,
+        Lieserson, and Rivest's <EM>Introduction to Algorithms</EM>.
+        This class was inspired by (and code cross-checked with) a 
+        similar class by Chuck McManis. The implementations of
+        rebalancings during insertion and deletion are
+        a little trickier than those versions since they
+        don't swap Cell contents or use special dummy nilnodes. 
+
+        Doug Lea
+
+*******************************************************************************/
+
+struct RedBlack (V, A = AttributeDummy)
+{
+        alias RedBlack!(V, A) Type;
+        alias Type            *Ref;
+
+        enum : bool {RED = false, BLACK = true}
+
+        /**
+         * Pointer to left child
+        **/
+
+        package Ref     left;
+
+        /**
+         * Pointer to right child
+        **/
+
+        package Ref     right;
+
+        /**
+         * Pointer to parent (null if root)
+        **/
+
+        package Ref     parent;
+
+        package V       value;
+
+        static if (!is(typeof(A) == AttributeDummy))
+        {
+               A        attribute;
+        }
+
+        /**
+         * The node color (RED, BLACK)
+        **/
+
+        package bool    color;
+
+        static if (!is(typeof(A) == AttributeDummy))
+        {
+                final Ref set (V v, A a)
+                {
+                        attribute = a;
+                        return set (v);
+                }
+        }
+
+        /**
+         * Make a new Cell with given value, null links, and BLACK color.
+         * Normally only called to establish a new root.
+        **/
+
+        final Ref set (V v)
+        {
+                value = v;
+                left = null;
+                right = null;
+                parent = null;
+                color = BLACK;
+                return this;
+        }
+
+        /**
+         * Return a new Ref with same value and color as self,
+         * but with null links. (Since it is never OK to have
+         * multiple identical links in a RB tree.)
+        **/ 
+
+        protected Ref dup (Ref delegate() alloc)
+        {
+                static if (is(typeof(A) == AttributeDummy))
+                           auto t = alloc().set (value);
+                       else
+                          auto t = alloc().set (value, attribute);
+
+                t.color = color;
+                return t;
+        }
+
+
+        /**
+         * See_Also: tango.util.collection.model.View.View.checkImplementation.
+        **/
+        public void checkImplementation ()
+        {
+
+                // It's too hard to check the property that every simple
+                // path from node to leaf has same number of black nodes.
+                // So restrict to the following
+
+                assert(parent is null ||
+                       this is parent.left ||
+                       this is parent.right);
+
+                assert(left is null ||
+                       this is left.parent);
+
+                assert(right is null ||
+                       this is right.parent);
+
+                assert(color is BLACK ||
+                       (colorOf(left) is BLACK) && (colorOf(right) is BLACK));
+
+                if (left !is null)
+                        left.checkImplementation();
+                if (right !is null)
+                        right.checkImplementation();
+        }
+
+        /**
+         * Return the minimum value of the current (sub)tree
+        **/
+
+        Ref leftmost ()
+        {
+                auto p = this;
+                for ( ; p.left; p = p.left) {}
+                return p;
+        }
+
+        /**
+         * Return the maximum value of the current (sub)tree
+        **/
+        Ref rightmost ()
+        {
+                auto p = this;
+                for ( ; p.right; p = p.right) {}
+                return p;
+        }
+
+        /**
+         * Return the root (parentless node) of the tree
+        **/
+        Ref root ()
+        {
+                auto p = this;
+                for ( ; p.parent; p = p.parent) {}
+                return p;
+        }
+
+        /**
+         * Return true if node is a root (i.e., has a null parent)
+        **/
+
+        bool isRoot ()
+        {
+                return parent is null;
+        }
+
+
+        /**
+         * Return the inorder successor, or null if no such
+        **/
+
+        Ref successor ()
+        {
+                if (right)
+                    return right.leftmost;
+
+                auto p = parent;
+                auto ch = this;
+                while (p && ch is p.right)
+                      {
+                      ch = p;
+                      p = p.parent;
+                      }
+                return p;
+        }
+
+        /**
+         * Return the inorder predecessor, or null if no such
+        **/
+
+        Ref predecessor ()
+        {
+                if (left)
+                    return left.rightmost;
+
+                auto p = parent;
+                auto ch = this;
+                while (p && ch is p.left)
+                      {
+                      ch = p;
+                      p = p.parent;
+                      }
+                return p;
+        }
+
+        /**
+         * Return the number of nodes in the subtree
+        **/
+        int size ()
+        {
+                auto c = 1;
+                if (left)
+                    c += left.size;
+                if (right)
+                    c += right.size;
+                return c;
+        }
+
+
+        /**
+         * Return node of current subtree containing value as value(), 
+         * if it exists, else null. 
+         * Uses Comparator cmp to find and to check equality.
+        **/
+
+        Ref find (V value, Compare!(V) cmp)
+        {
+                auto t = this;
+                for (;;)
+                    {
+                    auto diff = cmp (value, t.value);
+                    if (diff is 0)
+                        return t;
+                    else
+                       if (diff < 0)
+                           t = t.left;
+                       else
+                          t = t.right;
+                    if (t is null)
+                        break;
+                    }
+                return null;
+        }
+
+
+        /**
+         * Return node of subtree matching "value" 
+         * or, if none found, the one just after or before  
+         * if it doesn't exist, return null
+         * Uses Comparator cmp to find and to check equality.
+        **/
+        Ref findFirst (V value, Compare!(V) cmp, bool after = true)
+        {
+                auto t = this;
+                auto tLower = this;
+                auto tGreater  = this;
+            
+                for (;;)
+                    {
+                    auto diff = cmp (value, t.value);
+                    if (diff is 0)
+                        return t;
+                   else
+                      if (diff < 0)
+                         {
+                         tGreater = t;
+                         t = t.left;
+                         }
+                      else
+                         {
+                         tLower = t;
+                         t = t.right;
+                         }
+                   if (t is null)
+                       break;
+                   }
+    
+                if (after)
+                   { 
+                   if (cmp (value, tGreater.value) <= 0)
+                       if (cmp (value, tGreater.value) < 0)
+                           return tGreater;
+                   }
+                else
+                   {
+                   if (cmp (value, tLower.value) >= 0)
+                       if (cmp (value, tLower.value) > 0)
+                           return tLower;
+                   }
+
+                return null;
+        }
+        
+        /**
+         * Return number of nodes of current subtree containing value.
+         * Uses Comparator cmp to find and to check equality.
+        **/
+        int count (V value, Compare!(V) cmp)
+        {
+                auto c = 0;
+                auto t = this;
+                while (t)
+                      {
+                      int diff = cmp (value, t.value);
+                      if (diff is 0)
+                         {
+                         ++c;
+                         if (t.left is null)
+                             t = t.right;
+                         else
+                            if (t.right is null)
+                                t = t.left;
+                            else
+                               {
+                               c += t.right.count (value, cmp);
+                               t = t.left;
+                               }
+                            }
+                         else
+                            if (diff < 0)
+                                t = t.left;
+                            else
+                               t = t.right;
+                         }
+                return c;
+        }
+        
+        static if (!is(typeof(A) == AttributeDummy))
+        {
+        Ref findAttribute (A attribute, Compare!(A) cmp)
+        {
+                auto t = this;
+
+                while (t)
+                      {
+                      if (t.attribute == attribute)
+                          return t;
+                      else
+                        if (t.right is null)
+                            t = t.left;
+                        else
+                           if (t.left is null)
+                               t = t.right;
+                           else
+                              {
+                              auto p = t.left.findAttribute (attribute, cmp);
+
+                              if (p !is null)
+                                  return p;
+                              else
+                                 t = t.right;
+                              }
+                      }
+                return null; // not reached
+        }
+
+        int countAttribute (A attrib, Compare!(A) cmp)
+        {
+                int c = 0;
+                auto t = this;
+
+                while (t)
+                      {
+                      if (t.attribute == attribute)
+                          ++c;
+
+                      if (t.right is null)
+                          t = t.left;
+                      else
+                         if (t.left is null)
+                             t = t.right;
+                         else
+                            {
+                            c += t.left.countAttribute (attribute, cmp);
+                            t = t.right;
+                            }
+                      }
+                return c;
+        }
+
+        /**
+         * find and return a cell holding (key, element), or null if no such
+        **/
+        Ref find (V value, A attribute, Compare!(V) cmp)
+        {
+                auto t = this;
+
+                for (;;)
+                    {
+                    int diff = cmp (value, t.value);
+                    if (diff is 0 && t.attribute == attribute)
+                        return t;
+                    else
+                       if (diff <= 0)
+                           t = t.left;
+                       else
+                          t = t.right;
+
+                    if (t is null)
+                        break;
+                    }
+                return null;
+        }
+
+        }
+
+
+
+        /**
+         * Return a new subtree containing each value of current subtree
+        **/
+
+        Ref copyTree (Ref delegate() alloc)
+        {
+                auto t = dup (alloc);
+
+                if (left)
+                   {
+                   t.left = left.copyTree (alloc);
+                   t.left.parent = t;
+                   }
+
+                if (right)
+                   {
+                   t.right = right.copyTree (alloc);
+                   t.right.parent = t;
+                   }
+
+                return t;
+        }
+
+
+        /**
+         * There's no generic value insertion. Instead find the
+         * place you want to add a node and then invoke insertLeft
+         * or insertRight.
+         * <P>
+         * Insert Cell as the left child of current node, and then
+         * rebalance the tree it is in.
+         * @param Cell the Cell to add
+         * @param root, the root of the current tree
+         * Returns: the new root of the current tree. (Rebalancing
+         * can change the root!)
+        **/
+
+
+        Ref insertLeft (Ref cell, Ref root)
+        {
+                left = cell;
+                cell.parent = this;
+                return cell.fixAfterInsertion (root);
+        }
+
+        /**
+         * Insert Cell as the right child of current node, and then
+         * rebalance the tree it is in.
+         * @param Cell the Cell to add
+         * @param root, the root of the current tree
+         * Returns: the new root of the current tree. (Rebalancing
+         * can change the root!)
+        **/
+
+        Ref insertRight (Ref cell, Ref root)
+        {
+                right = cell;
+                cell.parent = this;
+                return cell.fixAfterInsertion (root);
+        }
+
+
+        /**
+         * Delete the current node, and then rebalance the tree it is in
+         * @param root the root of the current tree
+         * Returns: the new root of the current tree. (Rebalancing
+         * can change the root!)
+        **/
+
+
+        Ref remove (Ref root)
+        {
+                // handle case where we are only node
+                if (left is null && right is null && parent is null)
+                    return null;
+
+                // if strictly internal, swap places with a successor
+                if (left && right)
+                   {
+                   auto s = successor;
+
+                   // To work nicely with arbitrary subclasses of Ref, we don't want to
+                   // just copy successor's fields. since we don't know what
+                   // they are.  Instead we swap positions _in the tree.
+                   root = swapPosition (this, s, root);
+                   }
+
+                // Start fixup at replacement node (normally a child).
+                // But if no children, fake it by using self
+
+                if (left is null && right is null)
+                   {
+                   if (color is BLACK)
+                       root = this.fixAfterDeletion (root);
+
+                   // Unlink  (Couldn't before since fixAfterDeletion needs parent ptr)
+                   if (parent)
+                      {
+                      if (this is parent.left)
+                          parent.left = null;
+                      else
+                         if (this is parent.right)
+                             parent.right = null;
+                      parent = null;
+                      }
+                   }
+                else
+                   {
+                   auto replacement = left;
+                   if (replacement is null)
+                       replacement = right;
+
+                   // link replacement to parent
+                   replacement.parent = parent;
+
+                   if (parent is null)
+                       root = replacement;
+                   else
+                      if (this is parent.left)
+                          parent.left = replacement;
+                      else
+                         parent.right = replacement;
+
+                   left = null;
+                   right = null;
+                   parent = null;
+        
+                   // fix replacement
+                   if (color is BLACK)
+                       root = replacement.fixAfterDeletion (root);
+                   }
+                return root;
+        }
+
+        /**
+         * Swap the linkages of two nodes in a tree.
+         * Return new root, in case it changed.
+        **/
+
+        static Ref swapPosition (Ref x, Ref y, Ref root)
+        {
+                /* Too messy. TODO: find sequence of assigments that are always OK */
+
+                auto px = x.parent;
+                bool xpl = px !is null && x is px.left;
+                auto lx = x.left;
+                auto rx = x.right;
+
+                auto py = y.parent;
+                bool ypl = py !is null && y is py.left;
+                auto ly = y.left;
+                auto ry = y.right;
+
+                if (x is py)
+                   {
+                   y.parent = px;
+                   if (px !is null)
+                       if (xpl)
+                           px.left = y;
+                       else
+                          px.right = y;
+
+                   x.parent = y;
+                   if (ypl)
+                      {
+                      y.left = x;
+                      y.right = rx;
+                      if (rx !is null)
+                      rx.parent = y;
+                      }
+                   else
+                      {
+                      y.right = x;
+                      y.left = lx;
+                      if (lx !is null)
+                      lx.parent = y;
+                      }
+
+                   x.left = ly;
+                   if (ly !is null)
+                       ly.parent = x;
+
+                   x.right = ry;
+                   if (ry !is null)
+                       ry.parent = x;
+                   }
+                else
+                   if (y is px)
+                      {
+                      x.parent = py;
+                      if (py !is null)
+                          if (ypl)
+                              py.left = x;
+                          else
+                             py.right = x;
+
+                      y.parent = x;
+                      if (xpl)
+                         {
+                         x.left = y;
+                         x.right = ry;
+                         if (ry !is null)
+                             ry.parent = x;
+                         }
+                      else
+                         {
+                         x.right = y;
+                         x.left = ly;
+                         if (ly !is null)
+                             ly.parent = x;
+                         }
+
+                      y.left = lx;
+                      if (lx !is null)
+                          lx.parent = y;
+
+                      y.right = rx;
+                      if (rx !is null)
+                          rx.parent = y;
+                      }
+                   else
+                      {
+                      x.parent = py;
+                      if (py !is null)
+                          if (ypl)
+                              py.left = x;
+                          else
+                             py.right = x;
+
+                      x.left = ly;
+                      if (ly !is null)
+                          ly.parent = x;
+
+                      x.right = ry;
+                      if (ry !is null)
+                          ry.parent = x;
+        
+                      y.parent = px;
+                      if (px !is null)
+                          if (xpl)
+                              px.left = y;
+                          else
+                             px.right = y;
+
+                      y.left = lx;
+                      if (lx !is null)
+                          lx.parent = y;
+
+                      y.right = rx;
+                      if (rx !is null)
+                          rx.parent = y;
+                      }
+
+                bool c = x.color;
+                x.color = y.color;
+                y.color = c;
+
+                if (root is x)
+                    root = y;
+                else
+                   if (root is y)
+                       root = x;
+                return root;
+        }
+
+
+
+        /**
+         * Return color of node p, or BLACK if p is null
+         * (In the CLR version, they use
+         * a special dummy `nil' node for such purposes, but that doesn't
+         * work well here, since it could lead to creating one such special
+         * node per real node.)
+         *
+        **/
+
+        static bool colorOf (Ref p)
+        {
+                return (p is null) ? BLACK : p.color;
+        }
+
+        /**
+         * return parent of node p, or null if p is null
+        **/
+        static Ref parentOf (Ref p)
+        {
+                return (p is null) ? null : p.parent;
+        }
+
+        /**
+         * Set the color of node p, or do nothing if p is null
+        **/
+
+        static void setColor (Ref p, bool c)
+        {
+                if (p !is null)
+                    p.color = c;
+        }
+
+        /**
+         * return left child of node p, or null if p is null
+        **/
+
+        static Ref leftOf (Ref p)
+        {
+                return (p is null) ? null : p.left;
+        }
+
+        /**
+         * return right child of node p, or null if p is null
+        **/
+
+        static Ref rightOf (Ref p)
+        {
+                return (p is null) ? null : p.right;
+        }
+
+
+        /** From CLR **/
+        package Ref rotateLeft (Ref root)
+        {
+                auto r = right;
+                right = r.left;
+
+                if (r.left)
+                    r.left.parent = this;
+
+                r.parent = parent;
+                if (parent is null)
+                    root = r;
+                else
+                   if (parent.left is this)
+                       parent.left = r;
+                   else
+                      parent.right = r;
+
+                r.left = this;
+                parent = r;
+                return root;
+        }
+
+        /** From CLR **/
+        package Ref rotateRight (Ref root)
+        {
+                auto l = left;
+                left = l.right;
+
+                if (l.right !is null)
+                   l.right.parent = this;
+
+                l.parent = parent;
+                if (parent is null)
+                    root = l;
+                else
+                   if (parent.right is this)
+                       parent.right = l;
+                   else
+                      parent.left = l;
+
+                l.right = this;
+                parent = l;
+                return root;
+        }
+
+
+        /** From CLR **/
+        package Ref fixAfterInsertion (Ref root)
+        {
+                color = RED;
+                auto x = this;
+
+                while (x && x !is root && x.parent.color is RED)
+                      {
+                      if (parentOf(x) is leftOf(parentOf(parentOf(x))))
+                         {
+                         auto y = rightOf(parentOf(parentOf(x)));
+                         if (colorOf(y) is RED)
+                            {
+                            setColor(parentOf(x), BLACK);
+                            setColor(y, BLACK);
+                            setColor(parentOf(parentOf(x)), RED);
+                            x = parentOf(parentOf(x));
+                            }
+                         else
+                            {
+                            if (x is rightOf(parentOf(x)))
+                               {
+                               x = parentOf(x);
+                               root = x.rotateLeft(root);
+                               }
+
+                            setColor(parentOf(x), BLACK);
+                            setColor(parentOf(parentOf(x)), RED);
+                            if (parentOf(parentOf(x)) !is null)
+                                root = parentOf(parentOf(x)).rotateRight(root);
+                            }
+                         }
+                      else
+                         {
+                         auto y = leftOf(parentOf(parentOf(x)));
+                         if (colorOf(y) is RED)
+                            {
+                            setColor(parentOf(x), BLACK);
+                            setColor(y, BLACK);
+                            setColor(parentOf(parentOf(x)), RED);
+                            x = parentOf(parentOf(x));
+                            }
+                         else
+                            {
+                            if (x is leftOf(parentOf(x)))
+                               {
+                               x = parentOf(x);
+                               root = x.rotateRight(root);
+                               }
+        
+                            setColor(parentOf(x), BLACK);
+                            setColor(parentOf(parentOf(x)), RED);
+                            if (parentOf(parentOf(x)) !is null)
+                                root = parentOf(parentOf(x)).rotateLeft(root);
+                            }
+                         }
+                      }
+                root.color = BLACK;
+                return root;
+        }
+
+
+
+        /** From CLR **/
+        package Ref fixAfterDeletion(Ref root)
+        {
+                auto x = this;
+                while (x !is root && colorOf(x) is BLACK)
+                      {
+                      if (x is leftOf(parentOf(x)))
+                         {
+                         auto sib = rightOf(parentOf(x));
+                         if (colorOf(sib) is RED)
+                            {
+                            setColor(sib, BLACK);
+                            setColor(parentOf(x), RED);
+                            root = parentOf(x).rotateLeft(root);
+                            sib = rightOf(parentOf(x));
+                            }
+                         if (colorOf(leftOf(sib)) is BLACK && colorOf(rightOf(sib)) is BLACK)
+                            {
+                            setColor(sib, RED);
+                            x = parentOf(x);
+                            }
+                         else
+                            {
+                            if (colorOf(rightOf(sib)) is BLACK)
+                               {
+                               setColor(leftOf(sib), BLACK);
+                               setColor(sib, RED);
+                               root = sib.rotateRight(root);
+                               sib = rightOf(parentOf(x));
+                               }
+
+                            setColor(sib, colorOf(parentOf(x)));
+                            setColor(parentOf(x), BLACK);
+                            setColor(rightOf(sib), BLACK);
+                            root = parentOf(x).rotateLeft(root);
+                            x = root;
+                            }
+                         }
+                      else
+                         {
+                         auto sib = leftOf(parentOf(x));
+                         if (colorOf(sib) is RED)
+                            {
+                            setColor(sib, BLACK);
+                            setColor(parentOf(x), RED);
+                            root = parentOf(x).rotateRight(root);
+                            sib = leftOf(parentOf(x));
+                            }
+
+                         if (colorOf(rightOf(sib)) is BLACK && colorOf(leftOf(sib)) is BLACK)
+                            {
+                            setColor(sib, RED);
+                            x = parentOf(x);
+                            }
+                         else
+                            {
+                            if (colorOf(leftOf(sib)) is BLACK)
+                               {
+                               setColor(rightOf(sib), BLACK);
+                               setColor(sib, RED);
+                               root = sib.rotateLeft(root);
+                               sib = leftOf(parentOf(x));
+                               }
+
+                            setColor(sib, colorOf(parentOf(x)));
+                            setColor(parentOf(x), BLACK);
+                            setColor(leftOf(sib), BLACK);
+                            root = parentOf(x).rotateRight(root);
+                            x = root;
+                            }
+                         }
+                      }
+
+                setColor(x, BLACK);
+                return root;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/set.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,186 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.set;
+
+import tango.core.Traits;
+import candy.util.redblack;
+import candy.util.memory;
+import candy.util.array;
+
+/**
+ * Basic set implementation using Tango's RedBlack struct with my memory
+ * allocator. Since Tango's RedBlack is package-access only, I copied it
+ * to candy.util.RedBlack.
+ */
+public struct Set(T)
+{
+	private alias RedBlack!(T) TreeNode;
+
+	private StructPool!(TreeNode) pool;
+	private TreeNode* root;
+	private size_t count = 0;
+	
+	public bool add(T value)
+	{
+		return add(value, null);
+	}
+	
+	private bool add(T value, TreeNode* node)
+	{
+		if(root is null)
+		{
+			root = node ? node : pool.alloc.set(value);
+		}
+		else
+		{
+			TreeNode* t = root;
+			while(true)
+			{
+				int diff = cmp(value, t.value);
+				if(0 == diff)
+				{
+					return false;
+				}
+				else if(diff < 0)
+				{
+					if(t.left)
+						t = t.left;
+					else
+					{
+						root = t.insertLeft(node ? node : pool.alloc.set(value), root);
+						break;
+					}
+				}
+				else
+				{
+					if(t.right)
+						t = t.right;
+					else
+					{
+						root = t.insertRight(node ? node : pool.alloc.set(value), root);
+						break;
+					}
+				}
+			}
+		}
+		count++;
+		return true;
+	}
+
+	public void addAll(Iterable)(Iterable iter)
+	{
+		foreach(e; iter)
+			add(e);
+	}
+	
+	// TODO find out if there's a better way to do this
+	public alias addAll merge;
+
+	public int opApply(int delegate(ref T value) dg)
+	{
+		int result = 0;
+		if(!root)
+			return result;
+		TreeNode* node = root.leftmost();
+		while(node)
+		{
+			result = dg(node.value);
+			if(result)
+				break;
+			node = node.successor();
+		}
+		return result;
+	}
+	
+	public char[] toString()
+	{
+		if(!root)
+			return "{}";
+		bool comma = false;
+		Array!(char) r;
+		r ~= "{";
+		TreeNode* node = root.leftmost();
+		while(node)
+		{
+			if(comma)
+				r ~= ", ";
+			r ~= node.value.toString();
+			node = node.successor();
+			comma = true;
+		}
+		r ~= "}";
+		return r.toArray();
+	}
+	
+	public T[] toArray()
+	{
+		if(!root)
+			return null;
+		T[] arr = new T[count];
+		TreeNode* node = root.leftmost();
+		size_t i = 0;
+		while(node)
+		{
+			arr[i] = node.value;
+			node = node.successor();
+			i++;
+		}
+		assert(i == count);
+		return arr;
+	}
+	
+	public size_t length()
+	{
+		return count;
+	}
+	
+	public bool contains(T value)
+	{
+		return root.find(value, &cmp) !is null;
+	}
+	
+	final bool remove(T value)
+    {
+		TreeNode* node = root.find(value, &cmp);
+		if(value)
+		{
+			root = node.remove(root);
+			count--;
+			return true;
+		}
+		else
+			return false;
+    }
+	
+	static if(isReferenceType!(T) && !is(typeof(&((new T).opCmp))))
+	{
+		// Hack to allow classes/structs without an opCmp to be compared by their address
+		private static int cmp(ref T a, ref T b)
+		{
+			return cast(void*) a - cast(void*) b;
+		}
+	}
+	else
+	{
+		private static int cmp(ref T a, ref T b)
+		{
+			if(a is b)
+				return 0;
+			return typeid(T).compare(&a, &b);
+	    }
+	}
+	
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/util/sharedlib.d	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,65 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.sharedlib;
+
+public import tango.sys.SharedLib;
+
+version(Windows)    private const char[] SHARED_LIB_EXT = ".dll";
+else version(Posix) private const char[] SHARED_LIB_EXT = ".so";
+else static assert(false);
+
+private char[] stripUnderscore(char[] name)
+{
+	if(name.length && name[0] == '_')
+		return name[1 .. $];
+	return name;
+}
+
+public char[] shared_mixin(char[] libFile, char[][] functions)
+{
+	assert(functions.length % 2 == 0);
+	char[] r = "private SharedLib _lib;";
+	int numFuncs = functions.length / 2;
+	for(int i = 0; i < numFuncs; i++)
+	{
+		char[] type = functions[i * 2];
+		char[] name = stripUnderscore(functions[i * 2 + 1]);
+		if(!name.length || !type.length)
+		    continue;
+		r ~= "public static " ~ type ~ " " ~ name ~ ";";
+	}
+	r ~= "public void _loadLib() {if(_lib)return; scope(failure){_unloadLib();}";
+	r ~= "_lib = SharedLib.load(\"" ~ libFile ~ SHARED_LIB_EXT ~ "\");";
+	for(int i = 0; i < numFuncs; i++)
+	{
+		char[] nameu = functions[i * 2 + 1];
+		char[] name = stripUnderscore(nameu);
+		if(!name.length)
+		    continue;
+		r ~= name ~ " = " ~ "cast(typeof(" ~ name ~ ")) _lib.getSymbol(\"" ~ nameu ~ "\");";
+	}
+	r ~= "}";
+	r ~= "public void _unloadLib() { if(_lib){_lib.unload();}_lib=null;";
+	for(int i = 0; i < numFuncs; i++)
+	{
+		char[] name = stripUnderscore(functions[i * 2 + 1]);
+		if(!name.length)
+		    continue;
+		r ~= name ~ "=null;";
+	}
+	r ~= "}";
+	return r;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platif/hoofbaby.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,91 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "platif.h"
+#include "PltUPnP.h"
+#include "PltMediaConnect.h"
+#include "PltHttpServer.h"
+#include "NptStreams.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+static Hoofbaby hoofbaby;
+
+class HB_InputStream : public NPT_InputStream
+{
+private:
+	void* ctx;
+
+public:
+	HB_InputStream(void* _ctx) : ctx(_ctx) {}
+	NPT_Result Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read = 0) { return hoofbaby.Stream_Read(ctx, buffer, bytes_to_read, bytes_read); }
+	NPT_Result Seek(NPT_Position offset) { return hoofbaby.Stream_Seek(ctx, offset); }
+	NPT_Result Tell(NPT_Position& offset) { return hoofbaby.Stream_Tell(ctx, &offset); }
+	NPT_Result GetSize(NPT_LargeSize& size) { return hoofbaby.Stream_GetSize(ctx, &size); }
+	NPT_Result GetAvailable(NPT_LargeSize& available) { return hoofbaby.Stream_GetAvailable(ctx, &available); }
+};
+
+class HB_Server : public PLT_MediaConnect
+{
+	public:
+		HB_Server(const char* _path, const char* _friendly_name) : PLT_MediaConnect(_path, _friendly_name) {}
+		NPT_Result ServeFile(NPT_HttpRequest& request, const NPT_HttpRequestContext& context, 
+			NPT_HttpResponse& response, const NPT_String& file_path)
+		{
+			NPT_COMPILER_UNUSED(context);
+
+			printf("**********************************\n");
+			printf("ServeFile(%s)\n", file_path.GetChars());
+			printf("**********************************\n");
+			fflush(stdout);
+
+			NPT_Position start, end;
+			PLT_HttpHelper::GetRange(request, start, end);
+
+			return PLT_FileServer::ServeFile(response,
+				file_path, 
+				start, 
+				end, 
+				!request.GetMethod().Compare("HEAD"));
+		}
+};
+
+void initHoofbaby(Hoofbaby* interf)
+{
+	hoofbaby = *interf;
+}
+
+int startServer(const char* path)
+{
+	PLT_DeviceHostReference device(new HB_Server("D:\\Media\\Videos", "Platinum: Hoofbaby: "));
+
+    PLT_UPnP upnp;
+    upnp.AddDevice(device);
+
+    if (NPT_FAILED(upnp.Start()))
+        return 1;
+
+    char buf[256];
+    while (gets(buf))
+    {
+        if (*buf == 'q')
+        {
+            break;
+        }
+    }
+
+    upnp.Stop();
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platif/platif.h	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,40 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _PLATIF_H
+#define _PLATIF_H
+
+#include "../dtypes.h"
+
+#if __D
+module hoofbaby.platinum.platif;
+import hoofbaby.util.sharedlib;
+#endif
+
+struct Hoofbaby
+{
+	int (*Stream_New)(void**);
+	int (*Stream_Read)(void*, void*, D_LUINT, D_LUINT*);
+	int (*Stream_Seek)(void*, D_ULONG);
+	int (*Stream_Tell)(void*, D_ULONG*);
+	int (*Stream_GetSize)(void*, D_ULONG*);
+	int (*Stream_GetAvailable)(void*, D_ULONG*);
+};
+
+BEGIN_DFUNCTIONS("platif")
+	FUN(initHoofbaby, void, (Hoofbaby* interf))
+	FUN(startServer,  int,  (D_CONST char* path))
+END_DFUNCTIONS
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platif/platif.vcproj	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="platif"
+	ProjectGUID="{7D9FD95C-249A-4026-BEA1-BF21738D91A7}"
+	RootNamespace="platif"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\bin\hoofbaby-d"
+			IntermediateDirectory="..\..\bin\objs\platif-$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\deps\Platinum\Source\Core;..\..\deps\Platinum\Source\Devices\MediaServer;..\..\deps\Platinum\ThirdParty\Neptune\Source\Core;..\..\deps\Platinum\Source\Devices\MediaRenderer;..\..\deps\Platinum\Source\Devices\MediaConnect"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLATIF_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\$(ProjectName).dll"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\bin\hoofbaby"
+			IntermediateDirectory="..\..\bin\objs\platif-$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\..\deps\Platinum\Source\Core;..\..\deps\Platinum\Source\Devices\MediaServer;..\..\deps\Platinum\ThirdParty\Neptune\Source\Core;..\..\deps\Platinum\Source\Devices\MediaRenderer;..\..\deps\Platinum\Source\Devices\MediaConnect"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLATIF_EXPORTS"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\$(ProjectName).dll"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\hoofbaby.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\platif.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\dtypes.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platif/platif.vcproj.XPOFTHENIGHT.fraserofthenight.user	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioUserFile
+	ProjectType="Visual C++"
+	Version="9.00"
+	ShowAllFiles="false"
+	>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			>
+			<DebugSettings
+				Command=""
+				WorkingDirectory=""
+				CommandArguments=""
+				Attach="false"
+				DebuggerType="3"
+				Remote="1"
+				RemoteMachine="XPOFTHENIGHT"
+				RemoteCommand=""
+				HttpUrl=""
+				PDBPath=""
+				SQLDebugging=""
+				Environment=""
+				EnvironmentMerge="true"
+				DebuggerFlavor=""
+				MPIRunCommand=""
+				MPIRunArguments=""
+				MPIRunWorkingDirectory=""
+				ApplicationCommand=""
+				ApplicationArguments=""
+				ShimCommand=""
+				MPIAcceptMode=""
+				MPIAcceptFilter=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			>
+			<DebugSettings
+				Command=""
+				WorkingDirectory=""
+				CommandArguments=""
+				Attach="false"
+				DebuggerType="3"
+				Remote="1"
+				RemoteMachine="XPOFTHENIGHT"
+				RemoteCommand=""
+				HttpUrl=""
+				PDBPath=""
+				SQLDebugging=""
+				Environment=""
+				EnvironmentMerge="true"
+				DebuggerFlavor=""
+				MPIRunCommand=""
+				MPIRunArguments=""
+				MPIRunWorkingDirectory=""
+				ApplicationCommand=""
+				ApplicationArguments=""
+				ShimCommand=""
+				MPIAcceptMode=""
+				MPIAcceptFilter=""
+			/>
+		</Configuration>
+	</Configurations>
+</VisualStudioUserFile>