Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXhmikosR <xhmikosr@users.sourceforge.net>2010-08-25 13:35:12 +0400
committerXhmikosR <xhmikosr@users.sourceforge.net>2010-08-25 13:35:12 +0400
commit9ab2555aea33c56a553df6313c970cae05f4a9b3 (patch)
treee881b085bbdedc0ed22c2c48247a1dc0bfdabd27 /src/thirdparty/ZenLib
parent4da73e1c7894371da7ebd99d024cccf551925e9c (diff)
Added MediaInfoLib (v0.7.34) (there's no need for MediaInfo.dll anymore)
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@2340 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src/thirdparty/ZenLib')
-rw-r--r--src/thirdparty/ZenLib/Base64/base64.h158
-rw-r--r--src/thirdparty/ZenLib/BitStream.h349
-rw-r--r--src/thirdparty/ZenLib/BitStream_LE.h143
-rw-r--r--src/thirdparty/ZenLib/Conf.cpp55
-rw-r--r--src/thirdparty/ZenLib/Conf.h369
-rw-r--r--src/thirdparty/ZenLib/Conf_Internal.h96
-rw-r--r--src/thirdparty/ZenLib/CriticalSection.cpp199
-rw-r--r--src/thirdparty/ZenLib/CriticalSection.h84
-rw-r--r--src/thirdparty/ZenLib/Dir.cpp319
-rw-r--r--src/thirdparty/ZenLib/Dir.h70
-rw-r--r--src/thirdparty/ZenLib/File.cpp828
-rw-r--r--src/thirdparty/ZenLib/File.h112
-rw-r--r--src/thirdparty/ZenLib/FileName.cpp232
-rw-r--r--src/thirdparty/ZenLib/FileName.h81
-rw-r--r--src/thirdparty/ZenLib/Format/Html/Html_Handler.cpp66
-rw-r--r--src/thirdparty/ZenLib/Format/Html/Html_Handler.h91
-rw-r--r--src/thirdparty/ZenLib/Format/Html/Html_Request.cpp74
-rw-r--r--src/thirdparty/ZenLib/Format/Html/Html_Request.h77
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Cookies.cpp107
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Cookies.h91
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Handler.cpp65
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Handler.h87
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Request.cpp250
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Request.h81
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Utils.cpp160
-rw-r--r--src/thirdparty/ZenLib/Format/Http/Http_Utils.h76
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client.cpp135
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client.h64
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClient.c3646
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClient.h306
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.c665
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.h90
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientCommon.h120
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.c424
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.h23
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.c348
-rw-r--r--src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.h111
-rw-r--r--src/thirdparty/ZenLib/InfoMap.cpp177
-rw-r--r--src/thirdparty/ZenLib/InfoMap.h77
-rw-r--r--src/thirdparty/ZenLib/MemoryDebug.cpp190
-rw-r--r--src/thirdparty/ZenLib/MemoryDebug.h130
-rw-r--r--src/thirdparty/ZenLib/OS_Utils.cpp228
-rw-r--r--src/thirdparty/ZenLib/OS_Utils.h56
-rw-r--r--src/thirdparty/ZenLib/Thread.cpp650
-rw-r--r--src/thirdparty/ZenLib/Thread.h105
-rw-r--r--src/thirdparty/ZenLib/TinyXml/tinyxml.cpp1890
-rw-r--r--src/thirdparty/ZenLib/TinyXml/tinyxml.h1804
-rw-r--r--src/thirdparty/ZenLib/TinyXml/tinyxmlerror.cpp55
-rw-r--r--src/thirdparty/ZenLib/TinyXml/tinyxmlparser.cpp1640
-rw-r--r--src/thirdparty/ZenLib/Trace.h77
-rw-r--r--src/thirdparty/ZenLib/Translation.cpp169
-rw-r--r--src/thirdparty/ZenLib/Translation.h79
-rw-r--r--src/thirdparty/ZenLib/Utils.cpp921
-rw-r--r--src/thirdparty/ZenLib/Utils.h318
-rw-r--r--src/thirdparty/ZenLib/ZenLib.vcproj599
-rw-r--r--src/thirdparty/ZenLib/ZenLib.vcxproj212
-rw-r--r--src/thirdparty/ZenLib/ZenLib.vcxproj.filters213
-rw-r--r--src/thirdparty/ZenLib/Ztring.cpp2157
-rw-r--r--src/thirdparty/ZenLib/Ztring.h365
-rw-r--r--src/thirdparty/ZenLib/ZtringList.cpp373
-rw-r--r--src/thirdparty/ZenLib/ZtringList.h103
-rw-r--r--src/thirdparty/ZenLib/ZtringListList.cpp577
-rw-r--r--src/thirdparty/ZenLib/ZtringListList.h146
-rw-r--r--src/thirdparty/ZenLib/ZtringListListF.cpp376
-rw-r--r--src/thirdparty/ZenLib/ZtringListListF.h91
-rw-r--r--src/thirdparty/ZenLib/int128s.cpp410
-rw-r--r--src/thirdparty/ZenLib/int128s.h205
-rw-r--r--src/thirdparty/ZenLib/int128u.cpp392
-rw-r--r--src/thirdparty/ZenLib/int128u.h201
69 files changed, 25238 insertions, 0 deletions
diff --git a/src/thirdparty/ZenLib/Base64/base64.h b/src/thirdparty/ZenLib/Base64/base64.h
new file mode 100644
index 000000000..40a340c61
--- /dev/null
+++ b/src/thirdparty/ZenLib/Base64/base64.h
@@ -0,0 +1,158 @@
+//  //
+// #### ### ## -= Base64 library =-  //
+// # # # # # Base64.h - Base64 encoder/decoder  //
+// #### #### # #  //
+// # # # # ##### Encodes and decodes base64 strings  //
+// # # # # # Ideas taken from work done by Bob Withers  //
+// #### ### # R1 2002-05-07 by Markus Ewald  //
+//  //
+#ifndef B64_BASE64_H
+#define B64_BASE64_H
+
+#include <string>
+
+namespace Base64 {
+
+ /// Encode string to base64
+ inline std::string encode(const std::string &sString);
+ /// Encode base64 into string
+ inline std::string decode(const std::string &sString);
+
+}; // namespace Base64
+
+// ####################################################################### //
+// # Base64::encode() # //
+// ####################################################################### //
+/** Encodes the specified string to base64
+
+ @param sString String to encode
+ @return Base64 encoded string
+*/
+inline std::string Base64::encode(const std::string &sString) {
+ static const std::string sBase64Table(
+ // 0000000000111111111122222222223333333333444444444455555555556666
+ // 0123456789012345678901234567890123456789012345678901234567890123
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+ );
+ static const char cFillChar = '=';
+ std::string::size_type nLength = sString.length();
+ std::string sResult;
+
+ // Allocate memory for the converted string
+ sResult.reserve(nLength * 8 / 6 + 1);
+
+ for(std::string::size_type nPos = 0; nPos < nLength; nPos++) {
+ char cCode;
+
+ // Encode the first 6 bits
+ cCode = (sString[nPos] >> 2) & 0x3f;
+ sResult.append(1, sBase64Table[cCode]);
+
+ // Encode the remaining 2 bits with the next 4 bits (if present)
+ cCode = (sString[nPos] << 4) & 0x3f;
+ if(++nPos < nLength)
+ cCode |= (sString[nPos] >> 4) & 0x0f;
+ sResult.append(1, sBase64Table[cCode]);
+
+ if(nPos < nLength) {
+ cCode = (sString[nPos] << 2) & 0x3f;
+ if(++nPos < nLength)
+ cCode |= (sString[nPos] >> 6) & 0x03;
+
+ sResult.append(1, sBase64Table[cCode]);
+ } else {
+ ++nPos;
+ sResult.append(1, cFillChar);
+ }
+
+ if(nPos < nLength) {
+ cCode = sString[nPos] & 0x3f;
+ sResult.append(1, sBase64Table[cCode]);
+ } else {
+ sResult.append(1, cFillChar);
+ }
+ }
+
+ return sResult;
+}
+
+// ####################################################################### //
+// # Base64::decode() # //
+// ####################################################################### //
+/** Decodes the specified base64 string
+
+ @param sString Base64 string to decode
+ @return Decoded string
+*/
+inline std::string Base64::decode(const std::string &sString) {
+ static const std::string::size_type np = std::string::npos;
+ static const std::string::size_type DecodeTable[] = {
+ // 0 1 2 3 4 5 6 7 8 9
+ np, np, np, np, np, np, np, np, np, np, // 0 - 9
+ np, np, np, np, np, np, np, np, np, np, // 10 - 19
+ np, np, np, np, np, np, np, np, np, np, // 20 - 29
+ np, np, np, np, np, np, np, np, np, np, // 30 - 39
+ np, np, np, 62, np, np, np, 63, 52, 53, // 40 - 49
+ 54, 55, 56, 57, 58, 59, 60, 61, np, np, // 50 - 59
+ np, np, np, np, np, 0, 1, 2, 3, 4, // 60 - 69
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 70 - 79
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 80 - 89
+ 25, np, np, np, np, np, np, 26, 27, 28, // 90 - 99
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 100 - 109
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 110 - 119
+ 49, 50, 51, np, np, np, np, np, np, np, // 120 - 129
+ np, np, np, np, np, np, np, np, np, np, // 130 - 139
+ np, np, np, np, np, np, np, np, np, np, // 140 - 149
+ np, np, np, np, np, np, np, np, np, np, // 150 - 159
+ np, np, np, np, np, np, np, np, np, np, // 160 - 169
+ np, np, np, np, np, np, np, np, np, np, // 170 - 179
+ np, np, np, np, np, np, np, np, np, np, // 180 - 189
+ np, np, np, np, np, np, np, np, np, np, // 190 - 199
+ np, np, np, np, np, np, np, np, np, np, // 200 - 209
+ np, np, np, np, np, np, np, np, np, np, // 210 - 219
+ np, np, np, np, np, np, np, np, np, np, // 220 - 229
+ np, np, np, np, np, np, np, np, np, np, // 230 - 239
+ np, np, np, np, np, np, np, np, np, np, // 240 - 249
+ np, np, np, np, np, np // 250 - 256
+ };
+ static const char cFillChar = '=';
+
+ std::string::size_type nLength = sString.length();
+ std::string sResult;
+
+ sResult.reserve(nLength);
+
+ for(std::string::size_type nPos = 0; nPos < nLength; nPos++) {
+ unsigned char c, c1;
+
+ c = (char) DecodeTable[(unsigned char)sString[nPos]];
+ nPos++;
+ c1 = (char) DecodeTable[(unsigned char)sString[nPos]];
+ c = (c << 2) | ((c1 >> 4) & 0x3);
+ sResult.append(1, c);
+
+ if(++nPos < nLength) {
+ c = sString[nPos];
+ if(cFillChar == c)
+ break;
+
+ c = (char) DecodeTable[(unsigned char)sString[nPos]];
+ c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
+ sResult.append(1, c1);
+ }
+
+ if(++nPos < nLength) {
+ c1 = sString[nPos];
+ if(cFillChar == c1)
+ break;
+
+ c1 = (char) DecodeTable[(unsigned char)sString[nPos]];
+ c = ((c << 6) & 0xc0) | c1;
+ sResult.append(1, c);
+ }
+ }
+
+ return sResult;
+}
+
+#endif // B64_BASE64_H
diff --git a/src/thirdparty/ZenLib/BitStream.h b/src/thirdparty/ZenLib/BitStream.h
new file mode 100644
index 000000000..7230872be
--- /dev/null
+++ b/src/thirdparty/ZenLib/BitStream.h
@@ -0,0 +1,349 @@
+// ZenLib::bitStream - Read bit per bit
+// Copyright (C) 2006-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Read a stream bit per bit
+// Can read up to 32 bits at once
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenBitStreamH
+#define ZenBitStreamH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+#ifndef MIN
+ #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+class BitStream
+{
+public:
+ BitStream () {Buffer=NULL;
+ Buffer_Size=Buffer_Size_Init=Buffer_Size_BeforeLastCall=0;
+ LastByte_Size=0;
+ BufferUnderRun=true;
+ BookMark=false;}
+ BitStream (const int8u* Buffer_, size_t Size_) {Buffer=Buffer_;
+ Buffer_Size=Buffer_Size_Init=Buffer_Size_BeforeLastCall=Size_*8; //Size is in bits
+ LastByte_Size=0;
+ BufferUnderRun=Buffer_Size?false:true;
+ BookMark=false;}
+ virtual ~BitStream () {};
+
+ virtual void Attach(const int8u* Buffer_, size_t Size_)
+ {
+ if (Buffer_==Buffer)
+ return; //Nothing to do
+ Buffer=Buffer_;
+ Buffer_Size=Buffer_Size_Init=Buffer_Size_BeforeLastCall=Size_*8; //Size is in bits
+ LastByte_Size=0;
+ BufferUnderRun=Buffer_Size?false:true;
+ BookMark=false;
+ };
+
+ virtual int32u Get (size_t HowMany)
+ {
+ size_t ToReturn;
+ static const int32u Mask[33]={
+ 0x00000000,
+ 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
+ 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
+ 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
+ 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
+ 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
+ 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
+ 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
+ };
+
+ if (HowMany==0 || HowMany>32)
+ return 0;
+ if ((size_t)HowMany>Buffer_Size+LastByte_Size)
+ {
+ Buffer_Size=0;
+ LastByte_Size=0;
+ BufferUnderRun=true;
+ return 0;
+ }
+
+ Buffer_Size_BeforeLastCall=Buffer_Size+LastByte_Size;
+
+ if (HowMany<=LastByte_Size)
+ {
+ LastByte_Size-=HowMany;
+ ToReturn=LastByte>>LastByte_Size;
+ }
+ else
+ {
+ size_t NewBits=HowMany-LastByte_Size;
+ if (NewBits==32)
+ ToReturn=0;
+ else
+ ToReturn=LastByte<<NewBits;
+ switch ((NewBits-1)/8)
+ {
+ case 3 : NewBits-=8;
+ ToReturn|=*Buffer<<NewBits;
+ Buffer++;
+ Buffer_Size-=8;
+ case 2 : NewBits-=8;
+ ToReturn|=*Buffer<<NewBits;
+ Buffer++;
+ Buffer_Size-=8;
+ case 1 : NewBits-=8;
+ ToReturn|=*Buffer<<NewBits;
+ Buffer++;
+ Buffer_Size-=8;
+ case 0 :
+ LastByte=*Buffer;
+ Buffer++;
+ }
+ LastByte_Size=MIN(8, Buffer_Size)-NewBits;
+ Buffer_Size -=MIN(8, Buffer_Size);
+ ToReturn|=(LastByte>>LastByte_Size)&Mask[NewBits];
+ }
+ return (int32u)(ToReturn&Mask[HowMany]);
+ };
+
+ bool GetB ()
+ {
+ return Get(1)?true:false;
+ }
+
+ int8u Get1 (size_t HowMany)
+ {
+ return (int8u )Get(HowMany);
+ }
+
+ int16u Get2 (size_t HowMany)
+ {
+ return (int16u)Get(HowMany);
+ }
+
+ int32u Get4 (size_t HowMany)
+ {
+ return (int32u)Get(HowMany);
+ }
+
+ int64u Get8 (size_t HowMany)
+ {
+ if (HowMany>64)
+ return 0; //Not supported
+ size_t HowMany1, HowMany2;
+ int64u Value1, Value2;
+ if (HowMany>32)
+ HowMany1=HowMany-32;
+ else
+ HowMany1=0;
+ HowMany2=HowMany-HowMany1;
+ Value1=Get(HowMany1);
+ Value2=Get(HowMany2);
+ if (BufferUnderRun)
+ return 0;
+ return Value1*0x100000000LL+Value2;
+ }
+
+ virtual void Skip (size_t HowMany)
+ {
+ if (HowMany==0 || HowMany>32)
+ return;
+ if ((size_t)HowMany>Buffer_Size+LastByte_Size)
+ {
+ Buffer_Size=0;
+ LastByte_Size=0;
+ BufferUnderRun=true;
+ return;
+ }
+
+ Buffer_Size_BeforeLastCall=Buffer_Size+LastByte_Size;
+
+ if (HowMany<=LastByte_Size)
+ LastByte_Size-=HowMany;
+ else
+ {
+ size_t NewBits=HowMany-LastByte_Size;
+ switch ((NewBits-1)/8)
+ {
+ case 3 : NewBits-=8;
+ Buffer++;
+ Buffer_Size-=8;
+ case 2 : NewBits-=8;
+ Buffer++;
+ Buffer_Size-=8;
+ case 1 : NewBits-=8;
+ Buffer++;
+ Buffer_Size-=8;
+ case 0 :
+ LastByte=*Buffer;
+ Buffer++;
+ }
+ LastByte_Size=MIN(8, Buffer_Size)-NewBits;
+ Buffer_Size -=MIN(8, Buffer_Size);
+ }
+ };
+
+ void SkipB ()
+ {
+ Skip(1);
+ }
+
+ void Skip1 (size_t HowMany)
+ {
+ Skip(HowMany);
+ }
+
+ void Skip2 (size_t HowMany)
+ {
+ Skip(HowMany);
+ }
+
+ void Skip4 (size_t HowMany)
+ {
+ Skip(HowMany);
+ }
+
+ void Skip8 (size_t HowMany)
+ {
+ if (HowMany>64)
+ return; //Not supported
+ size_t HowMany1, HowMany2;
+ if (HowMany>32)
+ HowMany1=HowMany-32;
+ else
+ HowMany1=0;
+ HowMany2=HowMany-HowMany1;
+ Skip(HowMany1);
+ Skip(HowMany2);
+ }
+
+ int32u Peek(size_t HowMany)
+ {
+ BookMarkPos(true);
+ int32u ToReturn=Get(HowMany);
+ BookMarkPos(false);
+ return ToReturn;
+ }
+
+ bool PeekB()
+ {
+ return Peek(1)?true:false;
+ }
+
+ int8u Peek1(size_t HowMany)
+ {
+ return (int8u )Peek(HowMany);
+ }
+
+ int16u Peek2(size_t HowMany)
+ {
+ return (int16u)Peek(HowMany);
+ }
+
+ int32u Peek4(size_t HowMany)
+ {
+ return (int32u)Peek(HowMany);
+ }
+
+ int64u Peek8(size_t HowMany)
+ {
+ return (int64u)Peek(HowMany);
+ }
+
+ void BookMarkPos(bool ToSet)
+ {
+ if (ToSet)
+ {
+ BookMark=1;
+ Buffer_BookMark=Buffer;
+ Buffer_Size_BookMark=Buffer_Size;
+ LastByte_BookMark=LastByte;
+ LastByte_Size_BookMark=LastByte_Size;
+ BufferUnderRun_BookMark=BufferUnderRun;
+ }
+ else
+ {
+ BookMark=0;
+ Buffer=Buffer_BookMark;
+ Buffer_Size=Buffer_Size_BookMark;
+ LastByte=LastByte_BookMark;
+ LastByte_Size=LastByte_Size_BookMark;
+ BufferUnderRun=BufferUnderRun_BookMark;
+ }
+ };
+
+ virtual int32u Remain () //How many bits remain?
+ {
+ return (int32u)(Buffer_Size+LastByte_Size);
+ };
+
+ virtual void Byte_Align()
+ {
+ Get(LastByte_Size);
+ };
+
+ virtual size_t Offset_Get()
+ {
+ if (BufferUnderRun)
+ return 0;
+ return (Buffer_Size_Init-Buffer_Size)/8;
+ };
+
+ virtual size_t BitOffset_Get()
+ {
+ if (BufferUnderRun)
+ return 0;
+ return LastByte_Size;
+ };
+
+ virtual size_t OffsetBeforeLastCall_Get()
+ {
+ if (BufferUnderRun)
+ return 0;
+ return (Buffer_Size_Init-Buffer_Size_BeforeLastCall)/8;
+ };
+
+private :
+ const int8u* Buffer;
+ size_t Buffer_Size;
+ size_t Buffer_Size_Init;
+ size_t Buffer_Size_BeforeLastCall;
+ size_t LastByte;
+ size_t LastByte_Size;
+ bool BufferUnderRun;
+
+ bool BookMark;
+ const int8u* Buffer_BookMark;
+ size_t Buffer_Size_BookMark;
+ size_t LastByte_BookMark;
+ size_t LastByte_Size_BookMark;
+ bool BufferUnderRun_BookMark;
+};
+
+} //namespace ZenLib
+#endif
diff --git a/src/thirdparty/ZenLib/BitStream_LE.h b/src/thirdparty/ZenLib/BitStream_LE.h
new file mode 100644
index 000000000..abacb6685
--- /dev/null
+++ b/src/thirdparty/ZenLib/BitStream_LE.h
@@ -0,0 +1,143 @@
+// ZenLib::BitStream_LE - Read bit per bit, Little Endian version
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Read a stream bit per bit, Little Endian version (rarely used!!!)
+// Can read up to 32 bits at once
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenBitStream_LEH
+#define ZenBitStream_LEH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/BitStream.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+class BitStream_LE : BitStream
+{
+public:
+ BitStream_LE () :BitStream() {};
+ BitStream_LE (const int8u* Buffer_, size_t Size_) :BitStream(Buffer_, Size_) {};
+
+ void Attach(const int8u* Buffer_, size_t Size_)
+ {
+ endbyte=0;
+ endbit=0;
+ buffer=Buffer_;
+ ptr=Buffer_;
+ storage=(long)Size_;
+ };
+
+ int32u Get (size_t HowMany)
+ {
+ ptr_BeforeLastCall=ptr;
+
+ long ret;
+ static const int32u Mask[33]={
+ 0x00000000,
+ 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
+ 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
+ 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
+ 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
+ 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
+ 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
+ 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
+ };
+ unsigned long m=Mask[HowMany];
+
+ HowMany+=endbit;
+
+ if(endbyte+4>=storage){
+ ret=-1L;
+ if(endbyte*8+(long)HowMany>storage*8)goto overflow;
+ }
+
+ ret=ptr[0]>>endbit;
+ if(HowMany>8){
+ ret|=ptr[1]<<(8-endbit);
+ if(HowMany>16){
+ ret|=ptr[2]<<(16-endbit);
+ if(HowMany>24){
+ ret|=ptr[3]<<(24-endbit);
+ if(HowMany>32 && endbit){
+ ret|=ptr[4]<<(32-endbit);
+ }
+ }
+ }
+ }
+ ret&=m;
+
+ overflow:
+
+ ptr+=HowMany/8;
+ endbyte+=(long)HowMany/8;
+ endbit=(long)HowMany&7;
+ return(ret);
+ };
+
+ void Skip(size_t bits)
+ {
+ Get(bits);
+ }
+
+ int32u Remain () //How many bits remain?
+ {
+ return 32;
+ };
+
+ void Byte_Align()
+ {
+ };
+
+ size_t Offset_Get()
+ {
+ return ptr-buffer;
+ };
+
+ size_t BitOffset_Get()
+ {
+ return endbit;
+ };
+
+ size_t OffsetBeforeLastCall_Get()
+ {
+ return ptr_BeforeLastCall-buffer;
+ };
+
+private :
+ long endbyte;
+ int endbit;
+
+ const unsigned char *buffer;
+ const unsigned char *ptr;
+ const unsigned char *ptr_BeforeLastCall;
+ long storage;
+};
+
+} //namespace ZenLib
+#endif
diff --git a/src/thirdparty/ZenLib/Conf.cpp b/src/thirdparty/ZenLib/Conf.cpp
new file mode 100644
index 000000000..cafd1dcf8
--- /dev/null
+++ b/src/thirdparty/ZenLib/Conf.cpp
@@ -0,0 +1,55 @@
+// ZenLib::ZenTypes - To be independant of platform & compiler
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Platform differences
+//***************************************************************************
+
+//End of line
+#ifdef WINDOWS
+ const Char* EOL=_T("\r\n");
+ const Char PathSeparator=_T('\\');
+#endif
+#ifdef UNIX
+ const Char* EOL=_T("\n");
+ const Char PathSeparator=_T('/');
+#endif
+#if defined (MACOS) || defined (MACOSX)
+ const Char* EOL=_T("\r");
+ const Char PathSeparator=_T('/');
+#endif
+
+//***************************************************************************
+//
+//***************************************************************************
+
+} //namespace
diff --git a/src/thirdparty/ZenLib/Conf.h b/src/thirdparty/ZenLib/Conf.h
new file mode 100644
index 000000000..bb824ad2f
--- /dev/null
+++ b/src/thirdparty/ZenLib/Conf.h
@@ -0,0 +1,369 @@
+// ZenLib::ZenTypes - To be independant of platform & compiler
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenConfH
+#define ZenConfH
+//---------------------------------------------------------------------------
+
+//***************************************************************************
+// Platforms
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Win32
+#if defined(__NT__) || defined(_WIN32) || defined(WIN32)
+ #ifndef WIN32
+ #define WIN32
+ #endif
+ #ifndef _WIN32
+ #define _WIN32
+ #endif
+ #ifndef __WIN32__
+ #define __WIN32__ 1
+ #endif
+#endif
+
+//---------------------------------------------------------------------------
+//Win64
+#if defined(_WIN64) || defined(WIN64)
+ #ifndef WIN64
+ #define WIN64
+ #endif
+ #ifndef _WIN64
+ #define _WIN64
+ #endif
+ #ifndef __WIN64__
+ #define __WIN64__ 1
+ #endif
+#endif
+
+//---------------------------------------------------------------------------
+//Windows
+#if defined(WIN32) || defined(WIN64)
+ #ifndef WINDOWS
+ #define WINDOWS
+ #endif
+ #ifndef _WINDOWS
+ #define _WINDOWS
+ #endif
+ #ifndef __WINDOWS__
+ #define __WINDOWS__ 1
+ #endif
+#endif
+
+//---------------------------------------------------------------------------
+//Unix (Linux, HP, Sun, BeOS...)
+#if defined(UNIX) || defined(_UNIX) || defined(__UNIX__) \
+ || defined(__unix) || defined(__unix__) \
+ || defined(____SVR4____) || defined(__LINUX__) || defined(__sgi) \
+ || defined(__hpux) || defined(sun) || defined(__SUN__) || defined(_AIX) \
+ || defined(__EMX__) || defined(__VMS) || defined(__BEOS__)
+ #ifndef UNIX
+ #define UNIX
+ #endif
+ #ifndef _UNIX
+ #define _UNIX
+ #endif
+ #ifndef __UNIX__
+ #define __UNIX__ 1
+ #endif
+#endif
+
+//---------------------------------------------------------------------------
+//MacOS Classic
+#if defined(macintosh)
+ #ifndef MACOS
+ #define MACOS
+ #endif
+ #ifndef _MACOS
+ #define _MACOS
+ #endif
+ #ifndef __MACOS__
+ #define __MACOS__ 1
+ #endif
+#endif
+
+//---------------------------------------------------------------------------
+//MacOS X
+#if defined(__APPLE__) && defined(__MACH__)
+ #ifndef MACOSX
+ #define MACOSX
+ #endif
+ #ifndef _MACOSX
+ #define _MACOSX
+ #endif
+ #ifndef __MACOSX__
+ #define __MACOSX__ 1
+ #endif
+#endif
+
+//Test of targets
+#if defined(WINDOWS) && defined(UNIX) && defined(MACOS) && defined(MACOSX)
+ #pragma message Multiple platforms???
+#endif
+
+#if !defined(WIN32) && !defined(UNIX) && !defined(MACOS) && !defined(MACOSX)
+ #pragma message No known platforms, assume default
+#endif
+
+//***************************************************************************
+// Internationnal
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Unicode
+#if defined(_UNICODE) || defined(UNICODE) || defined(__UNICODE__)
+ #ifndef _UNICODE
+ #define _UNICODE
+ #endif
+ #ifndef UNICODE
+ #define UNICODE
+ #endif
+ #ifndef __UNICODE__
+ #define __UNICODE__ 1
+ #endif
+#endif
+
+//---------------------------------------------------------------------------
+//wchar_t stuff
+#if defined(MACOS) || defined(MACOSX)
+ #include <wchar.h>
+#endif
+
+//***************************************************************************
+// Compiler bugs/unuseful warning
+//***************************************************************************
+
+//MSVC6 : for(int t=0; t<10; ++t) { do something }; for(int t=0; t<10; ++t) { do something }
+#if defined(_MSC_VER) && _MSC_VER <= 1200
+ #define for if(true)for
+ #pragma warning(disable:4786) // MSVC6 doesn't like typenames longer than 255 chars (which generates an enormous amount of warnings).
+#endif
+
+//MSVC2005 : "deprecated" warning (replacement functions are not in MinGW32 or Borland!)
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ #pragma warning(disable : 4996)
+#endif
+
+//***************************************************************************
+// (Without Namespace)
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+#include <limits.h>
+
+//---------------------------------------------------------------------------
+#if defined(ZENLIB_DEBUG) && (defined(DEBUG) || defined(_DEBUG))
+ #include "ZenLib/MemoryDebug.h"
+#endif // defined(ZENLIB_DEBUG) && (defined(DEBUG) || defined(_DEBUG))
+
+//***************************************************************************
+// Compiler helpers
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Macro to cut down on compiler warnings
+#ifndef UNUSED
+#define UNUSED(Identifier)
+#endif
+
+//---------------------------------------------------------------------------
+//If we need size_t specific integer conversion
+#if defined(__LP64__) || defined(MACOSX)
+ #define NEED_SIZET
+#endif
+
+//---------------------------------------------------------------------------
+//(-1) is known to be the MAX of an unsigned int but GCC complains about it
+#include <new>
+namespace ZenLib
+{
+ const std::size_t Error=((std::size_t)(-1));
+ const std::size_t All=((std::size_t)(-1));
+ const std::size_t Unlimited=((std::size_t)(-1));
+}
+
+//***************************************************************************
+// (With namespace)
+//***************************************************************************
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// International
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Char types
+#undef _T
+#define _T(__x) __T(__x)
+#undef _TEXT
+#define _TEXT(__x) __T(__x)
+#undef __TEXT
+#define __TEXT(__x) __T(__x)
+#if defined(__UNICODE__)
+ #if defined (_MSC_VER) && !defined (_NATIVE_WCHAR_T_DEFINED)
+ #pragma message Native wchar_t is not defined, not tested, you should put /Zc:wchar_t in compiler options
+ #endif
+ typedef wchar_t Char;
+ #undef __T
+ #define __T(__x) L##__x
+#else // defined(__UNICODE__)
+ typedef char Char;
+ #undef __T
+ #define __T(__x) __x
+#endif // defined(__UNICODE__)
+#ifdef wchar_t
+ typedef wchar_t wchar;
+#endif // wchar_t
+
+//***************************************************************************
+// Platform differences
+//***************************************************************************
+
+//End of line
+extern const Char* EOL;
+extern const Char PathSeparator;
+
+//***************************************************************************
+// Types
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//int
+typedef signed int ints;
+typedef unsigned int intu;
+
+//---------------------------------------------------------------------------
+//8-bit int
+#if UCHAR_MAX==0xff
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 8
+ typedef signed char int8s;
+ typedef unsigned char int8u;
+#else
+ #pragma message This machine has no 8-bit integertype?
+#endif
+
+//---------------------------------------------------------------------------
+//16-bit int
+#if UINT_MAX == 0xffff
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 16
+ typedef signed int int16s;
+ typedef unsigned int int16u;
+#elif USHRT_MAX == 0xffff
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 16
+ typedef signed short int16s;
+ typedef unsigned short int16u;
+#else
+ #pragma message This machine has no 16-bit integertype?
+#endif
+
+//---------------------------------------------------------------------------
+//32-bit int
+#if UINT_MAX == 0xfffffffful
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 32
+ typedef signed int int32s;
+ typedef unsigned int int32u;
+#elif ULONG_MAX == 0xfffffffful
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 32
+ typedef signed long int32s;
+ typedef unsigned long int32u;
+#elif USHRT_MAX == 0xfffffffful
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 32
+ typedef signed short int32s;
+ typedef unsigned short int32u;
+#else
+ #pragma message This machine has no 32-bit integer type?
+#endif
+
+//---------------------------------------------------------------------------
+//64-bit int
+#if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__UNIX__) || defined(__MACOSX__)
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 64
+ typedef signed long long int64s;
+ typedef unsigned long long int64u;
+#elif defined(__WIN32__)
+ #undef MAXTYPE_INT
+ #define MAXTYPE_INT 64
+ typedef signed __int64 int64s;
+ typedef unsigned __int64 int64u;
+#else
+ #pragma message This machine has no 64-bit integer type?
+#endif
+
+//---------------------------------------------------------------------------
+//32-bit float
+#if defined(WINDOWS) || defined(UNIX) || defined(MACOSX)
+ #undef MAXTYPE_FLOAT
+ #define MAXTYPE_FLOAT 32
+ typedef float float32;
+#else
+ #pragma message This machine has no 32-bit float type?
+#endif
+
+//---------------------------------------------------------------------------
+//64-bit float
+#if defined(WINDOWS) || defined(UNIX) || defined(MACOSX)
+ #undef MAXTYPE_FLOAT
+ #define MAXTYPE_FLOAT 64
+ typedef double float64;
+#else
+ #pragma message This machine has no 64-bit float type?
+#endif
+
+//---------------------------------------------------------------------------
+//80-bit float
+#if defined(WINDOWS) || defined(UNIX) || defined(MACOSX)
+ #undef MAXTYPE_FLOAT
+ #define MAXTYPE_FLOAT 80
+ typedef long double float80;
+#else
+ #pragma message This machine has no 80-bit float type?
+#endif
+
+//***************************************************************************
+// Nested functions
+//***************************************************************************
+
+//Unices
+#if defined (UNIX)
+ #define snwprintf swprintf
+#endif
+
+//Windows - MSVC
+#if defined (_MSC_VER)
+ #define snprintf _snprintf
+ #define snwprintf _snwprintf
+#endif
+
+} //namespace
+#endif
+
diff --git a/src/thirdparty/ZenLib/Conf_Internal.h b/src/thirdparty/ZenLib/Conf_Internal.h
new file mode 100644
index 000000000..ba902d505
--- /dev/null
+++ b/src/thirdparty/ZenLib/Conf_Internal.h
@@ -0,0 +1,96 @@
+// ZenLib::Conf_Internal - To be independant of platform & compiler
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenConf_InternalH
+#define ZenConf_InternalH
+//---------------------------------------------------------------------------
+
+#include "ZenLib/Conf.h"
+
+//***************************************************************************
+// Choice of method
+//***************************************************************************
+
+#ifndef ZENLIB_USEWX
+ #ifdef WINDOWS
+ #else
+ #define ZENLIB_STANDARD //We select the C/C++ standard as much as possible
+ #endif
+#endif //ZENLIB_USEWX
+
+//***************************************************************************
+// Default values
+//***************************************************************************
+
+#ifndef _LARGE_FILES
+ #define _LARGE_FILES
+#endif //_LARGE_FILES
+
+//***************************************************************************
+// Includes
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Useful for precompiled headers
+#ifdef ZENLIB_USEWX
+ #ifndef __BORLANDC__ //Borland C++ does NOT support large files
+ #ifndef _FILE_OFFSET_BITS
+ #define _FILE_OFFSET_BITS 64
+ #endif //_FILE_OFFSET_BITS
+ #ifndef _LARGE_FILES
+ #define _LARGE_FILES
+ #endif //_LARGE_FILES
+ #ifndef _LARGEFILE_SOURCE
+ #define _LARGEFILE_SOURCE 1
+ #endif //_LARGEFILE_SOURCE
+ #endif //__BORLANDC__
+ #ifdef __BORLANDC__
+ #include <mem.h> //memcpy
+ #endif //__BORLANDC__
+ #include <wx/wxprec.h>
+#else //ZENLIB_USEWX
+ #if defined(__VISUALC__) || defined(__BORLANDC__)
+ #if defined WINDOWS && !defined ZENLIB_STANDARD
+ #undef __TEXT
+ #include <windows.h>
+ #endif //WINDOWS
+ #include <algorithm>
+ #include <cmath>
+ #include <complex>
+ #include <cstdio>
+ #include <cstdlib>
+ #include <cstring>
+ #include <ctime>
+ #include <fstream>
+ #include <functional>
+ #include <iomanip>
+ #include <map>
+ #include <memory>
+ #include <sstream>
+ #include <stack>
+ #include <string>
+ #endif //defined(__VISUALC__) || defined(__BORLANDC__)
+#endif //ZENLIB_USEWX
+
+#endif
+
diff --git a/src/thirdparty/ZenLib/CriticalSection.cpp b/src/thirdparty/ZenLib/CriticalSection.cpp
new file mode 100644
index 000000000..a5be9ffe7
--- /dev/null
+++ b/src/thirdparty/ZenLib/CriticalSection.cpp
@@ -0,0 +1,199 @@
+// ZenLib::CriticalSection - CriticalSection functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/CriticalSection.h"
+//---------------------------------------------------------------------------
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ZENLIB_USEWX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#ifdef ZENLIB_USEWX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include <wx/thread.h>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+CriticalSection::CriticalSection()
+{
+ CritSect=new wxCriticalSection();
+}
+
+//---------------------------------------------------------------------------
+CriticalSection::~CriticalSection()
+{
+ delete ((wxCriticalSection*)CritSect); //CritSect=NULL;
+}
+
+//***************************************************************************
+// Enter/Leave
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+void CriticalSection::Enter()
+{
+ ((wxCriticalSection*)CritSect)->Enter();
+}
+
+//---------------------------------------------------------------------------
+void CriticalSection::Leave()
+{
+ ((wxCriticalSection*)CritSect)->Leave();
+}
+
+} //Namespace
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// WINDOWS
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#else //ZENLIB_USEWX
+#ifdef WINDOWS
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#undef __TEXT
+#include <windows.h>
+//---------------------------------------------------------------------------
+
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+CriticalSection::CriticalSection()
+{
+ CritSect=new CRITICAL_SECTION;
+ InitializeCriticalSection((CRITICAL_SECTION*)CritSect);
+}
+
+//---------------------------------------------------------------------------
+CriticalSection::~CriticalSection()
+{
+ DeleteCriticalSection((CRITICAL_SECTION*)CritSect);
+ delete ((CRITICAL_SECTION*)CritSect); //CritSect=NULL;
+}
+
+//***************************************************************************
+// Enter/Leave
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+void CriticalSection::Enter()
+{
+ EnterCriticalSection((CRITICAL_SECTION*)CritSect);
+}
+
+//---------------------------------------------------------------------------
+void CriticalSection::Leave()
+{
+ LeaveCriticalSection((CRITICAL_SECTION*)CritSect);
+}
+
+} //Namespace
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// UNIX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#else //WINDOWS
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include <pthread.h>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+CriticalSection::CriticalSection()
+{
+ CritSect=new pthread_mutex_t;
+ pthread_mutex_init((pthread_mutex_t*)CritSect, NULL);
+}
+
+//---------------------------------------------------------------------------
+CriticalSection::~CriticalSection()
+{
+ pthread_mutex_destroy((pthread_mutex_t*)CritSect);
+ delete (pthread_mutex_t*)CritSect;
+}
+
+//***************************************************************************
+// Enter/Leave
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+void CriticalSection::Enter()
+{
+ pthread_mutex_lock((pthread_mutex_t*)CritSect);
+}
+
+//---------------------------------------------------------------------------
+void CriticalSection::Leave()
+{
+ pthread_mutex_unlock((pthread_mutex_t*)CritSect);
+}
+
+} //Namespace
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#endif //WINDOWS
+#endif //ZENLIB_USEWX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
diff --git a/src/thirdparty/ZenLib/CriticalSection.h b/src/thirdparty/ZenLib/CriticalSection.h
new file mode 100644
index 000000000..39ca0333f
--- /dev/null
+++ b/src/thirdparty/ZenLib/CriticalSection.h
@@ -0,0 +1,84 @@
+// ZenLib::CriticalSection - CriticalSection functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// CriticalSection functions
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_CriticalSectionH
+#define ZenLib_CriticalSectionH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#ifdef CS
+ #undef CS //Solaris defines this somewhere
+#endif
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief CriticalSection manipulation
+//***************************************************************************
+
+class CriticalSection
+{
+public :
+ //Constructor/Destructor
+ CriticalSection ();
+ ~CriticalSection ();
+
+ //Enter/Leave
+ void Enter();
+ void Leave();
+
+private :
+ void* CritSect;
+};
+
+//***************************************************************************
+/// @brief CriticalSectionLocker helper
+//***************************************************************************
+
+class CriticalSectionLocker
+{
+public:
+ CriticalSectionLocker (ZenLib::CriticalSection &CS)
+ {
+ CritSec=&CS;
+ CritSec->Enter();
+ }
+
+ ~CriticalSectionLocker ()
+ {
+ CritSec->Leave();
+ }
+
+private:
+ ZenLib::CriticalSection *CritSec;
+};
+
+} //NameSpace
+
+#endif
diff --git a/src/thirdparty/ZenLib/Dir.cpp b/src/thirdparty/ZenLib/Dir.cpp
new file mode 100644
index 000000000..d0a027e6a
--- /dev/null
+++ b/src/thirdparty/ZenLib/Dir.cpp
@@ -0,0 +1,319 @@
+// ZenLib::Dir - Directories functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifdef ZENLIB_USEWX
+ #include <wx/file.h>
+ #include <wx/filename.h>
+ #include <wx/utils.h>
+ #include <wx/dir.h>
+#else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ #undef WINDOWS
+ #endif
+ #ifdef WINDOWS
+ #undef __TEXT
+ #include <windows.h>
+ #else
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #undef __TEXT //dirent include windows.h on Windows/Borland
+ #include <dirent.h>
+ #include <glob.h>
+ #endif
+#endif //ZENLIB_USEWX
+#include "ZenLib/Dir.h"
+#include "ZenLib/File.h"
+#include "ZenLib/FileName.h"
+#include "ZenLib/ZtringList.h"
+#include "ZenLib/OS_Utils.h"
+#include <iostream>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+
+//***************************************************************************
+// Open/Close
+//***************************************************************************
+
+ZtringList Dir::GetAllFileNames(const Ztring &Dir_Name_, dirlist_t Options)
+{
+ ZtringList ToReturn;
+ Ztring Dir_Name=Dir_Name_;
+
+ #ifdef ZENLIB_USEWX
+ int Flags=wxDIR_FILES | wxDIR_DIRS;
+
+ //Search for files
+ wxArrayString Liste;
+ wxFileName FullPath; FullPath=Dir_Name.c_str();
+ //-File
+ if (FullPath.FileExists())
+ {
+ FullPath.Normalize();
+ Liste.Add(FullPath.GetFullPath());
+ }
+ //-Directory
+ else if (FullPath.DirExists())
+ {
+ FullPath.Normalize();
+ wxDir::GetAllFiles(FullPath.GetFullPath(), &Liste, Ztring(), Flags);
+ }
+ //-WildCards
+ else
+ {
+ wxString FileName=FullPath.GetFullName();
+ FullPath.SetFullName(Ztring()); //Supress filename
+ FullPath.Normalize();
+ if (FullPath.DirExists())
+ wxDir::GetAllFiles(FullPath.GetPath(), &Liste, FileName, Flags);
+ }
+
+ //Compatible array
+ ToReturn.reserve(Liste.GetCount());
+ for (size_t Pos=0; Pos<Liste.GetCount(); Pos++)
+ ToReturn.push_back(Liste[Pos].c_str());
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ //Is a dir?
+ if (Exists(Dir_Name))
+ Dir_Name+=_T("\\*");
+
+ //Path
+ Ztring Path=FileName::Path_Get(Dir_Name);
+ if (Path.empty())
+ {
+ #ifdef UNICODE
+ if (IsWin9X())
+ {
+ DWORD Path_Size=GetFullPathNameA(Dir_Name.To_Local().c_str(), 0, NULL, NULL);
+ char* PathTemp=new char[Path_Size+1];
+ if (GetFullPathNameA(Dir_Name.To_Local().c_str(), Path_Size+1, PathTemp, NULL))
+ Path=FileName::Path_Get(PathTemp);
+ delete [] PathTemp; //PathTemp=NULL;
+ }
+ else
+ {
+ DWORD Path_Size=GetFullPathName(Dir_Name.c_str(), 0, NULL, NULL);
+ Char* PathTemp=new Char[Path_Size+1];
+ if (GetFullPathNameW(Dir_Name.c_str(), Path_Size+1, PathTemp, NULL))
+ Path=FileName::Path_Get(PathTemp);
+ delete [] PathTemp; //PathTemp=NULL;
+ }
+ #else
+ DWORD Path_Size=GetFullPathName(Dir_Name.c_str(), 0, NULL, NULL);
+ Char* PathTemp=new Char[Path_Size+1];
+ if (GetFullPathName(Dir_Name.c_str(), Path_Size+1, PathTemp, NULL))
+ Path=FileName::Path_Get(PathTemp);
+ delete [] PathTemp; //PathTemp=NULL;
+ #endif //UNICODE
+ }
+
+ #ifdef UNICODE
+ WIN32_FIND_DATAA FindFileDataA;
+ WIN32_FIND_DATAW FindFileDataW;
+ HANDLE hFind;
+ if (IsWin9X())
+ hFind=FindFirstFileA(Dir_Name.To_Local().c_str(), &FindFileDataA);
+ else
+ hFind=FindFirstFileW(Dir_Name.c_str(), &FindFileDataW);
+ #else
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind=FindFirstFile(Dir_Name.c_str(), &FindFileData);
+ #endif //UNICODE
+
+ if (hFind==INVALID_HANDLE_VALUE)
+ return ZtringList();
+
+ BOOL ReturnValue;
+ do
+ {
+ #ifdef UNICODE
+ Ztring File_Name;
+ if (IsWin9X())
+ File_Name=FindFileDataA.cFileName;
+ else
+ File_Name=FindFileDataW.cFileName;
+ #else
+ Ztring File_Name(FindFileData.cFileName);
+ #endif //UNICODE
+ if (File_Name!=_T(".") && File_Name!=_T("..")) //Avoid . an ..
+ {
+ Ztring File_Name_Complete=Path+_T("\\")+File_Name;
+ if (Exists(File_Name_Complete))
+ {
+ if (Options&Parse_SubDirs)
+ ToReturn+=GetAllFileNames(File_Name_Complete, Options); //A SubDir
+ }
+ else if ((Options&Include_Hidden) || (!File_Name.empty() && File_Name[0]!=_T('.')))
+ ToReturn.push_back(File_Name_Complete); //A file
+ }
+ #ifdef UNICODE
+ if (IsWin9X())
+ ReturnValue=FindNextFileA(hFind, &FindFileDataA);
+ else
+ ReturnValue=FindNextFileW(hFind, &FindFileDataW);
+ #else
+ ReturnValue=FindNextFile(hFind, &FindFileData);
+ #endif //UNICODE
+ }
+ while (ReturnValue);
+
+ FindClose(hFind);
+ #else //WINDOWS
+ //A file?
+ if (File::Exists(Dir_Name))
+ {
+ ToReturn.push_back(Dir_Name); //TODO
+ return ToReturn;
+ }
+
+ //A dir?
+ if (!Dir::Exists(Dir_Name))
+ return ToReturn; //Does not exist
+
+ //open
+ #ifdef UNICODE
+ DIR* Dir=opendir(Dir_Name.To_Local().c_str());
+ #else
+ DIR* Dir=opendir(Dir_Name.c_str());
+ #endif //UNICODE
+ if (Dir)
+ {
+ //This is a dir
+ //Normalizing dir (the / at the end)
+ size_t Dir_Pos=Dir_Name.rfind(FileName_PathSeparator);
+ if (Dir_Pos==std::string::npos)
+ Dir_Name+=FileName_PathSeparator;
+ else if (Dir_Pos+Ztring(FileName_PathSeparator).size()!=Dir_Name.size())
+ Dir_Name+=FileName_PathSeparator;
+
+ struct dirent *DirEnt;
+ while((DirEnt=readdir(Dir))!=NULL)
+ {
+ //A file
+ Ztring File_Name(DirEnt->d_name);
+ if (File_Name!=_T(".") && File_Name!=_T("..")) //Avoid . an ..
+ {
+ Ztring File_Name_Complete=Dir_Name+File_Name;
+ if (Exists(File_Name_Complete))
+ {
+ if (Options&Parse_SubDirs)
+ ToReturn+=GetAllFileNames(File_Name_Complete, Options); //A SubDir
+ }
+ else if ((Options&Include_Hidden) || (!File_Name.empty() && File_Name[0]!=_T('.')))
+ ToReturn.push_back(File_Name_Complete); //A file
+ }
+ }
+
+ //Close it
+ closedir(Dir);
+ }
+ else
+ {
+ glob_t globbuf;
+ if (glob(Dir_Name.To_Local().c_str(), GLOB_NOSORT, NULL, &globbuf)==0)
+ {
+ for (int Pos=0; Pos<globbuf.gl_pathc; Pos++)
+ ToReturn.push_back(Ztring().From_Local(globbuf.gl_pathv[Pos]));
+ }
+ }
+ #endif
+ #endif //ZENLIB_USEWX
+
+ return ToReturn;
+}
+
+//***************************************************************************
+// Helpers
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool Dir::Exists(const Ztring &File_Name)
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(File_Name.c_str());
+ return FN.DirExists();
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ #ifdef UNICODE
+ DWORD FileAttributes;
+ if (IsWin9X())
+ FileAttributes=GetFileAttributesA(File_Name.To_Local().c_str());
+ else
+ FileAttributes=GetFileAttributesW(File_Name.c_str());
+ #else
+ DWORD FileAttributes=GetFileAttributes(File_Name.c_str());
+ #endif //UNICODE
+ return ((FileAttributes!=INVALID_FILE_ATTRIBUTES) && (FileAttributes&FILE_ATTRIBUTE_DIRECTORY));
+ #else //WINDOWS
+ struct stat buffer;
+ int status;
+ #ifdef UNICODE
+ status=stat(File_Name.To_Local().c_str(), &buffer);
+ #else
+ status=stat(File_Name.c_str(), &buffer);
+ #endif //UNICODE
+ return status==0 && S_ISDIR(buffer.st_mode);
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+bool Dir::Create(const Ztring &File_Name)
+{
+ #ifdef ZENLIB_USEWX
+ return wxFileName::Mkdir(File_Name.c_str());
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ #ifdef UNICODE
+ if (IsWin9X())
+ return CreateDirectoryA(File_Name.To_Local().c_str(), NULL)!=0;
+ else
+ return CreateDirectoryW(File_Name.c_str(), NULL)!=0;
+ #else
+ return CreateDirectory(File_Name.c_str(), NULL)!=0;
+ #endif //UNICODE
+ #else //WINDOWS
+ return mkdir(File_Name.To_Local().c_str(), 0700)==0;
+ #endif //WINDOWS
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+//
+//***************************************************************************
+
+} //namespace
+
diff --git a/src/thirdparty/ZenLib/Dir.h b/src/thirdparty/ZenLib/Dir.h
new file mode 100644
index 000000000..b1283d985
--- /dev/null
+++ b/src/thirdparty/ZenLib/Dir.h
@@ -0,0 +1,70 @@
+// ZenLib::Dir - Directories functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Directories functions
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_DirH
+#define ZenLib_DirH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/ZtringList.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Directory manipulation
+//***************************************************************************
+
+class Dir
+{
+public :
+ //---------------------------------------------------------------------------
+ /// @brief Options for Open method
+ enum dirlist_t
+ {
+ Nothing = 0x00, ///<
+ Include_Files = 0x01, ///< Include files
+ Include_Dirs = 0x02, ///< Include directories
+ Include_Hidden = 0x04, ///< Include hidden files
+ Parse_SubDirs = 0x10 ///< Parse subdirectories
+ };
+
+ //Constructor/Destructor
+
+ //Open/close
+ static ZtringList GetAllFileNames(const Ztring &Dir_Name, dirlist_t Options=(dirlist_t)(Include_Files|Parse_SubDirs));
+
+ //Helpers
+ static bool Exists(const Ztring &Dir_Name);
+ static bool Create(const Ztring &Dir_Name);
+};
+
+} //NameSpace
+
+#endif
diff --git a/src/thirdparty/ZenLib/File.cpp b/src/thirdparty/ZenLib/File.cpp
new file mode 100644
index 000000000..be5aa8a72
--- /dev/null
+++ b/src/thirdparty/ZenLib/File.cpp
@@ -0,0 +1,828 @@
+// ZenLib::File - File functions
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifdef ZENLIB_USEWX
+ #include <wx/file.h>
+ #include <wx/filename.h>
+ #include <wx/utils.h>
+#else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ #ifdef WINDOWS
+ #else
+ #include <cstdio>
+ #endif
+ /*
+ #ifdef WINDOWS
+ #include <io.h>
+ #else
+ #include <cstdio>
+ #endif
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #ifndef O_BINARY
+ #define O_BINARY 0
+ #endif
+ */
+ #include <sys/stat.h>
+ #include <fstream>
+ using namespace std;
+ #ifndef S_ISDIR
+ #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
+ #endif
+ #ifndef S_ISREG
+ #define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
+ #endif
+ #elif defined WINDOWS
+ #undef __TEXT
+ #include <windows.h>
+ #endif
+#endif //ZENLIB_USEWX
+#include "ZenLib/File.h"
+#include "ZenLib/OS_Utils.h"
+#include <map>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+File::File()
+{
+ File_Handle=NULL;
+ Position=(int64u)-1;
+ Size=(int64u)-1;
+}
+
+File::File(Ztring File_Name, access_t Access)
+{
+ if (!Open(File_Name, Access))
+ File_Handle=NULL;
+ Position=(int64u)-1;
+ Size=(int64u)-1;
+}
+
+//---------------------------------------------------------------------------
+File::~File()
+{
+ Close();
+}
+
+//***************************************************************************
+// Open/Close
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool File::Open (const tstring &File_Name_, access_t Access)
+{
+ File_Name=File_Name_;
+
+ #ifdef ZENLIB_USEWX
+ File_Handle=(void*)new wxFile();
+ if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
+ {
+ //Sometime the file is locked for few milliseconds, we try again later
+ wxMilliSleep(1000);
+ if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
+ //File is not openable
+ return false;
+ }
+ return true;
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ /*
+ int access;
+ switch (Access)
+ {
+ case Access_Read : access=O_BINARY|O_RDONLY ; break;
+ case Access_Write : access=O_BINARY|O_WRONLY|O_CREAT|O_TRUNC ; break;
+ case Access_Read_Write : access=O_BINARY|O_RDWR |O_CREAT ; break;
+ case Access_Write_Append : access=O_BINARY|O_WRONLY|O_CREAT|O_APPEND ; break;
+ default : access=0 ; break;
+ }
+ #ifdef UNICODE
+ File_Handle=open(File_Name.To_Local().c_str(), access);
+ #else
+ File_Handle=open(File_Name.c_str(), access);
+ #endif //UNICODE
+ return File_Handle!=-1;
+ */
+ ios_base::openmode mode;
+ switch (Access)
+ {
+ case Access_Read : mode=ios_base::binary|ios_base::in; break;
+ case Access_Write : mode=ios_base::binary|ios_base::out; break;
+ case Access_Read_Write : mode=ios_base::binary|ios_base::in|ios_base::out; break;
+ case Access_Write_Append : if (!Exists(File_Name))
+ mode=ios_base::binary|ios_base::out;
+ else
+ mode=ios_base::binary|ios_base::out|ios_base::app;
+ break;
+ default : ;
+ }
+ #ifdef UNICODE
+ File_Handle=new fstream(File_Name.To_Local().c_str(), mode);
+ #else
+ File_Handle=new fstream(File_Name.c_str(), mode);
+ #endif //UNICODE
+ if (!((fstream*)File_Handle)->is_open())
+ {
+ delete (fstream*)File_Handle; File_Handle=NULL;
+ return false;
+ }
+ return true;
+ #elif defined WINDOWS
+ DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
+ switch (Access)
+ {
+ case Access_Read : dwDesiredAccess=IsWin9X()?GENERIC_READ:FILE_READ_DATA; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_EXISTING; break;
+ case Access_Write : dwDesiredAccess=GENERIC_WRITE; dwShareMode=0; dwCreationDisposition=OPEN_ALWAYS; break;
+ case Access_Read_Write : dwDesiredAccess=(IsWin9X()?GENERIC_READ:FILE_READ_DATA)|GENERIC_WRITE; dwShareMode=0; dwCreationDisposition=OPEN_ALWAYS; break;
+ case Access_Write_Append : dwDesiredAccess=GENERIC_WRITE; dwShareMode=0; dwCreationDisposition=OPEN_ALWAYS; break;
+ default : dwDesiredAccess=0; dwShareMode=0; dwCreationDisposition=0; break;
+ }
+
+ #ifdef UNICODE
+ if (IsWin9X())
+ File_Handle=CreateFileA(File_Name.To_Local().c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ else
+ File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #else
+ File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #endif //UNICODE
+ if (File_Handle==INVALID_HANDLE_VALUE)
+ {
+ /*
+ //Sometime the file is locked for few milliseconds, we try again later
+ char lpMsgBuf[1000];
+ DWORD dw = GetLastError();
+ FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ lpMsgBuf,
+ 1000, NULL );
+ */
+ Sleep(1000);
+ #ifdef UNICODE
+ if (IsWin9X())
+ File_Handle=CreateFileA(Ztring(File_Name).To_Local().c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ else
+ File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #else
+ File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #endif //UNICODE
+ }
+ if (File_Handle==INVALID_HANDLE_VALUE)
+ //File is not openable
+ return false;
+
+ //Append
+ if (Access==Access_Write_Append)
+ GoTo(0, FromEnd);
+
+ return true;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+bool File::Create (const Ztring &File_Name, bool OverWrite)
+{
+ #ifdef ZENLIB_USEWX
+ File_Handle=(void*)new wxFile();
+ if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
+ {
+ //Sometime the file is locked for few milliseconds, we try again later
+ wxMilliSleep(3000);
+ if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
+ //File is not openable
+ return false;
+ }
+ return true;
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ /*
+ int access;
+ switch (OverWrite)
+ {
+ case false : access=O_BINARY|O_CREAT|O_WRONLY|O_EXCL ; break;
+ default : access=O_BINARY|O_CREAT|O_WRONLY|O_TRUNC; break;
+ }
+ #ifdef UNICODE
+ File_Handle=open(File_Name.To_Local().c_str(), access);
+ #else
+ File_Handle=open(File_Name.c_str(), access);
+ #endif //UNICODE
+ return File_Handle!=-1;
+ */
+ /*ios_base::openmode mode;
+
+ switch (OverWrite)
+ {
+ //case false : mode= ; break;
+ default : mode=0 ; break;
+ }*/
+ ios_base::openmode access;
+ switch (OverWrite)
+ {
+ case false : if (Exists(File_Name))
+ return false;
+ default : access=ios_base::binary|ios_base::in|ios_base::out|ios_base::trunc; break;
+ }
+ #ifdef UNICODE
+ File_Handle=new fstream(File_Name.To_Local().c_str(), access);
+ #else
+ File_Handle=new fstream(File_Name.c_str(), access);
+ #endif //UNICODE
+ return ((fstream*)File_Handle)->is_open();
+ #elif defined WINDOWS
+ DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
+ switch (OverWrite)
+ {
+ case false : dwDesiredAccess=GENERIC_WRITE; dwShareMode=0; dwCreationDisposition=CREATE_NEW; break;
+ default : dwDesiredAccess=GENERIC_WRITE; dwShareMode=0; dwCreationDisposition=CREATE_ALWAYS; break;
+ }
+
+ #ifdef UNICODE
+ if (IsWin9X())
+ File_Handle=CreateFileA(File_Name.To_Local().c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ else
+ File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #else
+ File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #endif //UNICODE
+ if (File_Handle==INVALID_HANDLE_VALUE)
+ {
+ //Sometime the file is locked for few milliseconds, we try again later
+ Sleep(3000);
+ #ifdef UNICODE
+ if (IsWin9X())
+ File_Handle=CreateFileA(File_Name.To_Local().c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ else
+ File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #else
+ File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
+ #endif //UNICODE
+ }
+ if (File_Handle==INVALID_HANDLE_VALUE)
+ //File is not openable
+ return false;
+ return true;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+void File::Close ()
+{
+ #ifdef ZENLIB_USEWX
+ delete (wxFile*)File_Handle; File_Handle=NULL;
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //close(File_Handle); File_Handle=-1;
+ delete (fstream*)File_Handle; File_Handle=NULL;
+ #elif defined WINDOWS
+ CloseHandle(File_Handle); File_Handle=NULL;
+ #endif
+ #endif //ZENLIB_USEWX
+ Position=(int64u)-1;
+ Size=(int64u)-1;
+}
+
+//***************************************************************************
+// Read/Write
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+size_t File::Read (int8u* Buffer, size_t Buffer_Size_Max)
+{
+ if (File_Handle==NULL)
+ return 0;
+
+ #ifdef ZENLIB_USEWX
+ size_t ByteRead=((wxFile*)File_Handle)->Read(Buffer, Buffer_Size_Max);
+ Position+=ByteRead;
+ return ByteRead;
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //return read((int)File_Handle, Buffer, Buffer_Size_Max);
+ if (Position==(int64u)-1)
+ Position_Get();
+ if (Size==(int64u)-1)
+ Size_Get();
+ if (Position!=(int64u)-1 && Position+Buffer_Size_Max>Size)
+ Buffer_Size_Max=(size_t)(Size-Position); //We don't want to enable eofbit (impossible to seek after)
+ ((fstream*)File_Handle)->read((char*)Buffer, Buffer_Size_Max);
+ size_t ByteRead=((fstream*)File_Handle)->gcount();
+ Position+=ByteRead;
+ return ByteRead;
+ #elif defined WINDOWS
+ DWORD Buffer_Size;
+ if (ReadFile(File_Handle, Buffer, (DWORD)Buffer_Size_Max, &Buffer_Size, NULL))
+ {
+ Position+=Buffer_Size;
+ return Buffer_Size;
+ }
+ else
+ return 0;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+size_t File::Write (const int8u* Buffer, size_t Buffer_Size)
+{
+ #ifdef ZENLIB_USEWX
+ if (File_Handle==NULL)
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //if (File_Handle==-1)
+ if (File_Handle==NULL)
+ #elif defined WINDOWS
+ if (File_Handle==NULL)
+ #endif
+ #endif //ZENLIB_USEWX
+ return 0;
+
+ #ifdef ZENLIB_USEWX
+ return ((wxFile*)File_Handle)->Write(Buffer, Buffer_Size);
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //return write(File_Handle, Buffer, Buffer_Size);
+ ((fstream*)File_Handle)->write((char*)Buffer, Buffer_Size);
+ return ((fstream*)File_Handle)->bad()?0:Buffer_Size;
+ #elif defined WINDOWS
+ DWORD Buffer_Size_Written;
+ if (WriteFile(File_Handle, Buffer, (DWORD)Buffer_Size, &Buffer_Size_Written, NULL))
+ return Buffer_Size_Written;
+ else
+ return 0;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+size_t File::Write (const Ztring &ToWrite)
+{
+ std::string AnsiString=ToWrite.To_UTF8();
+ return Write((const int8u*)AnsiString.c_str(), AnsiString.size());
+}
+
+//***************************************************************************
+// Moving
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool File::GoTo (int64s Position_ToMove, move_t MoveMethod)
+{
+ Position=(int64u)-1; //Disabling memory
+ #ifdef ZENLIB_USEWX
+ return ((wxFile*)File_Handle)->Seek(Position, (wxSeekMode)MoveMethod)!=wxInvalidOffset; //move_t and wxSeekMode are same
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ /*
+ int fromwhere;
+ switch (MoveMethod)
+ {
+ case FromBegin : fromwhere=SEEK_SET; break;
+ case FromCurrent : fromwhere=SEEK_CUR; break;
+ case FromEnd : fromwhere=SEEK_END; break;
+ default : fromwhere=SEEK_CUR; break;
+ }
+ return lseek(File_Handle, Position, fromwhere)!=-1;
+ */
+ ios_base::seekdir dir;
+ switch (MoveMethod)
+ {
+ case FromBegin : dir=ios_base::beg; break;
+ case FromCurrent : dir=ios_base::cur; break;
+ case FromEnd : dir=ios_base::end; break;
+ default : dir=ios_base::beg;
+ }
+ ((fstream*)File_Handle)->seekg((streamoff)Position_ToMove, dir);
+ return !((fstream*)File_Handle)->fail();
+ #elif defined WINDOWS
+ LARGE_INTEGER GoTo; GoTo.QuadPart=Position_ToMove;
+ //return SetFilePointerEx(File_Handle, GoTo, NULL, MoveMethod)!=0; //Not on win9X
+ GoTo.LowPart=SetFilePointer(File_Handle, GoTo.LowPart, &GoTo.HighPart, MoveMethod);
+ if (GoTo.LowPart==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR)
+ return false;
+ else
+ return true;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+int64u File::Position_Get ()
+{
+ if (Position!=(int64u)-1)
+ return Position;
+
+ #ifdef ZENLIB_USEWX
+ return (int64u)-1;
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ Position=((fstream*)File_Handle)->tellg();
+ return Position;
+ #elif defined WINDOWS
+ LARGE_INTEGER GoTo; GoTo.QuadPart=0;
+ GoTo.LowPart=SetFilePointer(File_Handle, GoTo.LowPart, &GoTo.HighPart, FILE_CURRENT);
+ Position=GoTo.QuadPart;
+ return Position;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+// Attributes
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+int64u File::Size_Get()
+{
+ if (Size!=(int64u)-1)
+ return Size;
+
+ if (File_Handle==NULL)
+ return 0;
+
+ #ifdef ZENLIB_USEWX
+ return ((wxFile*)File_Handle)->Length();
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ /*
+ int CurrentPos=lseek(File_Handle, 0, SEEK_CUR);
+ int64u File_Size;
+ File_Size=lseek(File_Handle, 0, SEEK_END);
+ lseek(File_Handle, CurrentPos, SEEK_SET);
+ */
+ streampos CurrentPos=((fstream*)File_Handle)->tellg();
+ if (CurrentPos!=(streampos)-1)
+ {
+ ((fstream*)File_Handle)->seekg(0, ios_base::end);
+ Size=((fstream*)File_Handle)->tellg();
+ ((fstream*)File_Handle)->seekg(CurrentPos, ios_base::beg);
+ }
+ else
+ Size=(int64u)-1;
+ return Size;
+ #elif defined WINDOWS
+ DWORD High;DWORD Low=GetFileSize(File_Handle, &High);
+ if (Low==INVALID_FILE_SIZE && GetLastError()!=NO_ERROR)
+ return (int64u)-1;
+ Size=0x100000000ULL*High+Low;
+ return Size;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring File::Created_Get()
+{
+ #ifdef ZENLIB_USEWX
+ if (File_Handle==NULL)
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //if (File_Handle==-1)
+ if (File_Handle==NULL)
+ #elif defined WINDOWS
+ if (File_Handle==NULL)
+ #endif
+ #endif //ZENLIB_USEWX
+ return Ztring();
+
+ #ifdef ZENLIB_USEWX
+ return Ztring(); //Not implemented
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ return Ztring(); //Not implemented
+ #elif defined WINDOWS
+ FILETIME TimeFT;
+ if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
+ {
+ int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
+ Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
+ return Time;
+ }
+ else
+ return Ztring(); //There was a problem
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring File::Created_Local_Get()
+{
+ #ifdef ZENLIB_USEWX
+ if (File_Handle==NULL)
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //if (File_Handle==-1)
+ if (File_Handle==NULL)
+ #elif defined WINDOWS
+ if (File_Handle==NULL)
+ #endif
+ #endif //ZENLIB_USEWX
+ return Ztring();
+
+ #ifdef ZENLIB_USEWX
+ return Ztring(); //Not implemented
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ return Ztring(); //Not implemented
+ #elif defined WINDOWS
+ FILETIME TimeFT;
+ if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
+ {
+ int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
+ TIME_ZONE_INFORMATION Info;
+ DWORD Result=GetTimeZoneInformation(&Info);
+ if (Result!=TIME_ZONE_ID_INVALID)
+ {
+ Time64-=((int64s)Info.Bias)*60*1000*1000*10;
+ if (Result==TIME_ZONE_ID_DAYLIGHT)
+ Time64-=((int64s)Info.DaylightBias)*60*1000*1000*10;
+ else
+ Time64-=((int64s)Info.StandardBias)*60*1000*1000*10;
+ }
+ Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
+ Time.FindAndReplace(_T("UTC "), _T(""));
+ return Time;
+ }
+ else
+ return Ztring(); //There was a problem
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring File::Modified_Get()
+{
+ #ifdef ZENLIB_USEWX
+ if (File_Handle==NULL)
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ if (File_Handle==NULL)
+ #elif defined WINDOWS
+ if (File_Handle==NULL)
+ #endif
+ #endif //ZENLIB_USEWX
+ return Ztring();
+
+ #ifdef ZENLIB_USEWX
+ return Ztring(); //Not implemented
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ struct stat Stat;
+ int Result=stat(File_Name.To_Local().c_str(), &Stat);
+ if (Result<0)
+ return Ztring(); //Error
+ Ztring Time; Time.Date_From_Seconds_1970(Stat.st_mtime);
+ return Time;
+ #elif defined WINDOWS
+ FILETIME TimeFT;
+ if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
+ {
+ int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
+ Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
+ return Time;
+ }
+ else
+ return Ztring(); //There was a problem
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring File::Modified_Local_Get()
+{
+ #ifdef ZENLIB_USEWX
+ if (File_Handle==NULL)
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //if (File_Handle==-1)
+ if (File_Handle==NULL)
+ #elif defined WINDOWS
+ if (File_Handle==NULL)
+ #endif
+ #endif //ZENLIB_USEWX
+ return Ztring();
+
+ #ifdef ZENLIB_USEWX
+ return Ztring(); //Not implemented
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ struct stat Stat;
+ int Result=stat(File_Name.To_Local().c_str(), &Stat);
+ if (Result<0)
+ return Ztring(); //Error
+ Ztring Time; Time.Date_From_Seconds_1970_Local(Stat.st_mtime);
+ return Time;
+ #elif defined WINDOWS
+ FILETIME TimeFT;
+ if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
+ {
+ int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime; //100-ns
+ TIME_ZONE_INFORMATION Info;
+ DWORD Result=GetTimeZoneInformation(&Info);
+ if (Result!=TIME_ZONE_ID_INVALID)
+ {
+ Time64-=((int64s)Info.Bias)*60*1000*1000*10;
+ if (Result==TIME_ZONE_ID_DAYLIGHT)
+ Time64-=((int64s)Info.DaylightBias)*60*1000*1000*10;
+ else
+ Time64-=((int64s)Info.StandardBias)*60*1000*1000*10;
+ }
+ Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
+ Time.FindAndReplace(_T("UTC "), _T(""));
+ return Time;
+ }
+ else
+ return Ztring(); //There was a problem
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+bool File::Opened_Get()
+{
+ #ifdef ZENLIB_USEWX
+ return File_Handle!=NULL;
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ //return File_Handle!=-1;
+ return File_Handle!=NULL && ((fstream*)File_Handle)->is_open();
+ #elif defined WINDOWS
+ return File_Handle!=NULL;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+// Helpers
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+int64u File::Size_Get(const Ztring &File_Name)
+{
+ File F(File_Name);
+ return F.Size_Get();
+}
+
+//---------------------------------------------------------------------------
+Ztring File::Created_Get(const Ztring &File_Name)
+{
+ File F(File_Name);
+ return F.Created_Get();
+}
+
+//---------------------------------------------------------------------------
+Ztring File::Modified_Get(const Ztring &File_Name)
+{
+ File F(File_Name);
+ return F.Modified_Get();
+}
+
+//---------------------------------------------------------------------------
+bool File::Exists(const Ztring &File_Name)
+{
+ if (File_Name.find(_T('*'))!=std::string::npos || File_Name.find(_T('?'))!=std::string::npos)
+ return false;
+
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(File_Name.c_str());
+ return FN.FileExists();
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ struct stat buffer;
+ int status;
+ #ifdef UNICODE
+ status=stat(File_Name.To_Local().c_str(), &buffer);
+ #else
+ status=stat(File_Name.c_str(), &buffer);
+ #endif //UNICODE
+ return status==0 && S_ISREG(buffer.st_mode);
+ #elif defined WINDOWS
+ #ifdef UNICODE
+ DWORD FileAttributes;
+ if (IsWin9X())
+ FileAttributes=GetFileAttributesA(File_Name.To_Local().c_str());
+ else
+ FileAttributes=GetFileAttributesW(File_Name.c_str());
+ #else
+ DWORD FileAttributes=GetFileAttributes(File_Name.c_str());
+ #endif //UNICODE
+ return ((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY));
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+bool File::Copy(const Ztring &Source, const Ztring &Destination, bool OverWrite)
+{
+ #ifdef ZENLIB_USEWX
+ return wxCopyFile(Source.c_str(), Destination.c_str(), OverWrite);
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ return false;
+ #elif defined WINDOWS
+ #ifdef UNICODE
+ if (IsWin9X())
+ return CopyFileA(Source.To_Local().c_str(), Destination.To_Local().c_str(), !OverWrite)!=0;
+ else
+ return CopyFileW(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
+ #else
+ return CopyFile(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
+ #endif //UNICODE
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+bool File::Move(const Ztring &Source, const Ztring &Destination, bool OverWrite)
+{
+ if (OverWrite && Exists(Source))
+ Delete(Destination);
+ #ifdef ZENLIB_USEWX
+ if (OverWrite && Exists(Destination))
+ wxRemoveFile(Destination.c_str());
+ return wxRenameFile(Source.c_str(), Destination.c_str());
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ return !std::rename(Source.To_Local().c_str(), Destination.To_Local().c_str());
+ #elif defined WINDOWS
+ #ifdef UNICODE
+ if (IsWin9X())
+ return MoveFileA(Source.To_Local().c_str(), Destination.To_Local().c_str())!=0;
+ else
+ return MoveFileW(Source.c_str(), Destination.c_str())!=0;
+ #else
+ return MoveFile(Source.c_str(), Destination.c_str())!=0;
+ #endif //UNICODE
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+bool File::Delete(const Ztring &File_Name)
+{
+ #ifdef ZENLIB_USEWX
+ return wxRemoveFile(File_Name.c_str());
+ #else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ #ifdef UNICODE
+ return remove(File_Name.To_Local().c_str())==0;
+ #else
+ return remove(File_Name.c_str())==0;
+ #endif //UNICODE
+ #elif defined WINDOWS
+ #ifdef UNICODE
+ if (IsWin9X())
+ return DeleteFileA(File_Name.To_Local().c_str())!=0;
+ else
+ return DeleteFileW(File_Name.c_str())!=0;
+ #else
+ return DeleteFile(File_Name.c_str())!=0;
+ #endif //UNICODE
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+//
+//***************************************************************************
+
+} //namespace
+
diff --git a/src/thirdparty/ZenLib/File.h b/src/thirdparty/ZenLib/File.h
new file mode 100644
index 000000000..34f214f6c
--- /dev/null
+++ b/src/thirdparty/ZenLib/File.h
@@ -0,0 +1,112 @@
+// ZenLib::File - File functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// File functions
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_FileH
+#define ZenLib_FileH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/Ztring.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief File manipulation
+//***************************************************************************
+
+class File
+{
+public :
+ //---------------------------------------------------------------------------
+ /// @brief Options for Open method
+ enum access_t
+ {
+ Access_Read = 0, ///< Read permission
+ Access_Write = 1, ///< Write permission
+ Access_Read_Write = 2, ///< Read and Write permissions
+ Access_Write_Append = 3, ///< Write permission without deleting old file
+ Access_Write_Excluding = 4 ///< Write permission preventing reading
+ };
+
+ //---------------------------------------------------------------------------
+ /// @brief Options for Move method
+ enum move_t
+ {
+ FromBegin = 0, ///< Begin of file
+ FromCurrent = 1, ///< Current position
+ FromEnd = 2 ///< End of file
+ };
+
+ //Constructor/Destructor
+ File ();
+ File (ZenLib::Ztring File_Name, access_t Access=Access_Read);
+ ~File ();
+
+ //Open/close
+ bool Open (const tstring &File_Name, access_t Access=Access_Read);
+ bool Create(const ZenLib::Ztring &File_Name, bool OverWrite=true);
+ void Close ();
+
+ //Read/Write
+ size_t Read (int8u* Buffer, size_t Buffer_Size);
+ size_t Write (const int8u* Buffer, size_t Buffer_Size);
+ size_t Write (const Ztring &ToWrite);
+
+ //Moving
+ bool GoTo (int64s Position, move_t MoveMethod=FromBegin);
+ int64u Position_Get ();
+
+ //Attributes
+ int64u Size_Get();
+ Ztring Created_Get();
+ Ztring Created_Local_Get();
+ Ztring Modified_Get();
+ Ztring Modified_Local_Get();
+ bool Opened_Get();
+
+ //Helpers
+ static int64u Size_Get(const Ztring &File_Name);
+ static Ztring Created_Get(const Ztring &File_Name);
+ static Ztring Modified_Get(const Ztring &File_Name);
+ static bool Exists(const Ztring &File_Name);
+ static bool Copy(const Ztring &Source, const Ztring &Destination, bool OverWrite=false);
+ static bool Move(const Ztring &Source, const Ztring &Destination, bool OverWrite=false);
+ static bool Delete(const Ztring &File_Name);
+
+ //Temp
+ Ztring File_Name;
+ int64u Position; //Position is saved, may be not good because position may change
+ int64u Size; //Size is saved, may be not good because size may change
+ void* File_Handle;
+};
+
+} //NameSpace
+
+#endif
diff --git a/src/thirdparty/ZenLib/FileName.cpp b/src/thirdparty/ZenLib/FileName.cpp
new file mode 100644
index 000000000..be3e065d0
--- /dev/null
+++ b/src/thirdparty/ZenLib/FileName.cpp
@@ -0,0 +1,232 @@
+// ZenLib::FileName - File name functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/FileName.h"
+#ifdef ZENLIB_USEWX
+ #include <wx/filename.h>
+#else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ #undef WINDOWS
+ #endif
+ #ifdef WINDOWS
+ #undef __TEXT
+ #include <windows.h>
+ #endif
+#endif //ZENLIB_USEWX
+//---------------------------------------------------------------------------
+#undef ZENLIB_USEWX
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Read/Write
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Ztring FileName::Path_Get() const
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(c_str());
+ return FN.GetPath().c_str();
+ #else //ZENLIB_USEWX
+ //Path limit
+ size_t Pos_Path=rfind(FileName_PathSeparator);
+ if (Pos_Path==Ztring::npos)
+ return Ztring(); //Not found
+ else
+ return Ztring(*this, 0, Pos_Path);
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring& FileName::Path_Set(const Ztring &Path)
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(c_str());
+ FN.SetPath(Path.c_str());
+ assign (FN.GetFullPath().c_str());
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ //Path limit
+ size_t Pos_Path=rfind(_T('\\'));
+ if (Pos_Path==Ztring::npos)
+ {
+ insert(0, 1, _T('\\')); //Not found
+ Pos_Path=0;
+ }
+ replace(0, Pos_Path, Path, 0, Ztring::npos);
+ #else
+ //Not supported
+ #endif
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+Ztring FileName::Name_Get() const
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(c_str());
+ if (FN==FN.GetName()) //Bug of WxWidgets? if C:\\dir\\(no name), name is C:\\dir\\(no name)
+ return Ztring();
+ return FN.GetName().c_str();
+ #else //ZENLIB_USEWX
+ size_t Pos_Path=rfind(FileName_PathSeparator); //Path limit
+ if (Pos_Path==Ztring::npos)
+ Pos_Path=(size_type)-1; //Not found
+ //Extension limit
+ size_t Pos_Ext=rfind(_T('.'));
+ if (Pos_Ext==Ztring::npos || Pos_Ext<Pos_Path)
+ Pos_Ext=size(); //Not found
+ return Ztring(*this, Pos_Path+1, Pos_Ext-Pos_Path-1);
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring& FileName::Name_Set(const Ztring &Name)
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(c_str());
+ if (FN==FN.GetName()) //Bug of WxWidgets? if C:\\dir\\(no name), name is C:\\dir\\(no name)
+ FN.SetPath(c_str());
+ FN.SetName(Name.c_str());
+ assign ((FN.GetFullPath()+FN.GetPathSeparator()/*FileName_PathSeparator*/+FN.GetFullName()).c_str());
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ //Path limit
+ size_t Pos_Path=rfind(_T('\\'));
+ if (Pos_Path==Ztring::npos)
+ Pos_Path=0; //Not found
+ //Extension limit
+ size_t Pos_Ext=rfind(_T('.'));
+ if (Pos_Ext==Ztring::npos || Pos_Ext<Pos_Path)
+ Pos_Ext=size(); //Not found
+ replace(Pos_Path+1, Pos_Ext-Pos_Path-1, Name, 0, Ztring::npos);
+ #else
+ //Not supported
+ #endif
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+Ztring FileName::Extension_Get() const
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(c_str());
+ return FN.GetExt().c_str();
+ #else //ZENLIB_USEWX
+ //Path limit
+ size_t Pos_Path=rfind(FileName_PathSeparator);
+ if (Pos_Path==Ztring::npos)
+ Pos_Path=0; //Not found
+ //Extension limit
+ size_t Pos_Ext=rfind(_T('.'));
+ if (Pos_Ext==Ztring::npos || Pos_Ext<Pos_Path)
+ return Ztring(); //Not found
+ else
+ return Ztring(*this, Pos_Ext+1, size()-Pos_Ext-1);
+ #endif //ZENLIB_USEWX
+}
+
+//---------------------------------------------------------------------------
+Ztring& FileName::Extension_Set(const Ztring &Extension)
+{
+ #ifdef ZENLIB_USEWX
+ wxFileName FN(c_str());
+ FN.SetExt(Extension.c_str());
+ assign (FN.GetFullPath().c_str());
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ //Path limit
+ size_t Pos_Path=rfind(_T('\\'));
+ if (Pos_Path==Ztring::npos)
+ Pos_Path=0; //Not found
+ //Extension limit
+ size_t Pos_Ext=rfind(_T('.'));
+ if (Pos_Ext==Ztring::npos || Pos_Ext<Pos_Path)
+ {
+ append(1, _T('.')); //Not found
+ Pos_Ext=size()-1;
+ }
+ replace(Pos_Ext+1, size()-Pos_Ext-1, Extension, 0, Ztring::npos);
+ #else
+ //Not supported
+ #endif
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+//***************************************************************************
+// Helpers
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Ztring FileName::TempFileName_Create(const Ztring &Prefix)
+{
+ #ifdef ZENLIB_USEWX
+ return wxFileName::CreateTempFileName(Prefix.c_str()).c_str();
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ Char Path[MAX_PATH+1];
+ if (!GetTempPath(MAX_PATH, Path))
+ return Ztring(); //Problem while getting a temp path
+
+ Char FileName[MAX_PATH+1];
+ if (!GetTempFileName(Path, Prefix.c_str(), 0, FileName))
+ return Ztring(); //Problem while getting a file name
+
+ return Ztring(FileName);
+ #else
+ return _T("C:\\xxx.txt");
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+// Platform differences
+//***************************************************************************
+
+//End of line
+#ifdef __WINDOWS__
+ const Char* FileName_PathSeparator=_T("\\");
+#endif
+#ifdef UNIX
+ const Char* FileName_PathSeparator=_T("/");
+#endif
+#ifdef MACOS
+ const Char* FileName_PathSeparator=_T("/");
+#endif
+#ifdef MACOSX
+ const Char* FileName_PathSeparator=_T("/");
+#endif
+
+} //namespace
+
diff --git a/src/thirdparty/ZenLib/FileName.h b/src/thirdparty/ZenLib/FileName.h
new file mode 100644
index 000000000..38cfcacbf
--- /dev/null
+++ b/src/thirdparty/ZenLib/FileName.h
@@ -0,0 +1,81 @@
+// ZenLib::FileName - FileName functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// File name related functions
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_FileNameH
+#define ZenLib_FileNameH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/Ztring.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief File name manipulation
+//***************************************************************************
+
+class FileName : public ZenLib::Ztring
+{
+public :
+ //Constructor/Destructor
+ FileName () : Ztring(){};
+ FileName (const tstring& str) : Ztring(str){};
+ FileName (const tstring& str, size_type pos, size_type n=npos) : Ztring(str, pos, n){};
+ FileName (const Char* s, size_type n) : Ztring(s, n){};
+ FileName (const Char* s) : Ztring(s){};
+ FileName (size_type n, char c) : Ztring(n, c){};
+
+ //Read/Write
+ ZenLib::Ztring Path_Get () const;
+ ZenLib::Ztring Name_Get () const;
+ ZenLib::Ztring Extension_Get () const;
+ ZenLib::Ztring& Path_Set (const Ztring &Path);
+ ZenLib::Ztring& Name_Set (const Ztring &Name);
+ ZenLib::Ztring& Extension_Set (const Ztring &Extension);
+
+ //Helpers
+ static ZenLib::Ztring Path_Get (const Ztring &File_Name) {return ((FileName&)File_Name).Path_Get();};
+ static ZenLib::Ztring Name_Get (const Ztring &File_Name) {return ((FileName&)File_Name).Name_Get();};
+ static ZenLib::Ztring Extension_Get (const Ztring &File_Name) {return ((FileName&)File_Name).Extension_Get();};
+ static ZenLib::Ztring TempFileName_Create (const Ztring &Prefix);
+};
+
+//Platform differences
+extern const Char* FileName_PathSeparator;
+
+} //NameSpace
+
+//---------------------------------------------------------------------------
+#ifdef __BORLANDC__
+ #pragma warn .8027
+#endif
+//---------------------------------------------------------------------------
+
+#endif
diff --git a/src/thirdparty/ZenLib/Format/Html/Html_Handler.cpp b/src/thirdparty/ZenLib/Format/Html/Html_Handler.cpp
new file mode 100644
index 000000000..5bf3ecff0
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Html/Html_Handler.cpp
@@ -0,0 +1,66 @@
+// ZenLib::Format::Html::Handler - A HTML Handler
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Html/Html_Handler.h"
+#include "ZenLib/Ztring.h"
+#include <sstream>
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Html
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Handler::Handler()
+{
+}
+
+//***************************************************************************
+// Helpers
+//***************************************************************************
+
+void Handler::CleanUp()
+{
+}
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
diff --git a/src/thirdparty/ZenLib/Format/Html/Html_Handler.h b/src/thirdparty/ZenLib/Format/Html/Html_Handler.h
new file mode 100644
index 000000000..2d6de898d
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Html/Html_Handler.h
@@ -0,0 +1,91 @@
+// ZenLib::Format::Html::Handler - A HTML Handler
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// A HTML Handler
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_Server_Html_HandlerH
+#define ZenLib_Server_Html_HandlerH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include <string>
+#include <ctime>
+#include <map>
+#include <vector>
+#include "ZenLib/Ztring.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Html
+{
+
+//***************************************************************************
+/// @brief
+//***************************************************************************
+
+struct header
+{
+ //In
+ Ztring Title;
+ Ztring Language;
+
+ //Init
+ header()
+ {
+ }
+};
+
+class Handler
+{
+public:
+ //Constructor/Destructor
+ Handler();
+
+ //Maintenance
+ void CleanUp();
+
+ //The data
+ header Header;
+};
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
+#define ENDL "\r\n"
+#define HTML_ENDL "<br />\r\n"
+
+#endif
+
+
+
+
diff --git a/src/thirdparty/ZenLib/Format/Html/Html_Request.cpp b/src/thirdparty/ZenLib/Format/Html/Html_Request.cpp
new file mode 100644
index 000000000..7e6c6c6c0
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Html/Html_Request.cpp
@@ -0,0 +1,74 @@
+// ZenLib::Server::Html::Request - A HTML request
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Html/Html_Request.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Html
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Request::Request()
+{
+ //Config
+ Html=new ZenLib::Format::Html::Handler;
+ IsCopy=false;
+}
+
+//---------------------------------------------------------------------------
+Request::Request(const Request &Req)
+{
+ //Config
+ Html=Req.Html;
+ IsCopy=true;
+}
+
+//---------------------------------------------------------------------------
+Request::~Request()
+{
+ //Config
+ if (!IsCopy)
+ delete Html; //Html=NULL
+}
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
diff --git a/src/thirdparty/ZenLib/Format/Html/Html_Request.h b/src/thirdparty/ZenLib/Format/Html/Html_Request.h
new file mode 100644
index 000000000..0a7011642
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Html/Html_Request.h
@@ -0,0 +1,77 @@
+// ZenLib::Format::Html::Request - A HTML request
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// A HTML Request
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_Server_Html_RequestH
+#define ZenLib_Server_Html_RequestH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Html/Html_Handler.h"
+#include <string>
+#include <ctime>
+#include <map>
+#include <vector>
+//---------------------------------------------------------------------------
+
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Html
+{
+
+//***************************************************************************
+/// @brief
+//***************************************************************************
+
+class Request
+{
+public:
+ //Constructor/Destructor
+ Request();
+ Request(const Request &Req);
+ ~Request();
+
+ //The data
+ ZenLib::Format::Html::Handler *Html;
+ bool IsCopy;
+};
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
+#endif
+
+
+
+
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Cookies.cpp b/src/thirdparty/ZenLib/Format/Http/Http_Cookies.cpp
new file mode 100644
index 000000000..e402672d1
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Cookies.cpp
@@ -0,0 +1,107 @@
+// ZenLib::Format::Http::Cookies - Cookies handling
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Http/Http_Cookies.h"
+#include "ZenLib/Format/Http/Http_Utils.h"
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Cookies::Cookies()
+{
+}
+
+//***************************************************************************
+// Helpers
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+size_t Cookies::Set(const std::string &Name, const std::string &Value, std::time_t Expires, const std::string &Path, const std::string &Domain, bool Secure)
+{
+ //Name must not be empty
+ if (Name.empty())
+ return 1;
+
+ //Default values handling
+ if (Value.empty())
+ Expires=time(NULL)-365*24*60*60-1; //minus 1 year
+
+ //Default value
+ if (Expires==(time_t)-1)
+ Expires=time(NULL)+1*365*24*60*60; //+1 year
+
+ //Expires can be the count of seconds to handle instead of real time
+ if (Expires>=0 && Expires<3*365*24*60*60) //Les than year 1973, this is not a date, this is a time
+ Expires+=time(NULL);
+
+ //Registering
+ Cookie Data;
+ Data.Value=Value.empty()?std::string("Deleted"):URL_Encoded_Encode(Value); //If no value, we force a default value for having the cookie understable
+ Data.Expires=Expires;
+ Data.Path=URL_Encoded_Encode(Path.empty()?string("/"):Path);
+ Data.Domain=URL_Encoded_Encode(Domain);
+ Data.Secure=Secure;
+ (*this)[URL_Encoded_Encode(Name)]=Data;
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+void Cookies::Create_Lines(std::ostream& Out)
+{
+ for (Cookies::iterator Cookie=begin(); Cookie!=end(); Cookie++)
+ {
+ Out << "Set-Cookie: " << Cookie->first << "=" << Cookie->second.Value;
+ if (Cookie->second.Expires!=(time_t)-1)
+ {
+ char Temp[200];
+ if (strftime(Temp, 200, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&Cookie->second.Expires)))
+ Out << "; expires=" << Temp;
+ }
+ if (!Cookie->second.Path.empty())
+ {
+ Out << "; path=" << Cookie->second.Path;
+ }
+ Out << "\r\n";
+ }
+}
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Cookies.h b/src/thirdparty/ZenLib/Format/Http/Http_Cookies.h
new file mode 100644
index 000000000..94030ec69
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Cookies.h
@@ -0,0 +1,91 @@
+// ZenLib::Format::Http::Cookies - Cookies handling
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Cookies handling
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_Format_Http_CookiesH
+#define ZenLib_Format_Http_CookiesH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include <string>
+#include <ctime>
+#include <map>
+#include <sstream>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+/// @brief
+//***************************************************************************
+
+struct Cookie
+{
+ std::string Value;
+ std::time_t Expires;
+ std::string Path;
+ std::string Domain;
+ bool Secure;
+
+ Cookie()
+ {
+ Expires=0;
+ Secure=false;
+ }
+};
+
+extern std::string EmptyString; //Must not change
+
+class Cookies : public std::map<std::string, Cookie>
+{
+public :
+ //Constructor/Destructor
+ Cookies();
+
+ //Helpers
+ size_t Set(const std::string &Name, const std::string &Value=EmptyString, std::time_t Expires=(std::time_t)-1, const std::string &Path=EmptyString, const std::string &Domain=EmptyString, bool Secure=false);
+ Cookie &Get(const std::string &Name);
+ void Create_Lines(std::ostream& Out);
+};
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
+#endif
+
+
+
+
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Handler.cpp b/src/thirdparty/ZenLib/Format/Http/Http_Handler.cpp
new file mode 100644
index 000000000..8efb22ec9
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Handler.cpp
@@ -0,0 +1,65 @@
+// ZenLib::Format::Http::Handler - A HTTP Handler
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Http/Http_Handler.h"
+#include "ZenLib/Ztring.h"
+#include <sstream>
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Handler::Handler()
+{
+ //In
+ Foreign_Port=0;
+ Local_Port=0;
+ HeadersOnly=false;
+
+ //Out
+ Response_HTTP_Code=200;
+}
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Handler.h b/src/thirdparty/ZenLib/Format/Http/Http_Handler.h
new file mode 100644
index 000000000..9c2d9090d
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Handler.h
@@ -0,0 +1,87 @@
+// ZenLib::Format::Http::Request - A HTTP request
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// A HTTP Request
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_Format_Http_RequestH
+#define ZenLib_Format_Http_RequestH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Http/Http_Cookies.h"
+#include <string>
+#include <ctime>
+#include <map>
+#include <vector>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+/// @brief
+//***************************************************************************
+
+class Handler
+{
+public:
+ //Constructor/Destructor
+ Handler();
+
+ //In
+ std::string Path; //The path being requested by this request
+ std::map<std::string, std::string> Request_Headers; //All the incoming HTTP headers from the client web browser.
+ std::map<std::string, std::string> Request_Cookies; //The set of cookies that came from the client along with this request
+ std::map<std::string, std::string> Request_Queries; //All the key/value pairs in the query string of this request
+ std::string Foreign_IP; //The foreign ip address for this request
+ std::string Local_IP; //The foreign port number for this request
+ unsigned short Foreign_Port; //The IP of the local interface this request is coming in on
+ unsigned short Local_Port; //The local port number this request is coming in on
+ bool HeadersOnly; //The request requests only the header
+
+ //Out
+ size_t Response_HTTP_Code; //HTTP code to be sent
+ std::map<std::string, std::string> Response_Headers; //Additional headers you wish to appear in the HTTP response to this request
+ Cookies Response_Cookies; //New cookies to pass back to the client along with the result of this request
+ std::string Response_Body; //To be displayed as the response to this request
+};
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
+#endif
+
+
+
+
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Request.cpp b/src/thirdparty/ZenLib/Format/Http/Http_Request.cpp
new file mode 100644
index 000000000..81a4e3a44
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Request.cpp
@@ -0,0 +1,250 @@
+// ZenLib::Server::Http::Request - A HTTP request
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Http/Http_Request.h"
+#include "ZenLib/Format/Http/Http_Utils.h"
+#include "ZenLib/Ztring.h"
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Request::Request()
+{
+ //Config
+ Http=new ZenLib::Format::Http::Handler;
+ IsCopy=false;
+}
+
+//---------------------------------------------------------------------------
+Request::Request(const Request &Req)
+{
+ //Config
+ Http=Req.Http;
+ IsCopy=true;
+}
+
+//---------------------------------------------------------------------------
+Request::~Request()
+{
+ //Config
+ if (!IsCopy)
+ delete Http; //Http=NULL
+}
+
+//***************************************************************************
+//
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool Request::Http_Begin(std::istream &In, std::ostream &Out)
+{
+ //First line, "Method Path Norm"
+ //-Method
+ string Method;
+ In>>Method;
+ if (Method.size()==3 && Method[0]=='G' && Method[1]=='E' && Method[2]=='T')
+ ;
+ else if (Method.size()==4 && Method[0]=='P' && Method[1]=='O' && Method[2]=='S' && Method[3]=='T')
+ ;
+ else if (Method.size()==4 && Method[0]=='H' && Method[1]=='E' && Method[2]=='A' && Method[2]=='D')
+ Http->HeadersOnly=true;
+ else
+ {
+ Out << "HTTP/1.0 501\r\n";
+ Out << "\r\n";
+ return false; //Unknown request
+ }
+ //-Path
+ In>>Http->Path;
+ if (Http->Path.empty() || Http->Path[0]!='/')
+ {
+ Out << "HTTP/1.0 404\r\n";
+ Out << "\r\n";
+ return false; //Problem
+ }
+ if (Http->Path.find("%")!=string::npos)
+ Http->Path=Format::Http::URL_Encoded_Decode(Http->Path);
+ //-Norm
+ string Line;
+ getline(In, Line); //Drop the first line, no more needed
+
+ //Headers
+ do
+ {
+ //Getting the line
+ getline(In, Line);
+ if (!Line.empty() && Line[Line.size()-1]=='\r')
+ Line.resize(Line.size()-1); //Remove the \r
+
+ //Processing the line, form is "aaa: bbb"
+ if (!Line.empty())
+ {
+ string::size_type Separator_Pos=Line.find(':');
+ string::size_type Content_Begin=Line.find_first_not_of(' ', Separator_Pos+1);
+ if (Separator_Pos!=string::npos && Content_Begin!=string::npos)
+ {
+ string Command=Line.substr(0, Separator_Pos);
+ if (Command=="Cookie")
+ {
+ string Cookie=Line.substr(Separator_Pos+1, string::npos);
+ while (!Cookie.empty())
+ {
+ string::size_type Cookie_Pos=Cookie.rfind(';');
+ if (Cookie_Pos==string::npos)
+ Cookie_Pos=(string::size_type)-1;
+ string Line2=Cookie.substr(Cookie_Pos+1, string::npos);
+ TrimLeft(Line2, ' ');
+ if (Cookie_Pos!=(string::size_type)-1)
+ {
+ Cookie.resize(Cookie_Pos);
+ TrimLeft(Line2, ' ');
+ }
+ else
+ Cookie.clear();
+
+ string::size_type Separator_Pos2=Line2.find('=');
+ if (Separator_Pos2!=string::npos)
+ Http->Request_Cookies[Line2.substr(0, Separator_Pos2)]=Format::Http::URL_Encoded_Decode(Line2.substr(Separator_Pos2+1, string::npos));
+ }
+ }
+ else
+ Http->Request_Headers[Command]=Line.substr(Content_Begin, string::npos);
+ }
+ }
+ }
+ while (!Line.empty());
+
+ //Info
+ if (Method.size()==3 && Method[0]=='G' && Method[1]=='E' && Method[2]=='T'
+ || Method.size()==4 && Method[0]=='P' && Method[1]=='O' && Method[2]=='S' && Method[3]=='T')
+ {
+ do
+ {
+ string Content;
+
+ //Getting the line
+ string::size_type Interogation_Pos=Http->Path.find('?');
+ if (Interogation_Pos!=string::npos)
+ {
+ Content=Http->Path.substr(Interogation_Pos+1, string::npos);
+ Http->Path.resize(Interogation_Pos);
+ }
+
+ if (Method.size()==4) //Only for POST
+ {
+ int64u Content_Lengh=0;
+ std::map<std::string, std::string>::iterator Header_Content_Lengh_Element=Http->Request_Headers.find("Content-Length");
+ if (Header_Content_Lengh_Element==Http->Request_Headers.end())
+ Header_Content_Lengh_Element=Http->Request_Headers.find("Content-length");
+ if (Header_Content_Lengh_Element!=Http->Request_Headers.end())
+ #ifdef UNICODE
+ Content_Lengh=Ztring().From_UTF8(Header_Content_Lengh_Element->second).To_int64u();
+ #else
+ Content_Lengh=Ztring(Header_Content_Lengh_Element->second).To_int64u();
+ #endif
+ if (Content_Lengh>1024) //Verifying there is no big element
+ {
+ Out << "HTTP/1.0 501\r\n";
+ Out << "\r\n";
+ return false; //Malformed request
+ }
+
+ size_t Content_Size_Current=Content.size();
+ if (Content_Size_Current)
+ {
+ Content+='&';
+ Content_Size_Current++;
+ }
+ Content.resize(Content_Size_Current+(size_t)Content_Lengh+1);
+ In.read(&Content[Content_Size_Current], (streamsize)Content_Lengh);
+ Content[Content_Size_Current+(size_t)Content_Lengh]='\0';
+ }
+
+ //Processing the line, form is "aaa=bbb&..."
+ while (!Content.empty())
+ {
+ string::size_type Content_Pos=Content.rfind('&');
+ if (Content_Pos==string::npos)
+ Content_Pos=(string::size_type)-1;
+ std::string Line2=Content.substr(Content_Pos+1, string::npos);
+ if (Content_Pos!=(string::size_type)-1)
+ Content.resize(Content_Pos);
+ else
+ Content.clear();
+
+ string::size_type Separator_Pos=Line2.find('=');
+ if (Separator_Pos!=string::npos)
+ Http->Request_Queries[Line2.substr(0, Separator_Pos)]=Format::Http::URL_Encoded_Decode(Line2.substr(Separator_Pos+1, string::npos));
+ }
+ }
+ while (!Line.empty());
+ }
+
+ return true;
+}
+
+void Request::Http_End(std::ostream &Out)
+{
+ Out << "HTTP/1.0 "<< Http->Response_HTTP_Code << "\r\n";
+ for (std::map<std::string, std::string>::iterator Temp=Http->Response_Headers.begin(); Temp!=Http->Response_Headers.end(); Temp++)
+ Out << Temp->first << ": " << Temp->second << "\r\n";
+ Http->Response_Cookies.Create_Lines(Out);
+ std::map<std::string, std::string>::iterator Content_Type_Element=Http->Response_Headers.find("Content-Type");
+ if (Content_Type_Element!=Http->Response_Headers.end())
+ Out << "Content-Type: "<< Content_Type_Element->second << "\r\n";
+ else if (Http->Response_HTTP_Code==200)
+ {
+ if (!Http->Response_Body.empty() && Http->Response_Body[0]=='<')
+ Out << "Content-Type: "<< "text/html; charset=utf-8" << "\r\n";
+ }
+ if (!Http->Response_Body.empty())
+ Out << "Content-Length: " << Http->Response_Body.size() << "\r\n";
+ Out << "\r\n";
+ if (!Http->HeadersOnly && !Http->Response_Body.empty())
+ Out << Http->Response_Body.c_str();
+}
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Request.h b/src/thirdparty/ZenLib/Format/Http/Http_Request.h
new file mode 100644
index 000000000..c7e5df9b5
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Request.h
@@ -0,0 +1,81 @@
+// ZenLib::Format::Http::Request - A HTTP request
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// A HTTP Request
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_Server_Http_RequestH
+#define ZenLib_Server_Http_RequestH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Http/Http_Handler.h"
+#include <string>
+#include <ctime>
+#include <map>
+#include <vector>
+//---------------------------------------------------------------------------
+
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+/// @brief
+//***************************************************************************
+
+class Request
+{
+public:
+ //Constructor/Destructor
+ Request();
+ Request(const Request &Req);
+ ~Request();
+
+ //The data
+ ZenLib::Format::Http::Handler *Http;
+ bool IsCopy;
+
+ //Helpers
+ bool Http_Begin(std::istream &In, std::ostream &Out);
+ void Http_End (std::ostream &Out);
+};
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
+#endif
+
+
+
+
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Utils.cpp b/src/thirdparty/ZenLib/Format/Http/Http_Utils.cpp
new file mode 100644
index 000000000..6ac726ca3
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Utils.cpp
@@ -0,0 +1,160 @@
+// ZenLib::Server::Http::Utils - Utils for HTTP handling
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Format/Http/Http_Utils.h"
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+// Global variables
+//***************************************************************************
+
+std::string EmptyString;
+
+//***************************************************************************
+// Character manipulation
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+unsigned char Char2Hex (unsigned char Char)
+{
+ if (Char<='9' && Char>='0')
+ Char-='0';
+ else if (Char<='f' && Char>='a')
+ Char-='a'-10;
+ else if (Char<='F' && Char>='A')
+ Char-='A'-10;
+ else
+ Char =0;
+ return Char;
+}
+
+//---------------------------------------------------------------------------
+string Hex2Char (unsigned char Char)
+{
+ string Result;
+ Result+=(char)((Char/16>=10?'a'-10:'0')+Char/16);
+ Result+=(char)((Char%16>=10?'a'-10:'0')+Char%16);
+ return Result;
+}
+
+//***************************************************************************
+// URL manipulation
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+std::string URL_Encoded_Encode (const std::string& URL)
+{
+ string Result;
+ string::size_type Pos;
+ for (Pos=0; Pos<URL.size(); Pos++)
+ {
+ if ((URL[Pos]>='\x00' && URL[Pos]<='\x20')
+ || URL[Pos]=='\0x7F'
+ || URL[Pos]==' '
+ || URL[Pos]=='<'
+ || URL[Pos]=='>'
+ || URL[Pos]=='#'
+ || URL[Pos]=='%'
+ || URL[Pos]=='\"'
+ || URL[Pos]=='{'
+ || URL[Pos]=='}'
+ || URL[Pos]=='|'
+ || URL[Pos]=='\\'
+ || URL[Pos]=='^'
+ || URL[Pos]=='['
+ || URL[Pos]==']'
+ || URL[Pos]=='`'
+ /*|| URL[Pos]==';'
+ || URL[Pos]=='/'
+ || URL[Pos]=='?'
+ || URL[Pos]==':'
+ || URL[Pos]=='@'
+ || URL[Pos]=='&'
+ || URL[Pos]=='='
+ || URL[Pos]=='+'
+ || URL[Pos]=='$'
+ || URL[Pos]==','*/)
+ Result+='%'+Hex2Char(URL[Pos]);
+ else
+ Result+=URL[Pos];
+ }
+ return Result;
+}
+
+//---------------------------------------------------------------------------
+std::string URL_Encoded_Decode (const std::string& URL)
+{
+ string Result;
+ string::size_type Pos;
+ for (Pos=0; Pos<URL.size(); Pos++)
+ {
+ if (URL[Pos]=='%' && Pos+2<URL.size()) //At least 3 chars
+ {
+ const unsigned char Char1 = Char2Hex(URL[Pos+1]);
+ const unsigned char Char2 = Char2Hex(URL[Pos+2]);
+ const unsigned char Char = (Char1<<4) | Char2;
+ Result+=Char;
+ Pos+=2; //3 chars are used
+ }
+ else if (URL[Pos]=='+')
+ Result+=' ';
+ else
+ Result+=URL[Pos];
+ }
+ return Result;
+}
+
+//***************************************************************************
+// Cleanup
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+void TrimLeft (std::string& String, char ToTrim)
+{
+ string::size_type First=0;
+ while (String.operator[](First)==ToTrim)
+ First++;
+ String.assign (String.c_str()+First);
+}
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
diff --git a/src/thirdparty/ZenLib/Format/Http/Http_Utils.h b/src/thirdparty/ZenLib/Format/Http/Http_Utils.h
new file mode 100644
index 000000000..50537cef5
--- /dev/null
+++ b/src/thirdparty/ZenLib/Format/Http/Http_Utils.h
@@ -0,0 +1,76 @@
+// ZenLib::Format::Http::Utils - Utils for HTTP handling
+// Copyright (C) 2008-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// HTTP utils
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_Server_Http_UtilsH
+#define ZenLib_Server_Http_UtilsH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include <string>
+#include <ctime>
+#include <map>
+#include <vector>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+namespace Format
+{
+
+namespace Http
+{
+
+//***************************************************************************
+//
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Character manipulation
+unsigned char Char2Hex (unsigned char Char);
+std::string Hex2Char (unsigned char Char);
+
+//---------------------------------------------------------------------------
+// URL manipulation
+std::string URL_Encoded_Encode (const std::string& URL);
+std::string URL_Encoded_Decode (const std::string& URL);
+
+//---------------------------------------------------------------------------
+// Cleanup
+void TrimLeft (std::string& String, char ToTrim);
+
+} //Namespace
+
+} //Namespace
+
+} //Namespace
+
+#endif //ZENLIB_SERVER_HTTP_UTILS
+
+
+
+
diff --git a/src/thirdparty/ZenLib/HTTP_Client.cpp b/src/thirdparty/ZenLib/HTTP_Client.cpp
new file mode 100644
index 000000000..947f54572
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client.cpp
@@ -0,0 +1,135 @@
+// ZenLib::HTTPClient - Basic HTTP client
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/HTTP_Client.h"
+#ifdef WINDOWS
+ #undef __TEXT
+ #include <windows.h>
+#endif //WINDOWS
+#include "ZenLib/HTTP_Client/HTTPClient.h"
+using namespace ZenLib;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+HTTP_Client::HTTP_Client ()
+{
+ #ifdef WINDOWS
+ WSADATA WsaData;
+ WSAStartup(MAKEWORD(1, 2), &WsaData);
+ #endif
+ Handle=0;
+}
+
+//---------------------------------------------------------------------------
+HTTP_Client::~HTTP_Client ()
+{
+ #ifdef WINDOWS
+ WSACleanup();
+ #endif
+}
+
+//***************************************************************************
+// Open/Close
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+int HTTP_Client::Open (Ztring Url)
+{
+ if (Handle)
+ Close();
+
+ //init
+ Handle=HTTPClientOpenRequest(0);
+
+ //Mehtod
+ if (HTTPClientSetVerb(Handle, VerbGet)!=0)
+ {
+ Close();
+ return 0;
+ }
+
+ //Send request
+ if (HTTPClientSendRequest(Handle, (char*)(Url.To_Local().c_str()), NULL, 0, FALSE, 0, 0)!=0)
+ {
+ Close();
+ return 0;
+ }
+
+ //Receive response
+ if (HTTPClientRecvResponse(Handle, 3)!=0)
+ {
+ Close();
+ return 0;
+ }
+
+ return 1;
+}
+
+//---------------------------------------------------------------------------
+void HTTP_Client::Close ()
+{
+ HTTPClientCloseRequest(&Handle);
+ Handle=0;
+}
+
+//***************************************************************************
+// Read
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Ztring HTTP_Client::Read ()
+{
+ if (Handle==0)
+ return Ztring();
+
+ char* Buffer=new char[16384];
+ int32u Size=0;
+
+ int32u ReturnValue=HTTPClientReadData(Handle, Buffer, 16384, 0, &Size);
+ if (ReturnValue!=0 && ReturnValue!=1000) //End of stream
+ {
+ Close();
+ delete[] Buffer;
+ return Ztring();
+ }
+
+ Ztring ToReturn; ToReturn.From_Local(Buffer, Size);
+ delete[] Buffer;
+ return ToReturn;
+}
+
+} //namespace
+
diff --git a/src/thirdparty/ZenLib/HTTP_Client.h b/src/thirdparty/ZenLib/HTTP_Client.h
new file mode 100644
index 000000000..c30437f3a
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client.h
@@ -0,0 +1,64 @@
+// ZenLib::HTTPClient - Basic HTTP client
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Basic HTTP client
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_HTTPClientH
+#define ZenLib_HTTPClientH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/Ztring.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Basic HTTP client
+//***************************************************************************
+
+class HTTP_Client
+{
+public :
+ //Constructor/Destructor
+ HTTP_Client ();
+ ~HTTP_Client ();
+
+ //Open/Close
+ int Open (Ztring URL);
+ void Close ();
+
+ //Read
+ Ztring Read();
+
+private :
+ int32u Handle;
+};
+
+} //NameSpace
+
+#endif
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClient.c b/src/thirdparty/ZenLib/HTTP_Client/HTTPClient.c
new file mode 100644
index 000000000..0f5900947
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClient.c
@@ -0,0 +1,3646 @@
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Module Name:
+// HTTPClient.c
+//
+// Abstract: Partially Implements the client side of the HTTP 1.1 Protocol as
+// Defined in RFC 2616,2617
+// Platform: Any that supports standard C calls and Berkeley sockets
+//
+// Author: Eitan Michaelson
+// Version: 1.0
+// Date 7/1/2006
+// Opens: HTTP Proxy authentication support (not fully tested).
+// HTTP Keep Alive not impliamented
+// HTTPS not implemented
+// The HTTP counters are not 100% correct (will be fixed)
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "HTTPClient.h"
+#include "HTTPClientAuth.h" // Crypto support (Digest, MD5)
+#include "HTTPClientString.h" // String utilities
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSetLocalConnection
+// Purpose : TBD
+// Gets :
+// Returns :
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSetLocalConnection (HTTP_SESSION_HANDLE pSession, UINT32 nPort)
+{
+
+ return 0;
+}
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientOpenRequest
+// Purpose : Allocate memory for a new HTTP Session
+// Gets : FLAGS
+// Returns : HTTP Session handle
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags)
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL; // Handle to the session pointer
+ UINT32 nAllocationSize; // Size of the dynamically allocated buffer
+
+ // Attempt to allocate the buffer
+ pHTTPSession = (P_HTTP_SESSION)malloc(ALIGN(sizeof(HTTP_SESSION)));
+
+ // Did we succeed?
+ if(!pHTTPSession)
+ {
+ // Null pointer is returned upon error
+ return 0;
+ }
+ // Reset the allocated space to zeros
+ memset(pHTTPSession,0x00,sizeof(HTTP_SESSION));
+
+ // Allocate space for the incoming and outgoing headers
+ // Check if the headers buffer is resizable
+ if(HTTP_CLIENT_MEMORY_RESIZABLE)
+ {
+ // Memory is resizable, so use the init defined size or the maximum buffer size (which ever is smaller)
+ nAllocationSize = MIN(HTTP_CLIENT_MAX_SEND_RECV_HEADERS,HTTP_CLIENT_INIT_SEND_RECV_HEADERS);
+
+ }
+ else
+ {
+ // Memory is not resizable so simply use the maximum defined size
+ nAllocationSize = HTTP_CLIENT_MAX_SEND_RECV_HEADERS;
+ }
+ // Allocate the headers buffer
+ pHTTPSession->HttpHeaders.HeadersBuffer.pParam = (CHAR*)malloc(ALIGN(nAllocationSize));
+ // Check the returned pointer
+ if(!pHTTPSession->HttpHeaders.HeadersBuffer.pParam)
+ {
+ // malloc() error, free the containing structure and exit.
+ free(pHTTPSession);
+ return 0;
+
+ }
+
+ // Reset the headers allocated memory
+ memset(pHTTPSession->HttpHeaders.HeadersBuffer.pParam ,0x00,nAllocationSize);
+ // Set the buffer length
+ pHTTPSession->HttpHeaders.HeadersBuffer.nLength = nAllocationSize;
+
+ // Set default values in the session structure
+ HTTPClientSetVerb((UINT32)pHTTPSession,(HTTP_VERB)HTTP_CLIENT_DEFAULT_VERB); // Default HTTP verb
+ pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_PORT; // Default TCP port
+ pHTTPSession->HttpConnection.HttpSocket = HTTP_INVALID_SOCKET; // Invalidate the socket
+ // Set the outgoing headers pointers
+ pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam;
+ // Set our state
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_INIT;
+
+ // Save the flags
+ pHTTPSession->HttpFlags = Flags;
+
+ // Reset the status
+ pHTTPSession->HttpHeadersInfo.nHTTPStatus = 0;
+ // Return an allocated session pointer (cast to UINT32 first)
+ return (HTTP_SESSION_HANDLE)pHTTPSession;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientReset
+// Purpose : Reset the HTTP session and make it ready for another call
+// Gets : FLAGS
+// Returns : HTTP Session handle
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientReset (HTTP_SESSION_HANDLE pSession)
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ return HTTPIntrnSessionReset(pHTTPSession,TRUE);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Function : HTTPClientCloseRequest
+// Purpose : Closes any active connection and free any used memory
+// Gets : a Session handle
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession)
+{
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)*(pSession);
+ if(!pHTTPSession)
+ {
+ // User passed a bad pointer
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ // Check for a valid pointer to the HTTP headers
+ if(pHTTPSession->HttpHeaders.HeadersBuffer.pParam)
+ {
+ // Release the used memory
+ free(pHTTPSession->HttpHeaders.HeadersBuffer.pParam);
+ }
+ // Close any active socket connection
+ HTTPIntrnConnectionClose(pHTTPSession);
+ // free the session structure
+ free(pHTTPSession);
+
+ pHTTPSession = 0; // NULL the pointer
+ *(pSession) = 0;
+
+ return HTTP_CLIENT_SUCCESS;
+}
+
+#ifdef _HTTP_DEBUGGING_
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSetDebugHook
+// Purpose : Sets the HTTP debug function pointer
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSetDebugHook (HTTP_SESSION_HANDLE pSession,
+ E_HTTPDebug *pDebug) // [IN] Function pointer to the the caller debugging function)
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ pHTTPSession->pDebug = pDebug;
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientSetDebugHook",NULL,0,"Debugging hook set, return code is %d",HTTP_CLIENT_SUCCESS);
+ }
+#endif
+
+
+ return HTTP_CLIENT_SUCCESS;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSetVerb
+// Purpose : Sets the HTTP verb for the outgoing request
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession,
+ HTTP_VERB HttpVerb) // [IN] Http verb (GET POST HEAD act')
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientSetVerb",NULL,0,"Selected Verb is %d",(INT32)HttpVerb);
+ }
+#endif
+
+ // Cache the verb (as integer) for later use
+ pHTTPSession->HttpHeaders.HttpVerb = HttpVerb;
+
+ // Convert the Verb parameter into its equivalent string representation
+ switch (HttpVerb)
+ {
+ case VerbGet:
+ strcpy(pHTTPSession->HttpHeaders.Verb,"GET");
+ break;
+ case VerbHead:
+ if(!HTTP_CLIENT_ALLOW_HEAD_VERB)
+ {
+ return HTTP_CLIENT_ERROR_BAD_VERB;
+ }
+ strcpy(pHTTPSession->HttpHeaders.Verb,"HEAD");
+ break;
+ case VerbPost:
+ strcpy(pHTTPSession->HttpHeaders.Verb,"POST");
+ break;
+ default:
+ // Unknown verb
+ return HTTP_CLIENT_ERROR_BAD_VERB;
+ };
+
+ return HTTP_CLIENT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSetVerb
+// Purpose : Sets the HTTP authentication schema
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession,
+ HTTP_AUTH_SCHEMA AuthSchema, // The type of the authentication to perform
+ void *pReserved)
+{
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientSetAuth",NULL,0,"Selected authentication is %d",(INT32)AuthSchema);
+ }
+#endif
+
+ switch(AuthSchema)
+ {
+ case(AuthSchemaBasic):
+ strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"basic");
+ break;
+ case(AuthSchemaDigest):
+ strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"digest");
+ break;
+ case(AuthSchemaKerberos):
+ strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"negotiate");
+ break;
+ };
+
+ if(AuthSchema >= AuthNotSupported)
+ {
+ return HTTP_CLIENT_ERROR_BAD_AUTH;
+ }
+
+ pHTTPSession->HttpCredentials.CredAuthSchema = AuthSchema;
+ return HTTP_CLIENT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSetProxy
+// Purpose : Sets all the proxy related parameters
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession,
+ CHAR *pProxyHost, // [IN] Null terminated string containing the host name
+ UINT16 nPort, // [IN] The proxy port number
+ CHAR *pUserName, // [IN] User name for proxy authentication (can be null)
+ CHAR *pPassword) // [IN] User password for proxy authentication (can be null)
+{
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientSetProxy",NULL,0,"Proxy host %s,Port %d, Username %s,Password %s",pProxyHost,nPort,pUserName,pPassword);
+ }
+#endif
+
+
+ // Cache the user supplied information in the internal session structure
+ strncpy(pHTTPSession->HttpProxy.ProxyHost,pProxyHost,HTTP_CLIENT_MAX_PROXY_HOST_LENGTH);
+ if(pUserName)
+ {
+ // Proxy user name (for Proxy server authentication)
+ strncpy(pHTTPSession->HttpProxy.ProxtUser,pUserName,HTTP_CLIENT_MAX_USERNAME_LENGTH);
+ }
+ if(pPassword)
+ {
+ // Proxy password (for proxy server authentication)
+ strncpy(pHTTPSession->HttpProxy.ProxyPassword,pPassword,HTTP_CLIENT_MAX_PASSWORD_LENGTH);
+ }
+ // Proxy TCP port
+ pHTTPSession->HttpProxy.nProxyPort = nPort;
+ // Set the Proxy flag in the connection structure
+ pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_USINGPROXY;
+ // Set the proxy auyjentication schema
+ if(pPassword && pUserName)
+ {
+ pHTTPSession->HttpProxy.ProxyAuthSchema = HTTP_CLIENT_DEFAULT_PROXY_AUTH;
+ }
+ return HTTP_CLIENT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSetCredentials
+// Purpose : Sets credentials for the target host
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession,
+ CHAR *pUserName, // [IN] Null terminated string containing the sessions user name
+ CHAR *pPassword) // [IN] Null terminated string containing the sessions password
+{
+ UINT32 nLength;
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ // Get the length of the user name string and see if it's not too long
+ nLength = strlen(pUserName);
+ if(nLength > HTTP_CLIENT_MAX_USERNAME_LENGTH)
+ {
+ return HTTP_CLIENT_ERROR_LONG_INPUT;
+ }
+
+ // Get the length of the password string and see if it's not too long
+ nLength = strlen(pPassword);
+ if(nLength > HTTP_CLIENT_MAX_PASSWORD_LENGTH)
+ {
+ return HTTP_CLIENT_ERROR_LONG_INPUT;
+ }
+
+ // Copy them into our internal buffer
+ strcpy(pHTTPSession->HttpCredentials.CredUser ,pUserName);
+ strcpy(pHTTPSession->HttpCredentials.CredPassword ,pPassword);
+
+ // Set the authentication Boolean flag
+ pHTTPSession->HttpHeadersInfo.HaveCredentials = TRUE;
+
+ return HTTP_CLIENT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientAddRequestHeaders
+// Purpose : Add headers to the outgoing request
+// Gets :
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession,
+ CHAR *pHeaderName, // [IN] The Headers name
+ CHAR *pHeaderData, // [IN] The headers data
+ BOOL nInsert) // [IN] Reserved could be any
+{
+
+ UINT32 nRetCode;
+ UINT32 nHeaderLength,nDataLength;
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientAddRequestHeaders",NULL,0,"Adding Header %s: %s",pHeaderName,pHeaderData);
+ }
+#endif
+
+ // Get the elements length
+ nHeaderLength = strlen(pHeaderName);
+ nDataLength = strlen(pHeaderData);
+
+ // Call the internal function to add the headers to our session buffer
+ nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,pHeaderName,nHeaderLength,pHeaderData,nDataLength);
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientSendRequest
+// Purpose : This function builds the request headers, performs a DNS resolution ,
+// opens the connection (if it was not opened yet by a previous request or if it has closed)
+// and sends the request headers.
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession,
+ CHAR *pUrl, // [IN] The requested URL
+ VOID *pData, // [IN] Data to post to the server
+ UINT32 nDataLength, // [IN] Length of posted data
+ BOOL TotalLength, // [IN]
+ UINT32 nTimeout, // [IN] Operation timeout
+ UINT32 nClientPort) // [IN] Client side port 0 for none
+{
+
+ UINT32 nRetCode; // Function call return code
+ UINT32 nBytes; // Bytes counter (socket operations)
+ UINT32 nUrlLength; // Length of the given Url
+ P_HTTP_SESSION pHTTPSession = NULL; // Session pointer
+ CHAR ContentLength[32];
+ CHAR *pPtr; // Content length (string conversion)
+ do
+ {
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientSendRequest",NULL,0,"Url: %s",pUrl);
+ }
+#endif
+
+ // Set the operation timeout counters
+ pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime();
+ // 0 makes us use the default defined value
+ pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout);
+ // Store the cliebt port for later usage
+ pHTTPSession->HttpConnection.HttpClientPort = nClientPort;
+
+ // Parse the URL
+ nUrlLength = strlen(pUrl);
+ nRetCode = HTTPIntrnSetURL(pHTTPSession,pUrl,nUrlLength);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ // Create the default headers
+ // Add the "Host" header. we should handle a special case of port incorporated within the host name.
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) != HTTP_CLIENT_FLAG_URLANDPORT)
+ {
+ // The case where we don't have the port
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,
+ "Host",4,
+ pHTTPSession->HttpUrl.UrlHost.pParam,
+ pHTTPSession->HttpUrl.UrlHost.nLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ else
+ {
+ // We have the port so use a deferent element
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Host",4,pHTTPSession->HttpUrl.UrlHost.pParam,
+ (pHTTPSession->HttpUrl.UrlPort.pParam - pHTTPSession->HttpUrl.UrlHost.pParam) -1 )) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ // We are in a post request without knowing the total length in advance so return error or use chunking
+ if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == FALSE)
+ {
+ // If the user specified the chunked flag
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED)
+ {
+ // Add the Transfer-Encoding: header
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Transfer-Encoding",17,"chunked",7))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;;
+ }
+ }
+ else
+ {
+ // Not a supported operation - unknown length
+ nRetCode = HTTP_CLIENT_ERROR_HEADER_NO_LENGTH;
+ break;
+ }
+ }
+
+ // Add the "User-Agent" header
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"User-Agent",10,HTTP_CLIENT_DEFAULT_AGENT,strlen(HTTP_CLIENT_DEFAULT_AGENT)))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Add the "Keep-Alive" header (if requested by the caller)
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_KEEP_ALIVE) == HTTP_CLIENT_FLAG_KEEP_ALIVE)
+ {
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY)
+ {
+ // No proxy keep alive:
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Connection",10,"Keep-Alive",10))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ else // proxy keep alive
+ {
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Proxy-Connection",15,"Keep-Alive",10))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ // If we know the total length in advance (only when posting)
+ if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == TRUE)
+ {
+ // set the total content length header
+ pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength = nDataLength; // Store for later usage
+ memset(ContentLength,0,32);
+ pPtr = IToA(ContentLength,nDataLength); // Convert the buffer length to a string value
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Length",14,ContentLength,strlen(ContentLength)))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // Add the "Cache control" header (if requested by the caller)
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_NO_CACHE) == HTTP_CLIENT_FLAG_NO_CACHE)
+ {
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Cache-Control",13,"no-cache",8))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+
+ // Now we can connect to the remote server and send the leading request followed by the HTTP headers
+ // Check for timeout
+ if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT;
+ break;
+ }
+ // Handle connection close message (reconnect)
+ if(pHTTPSession->HttpHeadersInfo.Connection == FALSE)
+ {
+ // Gracefully close the connection and set the socket as invalid
+ if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)
+ {
+ HTTPIntrnConnectionClose(pHTTPSession);
+ }
+ // Connect to the remote server (or proxy)
+ nRetCode = HTTPIntrnConnectionOpen(pHTTPSession);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // Send the request along with the rest of the headers
+ if(pHTTPSession->HttpCredentials.CredAuthSchema != AuthSchemaNone ||
+ pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone) // If we have to authenticate we should use the HEAD verb
+ {
+ if(HTTP_CLIENT_ALLOW_HEAD_VERB) // HEAD should not be ussed if not defined
+ {
+ if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,VerbHead)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the state flag
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEAD_SENT;
+ }
+ else
+ {
+ // Simply use the verb that was set by the caller without changing to HEAD
+ if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // This the case where the caller know the total length to receive in advance
+ // and he wishes to send the data right away
+ if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == TRUE)
+ {
+
+ // Send the data
+ nBytes = nDataLength;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pData,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the session state
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_POST_SENT;
+ }
+
+ }
+
+ // Retrive and analyze the Headers
+ if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession,nTimeout)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus != 401 && pHTTPSession->HttpHeadersInfo.nHTTPStatus != 407)
+ {
+
+ nRetCode = HTTP_CLIENT_ERROR_AUTH_MISMATCH;
+ break;
+ }
+ // Authenticate
+ if((nRetCode = HTTPIntrnAuthenticate(pHTTPSession)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ }
+ else
+ {
+ // No authentication use the verb that was requested by the caller
+ if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ // This the case where the caller know the total length to receive in advance
+ // and he wishes to send the data right away
+ if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == TRUE)
+ {
+
+ // Send the data
+ nBytes = nDataLength;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pData,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the session state
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_POST_SENT;
+ }
+
+ }while(0);
+
+
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientRecvResponse
+// Purpose : Receives the response header on the connection and parses it.
+// Performs any required authentication.
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession,
+ UINT32 nTimeout) // [IN] Timeout for the operation
+{
+
+ UINT32 nRetCode; // Function return code
+ P_HTTP_SESSION pHTTPSession = NULL; // Session pointer
+
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ do
+ {
+ if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession, nTimeout)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ } while(0);
+
+ return nRetCode;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientWriteData
+// Purpose : Write data to the remote server
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession,
+ VOID *pBuffer,
+ UINT32 nBufferLength,
+ UINT32 nTimeout)
+{
+
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS;
+ UINT32 nBytes;
+ CHAR Chunk[HTTP_CLIENT_MAX_CHUNK_HEADER];
+ CHAR *pChunkHeaderPtr;
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+
+ // Cast the handle to our internal structure and check the pointer validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ do
+ {
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Set the operation timeout counters
+ pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime();
+ pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout);
+
+ // Did the caller specified chunked sending?
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED)
+ {
+ // Prep the chunk Header and send it
+ memset(Chunk,0x00,HTTP_CLIENT_MAX_CHUNK_HEADER);
+ pChunkHeaderPtr = HTTPStrLToH(Chunk,nBufferLength);
+ strcat(Chunk,HTTP_CLIENT_CRLF);
+
+ // Send the leading CrLf (only after the first chunk)
+ if(pHTTPSession->HttpCounters.nSentChunks >= 1)
+ {
+ nBytes = 2;;
+ nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // Send the chunk header
+ nBytes = strlen(Chunk);
+ nRetCode = HTTPIntrnSend(pHTTPSession,Chunk,&nBytes);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // Send the data
+ nBytes = nBufferLength;
+ nRetCode = HTTPIntrnSend(pHTTPSession,pBuffer,&nBytes);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ // If we are using chunks then..
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED)
+ {
+ // Set the chunks count
+ pHTTPSession->HttpCounters.nSentChunks++;
+
+ // If it was the last chunk (0) we should re-get the headers from the server reply
+ if(nBufferLength == 0)
+ {
+ // Send the trailing CrLf
+ nBytes = 2;;
+ nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Get the remote headers (since the last chunk was transmitted we can expect the server to start the reply)
+ if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession,nTimeout)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ } while(0);
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientReadData
+// Purpose : Read data from the server. Parse out the chunks data.
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession,
+ VOID *pBuffer, // [IN OUT] a pointer to a buffer that will be filled with the servers response
+ UINT32 nBytesToRead, // [IN] The size of the buffer (numbers of bytes to read)
+ UINT32 nTimeout, // [IN] operation timeout in seconds
+ UINT32 *nBytesRecived) // [OUT] Count of the bytes that ware received in this operation
+ {
+
+ UINT32 nBytes = 0;
+ UINT32 nRetCode = 0 ;
+ INT32 nProjectedBytes = 0; // Should support negative numbers
+ CHAR *pNullPtr;
+ BOOL EndOfStream = FALSE;
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ // If the last verb that was used was HEAD there is no point to get this data (chanses are that we will endup with timeout)
+ if(pHTTPSession->HttpHeaders.HttpVerb == VerbHead)
+ {
+ return HTTP_CLIENT_EOS;
+
+ }
+
+ // Set the operation timeout counters
+ pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime();
+ pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout);
+
+
+ nBytes = nBytesToRead - 1; // We will spare 1 byte for the trailing null termination
+ *((CHAR*)pBuffer) = 0; // Null terminate the user supplied buffer
+ *(nBytesRecived) = 0; // Set the return bytes count to 0
+
+ // We can read the data only if we got valid headers (and not authentication requests for example)
+ if((pHTTPSession->HttpState & HTTP_CLIENT_STATE_HEADERS_PARSED) != HTTP_CLIENT_STATE_HEADERS_PARSED)
+ {
+ return HTTP_CLIENT_ERROR_BAD_STATE;
+ }
+
+ // Is it a chunked mode transfer?
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_CHUNKED) == HTTP_CLIENT_FLAG_CHUNKED)
+ {
+
+ // How many bytes left until the next chunk?
+ if(pHTTPSession->HttpCounters.nBytesToNextChunk == 0)
+ {
+ // Read the chunk header and get its length
+ if(HTTPIntrnGetRemoteChunkLength(pHTTPSession) != HTTP_CLIENT_SUCCESS)
+ {
+ // Could not parse the chunk parameter
+ return HTTP_CLIENT_ERROR_CHUNK;
+ }
+
+ // 0 Bytes chunk, we should return end of stream
+ if(pHTTPSession->HttpCounters.nRecivedChunkLength == 0)
+ {
+ return HTTP_CLIENT_EOS;
+ }
+ }
+ // If we are about to read pass the next chunk, reduce the read bytes so we will read
+ // non HTML data
+ nProjectedBytes = pHTTPSession->HttpCounters.nBytesToNextChunk - nBytes;
+ if ( nProjectedBytes <= 0)
+ {
+ // Set the correct bytes count we should read
+ nBytes = pHTTPSession->HttpCounters.nBytesToNextChunk;
+ }
+ }
+
+ // Do we have the content length?
+ if(pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0)
+ {
+ // Length of the projected buffer
+ nProjectedBytes = pHTTPSession->HttpCounters.nRecivedBodyLength + nBytes;
+ // If we are going to read more then the known content length then..
+ if(nProjectedBytes >= (INT32)pHTTPSession->HttpHeadersInfo.nHTTPContentLength)
+ {
+ // Reduce the received bytes count to the correct size
+ nBytes = pHTTPSession->HttpHeadersInfo.nHTTPContentLength - pHTTPSession->HttpCounters.nRecivedBodyLength;
+
+ }
+ }
+ // Receive the data from the socket
+ nRetCode = HTTPIntrnRecv(pHTTPSession,(CHAR*)pBuffer,&nBytes,FALSE);
+ // Set the return bytes count
+ *(nBytesRecived) = nBytes; // + 1; Fixed 11/9/2005
+
+ // Pointer to the end of the buffer
+ pNullPtr = (CHAR*)pBuffer + nBytes ;
+ // And null terminate
+ *pNullPtr = 0;
+
+ // Socket read went OK
+ if(nRetCode == HTTP_CLIENT_SUCCESS)
+ {
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPClientReadData",NULL,0,"Reading %d bytes",nBytes);
+ }
+#endif
+ // Set the HTTP counters
+ pHTTPSession->HttpCounters.nRecivedBodyLength += nBytes;
+ // If we know the total content length and..
+ if(pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0)
+ {
+ // If total received body is equal or greater then the known content length then..
+ if( pHTTPSession->HttpCounters.nRecivedBodyLength >= pHTTPSession->HttpHeadersInfo.nHTTPContentLength)
+ {
+ // Raise a flag to signal end of stream
+ EndOfStream = TRUE;
+ }
+ }
+ // Is it a chunked mode transfer?
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_CHUNKED) == HTTP_CLIENT_FLAG_CHUNKED)
+ {
+ // We are a little closer to the next chunk now
+ pHTTPSession->HttpCounters.nBytesToNextChunk -= nBytes;
+ }
+ // Is it End of stream?
+ if(EndOfStream == TRUE)
+ {
+ // So exit
+ return HTTP_CLIENT_EOS;
+ }
+ }
+
+ return nRetCode ;
+}
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientGetInfo
+// Purpose : Fill the users structure with the session information
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient)
+{
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+ // Reset the users info structure
+ memset(HTTPClient,0x00,sizeof(HTTP_CLIENT));
+
+ HTTPClient->HTTPStatusCode = pHTTPSession->HttpHeadersInfo.nHTTPStatus;
+ HTTPClient->RequestBodyLengthSent = pHTTPSession->HttpCounters.nSentBodyBytes;
+ HTTPClient->ResponseBodyLengthReceived = pHTTPSession->HttpCounters.nRecivedBodyLength;
+ HTTPClient->TotalResponseBodyLength = pHTTPSession->HttpHeadersInfo.nHTTPContentLength;
+ HTTPClient->HttpState = pHTTPSession->HttpState;
+
+ return HTTP_CLIENT_SUCCESS;
+
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientFindFirstHeader
+// Purpose : Initiate the headr searching functions
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength)
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+ UINT32 nClueLength;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ nClueLength = strlen(pSearchClue); // See if we are not to long
+ if(nClueLength >= HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE)
+ {
+ return HTTP_CLIENT_ERROR_HEADER_BIG_CLUE;
+ }
+ else
+ {
+ strcpy(pHTTPSession->HttpHeaders.SearchClue,pSearchClue);
+ pHTTPSession->HttpHeaders.HeaderSearch.nLength = 0;
+ pHTTPSession->HttpHeaders.HeaderSearch.pParam = NULL;
+ }
+
+ return HTTP_CLIENT_SUCCESS;
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientFindCloseHeader
+// Purpose : Terminate a headers search session
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession)
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ pHTTPSession->HttpHeaders.SearchClue[0] = 0;
+ pHTTPSession->HttpHeaders.HeaderSearch.nLength = 0;
+ pHTTPSession->HttpHeaders.HeaderSearch.pParam = NULL;
+
+ return HTTP_CLIENT_SUCCESS;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPClientGetNextHeader
+// Purpose : Terminate a headers search session
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength)
+{
+
+ P_HTTP_SESSION pHTTPSession = NULL;
+ UINT32 nOffset = 0;
+ UINT32 nRetCode;
+ HTTP_PARAM HttpHeader;
+ CHAR *pPtr;
+
+ // Cast the handle to our internal structure and check the pointers validity
+ pHTTPSession = (P_HTTP_SESSION)pSession;
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+ if(pHTTPSession->HttpHeaders.HeaderSearch.nLength > 0) // We must adjust the search offset since it is not the fierst iteration
+ {
+ nOffset = pHTTPSession->HttpHeaders.HeaderSearch.pParam - pHTTPSession->HttpHeaders.HeadersIn.pParam;
+ }
+ // Search for the next header
+ nRetCode = HTTPIntrnHeadersFind(pHTTPSession,pHTTPSession->HttpHeaders.SearchClue,&HttpHeader,TRUE,nOffset);
+
+ if(nRetCode == HTTP_CLIENT_SUCCESS)
+ {
+ if(HttpHeader.nLength > *(nLength)) // Check for sufficiant length
+ {
+ *(nLength) = HttpHeader.nLength;
+ pHeaderBuffer[0] = 0; // Reset the users buffer
+ return HTTP_CLIENT_ERROR_NO_MEMORY;
+ }
+
+ pPtr = HttpHeader.pParam;
+ nOffset = 0;
+ if(*pPtr == 0x0d)
+ {
+ nOffset++;
+ pPtr++;
+ }
+ if(*pPtr == 0x0a)
+ {
+ nOffset++;
+ pPtr++;
+ }
+
+ strncpy(pHeaderBuffer,pPtr,HttpHeader.nLength - nOffset);
+ pHeaderBuffer[HttpHeader.nLength - nOffset] = 0;
+ *(nLength) = HttpHeader.nLength - nOffset;
+ pHTTPSession->HttpHeaders.HeaderSearch.pParam = HttpHeader.pParam + HttpHeader.nLength;
+ pHTTPSession->HttpHeaders.HeaderSearch.nLength++;
+
+ return HTTP_CLIENT_SUCCESS;
+
+ }
+
+ return nRetCode;
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnSetURL
+// Purpose : Parse the user's URL
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnSetURL (P_HTTP_SESSION pHTTPSession,
+ CHAR *pUrl, // [IN] a null terminated string containing the Url we should retrieve
+ UINT32 nUrlLength) // [IN] The length the Url string
+{
+
+ UINT32 nUrlOffset; // Offset in bytes within the Url string
+ HTTP_URL *pUrlPtr; // a Pointer to the Url structure (within the global session structure)
+ CHAR *pPtr; // a Pointer for the Url port (Used in the parsing process)
+ CHAR UrlPort[16]; // a temporary byte array for the Url port conversion operation (string to number)
+
+ // Check for the session pointer validity
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+
+ // Get the length of the Url
+ nUrlLength = strlen(pUrl);
+
+ // Check if it is not longer than the permitted length
+ if((nUrlLength + 1) > HTTP_CLIENT_MAX_URL_LENGTH)
+ {
+ return HTTP_CLIENT_ERROR_LONG_INPUT;
+ }
+
+ // Point the local pointer on the global structure
+ pUrlPtr = &pHTTPSession->HttpUrl;
+
+ // Copy to the internal buffer
+ memcpy(pHTTPSession->HttpUrl.Url,pUrl,nUrlLength);
+ nUrlOffset = 0;
+
+ // Get the Url base ("http" or "https")
+ if(HTTPStrSearch(pUrlPtr->Url,":",nUrlOffset,nUrlLength,&pUrlPtr->UrlBsee) == FALSE)
+ {
+ return HTTP_CLIENT_ERROR_BAD_URL;
+ }
+ // Increase the offset parameter
+ nUrlOffset += pUrlPtr->UrlBsee.nLength;
+ // If we can parse the string "HTTPS" we can assume a secured session
+ if(HTTPStrInsensitiveCompare(pUrlPtr->UrlBsee.pParam,"https",pUrlPtr->UrlBsee.nLength) == TRUE)
+ {
+ // Set the secured flags on the session
+ pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_URLHTTPS;
+ pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_SECURE;
+ // ToDo: Init TLS (GetProtocol)
+#ifdef _HTTP_BUILD_AMT
+ // OS_GET_CLIENT_SUBSET_PROTOCOL(TRUE,&pHTTPSession->pSecProtocol);
+#endif
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnSetURL",NULL,0,"SSL Protected Url %s",pUrl);
+ }
+#endif
+ }
+ else // it should be "http"
+ {
+ if(HTTPStrInsensitiveCompare(pUrlPtr->UrlBsee.pParam,"http",pUrlPtr->UrlBsee.nLength) == FALSE)
+ {
+ return HTTP_CLIENT_ERROR_BAD_URL; // cOULD NOT DETECT http or https prefix
+
+ }
+ }
+ // Look for standard Url elements
+ if(HTTPStrSearch(pUrlPtr->Url,"://",nUrlOffset,3,0) == FALSE)
+ {
+ return HTTP_CLIENT_ERROR_BAD_URL; // Could not detect "://"
+ }
+ // Increase the offset parameter
+ nUrlOffset += 3;
+
+ // Get the host name
+ if(HTTPStrSearch(pUrlPtr->Url,"/",nUrlOffset,(nUrlLength - nUrlOffset),&pUrlPtr->UrlHost) == FALSE)
+ {
+ pUrlPtr->Url[nUrlLength] = '/';
+ nUrlLength++;
+ if(HTTPStrSearch(pUrlPtr->Url,"/",nUrlOffset,(nUrlLength - nUrlOffset),&pUrlPtr->UrlHost) == FALSE)
+ {
+ return HTTP_CLIENT_ERROR_BAD_URL;
+ }
+ }
+
+ nUrlOffset += pUrlPtr->UrlHost.nLength;
+
+ // Do we have the port within the hostname?
+ if(HTTPStrSearch(pUrlPtr->Url,":",
+ (nUrlOffset - pUrlPtr->UrlHost.nLength),
+ pUrlPtr->UrlHost.nLength,
+ &pUrlPtr->UrlPort) == TRUE)
+ {
+ if((pUrlPtr->UrlHost.nLength - pUrlPtr->UrlPort.nLength) < 10)
+ {
+ // To-Do: check the actual port length before the memcpy
+ pUrlPtr->UrlPort.pParam += pUrlPtr->UrlPort.nLength + 1;
+ memcpy(UrlPort,pUrlPtr->UrlPort.pParam,15);
+ pUrlPtr->UrlPort.nLength = 0;
+ pPtr = UrlPort;
+ while(*pPtr && pPtr++)
+ {
+
+ pUrlPtr->UrlPort.nLength++;
+ if(*pPtr == '/')
+ {
+ *pPtr = 0;
+ pUrlPtr->nPort = (UINT16)atol(UrlPort);
+ pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_URLANDPORT;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Port too big
+ return HTTP_CLIENT_ERROR_BAD_URL;
+ }
+ }
+
+ // Get the request body
+ pUrlPtr->UrlRequest.pParam = pUrlPtr->Url + nUrlOffset;
+ pUrlPtr->UrlRequest.nLength = nUrlLength - nUrlOffset;
+
+ // If we got SSL url with no port we should set the default ssl port
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLHTTPS) == HTTP_CLIENT_FLAG_URLHTTPS)
+ {
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) != HTTP_CLIENT_FLAG_URLANDPORT)
+ {
+ pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_SSL_PORT;
+
+ }
+
+ }
+
+ // Set the state flag
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_URL_PARSED;
+
+ return HTTP_CLIENT_SUCCESS;
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnResizeBuffer
+// Purpose : Resize the HTTP headers buffer and reset the pointers
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnResizeBuffer (P_HTTP_SESSION pHTTPSession,
+ UINT32 nNewBufferSize) // [IN] The new (and larger) buffer size
+{
+
+ CHAR *pPtr = NULL;
+ UINT32 nCurrentBufferSize;
+
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+ // If the new buffer size is less or equal to the current buffer size then..
+ if(pHTTPSession->HttpHeaders.HeadersBuffer.nLength >= nNewBufferSize)
+ {
+
+ // Return an error (bad buffer)
+ return HTTP_CLIENT_ERROR_BUFFER_RSIZE;
+ }
+
+ // If the new buffer size is bigger then the defined maximum buffer size then..
+ if(nNewBufferSize > HTTP_CLIENT_MAX_SEND_RECV_HEADERS)
+ {
+ // Return an error (bad buffer)
+ return HTTP_CLIENT_ERROR_BUFFER_RSIZE;
+ }
+ // Current buffer size is the sum of the incoming and outgoing headers strings lengths
+ nCurrentBufferSize = pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength;
+ // Allocate a new buffer with the requested buffer size
+ pPtr = (CHAR*)malloc(ALIGN(nNewBufferSize));
+ if(!pPtr)
+ {
+ // malloc() error
+ return HTTP_CLIENT_ERROR_NO_MEMORY;
+ }
+
+ // Copy the memory only if there is data to copy
+ if(nCurrentBufferSize > 0)
+ {
+ memcpy(pPtr,pHTTPSession->HttpHeaders.HeadersBuffer.pParam,nCurrentBufferSize);
+ // Reset the rest of the buffer
+ memset(pPtr + nCurrentBufferSize, 0x00,(nNewBufferSize - nCurrentBufferSize));
+ }
+ else
+ {
+ // Reset the entire buffer (no previous buffer was copied)
+ memset(pPtr,0x00,nNewBufferSize);
+ }
+
+ free(pHTTPSession->HttpHeaders.HeadersBuffer.pParam);
+
+ pHTTPSession->HttpHeaders.HeadersBuffer.pParam = pPtr;
+ pHTTPSession->HttpHeaders.HeadersBuffer.nLength = nNewBufferSize;
+
+ // Refresh the pointers
+ pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam;
+ if(pHTTPSession->HttpHeaders.HeadersIn.pParam)
+ {
+ pHTTPSession->HttpHeaders.HeadersIn.pParam =pHTTPSession->HttpHeaders.HeadersBuffer.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength;
+ }
+ return HTTP_CLIENT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnRemoveHeader
+// Purpose : Removes an HTTP headers by its name
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnHeadersRemove (P_HTTP_SESSION pHTTPSession,
+ CHAR *pHeaderName) // [IN] The header's name
+
+{
+
+ HTTP_PARAM HttpParam;
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS;
+ UINT32 nBytes;
+
+ if(!pHTTPSession) // Pointer validation check
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ // First see if we have that header in our outgoing headers buffer
+ do
+ {
+
+ if((nRetCode = HTTPIntrnHeadersFind(pHTTPSession,pHeaderName,&HttpParam,FALSE,0)) != HTTP_CLIENT_SUCCESS)
+ {
+ // Could not find this header
+ break;
+ }
+ // Calculate the new headers length
+ nBytes = (HttpParam.pParam - pHTTPSession->HttpHeaders.HeadersOut.pParam);
+ nBytes -= HttpParam.nLength;
+
+
+ // Copy the memory
+ memcpy(HttpParam.pParam, HttpParam.pParam + HttpParam.nLength,nBytes);
+
+ // Set the new length
+ pHTTPSession->HttpHeaders.HeadersOut.nLength -= HttpParam.nLength;
+
+ // Reset the buffer from it's modified end to it's previous end
+ memset(pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength,0x00,HttpParam.nLength);
+
+ } while(0);
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnHeadersRemove",NULL,0,"Removing Header %",pHeaderName);
+ }
+#endif
+
+
+ return nRetCode;
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnHeadersAdd
+// Purpose : Add HTTP headers to the outgoing headers buffers
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnHeadersAdd (P_HTTP_SESSION pHTTPSession,
+ CHAR *pHeaderName, // [IN] The header's name
+ UINT32 nNameLength, // [IN] Name length
+ CHAR *pHeaderData, // [IN] The Header's data
+ UINT32 nDataLength) // [IN] Data length
+{
+ CHAR *pPtr;
+ UINT32 nProjectedHeaderLength;
+ UINT32 nProjectedBufferLength;
+ INT32 nCurrentfreeSpace;
+ INT32 nProjectedfreeSpace;
+ UINT32 nRetCode;
+
+ if(!pHTTPSession) // pointer validation check
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ nProjectedHeaderLength = nNameLength + nDataLength + 4;
+ nProjectedBufferLength = nProjectedHeaderLength + pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength;
+ nCurrentfreeSpace = pHTTPSession->HttpHeaders.HeadersBuffer.nLength - (pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength);
+ nProjectedfreeSpace = nCurrentfreeSpace - nProjectedHeaderLength;
+
+ // Check total size limit
+ if(nProjectedBufferLength > HTTP_CLIENT_MAX_SEND_RECV_HEADERS)
+ {
+ return HTTP_CLIENT_ERROR_NO_MEMORY;
+ }
+
+ if((INT32)nProjectedfreeSpace < 0)
+ {
+ if(HTTP_CLIENT_MEMORY_RESIZABLE == FALSE)
+ {
+ // Need more space but we can't grow beyond the current size
+ return HTTP_CLIENT_ERROR_NO_MEMORY;
+ }
+ else
+ {
+ // We can resizes so..
+ nRetCode = HTTPIntrnResizeBuffer(pHTTPSession,nProjectedBufferLength + HTTP_CLIENT_MEMORY_RESIZE_FACTOR);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ return nRetCode;
+ }
+ }
+ }
+
+ // Move the incoming headers data within the buffer so we will have space for the added headers
+ if(pHTTPSession->HttpHeaders.HeadersIn.pParam)
+ {
+ // Move the data and reset the data in the offset.
+ memcpy(pHTTPSession->HttpHeaders.HeadersIn.pParam + nProjectedHeaderLength ,
+ pHTTPSession->HttpHeaders.HeadersIn.pParam,
+ pHTTPSession->HttpHeaders.HeadersIn.nLength);
+ // Reset the space created
+ memset(pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength,
+ 0x00,
+ nProjectedHeaderLength);
+
+ }
+
+ pPtr = pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength;
+ // Create the new header
+ memcpy(pPtr,pHeaderName,nNameLength);
+ pPtr += nNameLength;
+ memcpy(pPtr,": ",2);
+ pPtr += 2;
+ memcpy(pPtr,pHeaderData,nDataLength);
+ pPtr += nDataLength;
+ memcpy(pPtr,HTTP_CLIENT_CRLF,2);
+ pPtr += 2;
+
+ // Set the new length
+ pHTTPSession->HttpHeaders.HeadersOut.nLength += nProjectedHeaderLength;
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnHeadersAdd",NULL,0,"Adding Header %s: %s",pHeaderName,pHeaderData);
+ }
+#endif
+
+ return HTTP_CLIENT_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnConnectionClose
+// Purpose : Closes an active socket connection and invalidate the socket handle
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPIntrnConnectionClose (P_HTTP_SESSION pHTTPSession)
+{
+
+ INT32 nRetCode = HTTP_CLIENT_SUCCESS;
+
+ do
+ {
+ if(!pHTTPSession) // Validate the session pointer
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // If we have a valid socket then..
+ if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)// INVALID_SOCKET
+ {
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE)
+ {
+ // TLS Close
+ nRetCode = HTTPWrapperSSLClose(pHTTPSession->HttpConnection.HttpSocket);
+ }
+
+ // Gracefully close it
+ shutdown(pHTTPSession->HttpConnection.HttpSocket,0x01);
+ closesocket(pHTTPSession->HttpConnection.HttpSocket);
+ // And invalidate the socket
+ pHTTPSession->HttpConnection.HttpSocket = HTTP_INVALID_SOCKET;
+
+ break;;
+ }
+ else
+ {
+ // Not a valid socket error
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID;
+ break;
+ }
+
+ } while(0);
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnConnectionClose",NULL,0,"");
+ }
+#endif
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnConnectionOpen
+// Purpose : Opens a socket connection to the remote host or proxy server
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnConnectionOpen (P_HTTP_SESSION pHTTPSession)
+{
+ INT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value
+ UINT32 nNullOffset; // a helper value to null terminate a given string
+ int nNonBlocking = 1; // non blocking mode parameter
+ CHAR Backup; // a container for a char value (helps in temporary null termination)
+ // HTTP_HOSTNET *HostEntry; // Socket host entry pointer
+ UINT32 Address = 0;
+ HTTP_SOCKADDR_IN ServerAddress; // Socket address structure
+ HTTP_SOCKADDR_IN LoaclAddress; // Socket address structure (for client binding)
+ do
+ {
+
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+ // Use an existing connection if valid
+ if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)
+ {
+ // Set the state flag
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HOST_CONNECTED;
+ return HTTP_CLIENT_SUCCESS;
+ }
+ // Zero the socket events
+ FD_ZERO(&pHTTPSession->HttpConnection.FDRead);
+ FD_ZERO(&pHTTPSession->HttpConnection.FDWrite);
+ FD_ZERO(&pHTTPSession->HttpConnection.FDError);
+
+ if(pHTTPSession->HttpConnection.HttpSocket == HTTP_INVALID_SOCKET)
+ {
+
+ // Create a TCP/IP stream socket
+ pHTTPSession->HttpConnection.HttpSocket = socket(AF_INET, // Address family
+ SOCK_STREAM, // Socket type
+ IPPROTO_TCP); // Protocol
+ }
+
+ // Exit if we don't have a valid socket
+ if(pHTTPSession->HttpConnection.HttpSocket == HTTP_INVALID_SOCKET)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID;
+ break;
+ }
+ // Set non blocking socket
+ nRetCode = ioctlsocket(pHTTPSession->HttpConnection.HttpSocket, FIONBIO, &nNonBlocking);
+ if(nRetCode != 0)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_CANT_SET;
+ break;
+ }
+ // Resolve the target host name
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY)
+ {
+ // No proxy, directly resolving the host name
+ // Prep the parameter
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) == HTTP_CLIENT_FLAG_URLANDPORT)
+ {
+ nNullOffset = pHTTPSession->HttpUrl.UrlHost.nLength - pHTTPSession->HttpUrl.UrlPort.nLength - 1;
+ }
+ else
+ {
+ nNullOffset = pHTTPSession->HttpUrl.UrlHost.nLength;
+ }
+
+ Backup = HTTPStrExtract(pHTTPSession->HttpUrl.UrlHost.pParam,nNullOffset,0);
+ // Resolve the host name
+ nRetCode = HostByName(pHTTPSession->HttpUrl.UrlHost.pParam,&Address);
+
+ // Restore from backup (fix the buffer)
+ HTTPStrExtract(pHTTPSession->HttpUrl.UrlHost.pParam,nNullOffset,Backup);
+
+ }
+
+ else
+ {
+ // Using a Proxy server so resolve the proxy host name
+ nRetCode = HostByName(pHTTPSession->HttpProxy.ProxyHost,&Address);
+ }
+
+ // See if we have a valid response from the net resolve operation
+ /*
+ if(nRetCode)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_RESOLVE;
+ break;
+ }
+ */
+ // Reset the address structures
+ memset(&ServerAddress, 0, sizeof(HTTP_SOCKADDR_IN));
+ memset(&LoaclAddress, 0, sizeof(HTTP_SOCKADDR_IN));
+
+ // Fill in the address structure
+ ServerAddress.sin_family = AF_INET;
+#ifdef _HTTP_BUILD_AMT
+ ServerAddress.sin_len = sizeof(HTTP_SOCKADDR_IN);
+ ServerAddress.sin_addr.s_addr = htonl(Address); // Server's address
+#endif
+#ifdef _HTTP_BUILD_WIN32
+ ServerAddress.sin_addr.s_addr = Address; // Server's address
+#endif
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY)
+ {
+ // Use the remote web server port
+ ServerAddress.sin_port = htons(pHTTPSession->HttpUrl.nPort); // Host Port number
+ }
+ else
+ {
+ // Use the proxy port
+ ServerAddress.sin_port = htons(pHTTPSession->HttpProxy.nProxyPort); // Proxy Port number
+ }
+
+ // Client-side Binding
+ if(pHTTPSession->HttpConnection.HttpClientPort != 0)
+ {
+ LoaclAddress.sin_family = AF_INET;
+#ifdef _HTTP_BUILD_AMT
+ LoaclAddress.sin_len = sizeof(HTTP_SOCKADDR_IN);
+#endif
+ LoaclAddress.sin_port = htons((unsigned short)pHTTPSession->HttpConnection.HttpClientPort);
+
+ nRetCode = bind(pHTTPSession->HttpConnection.HttpSocket,
+ (HTTP_SOCKADDR*)&LoaclAddress,
+ sizeof(HTTP_SOCKADDR_IN));
+
+ if(nRetCode != 0)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_BIND;
+ }
+ }
+
+ // Connect using TLS or otherwise clear connection
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE)
+ { // Is it a TLS connection?
+ nRetCode = HTTPWrapperSSLConnect(pHTTPSession->HttpConnection.HttpSocket, // Socket
+ (HTTP_SOCKADDR*)&ServerAddress, // Server address
+ sizeof(HTTP_SOCKADDR), // Length of server address structure
+ "desktop"); // Hostname (ToDo: Fix this)
+ }
+ else // Non TLS so..
+ {
+ nRetCode = connect(pHTTPSession->HttpConnection.HttpSocket, // Socket
+ (HTTP_SOCKADDR*)&ServerAddress, // Server address
+ sizeof(HTTP_SOCKADDR)); // Length of server address structure
+ }
+
+ // The socket was set to be asyn so we should check the error being returned from connect()
+ nRetCode = SocketGetErr(pHTTPSession->HttpConnection.HttpSocket);
+ if(nRetCode == 0 || nRetCode == HTTP_EWOULDBLOCK || nRetCode == HTTP_EINPROGRESS)
+ {
+ // Set TLS Nego flag to flase
+ pHTTPSession->HttpConnection.TlsNego = FALSE;
+ // Set the Write fd_sets for a socket connection event
+ FD_SET(pHTTPSession->HttpConnection.HttpSocket, &pHTTPSession->HttpConnection.FDWrite);
+ // Set the state flag
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HOST_CONNECTED;
+ // We have connected so set the return value to success
+ nRetCode = HTTP_CLIENT_SUCCESS;
+ break;
+ }
+ else
+ {
+ // Socket connection problem
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_CONNECT;
+ break;
+ }
+ }while(0);
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnConnectionOpen",NULL,0,"");
+ }
+#endif
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnSend
+// Purpose : Send data to the remote server (Asynchronous sockets)
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnSend (P_HTTP_SESSION pHTTPSession,
+ CHAR *pData, // [IN] a pointer to the data to be sent
+ UINT32 *nLength) // [IN OUT] Length of data to send and the transmitted bytes count
+{
+
+ INT32 nSocketEvents; // Socket events center
+ INT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value
+ HTTP_TIMEVAL Timeval = { 1 , 0 }; // Timeout value for the socket() method
+ HTTP_CONNECTION *pConnection = NULL; // Pointer for the connection structure
+
+
+ do
+ {
+ // Validate the session pointer
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Have a pointer on the internal connection structure for simplifying code reading
+ pConnection = &pHTTPSession->HttpConnection;
+
+ while(1)
+ {
+
+ // Check for timeout
+ if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT;
+ break;
+ }
+
+ // Reset socket events , only Error, since we don't want to get
+ // a repeated Write events (socket is connected)
+
+ FD_SET(pConnection->HttpSocket, &pConnection->FDError);
+
+ // See if we got any events on the socket
+ nSocketEvents = select((pConnection->HttpSocket + 1), 0,
+ &pConnection->FDWrite,
+ &pConnection->FDError,
+ &Timeval);
+
+ if(nSocketEvents < 0) // No events on the socket
+ {
+ *(nLength) = 0;
+ break; // To-Do: This might be an error
+ }
+
+ if(nSocketEvents == 0) // No new events so
+ {
+ continue; // restart this loop
+ }
+
+ // Socket is writable (we are connected) so send the data
+ if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDWrite))
+ {
+
+ // Send the data
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE)
+ {
+ // TLS Protected connection
+ if(pConnection->TlsNego == FALSE)
+ {
+ nRetCode = HTTPWrapperSSLNegotiate(pConnection->HttpSocket,0,0,"desktop");
+ if(nRetCode != 0)
+ {
+ // TLS Error
+ nRetCode = HTTP_CLIENT_ERROR_TLS_NEGO;
+ break;
+ }
+ pConnection->TlsNego = TRUE;
+ }
+ nRetCode = HTTPWrapperSSLSend(pConnection->HttpSocket,pData,*(nLength),0);
+ }
+ else
+ {
+ nRetCode = send(pConnection->HttpSocket,pData,*(nLength),0);
+ }
+ if(nRetCode == SOCKET_ERROR)
+ {
+ nRetCode = SocketGetErr(pHTTPSession->HttpConnection.HttpSocket);
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_SEND;
+ break;
+ }
+ // The data was sent to the remote server
+ *(nLength) = nRetCode;
+ nRetCode = HTTP_CLIENT_SUCCESS;
+ break;
+ }
+
+ // We had a socket related error
+ if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDError))
+ {
+ FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDError);
+ *(nLength) = 0;
+ // To-Do: Handle this case
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_SEND;
+ break;
+ }
+ }
+ } while(0);
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnSend",pData,*(nLength),"");
+ }
+#endif
+
+
+ return nRetCode;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnRecv
+// Purpose : Receive data from the connected socket using asynchronous sockets
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnRecv (P_HTTP_SESSION pHTTPSession,
+ CHAR *pData, // [IN] a pointer for a buffer that receives the data
+ UINT32 *nLength, // [IN OUT] Length of the buffer and the count of the received bytes
+ BOOL PeekOnly) // [IN] State if we should only peek the socket (default is no)
+{
+ INT32 nSocketEvents;
+ INT32 nRetCode = HTTP_CLIENT_SUCCESS;
+ HTTP_TIMEVAL Timeval = { 0, 50000 };
+ HTTP_CONNECTION *pConnection = NULL;
+
+ do
+ {
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Set a pointer on the session internal connection structure (simplify code reading)
+ pConnection = &pHTTPSession->HttpConnection;
+ while(1)
+ {
+ // Check for timeout
+ if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT;
+ break;
+ }
+
+
+ // Reset socket events
+ FD_SET(pConnection->HttpSocket, &pConnection->FDRead);
+ FD_SET(pConnection->HttpSocket, &pConnection->FDError);
+
+ // See if we got any events on the socket
+ nSocketEvents = select(pConnection->HttpSocket + 1, &pConnection->FDRead,
+ 0,
+ &pConnection->FDError,
+ &Timeval);
+
+ if(nSocketEvents < 0) // Error or no new socket events
+ {
+ *(nLength) = 0;
+ break;
+ }
+ if(nSocketEvents == 0)
+ {
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // This is a simple bypass for the TSL session (for some reason the socket read event is not set so
+ // The pending bytes on the socket are being checked manualy.
+ // TLS hack:
+
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE)
+ {
+ nRetCode = HTTPWrapperSSLRecvPending(pConnection->HttpSocket);
+ if(nRetCode > 0)
+ {
+ // Recive without being notified by the socket event
+ if((nRetCode = HTTPWrapperSSLRecv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR)
+ {
+ // Socket error
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV;
+ break;
+ }
+ *(nLength) = nRetCode;
+ // Break on no data or server connection reset
+ if ( nRetCode == 0 || nRetCode == HTTP_ECONNRESET)
+ {
+ // Connection closed, simply break - this is not an error
+ nRetCode = HTTP_CLIENT_EOS; // Signal end of stream
+ break;
+ }
+ // We have successfully got the data from the server
+ nRetCode = HTTP_CLIENT_SUCCESS;
+ break;
+ }
+ }
+ // End Of the TLS bypass section
+ //
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ continue; // select() timed out - restart this loop
+ }
+ if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDRead)) // Are there any read events on the socket ?
+ {
+ // Clear the event
+ FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDRead);
+
+ // Socket is readable so so read the data
+ if(PeekOnly == FALSE)
+ {
+ // Get the data (secuure)
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE)
+ {
+ if((nRetCode = HTTPWrapperSSLRecv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR)
+ {
+ // Socket error
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV;
+ break;
+ }
+ }
+ else // Get the data (non secuure)
+ {
+ if((nRetCode = recv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR)
+ {
+ // Socket error
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV;
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ // Only peek te socket
+ if((nRetCode = recv(pConnection->HttpSocket,pData,*(nLength),MSG_PEEK)) == SOCKET_ERROR)
+ {
+ // Socket error
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV;
+ break;
+ }
+
+ }
+ *(nLength) = nRetCode;
+ // Break on no data or server connection reset
+ // MSDN: If the connection has been gracefully closed, the return value is zero.
+ if ( nRetCode == 0 || nRetCode == HTTP_ECONNRESET)
+ {
+ // Connection closed, simply break - this is not an error
+ nRetCode = HTTP_CLIENT_EOS; // Signal end of stream
+ break;
+ }
+ // We have successfully got the data from the server
+ nRetCode = HTTP_CLIENT_SUCCESS;
+ break;
+ }
+
+ // We had a socket related error
+ if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDError))
+ {
+ FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDError);
+ *(nLength) = 0;
+
+ // To-Do: Handle this case
+ nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV;
+ break;
+
+ }
+ }
+ }while(0);
+
+ return nRetCode;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnGetRemoteChunkLength
+// Purpose : Receive (byte by byte) the chunk parameter (while in chunk mode receive) and
+// Convert the HEX string into an integer
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnGetRemoteChunkLength (P_HTTP_SESSION pHTTPSession)
+{
+
+ UINT32 nBytesRead = 1;
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS;
+ UINT32 nBytesCount = 0;
+ CHAR ChunkHeader[HTTP_CLIENT_MAX_CHUNK_HEADER];
+ CHAR *pPtr;
+
+ do
+ {
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Read byte by byte until we get a CrLf
+ pPtr = ChunkHeader; // Get a pointer to the received buffer
+ *pPtr = 0; // Terminate with null
+
+ while(nBytesRead > 0)
+ {
+ // Receive a single byte
+ nRetCode = HTTPIntrnRecv(pHTTPSession,pPtr,&nBytesRead,FALSE);
+ // Did we succeed?
+ if(nRetCode == HTTP_CLIENT_SUCCESS && nBytesRead > 0)
+ {
+ // Increment the bytes count
+ nBytesCount += nBytesRead;
+ if(nBytesRead > HTTP_CLIENT_MAX_CHUNK_HEADER)
+ {
+ // Error chunk buffer is full
+ nRetCode = HTTP_CLIENT_ERROR_CHUNK_TOO_BIG;
+ break;
+ }
+ // Don't Process if the fist 2 bytes are CrLf.
+ if(! ((nBytesCount == 1 && *pPtr == 0x0d) || (nBytesCount == 2 && *pPtr == 0x0a)))
+ {
+ // Advance the pointer by the received data length
+ pPtr += nBytesRead;
+ // Look for CrLf in the last 2 bytes
+ if(memcmp(pPtr - 2,HTTP_CLIENT_CRLF,2) == 0)
+ {
+ // Chunk Header was received
+ *pPtr = 0; // null terminate the chunk parameter
+ pHTTPSession->HttpCounters.nRecivedChunkLength = HTTPStrHToL(ChunkHeader); // Convert to a number
+ // Set the HTTP counters
+ pHTTPSession->HttpCounters.nBytesToNextChunk = pHTTPSession->HttpCounters.nRecivedChunkLength;
+ break;
+ }
+ }
+ }
+ else // Socket Error
+ {
+ nRetCode = 0;
+ break;
+ }
+ }
+ } while(0);
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnGetRemoteChunkLength",NULL,0,"Next chunk is %d bytes",pHTTPSession->HttpCounters.nRecivedChunkLength);
+ }
+#endif
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnGetRemoteHeaders
+// Purpose : Perform a socket receive (byte by byte) until all the HTTP headers are received
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnGetRemoteHeaders (P_HTTP_SESSION pHTTPSession)
+{
+
+ UINT32 nBytesRead = 1;
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS;
+ UINT32 nProjectedHeaderLength;
+ UINT32 nProjectedBufferLength;
+ INT32 nCurrentfreeSpace;
+ INT32 nProjectedfreeSpace;
+ CHAR *pPtr;
+
+ do
+ {
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Read byte by byte until we get CrLf followed by CrLf
+ // Set the incoming headers pointer
+
+ if(!pHTTPSession->HttpHeaders.HeadersIn.pParam)
+ {
+ /// The incoming headers starts where the outgoing headers ends
+ pHTTPSession->HttpHeaders.HeadersIn.pParam = pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength;
+ }
+
+ // Receive until we get all the headers or any other error event
+ while(nBytesRead > 0)
+ {
+
+ // Size of the projected buffer we are going to receive
+ nProjectedHeaderLength = nBytesRead;
+ // Size of the projected total incoming buffer
+ nProjectedBufferLength = nProjectedHeaderLength + pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength;
+ // Current free space on the incoming headers buffer
+ nCurrentfreeSpace = pHTTPSession->HttpHeaders.HeadersBuffer.nLength - (pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength);
+ // Projected free space after the completion of the receive
+ nProjectedfreeSpace = nCurrentfreeSpace - nProjectedHeaderLength;
+
+ // Check total size limit
+ if(nProjectedBufferLength > HTTP_CLIENT_MAX_SEND_RECV_HEADERS)
+ {
+ return HTTP_CLIENT_ERROR_NO_MEMORY;
+ }
+
+ if((INT32)nProjectedfreeSpace < 0)
+ {
+ if(HTTP_CLIENT_MEMORY_RESIZABLE == FALSE)
+ {
+ // Need more space but we can't grow beyond the current size
+ nRetCode = HTTP_CLIENT_ERROR_NO_MEMORY;
+ break;
+ }
+ else
+ {
+ // We can resizes so..
+ nRetCode = HTTPIntrnResizeBuffer(pHTTPSession,nProjectedBufferLength + HTTP_CLIENT_MEMORY_RESIZE_FACTOR);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+ // Jump to the beginning of the incoming headers (just after the end of the outgoing headers)
+ pPtr = pHTTPSession->HttpHeaders.HeadersIn.pParam + pHTTPSession->HttpHeaders.HeadersIn.nLength;
+ // Read a single byte
+ nRetCode = HTTPIntrnRecv(pHTTPSession,pPtr,&nBytesRead,FALSE);
+
+ // ToDo: Break if not getting HTTP on the first 4 bytes
+
+ if(nRetCode == HTTP_CLIENT_SUCCESS && nBytesRead > 0)
+ {
+ // Advance the pointer by 1 byte
+ pPtr += nBytesRead;
+ // Increase the total receive length
+ pHTTPSession->HttpHeaders.HeadersIn.nLength++;
+
+ // Set the HTTP counters
+ pHTTPSession->HttpCounters.nRecivedHeaderLength++;
+
+ if(memcmp(pPtr - 4,HTTP_CLIENT_CRLFX2,4) == 0)
+ {
+ // Headers were received
+ break;
+ }
+ }
+ else
+ {
+ nRetCode = HTTP_CLIENT_ERROR_HEADER_RECV; // This was marked out for some reason
+ break;
+ }
+ }
+ }while(0);
+
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnGetRemoteHeaders",NULL,0,"Got %d bytes",pHTTPSession->HttpHeaders.HeadersIn.nLength);
+ }
+#endif
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnHeadersFind
+// Purpose : Look for a header (insensitive search) by its name
+// Gets : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnHeadersFind (P_HTTP_SESSION pHTTPSession,CHAR *pHeaderName,
+ HTTP_PARAM *pParam, // [OUT] HTTP parameter structure that holds the search results
+ BOOL IncommingHeaders, // [IN] Indicate if we are to search in the incoming or outgoing headers
+ UINT32 nOffset) // [IN] Optionaly privide an offset to start looking from
+{
+ CHAR *pHeaderEnd;
+ CHAR Header[HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE]; // To-Do: Use pointers insted of fixed length
+ UINT32 nLength;
+ UINT32 nRetCode = HTTP_CLIENT_ERROR_HEADER_NOT_FOUND;
+
+ do
+ {
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Reset the input parameter structure
+ pParam->pParam = NULL;
+ pParam->nLength = 0;
+ // Get the requested header length
+ nLength = strlen(pHeaderName);
+ if(nLength > (HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE - 3))
+ {
+ // Error : header search clue too big
+ nRetCode = HTTP_CLIENT_ERROR_HEADER_BIG_CLUE;
+ break;
+ }
+ // Build the searched header name , add a leading CrLf before the header name and trailing ":"
+ memset(Header,0x00,HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE);
+ strcpy(Header,HTTP_CLIENT_CRLF);
+ strcat(Header,pHeaderName);
+ strcat(Header,":");
+ // Case insensitive search for the header name (search the incoming headers)
+ if(IncommingHeaders == TRUE)
+ {
+ pParam->pParam = HTTPStrCaseStr(pHTTPSession->HttpHeaders.HeadersIn.pParam + nOffset,
+ pHTTPSession->HttpHeaders.HeadersIn.nLength,
+ Header);
+ }
+ else
+ {
+ // Optionally search the outgoing headers
+ pParam->pParam = HTTPStrCaseStr(pHTTPSession->HttpHeaders.HeadersOut.pParam + nOffset,
+ pHTTPSession->HttpHeaders.HeadersOut.nLength,
+ Header);
+ }
+
+ if(pParam->pParam) // Did we find it?
+ {
+ // Search for the token end (trailing CrLf)
+ pHeaderEnd = strstr(pParam->pParam + 2,HTTP_CLIENT_CRLF);
+ if(pHeaderEnd)
+ {
+ // Get the length (up to the CrLf)
+ pParam->nLength = pHeaderEnd - pParam->pParam;
+ nRetCode = HTTP_CLIENT_SUCCESS;
+ break;
+
+ }
+ }
+ }while(0);
+
+ // Could not find the header
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnAuthenticate
+// Purpose :
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnAuthenticate(P_HTTP_SESSION pHTTPSession)
+{
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS; // Function call return code
+ UINT32 nBytes = 32;
+ UINT32 nTotalBytes = 0;
+ CHAR ErrorPage[32];
+ BOOL NewConnection = FALSE;
+
+
+ do
+ {
+ // Validate the session pointer
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ // Handle connection close message (reconnect)
+ if(pHTTPSession->HttpHeadersInfo.Connection == FALSE)
+ {
+ // Gracefully close the connection and set the socket as invalid
+ if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)
+ {
+ HTTPIntrnConnectionClose(pHTTPSession);
+ }
+ // Connect to the remote server (or proxy)
+ nRetCode = HTTPIntrnConnectionOpen(pHTTPSession);
+ if(nRetCode != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ NewConnection = TRUE;
+ }
+
+ // Analyze the security headers and optionally build the authentication reply header
+ if((nRetCode = HTTPIntrnParseAuthHeader(pHTTPSession))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // We have to recive any HTML data here inorder to "Clear" the socket buffer for later usage
+ // Note: We should skip this when the HEAD verb was used
+ while(NewConnection == FALSE && pHTTPSession->HttpHeaders.HttpLastVerb != VerbHead && pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0 && nBytes > 0)
+ {
+ ErrorPage[0] = 0;
+ if((nRetCode = HTTPIntrnRecv(pHTTPSession,ErrorPage,&nBytes,FALSE)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ nTotalBytes += nBytes;
+ if(nTotalBytes >= pHTTPSession->HttpHeadersInfo.nHTTPContentLength)
+ {
+ break;
+ }
+ }
+
+ // Re-Send the headers after having analyzed the authorizaton headers
+ if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ }while(0);
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnAuthenticate",NULL,0,"");
+ }
+#endif
+
+ return nRetCode;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnHeadersParse
+// Purpose : Parse the HTTP incoming headers.
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnHeadersParse (P_HTTP_SESSION pHTTPSession)
+{
+
+ CHAR *pPtr; // a pointer that points on the incoming headers
+ UINT32 nTokenLength = 0; // Length of the parsed token
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value
+ UINT32 nOffset = 0; // Bytes offset (strings comperision)
+ CHAR HTTPToken[HTTP_CLIENT_MAX_TOKEN_LENGTH]; // Buffer for the parsed HTTP token
+ HTTP_PARAM HTTPParam; // A generic pointer\length parameter for parsing
+ BOOL AuthHeaders = FALSE; // While we are searching the authentication methods
+
+ do
+ {
+ // Validate the session pointer
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnHeadersParse",pHTTPSession->HttpHeaders.HeadersIn.pParam,pHTTPSession->HttpHeaders.HeadersIn.nLength,"[Incomming Headers]");
+ }
+#endif
+
+
+ // Set a pointer on the incoming headers
+ pPtr = pHTTPSession->HttpHeaders.HeadersIn.pParam;
+
+ // Detect the leading HTTP string
+ if(HTTPStrInsensitiveCompare(pPtr,"http",4) != TRUE)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER;
+ break;
+ }
+
+ // Get the HTTP Version
+ while ((*pPtr) && (*pPtr != 0x20))
+ {
+ nTokenLength++;
+ pPtr++; // Move to the first space
+ }
+ strncpy(pHTTPSession->HttpHeadersInfo.HTTPVersion,
+ pPtr - nTokenLength,
+ MIN(15,nTokenLength));
+ pPtr++;
+
+ // Get the HTTP status code
+ memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH);
+ nTokenLength = 0;
+ while ((*pPtr) && (*pPtr != 0x20))
+ {
+ nTokenLength++;
+ pPtr++; // Move to the next space
+ }
+ strncpy(HTTPToken,(pPtr - nTokenLength),MIN(HTTP_CLIENT_MAX_TOKEN_LENGTH,nTokenLength));
+
+ pHTTPSession->HttpHeadersInfo.nHTTPStatus = atol(HTTPToken);
+
+ // Search for content length
+ pHTTPSession->HttpHeadersInfo.nHTTPContentLength = 0; // Default no unknown length
+ // Look for the token
+ if(HTTPIntrnHeadersFind(pHTTPSession,"content-length",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS)
+ {
+
+ memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); // Reset the token buffer
+ nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; // Set the buffer length
+ // Attempt to extract the token
+ if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength))
+ {
+ // Convert the content-length into an integer.
+ pHTTPSession->HttpHeadersInfo.nHTTPContentLength = atol(HTTPToken);
+ }
+ }
+
+ // Search for connection status
+ pHTTPSession->HttpHeadersInfo.Connection = TRUE; // Default status where no server connection header was detected
+ // Look for token (can be standard connection or a proxy connection)
+ if( (HTTPIntrnHeadersFind(pHTTPSession,"connection",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) ||
+ (HTTPIntrnHeadersFind(pHTTPSession,"proxy-connection",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS))
+ {
+
+ memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH);
+ nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH;
+ // Attempt to extract the token
+ if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength))
+ {
+ // Is this a keep alive session?
+ pHTTPSession->HttpHeadersInfo.Connection = HTTPStrInsensitiveCompare(HTTPToken,"keep-alive",0);
+ // Is it a closed session
+ if(HTTPStrInsensitiveCompare(HTTPToken,"close",0) == TRUE)
+ {
+ pHTTPSession->HttpHeadersInfo.Connection = FALSE;
+ }
+ }
+ }
+
+ // Search for chunking mode transfer
+ pHTTPSession->HttpFlags = pHTTPSession->HttpFlags &~ HTTP_CLIENT_FLAG_CHUNKED; // Remove the flag
+ if(HTTPIntrnHeadersFind(pHTTPSession,"transfer-encoding",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS)
+ {
+
+ memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH);
+ nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH;
+ if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength))
+ {
+ // If the chunks token was find then set the session flag accordingly
+ if(HTTPStrInsensitiveCompare(HTTPToken,"chunked",0) == TRUE)
+ {
+ pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_CHUNKED;
+ }
+ }
+ }
+ // Look for the authentication header
+ while(AuthHeaders == FALSE) // address multiple authentication methods presented by the server
+ {
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_UNAUTHORIZED)
+ {
+ // Double check for the "www-authenticate" header token
+ if(HTTPIntrnHeadersFind(pHTTPSession,"www-authenticate",&pHTTPSession->HttpAuthHeader.AuthHeader,TRUE,nOffset) != HTTP_CLIENT_SUCCESS)
+ {
+ if(nOffset > 0) // an authentication header was found but not the right one so adjust the error
+ {
+ nRetCode = HTTP_CLIENT_ERROR_AUTH_MISMATCH;
+ }
+ else
+ {
+ nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER;
+ }
+
+ break;
+ }
+
+ // Make sure that we get an authentication header that maches the caller requested schema
+ pPtr = HTTPStrCaseStr(pHTTPSession->HttpAuthHeader.AuthHeader.pParam,
+ pHTTPSession->HttpAuthHeader.AuthHeader.nLength,
+ pHTTPSession->HttpCredentials.AuthSchemaName);
+ if(pPtr)
+ {
+ AuthHeaders = TRUE;
+ }
+ else
+ {
+ // Simply pass the point where the last "www" was found
+ nOffset = (pHTTPSession->HttpAuthHeader.AuthHeader.pParam - pHTTPSession->HttpHeaders.HeadersIn.pParam) + 3;
+ }
+ }
+ else
+ {
+ AuthHeaders = TRUE;
+ }
+ }
+
+ // Is this a proxy authentication header?
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED)
+ {
+ // Double check for the "Proxy-Authentication" header token
+ if (HTTPIntrnHeadersFind(pHTTPSession,"proxy-authenticate",&pHTTPSession->HttpAuthHeader.AuthHeader,TRUE,0) != HTTP_CLIENT_SUCCESS)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER;
+ break;
+ }
+ }
+
+ // Do we have a redirection response?
+ if( (pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OBJECT_MOVED) ||
+ (pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OBJECT_MOVED_PERMANENTLY))
+ {
+ // Check for the "Location" header token
+ if (HTTPIntrnHeadersFind(pHTTPSession,"location",&pHTTPSession->HttpHeadersInfo.HttpRedirectURL,TRUE,0) != HTTP_CLIENT_SUCCESS)
+ {
+ // Protocol violation, we got a redirect code without the host name to redirect to
+ nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER;
+ break;
+ }
+ // Fix the pointers location (address the "Location: " prefix)
+ pHTTPSession->HttpHeadersInfo.HttpRedirectURL.pParam += 12;
+ pHTTPSession->HttpHeadersInfo.HttpRedirectURL.nLength -= 12;
+
+ }
+
+ }while(0);
+
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnParseAuthHeader
+// Purpose : Parse the HTTP headers for the required authentication method
+// Gets :
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnParseAuthHeader(P_HTTP_SESSION pHTTPSession)
+{
+
+ CHAR *pPtrStart, *pPtrEnd;
+
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ if(pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone)
+ {
+ // for proxy authentication simply assume basic and exit
+ return HTTP_CLIENT_SUCCESS;
+ }
+ // Advance the pointer in the string and break on the first space
+ pPtrEnd = pHTTPSession->HttpAuthHeader.AuthHeader.pParam + pHTTPSession->HttpAuthHeader.AuthHeader.nLength;
+ pPtrStart = pHTTPSession->HttpAuthHeader.AuthHeader.pParam;
+ // Jump to the first space
+ while ((pPtrEnd - pPtrStart) > 0 && *pPtrStart != 0x20) pPtrStart++;
+
+ do
+ {
+ if(HTTPStrCaseStr(pPtrStart,8,"basic"))
+ {
+ pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaBasic;
+ break;
+ }
+
+ if(HTTPStrCaseStr(pPtrStart,8,"digest"))
+ {
+ pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaDigest;
+ break;
+ }
+ if(HTTPStrCaseStr(pPtrStart,8,"negotiate")) // Note that this could be NLM negotiation as well (which is not supported)
+ {
+ pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaKerberos;
+ break;
+ }
+ // To-Do: Add any other supported authentication method
+ }
+ while(0);
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnParseAuthHeader",pHTTPSession->HttpAuthHeader.AuthHeader.pParam,
+ pHTTPSession->HttpAuthHeader.AuthHeader.nLength,"[Incomming Auth Headers: %d]",pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA);
+ }
+#endif
+
+ // If we could not detect the authentication schema return an error
+ if(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA == AuthSchemaNone)
+ {
+ return HTTP_CLIENT_ERROR_BAD_AUTH;
+ }
+
+ //Make sure we are going to authenticate with the method specified by the caller
+ if(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA != (UINT32)pHTTPSession->HttpCredentials.CredAuthSchema)
+ {
+ return HTTP_CLIENT_ERROR_AUTH_MISMATCH;
+ }
+
+
+ return HTTP_CLIENT_SUCCESS;
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnHeadersSend
+// Purpose : Build and send the HTTP request. this includes the HTTP headers
+// and any required authentication data
+// Gets :
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnHeadersSend(P_HTTP_SESSION pHTTPSession,
+ HTTP_VERB HttpVerb) // [IN] Argument that can bypass the requested verb
+ // Can be used for evaluating a HEAD request
+{
+
+ UINT32 nBytes;
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS;
+ CHAR RequestCmd[16];
+ CHAR ContentLength[32];
+ BOOL RestoreHeadersFlag = FALSE;
+ HTTP_VERB HttpCachedVerb;
+ CHAR *pPtr; // Content length conversion
+
+ if(!pHTTPSession)
+ {
+ // Bad session pointer error
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnHeadersSend",NULL,
+ 0,"Using Verb: %d",(INT32)HttpVerb);
+ }
+#endif
+ // Cache the original VERB
+ HttpCachedVerb = pHTTPSession->HttpHeaders.HttpVerb;
+
+ do
+ {
+
+ // Set the verb (temporarily)
+ if(pHTTPSession->HttpHeaders.HttpVerb != HttpVerb)
+ {
+ if((nRetCode = HTTPClientSetVerb((HTTP_SESSION_HANDLE)pHTTPSession,HttpVerb)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // Remeber this state for later usage
+ pHTTPSession->HttpHeaders.HttpLastVerb = pHTTPSession->HttpHeaders.HttpVerb;
+
+ // If this is a head request we should temporary remove the chunking header and the content length header
+ if(pHTTPSession->HttpHeaders.HttpVerb == VerbHead)
+ {
+
+ // If send in chunks flag was set
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED)
+ {
+ // Chunking
+ if((nRetCode = HTTPIntrnHeadersRemove(pHTTPSession,"Transfer-Encoding")) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ // Content-Length
+ if(pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength > 0) // Attempt to remove only if it was previusly set
+ {
+ if((nRetCode = HTTPIntrnHeadersRemove(pHTTPSession,"Content-Length")) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ RestoreHeadersFlag = TRUE; // So it would be restored later
+ }
+ // Request Verb
+ nBytes = strlen(pHTTPSession->HttpHeaders.Verb) + 1;
+ memset(RequestCmd,0x00,16);
+ strcpy(RequestCmd,pHTTPSession->HttpHeaders.Verb);
+ strcat(RequestCmd," ");
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,RequestCmd,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes;
+
+
+ // Request URI
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY)
+ {
+ nBytes = pHTTPSession->HttpUrl.UrlRequest.nLength;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.UrlRequest.pParam,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes;
+ }
+ else
+ {
+ nBytes = strlen(pHTTPSession->HttpUrl.Url);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.Url,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes;
+ }
+ // Request HTTP Version
+ memset(RequestCmd,0x00,16);
+ strcpy(RequestCmd," ");
+ strcat(RequestCmd,HTTP_CLIENT_DEFAULT_VER);
+ strcat(RequestCmd,HTTP_CLIENT_CRLF);
+ nBytes = strlen(RequestCmd);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,RequestCmd,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes;
+
+ // Request headers
+ nBytes = pHTTPSession->HttpHeaders.HeadersOut.nLength;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpHeaders.HeadersOut.pParam,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes;
+
+ // Optionally add authentication headers and send them (for host or proxy authentication)
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_UNAUTHORIZED || pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED )
+ {
+
+ if((nRetCode = HTTPIntrnAuthHandler(pHTTPSession)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // Request terminating CrLf
+ nBytes = strlen(HTTP_CLIENT_CRLF);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes;
+
+ // Restore the verb
+ if(pHTTPSession->HttpHeaders.HttpVerb != HttpCachedVerb)
+ {
+ if((nRetCode = HTTPClientSetVerb((HTTP_SESSION_HANDLE)pHTTPSession,HttpCachedVerb)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ if(RestoreHeadersFlag == TRUE)
+ {
+ // Restore chunking header (since it was temporarily removed for the head request
+ // Add the Transfer-Encoding: header
+ if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED)
+ {
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Transfer-Encoding",17,"chunked",7))!= HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ }
+ // Restore the content length
+ if(pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength > 0) // Attempt to remove only if it was previusly set
+ {
+ pPtr = IToA(ContentLength,pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength); // Convert the buffer length to a string value
+ if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Length",14,ContentLength,strlen(ContentLength)))!= HTTP_CLIENT_SUCCESS)
+ {
+ return nRetCode;
+ }
+ }
+ }
+ // Set the session stage
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_REQUEST_SENT;
+
+ } while(0);
+
+
+ return nRetCode; // end of HTTPIntrnSendHeaders()
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnAuthHandler
+// Purpose : Differentiate between the authenticate method that we have to implement and perform
+// the required operation.
+// Gets :
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnAuthHandler (P_HTTP_SESSION pHTTPSession)
+{
+
+ UINT32 nRetCode = HTTP_CLIENT_SUCCESS;
+
+ if(!pHTTPSession)
+ {
+ // Bad session pointer error
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ if(pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone)
+ {
+ // For proxy authentication simply assume basic and exit
+ // Basic authentication
+ nRetCode = HTTPIntrnAuthSendBasic(pHTTPSession);
+ return nRetCode;
+ }
+
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnAuthHandler",NULL,
+ 0,"");
+ }
+#endif
+
+ // Use the correct authentication method as requested by the server
+ switch(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA)
+ {
+
+ case AuthSchemaBasic:
+ {
+ // Basic authentication
+ nRetCode = HTTPIntrnAuthSendBasic(pHTTPSession);
+ break;
+
+ }
+ case AuthSchemaDigest:
+ {
+ // Digest authentication
+ nRetCode = HTTPIntrnAuthSendDigest(pHTTPSession);
+ break;
+
+ }
+ case AuthSchemaKerberos:
+ {
+ // ToDo: impliament the Kerberos nego authentication here
+ nRetCode = HTTP_CLIENT_ERROR_NOT_IMPLEMENTED;
+ break;
+
+ }
+ default:
+ {
+ // Not supported method
+ return HTTP_CLIENT_ERROR_BAD_AUTH; // Not implemented error
+ }
+
+ };
+
+ // This session requested an authentication so..
+ pHTTPSession->HttpCredentials.Authentication = TRUE;
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnAuthSendBasic
+// Purpose : Handle basic authentication for direst host connection and proxy authentication
+// Gets :
+// Returns :
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+static UINT32 HTTPIntrnAuthSendBasic (P_HTTP_SESSION pHTTPSession)
+{
+
+ UINT32 nSegmentLength;
+ UINT32 nRetCode;
+ CHAR Cred[HTTP_CLIENT_MAX_64_ENCODED_CRED /2]; // Credentials (Clear)
+ CHAR Cred64[HTTP_CLIENT_MAX_64_ENCODED_CRED]; // Credentials (64 bit encoded)
+ UINT32 nSrcLength, nDestLength;
+ CHAR* pPtr;
+ CHAR* INITIAL_HDR = "Authorization: Basic ";
+ CHAR* INITIAL_PROXY_HDR = "Proxy-Authorization: Basic ";
+
+
+ do
+ {
+ if(!pHTTPSession)
+ {
+ nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ break;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnAuthSendBasic",NULL,
+ 0,"");
+ }
+#endif
+
+ memset(Cred,0x00,HTTP_CLIENT_MAX_64_ENCODED_CRED /2);
+ memset(Cred64,0x00,HTTP_CLIENT_MAX_64_ENCODED_CRED);
+
+
+ switch (pHTTPSession->HttpHeadersInfo.nHTTPStatus)
+ {
+ case( HTTP_STATUS_UNAUTHORIZED): // For host authentication
+ {
+
+ // Copy the clear text credentials to a format of user:password
+ strcpy(Cred,pHTTPSession->HttpCredentials.CredUser);
+ strcat(Cred,":");
+ strcat(Cred,pHTTPSession->HttpCredentials.CredPassword);
+ nSrcLength = strlen(Cred);
+ nDestLength = HTTP_CLIENT_MAX_64_ENCODED_CRED;
+ nSegmentLength = strlen(INITIAL_HDR);
+ // Build and send the data first the hard-coded static portion
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // Convert to base 64
+ HTTPBase64Encoder((unsigned char *)Cred64,(CONST unsigned char *)Cred,nSrcLength);
+ nDestLength = strlen(Cred64);
+
+ };
+ break;
+ case (HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED): // For Proxy authentication
+ {
+ // Copy the clear text credentials to a format of user:password
+ strcpy(Cred,pHTTPSession->HttpProxy.ProxtUser);
+ strcat(Cred,":");
+ strcat(Cred,pHTTPSession->HttpProxy.ProxyPassword);
+ nSrcLength = strlen(Cred);
+ nDestLength = HTTP_CLIENT_MAX_64_ENCODED_CRED;
+
+ // Convert to base 64
+ HTTPBase64Encoder((unsigned char *)Cred64,(unsigned char *)Cred,nSrcLength);
+ nDestLength = strlen(Cred64);
+ nSegmentLength = strlen(INITIAL_PROXY_HDR);
+ // Build and send the data first the hard-coded static portion
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_PROXY_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ };
+ break;
+ default:
+ {
+ return HTTP_CLIENT_ERROR_BAD_AUTH; // Wrong status for this function
+ };
+ };
+
+ // Send the base 64 encoded data
+ pPtr = Cred64;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pPtr, &nDestLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nDestLength;
+
+ // Terminating CRLF
+ nSegmentLength = strlen(HTTP_CLIENT_CRLF);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+
+ } while (0);
+
+ return nRetCode;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnAuthSendDigest
+// Purpose : Handle digest authentication for direct host connection and proxy authentication
+// Gets :
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnAuthSendDigest (P_HTTP_SESSION pHTTPSession)
+{
+ CHAR Cnonce[33];
+ UINT32 nSegmentLength;
+ UINT32 nRetCode;
+ UINT32 nAlgType = 0; // a flag for the algorithem type (default to MD5)
+ HTTP_PARAM HttpParamOpq,HttpParamRealm,HttpParamNonce,HttpParamQop,HttpParamAlg; // Pointers and lengths of the dynamic sections
+ // of the Digest response.
+
+
+ // Fragments of the Digest client response (The hard coded text portion of the response)
+ CHAR* INITIAL_HDR = "Authorization: Digest username=\"";
+ CHAR* INITIAL_PROXY_HDR = "Proxy-Authorization: Digest username=\"";
+ CHAR* REALEM_HDR = "\", realm=\"";
+ CHAR* QOP_HDR = "\", qop=\"";
+ CHAR* ALGO_HDR = "\", algorithm=\"";
+ CHAR* URI_HDR = "\", uri=\"";
+ CHAR* NONCE_HDR = "\", nonce=\"";
+ CHAR* NC_HDR = "\", nc=00000001, cnonce=\""; // To-Do: This should be tested!!
+ CHAR* RSP_HDR = "\", response=\"";
+ CHAR* OPQ_HDR = "\", opaque=\"";
+ // Digest Calculation related
+ HASHHEX HA1;
+ HASHHEX HA2 = "";
+ HASHHEX Response;
+
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnAuthSendDigest",NULL,
+ 0,"");
+ }
+#endif
+
+ // Generate random Cnonce number
+ HTTPDigestGenerateCNonce(Cnonce);
+
+ switch (pHTTPSession->HttpHeadersInfo.nHTTPStatus)
+ {
+ case( HTTP_STATUS_UNAUTHORIZED): // For host authentication
+ {
+ // "Authorization: Digest username="
+ nSegmentLength = strlen(INITIAL_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ return nRetCode;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+ };
+ break;
+ case (HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED): // For Proxy authentication
+ {
+ // "Proxy-Authorization: Digest username="
+ nSegmentLength = strlen(INITIAL_PROXY_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_PROXY_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ return nRetCode;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+ };
+ break;
+ default:
+ {
+ return HTTP_CLIENT_ERROR_BAD_AUTH; // Wrong status for this function
+ };
+ };
+
+ do
+ {
+
+ // "Authorization: Digest username="username
+ nSegmentLength = strlen(pHTTPSession->HttpCredentials.CredUser);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpCredentials.CredUser, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // "Authorization: Digest username="username", realm="
+ nSegmentLength = strlen(REALEM_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,REALEM_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // "Authorization: Digest username="username", realm="realm
+ if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"realm", &HttpParamRealm)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamRealm.pParam, &HttpParamRealm.nLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamRealm.nLength;
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ nSegmentLength = strlen(QOP_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,QOP_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"qop", &HttpParamQop)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamQop.pParam, &HttpParamQop.nLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamQop.nLength;
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5",
+
+ nSegmentLength = strlen(ALGO_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,ALGO_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"algorithm", &HttpParamAlg)) != HTTP_CLIENT_SUCCESS)
+ {
+
+ // The server did not state its required algorithm so use the default
+ HttpParamAlg.pParam = HTTP_CLIENT_DEFAULT_DIGEST_AUTH;
+ HttpParamAlg.nLength = strlen(HTTP_CLIENT_DEFAULT_DIGEST_AUTH);
+ }
+ // Get the algorithem type
+ if(HTTPStrInsensitiveCompare(HttpParamAlg.pParam ,"md5",3 ) == TRUE)
+ {
+ if(HTTPStrInsensitiveCompare(HttpParamAlg.pParam ,"md5-sess", HttpParamAlg.nLength) == TRUE)
+ {
+ nAlgType = 1;
+ }
+
+ }
+ else
+ {
+ // Error algorithem not supported
+ nRetCode = HTTP_CLIENT_ERROR_NO_DIGEST_ALG;
+ break;
+ }
+
+ // Send the algorithem
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamAlg.pParam, &HttpParamAlg.nLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamAlg.nLength;
+
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="
+ nSegmentLength = strlen(URI_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,URI_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service
+ nSegmentLength = strlen(pHTTPSession->HttpUrl.UrlRequest.pParam);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.UrlRequest.pParam, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service", nonce="
+ nSegmentLength = strlen(NONCE_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,NONCE_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service", nonce="7a5c...
+ if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"nonce", &HttpParamNonce)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamNonce.pParam, &HttpParamNonce.nLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamNonce.nLength;
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="
+ nSegmentLength = strlen(NC_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,NC_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...
+ nSegmentLength = strlen(Cnonce);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,Cnonce, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // Send the opaque data if we got it from the server
+ if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"opaque", &HttpParamOpq)) == HTTP_CLIENT_SUCCESS)
+ {
+
+ nSegmentLength = strlen(OPQ_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,OPQ_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamOpq.pParam, &HttpParamOpq.nLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamOpq.nLength;
+
+ }
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...", response="
+ nSegmentLength = strlen(RSP_HDR);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,RSP_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // Calculate response
+ HTTPDigestCalcHA1(nAlgType, pHTTPSession->HttpCredentials.CredUser,
+ HttpParamRealm.pParam,HttpParamRealm.nLength ,
+ pHTTPSession->HttpCredentials.CredPassword ,
+ HttpParamNonce.pParam, HttpParamNonce.nLength,
+ Cnonce, HA1);
+
+ HTTPDigestCalcResponse(HA1,
+ HttpParamNonce.pParam, HttpParamNonce.nLength,
+ "00000001", Cnonce,
+ HttpParamQop.pParam,HttpParamQop.nLength, pHTTPSession->HttpHeaders.Verb,
+ pHTTPSession->HttpUrl.UrlRequest.pParam,pHTTPSession->HttpUrl.UrlRequest.nLength,
+ HA2, Response);
+
+ // "Authorization: Digest username="username", realm="myRealm", qop="auth",
+ // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...", response="8bbf2...
+ nSegmentLength = strlen(Response);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,Response, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+
+ // Terminate 0x24 (")
+ nSegmentLength = 1;
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,"\"", &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ // Terminating CRLF
+ nSegmentLength = strlen(HTTP_CLIENT_CRLF);
+ if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF, &nSegmentLength)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+ // Set the counters
+ pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength;
+
+ } while(0);
+
+ return nRetCode; // End of digest respobse sending
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnSessionReset
+// Purpose : Reset the session data for the next operation
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnSessionReset (P_HTTP_SESSION pHTTPSession, BOOL EntireSession)
+{
+ UINT32 nActionTimeout; // For restoring a parameter after this reset
+ UINT32 nAllocationSize;
+
+ // Validate the pointer
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ pHTTPSession->pDebug("HTTPIntrnSessionReset",NULL,
+ 0,"");
+ }
+#endif
+
+
+ memset(pHTTPSession->HttpHeaders.HeadersIn.pParam,0x00,pHTTPSession->HttpHeaders.HeadersIn.nLength);
+ pHTTPSession->HttpHeaders.HeadersIn.nLength = 0;
+
+
+ // Reset the HTTP counters
+ nActionTimeout = pHTTPSession->HttpCounters.nActionTimeout;
+ memset(&pHTTPSession->HttpCounters,0x00,sizeof(HTTP_COUNTERS));
+ pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime();
+ // Restore the parameter
+ pHTTPSession->HttpCounters.nActionTimeout = nActionTimeout;
+ // Reset the authentication flag
+ pHTTPSession->HttpCredentials.Authentication = FALSE;
+
+
+ if(EntireSession == TRUE) // Partial reset, clear only the incoming headers
+ {
+ memset(&pHTTPSession->HttpUrl,0,sizeof(HTTP_URL));
+ nAllocationSize = pHTTPSession->HttpHeaders.HeadersBuffer.nLength;
+ // Reset the headers allocated memory
+ memset(pHTTPSession->HttpHeaders.HeadersBuffer.pParam ,0x00,nAllocationSize);
+
+ // Set default values in the session structure
+ HTTPClientSetVerb((UINT32)pHTTPSession,(HTTP_VERB)HTTP_CLIENT_DEFAULT_VERB); // Default HTTP verb
+ pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_PORT; // Default TCP port
+ // Set the outgoing headers pointers
+ memset(&pHTTPSession->HttpHeaders.HeadersIn,0,sizeof(HTTP_PARAM));
+ memset(&pHTTPSession->HttpHeaders.HeadersOut,0,sizeof(HTTP_PARAM));
+
+ pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam;
+ // Set our state
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_INIT;
+
+ memset(&pHTTPSession->HttpHeadersInfo,0,sizeof(HTTP_HEADERS_INFO));
+ if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)
+ {
+ pHTTPSession->HttpHeadersInfo.Connection = TRUE;
+ }
+ memset(&pHTTPSession->HttpAuthHeader,0,sizeof(HTTP_AUTH_HEADER));
+ memset(&pHTTPSession->HttpProxy,0,sizeof(HTTP_PROXY));
+
+ }
+
+ return HTTP_CLIENT_SUCCESS;
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnHeadersReceive
+// Purpose : Receives the response header on the connection and parses it.
+// Performs any required authentication.
+// Returns : HTTP Status
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnHeadersReceive (P_HTTP_SESSION pHTTPSession,
+ UINT32 nTimeout) // [IN] Timeout for the operation
+
+{
+
+ UINT32 nRetCode; // Function call return code
+ UINT32 nCount = 0;
+ if(!pHTTPSession)
+ {
+ // Bad session pointer error
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ do
+ {
+
+
+ // Set the operation time out if was set by the caller
+ if(nTimeout > 0)
+ {
+ // 0 makes us use the default defined value
+ pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout);
+
+ }
+
+ // Reset the incoming headers
+ if((nRetCode = HTTPIntrnSessionReset(pHTTPSession,FALSE)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ // Get the server response
+ if((nRetCode = HTTPIntrnGetRemoteHeaders(pHTTPSession)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ // Set the session state
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_RECIVED;
+
+ // Parse the response headers
+ if((nRetCode = HTTPIntrnHeadersParse(pHTTPSession)) != HTTP_CLIENT_SUCCESS)
+ {
+ break;
+ }
+
+ // Set the session state
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_PARSED;
+
+ // Set the session stage upon seccess
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OK)
+ {
+ pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_OK;
+ }
+ // Handle 100 continue message
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus != HTTP_STATUS_CONTINUE)
+ {
+ nCount++;
+ }
+
+#ifdef _HTTP_DEBUGGING_
+ if(pHTTPSession->pDebug)
+ {
+ if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_CONTINUE)
+ {
+ pHTTPSession->pDebug("HTTPIntrnHeadersReceive",NULL,0,"100 Continue Header");
+ }
+ }
+#endif
+
+ }while(nCount < 1);
+
+ return nRetCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnGetTicks
+// Purpose : Like GetTickCount() (implemented with time.h)
+// Gets : void
+// Returns : System ticks
+// Last updated : 01/09/200515/05/2005
+// Author Name : Eitan Michaelson
+// Notes : Assuming 1000 ticks per sec, should be implemented by the OS
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT32 HTTPIntrnSessionGetUpTime(VOID)
+{
+
+ return GetUpTime();
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPIntrnSessionEvalTimeout
+// Purpose : Check if we have to break the operation and return a time out error
+// Gets : a pointer to the session structure
+// Returns : BOOL, True if we have to break
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static BOOL HTTPIntrnSessionEvalTimeout(P_HTTP_SESSION pHTTPSession)
+{
+
+ UINT32 nElapsedTime; // Integer for calculating the elapsed time
+
+ // Validate the session pointer
+ if(!pHTTPSession)
+ {
+ return HTTP_CLIENT_ERROR_INVALID_HANDLE;
+ }
+
+ // Calculate the elapsed time since the last call
+ nElapsedTime = HTTPIntrnSessionGetUpTime() - pHTTPSession->HttpCounters.nActionStartTime;
+ // If the elapsed time is greater then the time out value we should return true
+ if(nElapsedTime >= pHTTPSession->HttpCounters.nActionTimeout)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClient.h b/src/thirdparty/ZenLib/HTTP_Client/HTTPClient.h
new file mode 100644
index 000000000..fac290ae1
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClient.h
@@ -0,0 +1,306 @@
+
+#ifndef _HTTP_CLIENT
+#define _HTTP_CLIENT
+
+#include "HTTPClientWrapper.h"
+#include "HTTPClientCommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // Section : HTTP API global definitions
+ // Last updated : 01/09/2005
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+#ifdef _HTTP_BUILD_AMT
+#define CMSI_HTTPCLIENT_PROTOCOL_GUID {0x471b2c0e, 0x6137, 0x4d55, 0x92, 0x36, 0xdd, 0x0f, 0xdb, 0xc2, 0x52, 0xfb}
+#endif
+
+ // Debug hook
+ // #define _HTTP_DEBUGGING_ // Simply dumps more debugging data to the console
+
+ // API Version
+#define HTTP_CLIENT_VERSION_MINOR 0
+#define HTTP_CLIENT_VERSION_MAJOR 1
+
+ // Global default sizes
+#define HTTP_CLIENT_MAX_SEND_RECV_HEADERS 1024 // Maximum Send and receive buffers size
+#define HTTP_CLIENT_INIT_SEND_RECV_HEADERS 2048 // If we can resize the buffers this would be the initial size
+
+#define HTTP_CLIENT_MAX_USERNAME_LENGTH 16 // Maximum length the user name (host and proxy authentication)
+#define HTTP_CLIENT_MAX_PASSWORD_LENGTH 16 // Maximum length for the password
+ // Maximum length for the base 64 encoded credentials (twice the size of the user name and password max parameters)
+#define HTTP_CLIENT_MAX_64_ENCODED_CRED ((HTTP_CLIENT_MAX_USERNAME_LENGTH + HTTP_CLIENT_MAX_PASSWORD_LENGTH) * 2) + 4
+#define HTTP_CLIENT_MAX_CHUNK_HEADER 64 // Maximum length for the received chunk header (hex - string) size
+#define HTTP_CLIENT_MAX_PROXY_HOST_LENGTH 64 // Maximum length for the proxy host name
+#define HTTP_CLIENT_MAX_TOKEN_LENGTH 512 // Maximum length for an HTTP token data (authentication header elements)
+#define HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH 32 // Maximum length for an HTTP authorization token name ("qop")
+#define HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE 1024 // Maximum length for a search clue string (Headers searching)
+#define HTTP_CLIENT_ALLOW_HEAD_VERB 0 // Can we use the HTTP HEAD verb in our outgoing requests?
+
+#define HTTP_CLIENT_MEMORY_RESIZABLE FALSE // Permission to dynamically resize the headers buffer
+#define HTTP_CLIENT_MEMORY_RESIZE_FACTOR 16 // Factor for memory resizing operation
+
+#define HTTP_CLIENT_DEFAULT_PORT 80 // Default HTTP port
+#define HTTP_CLIENT_DEFAULT_SSL_PORT 443 // Default HTTPS port
+#define HTTP_CLIENT_DEFAULT_VERB 0 // GET
+#define HTTP_CLIENT_DEFAULT_VER "HTTP/1.1" // We will send this in the outgoing header
+#define HTTP_CLIENT_DEFAULT_PROXY_VER "HTTP/1.0" // We will send this in the outgoing header (proxy)
+#define HTTP_CLIENT_DEFAULT_AGENT "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"
+#define HTTP_CLIENT_DEFAULT_TIMEOUT 30 // Default timeout in seconds
+#define HTTP_CLIENT_DEFAULT_KEEP_ALIVE 30 // Default Keep-alive value in seconds
+#define HTTP_CLIENT_DEFAULT_DIGEST_AUTH "MD5" // This is for bypassing a known bug in AMT05..
+#define HTTP_CLIENT_DEFAULT_PROXY_AUTH 1 // Basic
+
+#define HTTP_CLIENT_CRLF "\r\n" // End of line macro
+#define HTTP_CLIENT_CRLFX2 "\r\n\r\n" // Double End of line macro
+
+ // HTTP Session internal API flags
+ // Note: Not intended to be set the by the API user
+#define HTTP_CLIENT_FLAG_SECURE 0x00000010 // The session is secured using TLS
+#define HTTP_CLIENT_FLAG_URLANDPORT 0x00000020 // Url has a port within
+#define HTTP_CLIENT_FLAG_URLHTTPS 0x00000040 // Url has a https prefix
+#define HTTP_CLIENT_FLAG_USINGPROXY 0x00000080 // Operation will be performed using a proxy server
+#define HTTP_CLIENT_FLAG_CHUNKED 0x00000100 // The incoming data is chunked
+
+ // HTTP Status codes
+#define HTTP_STATUS_OK 200 // The request has succeeded
+#define HTTP_STATUS_UNAUTHORIZED 401 // The request requires user authentic
+#define HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED 407 // The client must first authenticate itself with the proxy
+
+ // Redirection (Note: there are more 30x codes, those are the most popular)
+#define HTTP_STATUS_OBJECT_MOVED 302 // Page redirection notification
+#define HTTP_STATUS_OBJECT_MOVED_PERMANENTLY 301 // Page redirection notification
+#define HTTP_STATUS_CONTINUE 100 // Page continue message
+
+
+ // MIN AMX macro
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+ // HTTP timeout macro for selecting the default value if the caller passed 0 (no timeout) to the function
+#define HTTP_TIMEOUT(nTimeout) (((nTimeout) > (0)) ? (nTimeout) : (HTTP_CLIENT_DEFAULT_TIMEOUT))
+
+ // 32 bit alignment macro
+#define ALIGN(size) ((size & 0xfffffffc) + ((size & 3) ? 4 : 0))
+
+
+#ifdef _HTTP_DEBUGGING_
+ typedef VOID _stdcall E_HTTPDebug(const char *,const char*,UINT32,char *,...); // HTTPDebug hook function
+#endif
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // Section : HTTP API internals structures
+ // Last updated : 01/09/2005
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // Generic parameter structure contains a pointer to the buffer and its length
+
+ typedef struct _HTTP_PARAM
+ {
+
+ CHAR *pParam;
+ UINT32 nLength;
+
+ } HTTP_PARAM;
+
+ // HTTP socket events
+ typedef struct _HTTP_CONNECTION
+ {
+
+ fd_set FDRead; // socket read event
+ fd_set FDWrite; // socket write event
+ fd_set FDError; // socket error event
+ INT32 HttpSocket; // The underling socket
+ UINT32 HttpStartTime; // Time stamp for the session
+ UINT32 HttpClientPort; // For client side binding
+ BOOL TlsNego; // TLS negotiation flag
+
+ } HTTP_CONNECTION;
+
+ // Request URL
+ typedef struct _HTTP_URL
+ {
+
+ HTTP_PARAM UrlBsee; // a pointer and length to the "http" section of the URL
+ HTTP_PARAM UrlHost; // a pointer and length to the host section of the URL
+ HTTP_PARAM UrlPort; // a pointer and length to the PORT (if was specified section)
+ HTTP_PARAM UrlRequest; // a pointer and length of the request section of the URL
+ UINT16 nPort; // the PORT that we should use (could be default or the one found within the URL)
+ CHAR Url[HTTP_CLIENT_MAX_URL_LENGTH]; // a buffer for the URL
+
+ }HTTP_URL;
+ // HTTP headers (incoming and outgoing)
+ typedef struct _HTTP_HEADERS
+ {
+
+ HTTP_PARAM HeadersBuffer; // a pointer and length of the complete Headers (in\out) buffer
+ HTTP_PARAM HeadersOut; // a pointer and length of the outgoing HTTP headers
+ HTTP_PARAM HeadersIn; // a pointer and length of the incoming headers
+ HTTP_PARAM HeaderSearch; // Index and pointer for the header search functions
+ HTTP_VERB HttpVerb; // the HTTP verb that was used in the session
+ HTTP_VERB HttpLastVerb; // the HTTP verb that was last transmited to the server
+ CHAR SearchClue[HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE];
+ CHAR Verb[16]; // the actual string buffer of the HTTP verb
+
+
+ }HTTP_HEADERS;
+
+ // HTTP headers (parsed headers information)
+ typedef struct _HTTP_HEADERS_INFO
+ {
+ HTTP_PARAM HttpRedirectURL; // Stores the redirection URL if we got a 301 or 303 return code
+ UINT32 nHTTPStatus; // the HTTP status code (200 401 407 act')
+ UINT32 nHTTPContentLength; // the Content length if specified of the returned data
+ UINT32 nHTTPPostContentLength;// the Content-Length of the POSTed data (if known)
+ BOOL Connection; // True = Keep alive or undefined, False = Closed
+ BOOL ValidHeaders; // a flag that indicates if the incoming header ware parsed OK and found to be valid
+ BOOL HaveCredentials; // a flag that indicates if we have credentials for the session
+ CHAR HTTPVersion[16]; // HTTP version string buffer (for example: "HTTP 1.1")
+
+ }HTTP_HEADERS_INFO;
+
+ // Authentication parameters that ware extracted from the incoming headers
+ typedef struct _HTTP_AUTH_HEADER
+ {
+
+ HTTP_PARAM AuthHeader; // the pointer and length of the authentication header
+ UINT32 HTTP_AUTH_SCHEMA; // Its schema (could be any of the supported)
+
+ }HTTP_AUTH_HEADER;
+ // Proxy related data
+ typedef struct _HTTP_PROXY
+ {
+ CHAR ProxyHost[HTTP_CLIENT_MAX_PROXY_HOST_LENGTH];
+ CHAR ProxtUser[HTTP_CLIENT_MAX_USERNAME_LENGTH];
+ CHAR ProxyPassword[HTTP_CLIENT_MAX_PASSWORD_LENGTH];
+ UINT16 nProxyPort;
+ CHAR AuthSchemaName[16]; // The authentication schema name (for string comperission)
+ HTTP_AUTH_SCHEMA ProxyAuthSchema;
+
+ }HTTP_PROXY;
+
+ // HTTP User credentials
+ typedef struct _HTTP_CREDENTIALS
+ {
+
+ CHAR CredUser[HTTP_CLIENT_MAX_USERNAME_LENGTH];
+ CHAR CredPassword[HTTP_CLIENT_MAX_PASSWORD_LENGTH];
+ CHAR AuthSchemaName[16]; // The authentication schema name (for string comperission)
+ HTTP_AUTH_SCHEMA CredAuthSchema; // The schema that calle has selected for the session
+ BOOL Authentication; // a flag that indicates that this session has requested a user authentication
+
+ }HTTP_CREDENTIALS;
+ // HTTP Counters
+ typedef struct _HTTP_COUNTERS
+ {
+
+ UINT32 nRecivedHeaderLength; // Bytes count of the incoming header
+ UINT32 nRecivedBodyLength; // Bytes count of the incoming body length
+ UINT32 nRecivedChunkLength; // The next chunk length in bytes
+ UINT32 nBytesToNextChunk; // How many bytes we have to read until we can expect the next chunk
+ UINT32 nActionStartTime; // Operation start time
+ UINT32 nActionTimeout; // Timeout for the session
+ UINT32 nSentChunks; // Count of sent chunks
+ UINT32 nSentBodyBytes; // Count of body bytes that ware sent
+ UINT32 nSentHeaderBytes; // Count of header bytes thhat ware sent
+
+ }HTTP_COUNTERS;
+
+ // HTTP Client Session data
+ typedef struct _HTTP_REQUEST
+ {
+
+ HTTP_URL HttpUrl;
+ HTTP_HEADERS HttpHeaders;
+ HTTP_HEADERS_INFO HttpHeadersInfo;
+ HTTP_AUTH_HEADER HttpAuthHeader;
+ HTTP_PROXY HttpProxy;
+ HTTP_CREDENTIALS HttpCredentials;
+ HTTP_CONNECTION HttpConnection;
+ HTTP_COUNTERS HttpCounters;
+ UINT32 HttpState;
+ UINT32 HttpFlags;
+#ifdef _HTTP_DEBUGGING_
+ E_HTTPDebug *pDebug;
+#endif
+ } HTTP_SESSION, *P_HTTP_SESSION;
+
+
+ // HTTP Type Definitions
+ typedef UINT32 HTTP_SESSION_HANDLE;
+ typedef UINT32 HTTP_CLIENT_SESSION_FLAGS;
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // Section : HTTP API public interface
+ // Last updated : 01/09/2005
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+
+ HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags);
+ UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession);
+ UINT32 HTTPClientSetLocalConnection (HTTP_SESSION_HANDLE pSession, UINT32 nPort);
+ UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, HTTP_AUTH_SCHEMA AuthSchema, void *pReserved);
+ UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, CHAR *pUserName, CHAR *pPassword);
+ UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, CHAR *pProxyName, UINT16 nPort, CHAR *pUserName, CHAR *pPassword);
+ UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, HTTP_VERB HttpVerb);
+ UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderName, CHAR *pHeaderData, BOOL nInsert);
+ UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, CHAR *pUrl, VOID *pData, UINT32 nDataLength, BOOL TotalLength, UINT32 nTimeout,UINT32 nClientPort);
+ UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBufferLength, UINT32 nTimeout);
+ UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, UINT32 nTimeout);
+ UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBytesToRead, UINT32 nTimeout, UINT32 *nBytesRecived);
+ UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient);
+
+ UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength);
+ UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength);
+ UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession);
+
+
+#ifdef _HTTP_DEBUGGING_
+ UINT32 HTTPClientSetDebugHook (HTTP_SESSION_HANDLE pSession,E_HTTPDebug *pDebug);
+#endif
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // Section : HTTP API private function
+ // Last updated : 01/09/2005
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ UINT32 HTTPIntrnResizeBuffer (P_HTTP_SESSION pHTTPSession, UINT32 nNewSize);
+ UINT32 HTTPIntrnSetURL (P_HTTP_SESSION pHTTPSession, CHAR *pUrl,UINT32 nUrlLength);
+ UINT32 HTTPIntrnConnectionClose (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnConnectionOpen (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnGetRemoteHeaders (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnGetRemoteChunkLength (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnSend (P_HTTP_SESSION pHTTPSession, CHAR *pData,UINT32 *nLength);
+ UINT32 HTTPIntrnRecv (P_HTTP_SESSION pHTTPSession, CHAR *pData,UINT32 *nLength,BOOL PeekOnly);
+ UINT32 HTTPIntrnParseAuthHeader (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnAuthHandler (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnAuthSendDigest (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnAuthSendBasic (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnAuthenticate (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnHeadersAdd (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName, UINT32 nNameLength, CHAR *pHeaderData, UINT32 nDataLength);
+ UINT32 HTTPIntrnHeadersRemove (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName);
+ UINT32 HTTPIntrnHeadersReceive (P_HTTP_SESSION pHTTPSession, UINT32 nTimeout);
+ UINT32 HTTPIntrnHeadersSend (P_HTTP_SESSION pHTTPSession, HTTP_VERB HttpVerb);
+ UINT32 HTTPIntrnHeadersParse (P_HTTP_SESSION pHTTPSession);
+ UINT32 HTTPIntrnHeadersFind (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName, HTTP_PARAM *pParam,BOOL IncommingHeaders,UINT32 nOffset);
+ UINT32 HTTPIntrnSessionReset (P_HTTP_SESSION pHTTPSession, BOOL EntireSession);
+ UINT32 HTTPIntrnSessionGetUpTime (VOID);
+ BOOL HTTPIntrnSessionEvalTimeout (P_HTTP_SESSION pHTTPSession);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_HTTP_CLIENT
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.c b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.c
new file mode 100644
index 000000000..7874be518
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.c
@@ -0,0 +1,665 @@
+
+///////////////////////////////////////////////////////////////////////////////
+// Module Name:
+// HTTPClientAuth.c
+//
+// Abstract: Handle Digest, MD5 and 64 Bit Encoding
+//
+// Platform: Any that supports standard C calls
+///////////////////////////////////////////////////////////////////////////////
+
+#include "HTTPClientAuth.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPBase64Encoder
+// Purpose : Converts a given string into a base64 encoded buffer.
+// Last updated : 01/09/200515/05/2005
+// Author Name : Eitan Michaelson
+// Notes :
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPBase64Encoder(unsigned char *out, const unsigned char *in, int inlen)
+// [OUT] out A pointer to a char to hold the converted string
+// [IN] in String to convert
+// [IN] inlen Length of the string to be converted
+
+{
+ for (; inlen >= 3; inlen -= 3)
+ {
+ *out++ = base64digits[in[0] >> 2];
+ *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
+ *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
+ *out++ = base64digits[in[2] & 0x3f];
+ in += 3;
+ }
+
+ if (inlen > 0)
+ {
+ unsigned char fragment;
+
+ *out++ = base64digits[in[0] >> 2];
+ fragment = (in[0] << 4) & 0x30;
+
+ if (inlen > 1)
+ fragment |= in[1] >> 4;
+
+ *out++ = base64digits[fragment];
+ *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
+ *out++ = '=';
+ }
+
+ *out = '\0';
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPBase64Decoder
+// Purpose : Converts a given base64 string into a bytes buffer.
+// Last updated : 01/09/200515/05/2005
+// Author Name : Eitan Michaelson
+// Notes :
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPBase64Decoder(char *out, const char *in)
+{ // [OUT] out Where to save the converted string
+ // [IN] in String to convert
+
+ int len = 0;
+ register unsigned char digit1, digit2, digit3, digit4;
+
+ if (in[0] == '+' && in[1] == ' ')
+ in += 2;
+ if (*in == '\r')
+ return(0);
+
+ do {
+
+ digit1 = in[0];
+ if (DECODE64(digit1) == BAD)
+ return(-1);
+ digit2 = in[1];
+ if (DECODE64(digit2) == BAD)
+ return(-1);
+ digit3 = in[2];
+ if (digit3 != '=' && DECODE64(digit3) == BAD)
+ return(-1);
+ digit4 = in[3];
+ if (digit4 != '=' && DECODE64(digit4) == BAD)
+ return(-1);
+ in += 4;
+ *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
+ ++len;
+ if (digit3 != '=')
+ {
+ *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
+ ++len;
+ if (digit4 != '=')
+ {
+ *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
+ ++len;
+ }
+ }
+ } while (*in && *in != '\r' && digit4 != '=');
+
+ return (len);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Purpose : The following code implements the calculations of H(A1), H(A2),
+// request-digest and response-digest
+// Last updated : 01/09/200515/05/2005
+// Author Name : Public Domain\RFC2617
+// Notes : Digest Access Authentication
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : GenerateCNonce
+// Purpose : Generates a 32 byte random hexadecimal string such as "4f6ba982..."
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes :
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPDigestGenerateCNonce(char *outbuff)
+{
+ int i,num;
+ InitRandomeNumber();
+ for(i = 0; i < 32; i++) {
+ num = GetRandomeNumber();
+ switch(num) {
+ case 0: case 1: case 2: case 3: case 4: case 5:
+ case 6: case 7: case 8: case 9:
+ outbuff[i] = '0' + num;
+ break;
+ case 10: case 11: case 12: case 13: case 14: case 15:
+ outbuff[i] = 'a' + (num-10);
+ break;
+ default:
+ outbuff[i] = 'f';
+ }
+ }
+ outbuff[32] = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : DigestCvtHex
+// Purpose : CConvert to HEX
+// Last updated : 15/05/2005
+// Author Name : Public Domain\RFC2617
+// Notes :
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void HTTPDigestCvtHex(IN HASH Bin,OUT HASHHEX Hex)
+{
+ unsigned short i;
+ unsigned char j;
+
+ for (i = 0; i < HASHLEN; i++) {
+ j = (Bin[i] >> 4) & 0xf;
+ if (j <= 9)
+ Hex[i*2] = (j + '0');
+ else
+ Hex[i*2] = (j + 'a' - 10);
+ j = Bin[i] & 0xf;
+ if (j <= 9)
+ Hex[i*2+1] = (j + '0');
+ else
+ Hex[i*2+1] = (j + 'a' - 10);
+ };
+ Hex[HASHHEXLEN] = '\0';
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : DigestCalcHA1
+// Purpose : Calculate H(A1) as per spec
+// Last updated : 15/05/2005
+// Author Name : Public Domain\RFC2617
+// Notes :
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPDigestCalcHA1(
+ IN int nAlg, /* 0 = MD5, 1 = MD5-Sess */
+ IN char * pszUserName,
+ IN char * pszRealm,
+ IN int nRealmLength,
+ IN char * pszPassword,
+ IN char * pszNonce,
+ IN int nNonceLength,
+ IN char * pszCNonce,
+ OUT HASHHEX SessionKey
+ )
+{
+ MD5_CTX Md5Ctx;
+ HASH HA1;
+ HASHHEX HASess;
+ HASH HAll;
+
+ HTTPMD5Init(&Md5Ctx);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName)); //Daniel casting
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszRealm, nRealmLength); //Daniel
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword)); //Daniel
+ HTTPMD5Final((unsigned char *)HA1, &Md5Ctx);
+
+ if (nAlg == 1) /* MD5-Sess */
+ {
+ HTTPDigestCvtHex(HA1, HASess);
+ HTTPMD5Init(&Md5Ctx);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)HASess, HASHHEXLEN);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonce, nNonceLength);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+ HTTPMD5Final((unsigned char *)HAll, &Md5Ctx);
+ HTTPDigestCvtHex(HAll, SessionKey);
+ return;
+
+ }
+
+ HTTPDigestCvtHex(HA1, SessionKey);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : DigestCalcResponse
+// Purpose : Calculate request-digest/response-digest as per HTTP Digest spec
+// Last updated : 15/05/2005
+// Author Name : Public Domain\RFC2617
+// Notes :
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPDigestCalcResponse(
+ IN HASHHEX HA1, // H(A1)
+ IN char * pszNonce, // nonce from server
+ IN int nNonceLength, // Length of nonce
+ IN char * pszNonceCount, // 8 hex digits
+ IN char * pszCNonce, // client nonce */
+ IN char * pszQop, // qop-value: "", "auth", "auth-int"
+ IN int nQopLength, // qop param length
+ IN char * pszMethod, // method from the request
+ IN char * pszDigestUri, // requested URL
+ IN int nDigestUriLebgth, // Uri Length
+ IN HASHHEX HEntity, // H(entity body) if qop="auth-int"
+ OUT HASHHEX Response // request-digest or response-digest
+ )
+{
+ MD5_CTX Md5Ctx;
+ HASH HA2;
+ HASH RespHash;
+ HASHHEX HA2Hex;
+
+ // Calculate H(A2)
+ HTTPMD5Init(&Md5Ctx);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod));
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, nDigestUriLebgth);
+ if (stricmp(pszQop, "auth-int") == 0)
+ {
+
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
+ };
+ HTTPMD5Final((unsigned char *)HA2, &Md5Ctx);
+ HTTPDigestCvtHex(HA2, HA2Hex);
+
+ // Calculate response
+ HTTPMD5Init(&Md5Ctx);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonce, nNonceLength);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ if (*pszQop)
+ {
+
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszQop, nQopLength);
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+ };
+ HTTPMD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
+ HTTPMD5Final((unsigned char *)RespHash, &Md5Ctx);
+ HTTPDigestCvtHex(RespHash, Response);
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Purpose : This code implements the MD5 message-digest algorithm.
+// The algorithm is due to Ron Rivest. This code was
+// written by Colin Plumb in 1993, no copyright is claimed.
+// This code is in the public domain; do with it what you wish.
+// Equivalent code is available from RSA Data Security, Inc.
+// This code has been tested against that, and is equivalent,
+// except that you don't need to include two pages of legalese
+// with every copy.
+// Usage : To compute the message digest of a chunk of bytes, declare an
+// MD5Context structure, pass it to MD5Init, call MD5Update as
+// needed on buffers full of bytes, and then call MD5Final, which
+// will fill a supplied 16-byte array with the digest.
+// Last updated : 15/05/2005
+// Author Name : Public Domain
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef HIGHFIRST
+#define HTTPMD5ByteReverse(buf, len) /* Nothing */
+#else
+void HTTPMD5ByteReverse(unsigned char *buf, unsigned longs);
+#ifndef ASM_MD5
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : ByteReverse
+// Purpose : Little\Big Endian support
+// Gets :
+// Returns :
+// Last updated : 15/05/2005
+// Author Name : Public Domain
+// Notes : this code is harmless on little-endian machines.
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPMD5ByteReverse(unsigned char *buf, unsigned longs)
+{
+ uint32 t;
+ do {
+ t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(uint32 *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+#endif
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : MD5Init
+// Purpose : Initialize the MD5Context structure
+// Gets : MD5Context structure
+// Returns :
+// Last updated : 15/05/2005
+// Author Name : Public Domain
+// Notes : Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+// initialization constants.
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void HTTPMD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : MD5Update
+// Purpose : Update the MD5Context structure with the target byte array
+// Gets : MD5Context structure, buffer and length
+// Returns :
+// Last updated : 15/05/2005
+// Author Name : Public Domain
+// Notes : Update context to reflect the concatenation of another buffer full of bytes.
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPMD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ uint32 t;
+
+ // Update bitcount
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+ ctx->bits[1]++; // Carry from low to high
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data
+
+ // Handle any leading odd-sized chunks
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ HTTPMD5ByteReverse(ctx->in, 16);
+ HTTPMD5Transform(ctx->buf, (uint32 *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ // Process data in 64-byte chunks
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ HTTPMD5ByteReverse(ctx->in, 16);
+ HTTPMD5Transform(ctx->buf, (uint32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ // Handle any remaining bytes of data.
+
+ memcpy(ctx->in, buf, len);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : MD5Final
+// Purpose : Finalize.
+// Gets : Output digest structure, MD5Context structure
+// Returns :
+// Last updated : 15/05/2005
+// Author Name : Public Domain
+// Notes : Final wrapup - pad to 64-byte boundary with the bit pattern
+// 1 0* (64-bit count of bits processed, MSB-first).
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
+
+
+void HTTPMD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ // Compute number of bytes mod 64
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ // Set the first char of padding to 0x80. This is safe since there is
+ // always at least one byte free
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ // Bytes of padding needed to make 64 bytes
+ count = 64 - 1 - count;
+
+ // Pad out to 56 mod 64 */
+ if (count < 8) {
+ // Two lots of padding: Pad the first block to 64 bytes
+ memset(p, 0, count);
+ HTTPMD5ByteReverse(ctx->in, 16);
+ HTTPMD5Transform(ctx->buf, (uint32 *) ctx->in);
+
+ // Now fill the next block with 56 bytes
+ memset(ctx->in, 0, 56);
+ } else {
+ // Pad block to 56 bytes
+ memset(p, 0, count - 8);
+ }
+ HTTPMD5ByteReverse(ctx->in, 14);
+
+ // Append length in bits and transform
+ ((uint32 *) ctx->in)[14] = ctx->bits[0];
+ ((uint32 *) ctx->in)[15] = ctx->bits[1];
+
+ HTTPMD5Transform(ctx->buf, (uint32 *) ctx->in);
+ HTTPMD5ByteReverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); // In case it's sensitive
+}
+
+#ifndef ASM_MD5
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function :
+// Purpose : The four core functions - F1 is optimized somewhat
+// Last updated : 15/05/2005
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+// This is the central step in the MD5 algorithm.
+#ifdef __PUREC__
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f /*(x, y, z)*/ + data, w = w<<s | w>>(32-s), w += x )
+#else
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Function : MD5Transform
+// Purpose : The core of the MD5 algorithm, this alters an existing MD5 hash to
+// reflect the addition of 16 longwords of new data. MD5Update blocks
+// the data and converts bytes into longwords for this routine.
+// Last updated : 15/05/2005
+// Author Name : Public Domain
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void HTTPMD5Transform(uint32 buf[4], uint32 const in[16])
+{
+ register uint32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+#ifdef __PUREC__ // PureC Weirdness... (GG)
+ MD5STEP(F1(b,c,d), a, b, c, d, in[0] + 0xd76aa478L, 7);
+ MD5STEP(F1(a,b,c), d, a, b, c, in[1] + 0xe8c7b756L, 12);
+ MD5STEP(F1(d,a,b), c, d, a, b, in[2] + 0x242070dbL, 17);
+ MD5STEP(F1(c,d,a), b, c, d, a, in[3] + 0xc1bdceeeL, 22);
+ MD5STEP(F1(b,c,d), a, b, c, d, in[4] + 0xf57c0fafL, 7);
+ MD5STEP(F1(a,b,c), d, a, b, c, in[5] + 0x4787c62aL, 12);
+ MD5STEP(F1(d,a,b), c, d, a, b, in[6] + 0xa8304613L, 17);
+ MD5STEP(F1(c,d,a), b, c, d, a, in[7] + 0xfd469501L, 22);
+ MD5STEP(F1(b,c,d), a, b, c, d, in[8] + 0x698098d8L, 7);
+ MD5STEP(F1(a,b,c), d, a, b, c, in[9] + 0x8b44f7afL, 12);
+ MD5STEP(F1(d,a,b), c, d, a, b, in[10] + 0xffff5bb1L, 17);
+ MD5STEP(F1(c,d,a), b, c, d, a, in[11] + 0x895cd7beL, 22);
+ MD5STEP(F1(b,c,d), a, b, c, d, in[12] + 0x6b901122L, 7);
+ MD5STEP(F1(a,b,c), d, a, b, c, in[13] + 0xfd987193L, 12);
+ MD5STEP(F1(d,a,b), c, d, a, b, in[14] + 0xa679438eL, 17);
+ MD5STEP(F1(c,d,a), b, c, d, a, in[15] + 0x49b40821L, 22);
+
+ MD5STEP(F2(b,c,d), a, b, c, d, in[1] + 0xf61e2562L, 5);
+ MD5STEP(F2(a,b,c), d, a, b, c, in[6] + 0xc040b340L, 9);
+ MD5STEP(F2(d,a,b), c, d, a, b, in[11] + 0x265e5a51L, 14);
+ MD5STEP(F2(c,d,a), b, c, d, a, in[0] + 0xe9b6c7aaL, 20);
+ MD5STEP(F2(b,c,d), a, b, c, d, in[5] + 0xd62f105dL, 5);
+ MD5STEP(F2(a,b,c), d, a, b, c, in[10] + 0x02441453L, 9);
+ MD5STEP(F2(d,a,b), c, d, a, b, in[15] + 0xd8a1e681L, 14);
+ MD5STEP(F2(c,d,a), b, c, d, a, in[4] + 0xe7d3fbc8L, 20);
+ MD5STEP(F2(b,c,d), a, b, c, d, in[9] + 0x21e1cde6L, 5);
+ MD5STEP(F2(a,b,c), d, a, b, c, in[14] + 0xc33707d6L, 9);
+ MD5STEP(F2(d,a,b), c, d, a, b, in[3] + 0xf4d50d87L, 14);
+ MD5STEP(F2(c,d,a), b, c, d, a, in[8] + 0x455a14edL, 20);
+ MD5STEP(F2(b,c,d), a, b, c, d, in[13] + 0xa9e3e905L, 5);
+ MD5STEP(F2(a,b,c), d, a, b, c, in[2] + 0xfcefa3f8L, 9);
+ MD5STEP(F2(d,a,b), c, d, a, b, in[7] + 0x676f02d9L, 14);
+ MD5STEP(F2(c,d,a), b, c, d, a, in[12] + 0x8d2a4c8aL, 20);
+
+ MD5STEP(F3(b,c,d), a, b, c, d, in[5] + 0xfffa3942L, 4);
+ MD5STEP(F3(a,b,c), d, a, b, c, in[8] + 0x8771f681L, 11);
+ MD5STEP(F3(d,a,b), c, d, a, b, in[11] + 0x6d9d6122L, 16);
+ MD5STEP(F3(c,d,a), b, c, d, a, in[14] + 0xfde5380cL, 23);
+ MD5STEP(F3(b,c,d), a, b, c, d, in[1] + 0xa4beea44L, 4);
+ MD5STEP(F3(a,b,c), d, a, b, c, in[4] + 0x4bdecfa9L, 11);
+ MD5STEP(F3(d,a,b), c, d, a, b, in[7] + 0xf6bb4b60L, 16);
+ MD5STEP(F3(c,d,a), b, c, d, a, in[10] + 0xbebfbc70L, 23);
+ MD5STEP(F3(b,c,d), a, b, c, d, in[13] + 0x289b7ec6L, 4);
+ MD5STEP(F3(a,b,c), d, a, b, c, in[0] + 0xeaa127faL, 11);
+ MD5STEP(F3(d,a,b), c, d, a, b, in[3] + 0xd4ef3085L, 16);
+ MD5STEP(F3(c,d,a), b, c, d, a, in[6] + 0x04881d05L, 23);
+ MD5STEP(F3(b,c,d), a, b, c, d, in[9] + 0xd9d4d039L, 4);
+ MD5STEP(F3(a,b,c), d, a, b, c, in[12] + 0xe6db99e5L, 11);
+ MD5STEP(F3(d,a,b), c, d, a, b, in[15] + 0x1fa27cf8L, 16);
+ MD5STEP(F3(c,d,a), b, c, d, a, in[2] + 0xc4ac5665L, 23);
+
+ MD5STEP(F4(b,c,d), a, b, c, d, in[0] + 0xf4292244L, 6);
+ MD5STEP(F4(a,b,c), d, a, b, c, in[7] + 0x432aff97L, 10);
+ MD5STEP(F4(d,a,b), c, d, a, b, in[14] + 0xab9423a7L, 15);
+ MD5STEP(F4(c,d,a), b, c, d, a, in[5] + 0xfc93a039L, 21);
+ MD5STEP(F4(b,c,d), a, b, c, d, in[12] + 0x655b59c3L, 6);
+ MD5STEP(F4(a,b,c), d, a, b, c, in[3] + 0x8f0ccc92L, 10);
+ MD5STEP(F4(d,a,b), c, d, a, b, in[10] + 0xffeff47dL, 15);
+ MD5STEP(F4(c,d,a), b, c, d, a, in[1] + 0x85845dd1L, 21);
+ MD5STEP(F4(b,c,d), a, b, c, d, in[8] + 0x6fa87e4fL, 6);
+ MD5STEP(F4(a,b,c), d, a, b, c, in[15] + 0xfe2ce6e0L, 10);
+ MD5STEP(F4(d,a,b), c, d, a, b, in[6] + 0xa3014314L, 15);
+ MD5STEP(F4(c,d,a), b, c, d, a, in[13] + 0x4e0811a1L, 21);
+ MD5STEP(F4(b,c,d), a, b, c, d, in[4] + 0xf7537e82L, 6);
+ MD5STEP(F4(a,b,c), d, a, b, c, in[11] + 0xbd3af235L, 10);
+ MD5STEP(F4(d,a,b), c, d, a, b, in[2] + 0x2ad7d2bbL, 15);
+ MD5STEP(F4(c,d,a), b, c, d, a, in[9] + 0xeb86d391L, 21);
+#else
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+#endif
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+#endif
+
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.h b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.h
new file mode 100644
index 000000000..65af8a5cb
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientAuth.h
@@ -0,0 +1,90 @@
+
+#ifndef HTTP_CLIENT_AUTH_H
+#define HTTP_CLIENT_AUTH_H
+
+#include "HTTPClientWrapper.h" // Cross platform support
+
+
+#define HASHLEN 16
+#define HASHHEXLEN 32
+#define IN
+#define OUT
+
+typedef char HASH[HASHLEN];
+typedef char HASHHEX[HASHHEXLEN+1];
+typedef unsigned long uint32;
+
+// Base 64 Related
+#define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
+#define BAD -1
+
+static const char base64digits[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char base64val[] = {
+BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
+52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
+BAD, 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,BAD, BAD,BAD,BAD,BAD,
+BAD, 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,BAD, BAD,BAD,BAD,BAD
+};
+
+void HTTPBase64Encoder(unsigned char *out, const unsigned char *in, int inlen);
+int HTTPBase64Decoder(char *out, const char *in);
+
+
+// Digest Related
+// Generates a 32 byte random hexadecimal string such as "4f6ba982..."
+void HTTPDigestGenerateCNonce(char *outbuff);
+
+// Calculate H(A1) as per HTTP Digest spec
+void HTTPDigestCalcHA1(
+ IN int nAlg, /* 0 = MD5, 1 = MD5-Sess */
+ IN char * pszUserName,
+ IN char * pszRealm,
+ IN int nRealmLength,
+ IN char * pszPassword,
+ IN char * pszNonce,
+ IN int nNonceLength,
+ IN char * pszCNonce,
+ OUT HASHHEX SessionKey
+ );
+
+// Calculate request-digest/response-digest as per HTTP Digest spec
+void HTTPDigestCalcResponse(
+ IN HASHHEX HA1, // H(A1)
+ IN char * pszNonce, // nonce from server
+ IN int nNonceLength, // Length of nonce
+ IN char * pszNonceCount, // 8 hex digits
+ IN char * pszCNonce, // client nonce
+ IN char * pszQop, // qop-value: "", "auth", "auth-int"
+ IN int nQopLength, // qop param length
+ IN char * pszMethod, // method from the request
+ IN char * pszDigestUri, // requested URL
+ IN int nDigestUriLebgth, // Uri Length
+ IN HASHHEX HEntity, // H(entity body) if qop="auth-int"
+ OUT HASHHEX Response // request-digest or response-digest
+ );
+
+// MD5 structures and functions
+struct MD5Context
+{
+ uint32 buf[4];
+ uint32 bits[2];
+ unsigned char in[64];
+};
+
+void HTTPMD5Init (struct MD5Context *context);
+void HTTPMD5Update (struct MD5Context *context, unsigned char const *buf,unsigned len);
+void HTTPMD5Final (unsigned char digest[16], struct MD5Context *context);
+void HTTPMD5Transform (uint32 buf[4], uint32 const in[16]);
+
+
+// This is needed to make RSAREF happy on some MS-DOS compilers.
+typedef struct MD5Context MD5_CTX;
+
+#endif
+
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientCommon.h b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientCommon.h
new file mode 100644
index 000000000..b54eb3ec5
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientCommon.h
@@ -0,0 +1,120 @@
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Module Name:
+// CmsiHTTPClientCommon.h
+//
+// Abstract: Coomon structs and types for the HTTP protocol API
+// Author: Eitan Michaelso
+// Version: 1.0
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _HTTPCLIENT_PROTOCOL_H_
+#define _HTTPCLIENT_PROTOCOL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Global default sizes
+#define HTTP_CLIENT_MAX_URL_LENGTH 512 // Maximum length for an HTTP Url parameter
+
+ // HTTP Session flags (Public flags)
+#define HTTP_CLIENT_FLAG_KEEP_ALIVE 0x00000001 // Set the keep alive header
+#define HTTP_CLIENT_FLAG_SEND_CHUNKED 0x00000002 // The outgoing should chunked
+#define HTTP_CLIENT_FLAG_NO_CACHE 0x00000004 // Set the no cache header
+#define HTTP_CLIENT_FLAG_ASYNC 0x00000008 // Currently not implemented
+
+ // HTTP status internal flags
+#define HTTP_CLIENT_STATE_PRE_INIT 0x00000000 // Starting stage
+#define HTTP_CLIENT_STATE_INIT 0x00000001 // API was initialized (memory was allocated)
+#define HTTP_CLIENT_STATE_URL_PARSED 0x00000002 // Url was parsed
+#define HTTP_CLIENT_STATE_HOST_CONNECTED 0x00000004 // HEAD verb was sent
+#define HTTP_CLIENT_STATE_HEAD_SENT 0x00000008 // Post verb was sent
+#define HTTP_CLIENT_STATE_POST_SENT 0x00000010 // HTTP requet was sent
+#define HTTP_CLIENT_STATE_REQUEST_SENT 0x00000020 // HTTP request was sent
+#define HTTP_CLIENT_STATE_HEADERS_RECIVED 0x00000040 // Headers ware recived from the server
+#define HTTP_CLIENT_STATE_HEADERS_PARSED 0x00000080 // HTTP headers ware parsed
+#define HTTP_CLIENT_STATE_HEADERS_OK 0x00000100 // Headers status was OK
+
+ // HTTP Return codes
+#define HTTP_CLIENT_SUCCESS 0 // HTTP Success status
+
+#define HTTP_CLIENT_UNKNOWN_ERROR 1 // Unknown error
+#define HTTP_CLIENT_ERROR_INVALID_HANDLE 2 // an Invalid handle or possible bad pointer was passed to a function
+#define HTTP_CLIENT_ERROR_NO_MEMORY 3 // Buffer too small or a failure while in memory allocation
+#define HTTP_CLIENT_ERROR_SOCKET_INVALID 4 // an attempt to use an invalid socket handle was made
+#define HTTP_CLIENT_ERROR_SOCKET_CANT_SET 5 // Can't send socket parameters
+#define HTTP_CLIENT_ERROR_SOCKET_RESOLVE 6 // Error while resolving host name
+#define HTTP_CLIENT_ERROR_SOCKET_CONNECT 7 // Error while connecting to the remote server
+#define HTTP_CLIENT_ERROR_SOCKET_TIME_OUT 8 // socket time out error
+#define HTTP_CLIENT_ERROR_SOCKET_RECV 9 // Error while receiving data
+#define HTTP_CLIENT_ERROR_SOCKET_SEND 10 // Error while sending data
+#define HTTP_CLIENT_ERROR_HEADER_RECV 11 // Error while receiving the remote HTTP headers
+#define HTTP_CLIENT_ERROR_HEADER_NOT_FOUND 12 // Could not find element within header
+#define HTTP_CLIENT_ERROR_HEADER_BIG_CLUE 13 // The headers search clue was too large for the internal API buffer
+#define HTTP_CLIENT_ERROR_HEADER_NO_LENGTH 14 // No content length was specified for the outgoing data. the caller should specify chunking mode in the session creation
+#define HTTP_CLIENT_ERROR_CHUNK_TOO_BIG 15 // The HTTP chunk token that was received from the server was too big and possibly wrong
+#define HTTP_CLIENT_ERROR_AUTH_HOST 16 // Could not authenticate with the remote host
+#define HTTP_CLIENT_ERROR_AUTH_PROXY 17 // Could not authenticate with the remote proxy
+#define HTTP_CLIENT_ERROR_BAD_VERB 18 // Bad or not supported HTTP verb was passed to a function
+#define HTTP_CLIENT_ERROR_LONG_INPUT 19 // a function received a parameter that was too large
+#define HTTP_CLIENT_ERROR_BAD_STATE 20 // The session state prevents the current function from proceeding
+#define HTTP_CLIENT_ERROR_CHUNK 21 // Could not parse the chunk length while in chunked transfer
+#define HTTP_CLIENT_ERROR_BAD_URL 22 // Could not parse curtail elements from the URL (such as the host name, HTTP prefix act')
+#define HTTP_CLIENT_ERROR_BAD_HEADER 23 // Could not detect key elements in the received headers
+#define HTTP_CLIENT_ERROR_BUFFER_RSIZE 24 // Error while attempting to resize a buffer
+#define HTTP_CLIENT_ERROR_BAD_AUTH 25 // Authentication schema is not supported
+#define HTTP_CLIENT_ERROR_AUTH_MISMATCH 26 // The selected authentication schema does not match the server response
+#define HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN 27 // an element was missing while parsing the digest authentication challenge
+#define HTTP_CLIENT_ERROR_NO_DIGEST_ALG 28 // Digest algorithem could be MD5 or MD5-sess other types are not supported
+#define HTTP_CLIENT_ERROR_SOCKET_BIND 29 // Binding error
+#define HTTP_CLIENT_ERROR_TLS_NEGO 30 // Tls negotiation error
+#define HTTP_CLIENT_ERROR_NOT_IMPLEMENTED 64 // Feature is not (yet) implemented
+#define HTTP_CLIENT_EOS 1000 // HTTP end of stream message
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // Section : HTTP API structures
+ // Last updated : 01/09/2005
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // HTTP Supported authentication methods
+ typedef enum _HTTP_AUTH_SCHEMA
+ {
+ AuthSchemaNone = 0,
+ AuthSchemaBasic,
+ AuthSchemaDigest,
+ AuthSchemaKerberos,
+ AuthNotSupported
+
+ } HTTP_AUTH_SCHEMA;
+
+ // HTTP supported verbs
+ typedef enum _HTTP_VERB
+ {
+ VerbGet = 0,
+ VerbHead,
+ VerbPost,
+ VerbNotSupported
+ // Note: others verb such as connect and put are currently not supported
+
+ } HTTP_VERB;
+
+ // Data structure that the caller can request at any time that will include some information regarding the session
+ typedef struct _HTTP_CLIENT
+ {
+ UINT32 HTTPStatusCode; // HTTP Status code (200 OK)
+ UINT32 RequestBodyLengthSent; // Total bytes sent (body only)
+ UINT32 ResponseBodyLengthReceived; // Total bytes received (body only)
+ UINT32 TotalResponseBodyLength; // as extracted from the “content-length" header
+ UINT32 HttpState;
+ } HTTP_CLIENT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HTTPCLIENT_PROTOCOL_H_
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.c b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.c
new file mode 100644
index 000000000..b1010cc8b
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.c
@@ -0,0 +1,424 @@
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Module Name:
+// HTTPClientString.c
+//
+// Abstract: Helper function (string parsing related) for HTTPClient.c module
+//
+// Platform: Any that supports standard C calls
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "HTTPClient.h"
+#include "HTTPClientWrapper.h" // Cross platform support
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPStrInsensitiveCompare
+// Purpose : Same as strcmp() only case insensitive
+// Returns : BOOL - TRUE if destination string is identical to the source
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+BOOL HTTPStrInsensitiveCompare(CHAR *pSrc, // [IN] a pointer to the source string
+ CHAR* pDest, // [IN] a pointer to the string we should search for
+ UINT32 nLength) // [IN] The bytes range we should search in
+{
+
+ // Lower case comparison
+ UINT32 nPosition;
+ UINT32 nDestLength;
+ CHAR *pSrcIn, *pDestIn;
+ CHAR a,b;
+ pSrcIn = pSrc;
+ pDestIn = pDest;
+
+ nPosition = 0;
+ nDestLength = strlen(pDest);
+
+ if(nLength == 0)
+ {
+ nLength = strlen(pSrc);
+ }
+ if(nDestLength != nLength)
+ {
+ return FALSE;
+ }
+
+ while(pSrcIn || pDestIn)
+ {
+
+ if(nLength > 0 && nPosition == nLength)
+ {
+ return TRUE;
+ }
+
+ a = *pSrcIn;
+ b = *pDestIn;
+
+
+ if(*pSrcIn >= 64 && *pSrcIn <= 90)
+ {
+ // Upper case to lower case
+ a = *pSrcIn + 32;
+ }
+
+ if(*pDestIn >= 64 && *pDestIn <= 90)
+ {
+ // Upper case to lower case
+ b = *pDestIn + 32;
+ }
+
+ if(a != b)
+ {
+ return FALSE;
+ }
+
+ pSrcIn++;
+ pDestIn++;
+ nPosition++;
+ }
+ return TRUE;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPStrExtract
+// Purpose : Extract a string by placing null in the offset parameter
+// Returns : a pointer to the new string
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+CHAR HTTPStrExtract(CHAR *pParam, // [IN] a pointer to the input parameter
+ UINT32 nOffset, // [IN] the offset position (where we should null terminate the string)
+ CHAR Restore) // [IN] if this is not 0 we should restore it (instead of the null)
+ // and reverse the effect.
+{
+ CHAR Replaced;
+
+ if(!pParam)
+ {
+ return 0;
+ }
+ // We should restore
+ if(Restore != 0)
+ {
+ pParam[nOffset] = Restore;
+ return Restore;
+ }
+ else
+ {
+ Replaced = pParam[nOffset];
+ pParam[nOffset] = 0;
+ return Replaced;
+
+ }
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPStrSearch
+// Purpose : Search a string within another and return its pointer and a length
+// Returns : BOOL - TRUE on success
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+BOOL HTTPStrSearch(CHAR *pSrc, // [IN] The source string
+ CHAR *pSearched, // [IN] Parameter to search for
+ UINT32 nOffset, // [IN] Offset from the source string start position
+ UINT32 nScope, // [IN] Length in bytes we should search in
+ HTTP_PARAM *HttpParam) // [IN OUT] The Pointer\Length value that will be returned on success
+{
+
+ CHAR *pSrcStart;
+ CHAR *pDstStart;
+ CHAR nOrigCharacter;
+ UINT32 nPosition = 0;
+
+ do
+ {
+ pSrcStart = pSrc + nOffset;
+ nOrigCharacter = pSrcStart[nScope];
+
+ // Temporarily null terminate
+ pSrcStart[nScope] = 0;
+
+ pDstStart = strstr(pSrcStart,pSearched);
+ if(!pDstStart)
+ {
+ break;
+ }
+
+ nPosition = pDstStart - pSrcStart + 1;
+
+ } while(0);
+
+ // Remove the null termination
+ pSrcStart[nScope] = nOrigCharacter;
+
+ if(!nPosition)
+ {
+ return FALSE;
+ }
+
+ if(HttpParam)
+ {
+
+ HttpParam->nLength = nPosition -1;
+ HttpParam->pParam = pSrcStart;
+ }
+
+ return TRUE;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPStrCaseStr
+// Purpose : Same as strstr() only case insensitive
+// Returns : a pointer to the position of the searched string (or 0 on error)
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+CHAR *HTTPStrCaseStr(const char *pSrc,UINT32 nSrcLength,const char *pFind)
+{
+ const char *ptr = pSrc;
+ const char *ptr2;
+ UINT32 iLength = 0;
+
+ while(1)
+ {
+ if(iLength >= nSrcLength)
+ {
+ break;
+ }
+ ptr = strchr(pSrc,toupper(*pFind));
+ ptr2 = strchr(pSrc,tolower(*pFind));
+ if (!ptr)
+ {
+ ptr = ptr2;
+ }
+ if (!ptr)
+ {
+ break;
+ }
+ if (ptr2 && (ptr2 < ptr)) {
+ ptr = ptr2;
+ }
+ if (!strnicmp(ptr,pFind,strlen(pFind)))
+ {
+ return (char *) ptr;
+ }
+ pSrc = ptr+1;
+ iLength++;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPStrCaseStr
+// Purpose :
+// Gets :
+// Returns :
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength)
+{
+
+ // Get text between the ":" and \r\n or end of string.
+ CHAR *pStart = pSrc;
+ CHAR *pEnd;
+ UINT32 nTokenLength = 0;
+ UINT32 nPosition = 0;
+
+ pStart = strchr(pSrc,':') + 1;
+ if(pStart)
+ {
+ pEnd = pStart ;
+ // First pass, count required space
+ while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n'))
+ {
+ if(*pEnd != 0x20)
+ {
+ nTokenLength++;
+ }
+
+ if(nSrcLength && nPosition > nSrcLength)
+ {
+ break;
+ }
+ pEnd++;
+ nPosition++;
+ }
+
+ if(nTokenLength > *(nDestLength))
+ {
+ *(nDestLength) = nTokenLength;
+ pDest = NULL;
+ return pDest;
+ }
+
+ // Second pass copy into the destination buffer
+ pEnd = pStart;
+ *(nDestLength) = nTokenLength;
+ nTokenLength = 0;
+ // First pass, count required space
+ while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n'))
+ {
+ if(*pEnd != 0x20)
+ {
+ pDest[nTokenLength++] = *pEnd;
+ }
+ pEnd++;
+ }
+
+ pDest[nTokenLength] = 0;
+
+ }
+
+
+ return pDest;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function : HTTPStrGetDigestToken
+// Purpose :
+// Gets :
+// Returns :
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest)
+{
+
+ CHAR Token[HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH];
+ CHAR *pPtrStart, *pPtrEnd, *pPtrEndSrc;
+ BOOL Brackets = FALSE;
+
+ // Build the searched token
+ memset(Token,0x00,HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH);
+ strcpy(Token,pSearched);
+ strcat(Token,"=");
+
+ // Reset destination values
+ pParamDest->nLength = 0;
+ pParamDest->pParam = 0;
+
+ pPtrEndSrc = pParamSrc.pParam + pParamSrc.nLength;
+
+ pPtrStart = HTTPStrCaseStr(pParamSrc.pParam,pParamSrc.nLength,Token);
+ if(pPtrStart)
+ {
+ // Found the token so jump to the end of it
+ pPtrStart += strlen(Token);
+ // jump passed any spaces that may be
+ while ((*pPtrStart) && (*pPtrStart == 0x20) && (pPtrStart != pPtrEndSrc)) pPtrStart++;
+ // Any Brackets around the string?
+ if(*pPtrStart == 0x22) Brackets = TRUE;
+
+
+ switch (Brackets)
+ {
+
+ case TRUE:
+ // Find the next brackets
+ pPtrStart++;
+ pPtrEnd = pPtrStart;
+ while ((*pPtrEnd) && (*pPtrEnd != 0x22) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++;
+ break;
+
+ case FALSE:
+ // Find the next space or comma (0x2c)
+ pPtrEnd = pPtrStart;
+ while ((*pPtrEnd) && (*pPtrEnd != 0x20) && (*pPtrEnd != 0x2c) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++;
+ break;
+
+ };
+
+ pParamDest->nLength = (pPtrEnd - pPtrStart);
+ pParamDest->pParam = pPtrStart;
+
+ return HTTP_CLIENT_SUCCESS;
+ }
+ return HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN;
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// Function : HTTPStrHToL
+// Purpose : Convert a hex string "0x00" to long 0
+// Gets : a pointer to the Hex string
+// Last updated : 15/05/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+UINT32 HTTPStrHToL (CHAR * s)
+{
+ UINT32 i , nn, digit;
+ UINT32 n ;
+
+ n = i = nn = 0;
+ do
+ {
+ if ( isalnum(s[i]) ) {
+ s[i] = toupper(s[i]) ;
+ if (s[i] == 'X') nn=n=0; else {
+ digit = (isalpha(s[i]) ? (s[i] - 'A' + 10) : s[i] - '0') ;
+ if ( digit > 15 ) digit = 15;
+ n = n * 16 + digit;
+ if (n |= 0) nn++;
+ if (nn == 8) break;}
+ }
+ i++;
+ }
+ while ( s[i] |= 0 );
+ return n ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// Function : HTTPStrLToH
+// Purpose : Convert a long to hex string 0 to "00"
+// Gets :
+// Last updated : 15/05/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc)
+{
+
+ char *hex = "0123456789abcdef";
+ INT i;
+
+ if (nSrc == 0) {
+ dest[0] = '0';
+ dest[1] = 0;
+ }
+ else
+ {
+ for(i = 28; ((nSrc >> i) && 0xf) == 0; i -= 4);
+ for(; i >= 0; i -= 4) {
+ *dest++ = hex[(nSrc >> i) & 0xf];
+ }
+ *dest = 0;
+ }
+
+ return dest;
+}
+
+
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.h b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.h
new file mode 100644
index 000000000..fdc58e350
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientString.h
@@ -0,0 +1,23 @@
+
+#ifndef _HTTP_CLIENT_STRING
+#define _HTTP_CLIENT_STRING
+
+#include "HTTPClientWrapper.h" // Cross platform support
+#include "HTTPClient.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTP Api global definitions
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+BOOL HTTPStrInsensitiveCompare (CHAR *pSrc, CHAR* pDest, UINT32 nLength);
+BOOL HTTPStrSearch (CHAR *pSrc, CHAR *pSearched, UINT32 nOffset, UINT32 nScope,HTTP_PARAM *HttpParam);
+CHAR HTTPStrExtract (CHAR *pParam,UINT32 nOffset,CHAR Restore);
+CHAR* HTTPStrCaseStr (CHAR *pSrc, UINT32 nSrcLength, CHAR *pFind);
+CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength);
+UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest);
+UINT32 HTTPStrHToL (CHAR * s);
+CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc);
+#endif
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.c b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.c
new file mode 100644
index 000000000..046b6e0c7
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.c
@@ -0,0 +1,348 @@
+
+#include "HTTPClientWrapper.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : Stdc: HTTPWrapperIsAscii
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : Same as stdc: isascii
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperIsAscii(int c)
+{
+ return (!(c & ~0177));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : Stdc: HTTPWrapperToUpper
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : Convert character to uppercase.
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperToUpper(int c)
+{
+ // -32
+ if(HTTPWrapperIsAscii(c) > 0)
+ {
+ if(c >= 97 && c <= 122)
+ {
+ return (c - 32);
+ }
+ }
+
+ return c;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : Stdc: HTTPWrapperToLower
+// Last updated : 13/06/2006
+// Author Name : Eitan Michaelson
+// Notes : Convert character to lowercase.
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperToLower(int c)
+{
+ // +32
+ if(HTTPWrapperIsAscii(c) > 0)
+ {
+ if(c >= 65 && c <= 90)
+ {
+ return (c + 32);
+ }
+ }
+
+ return c;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : Stdc: isalpha
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : returns nonzero if c is a particular representation of an alphabetic character
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperIsAlpha(int c)
+{
+
+ if(HTTPWrapperIsAscii(c) > 0)
+ {
+ if( (c >= 97 && c <= 122) || (c >= 65 && c <= 90))
+ {
+ return c;
+ }
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : Stdc: isalnum
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : returns nonzero if c is a particular representation of an alphanumeric character
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperIsAlNum(int c)
+{
+ if(HTTPWrapperIsAscii(c) > 0)
+ {
+
+ if(HTTPWrapperIsAlpha(c) > 0)
+ {
+ return c;
+ }
+
+ if( c >= 48 && c <= 57)
+ {
+ return c;
+ }
+
+ }
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTPWrapper_itoa
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : same as stdc itoa() // hmm.. allmost the same
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+char* HTTPWrapperItoa(char *s,int a)
+{
+
+ unsigned int b;
+ if(a > 2147483647)
+ {
+ return 0; // overflow
+ }
+
+ if (a < 0) b = -a, *s++ = '-';
+ else b = a;
+ for(;a;a=a/10) s++;
+ for(*s='\0';b;b=b/10) *--s=b%10+'0';
+ return s;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTPWrapper_ShutDown
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : Handles parameter changes in the socket shutdown() function in AMT
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+int HTTPWrapperShutDown (int s,int how)
+{
+ return shutdown(s,how);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTPWrapper_GetSocketError
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : WSAGetLastError Wrapper (Win32 Specific)
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperGetSocketError (int s)
+{
+
+ return WSAGetLastError();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTPWrapper_GetHostByName
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : gethostbyname for Win32 (supports the AMT edition of the function)
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+unsigned long HTTPWrapperGetHostByName(char *name,unsigned long *address)
+{
+ HTTP_HOSTNET *HostEntry;
+ int iPos = 0, iLen = 0,iNumPos = 0,iDots =0;
+ long iIPElement;
+ char c = 0;
+ char Num[4];
+ int iHostType = 0; // 0 : numeric IP
+
+ // Check if the name is an IP or host
+ iLen = strlen(name);
+ for(iPos = 0; iPos <= iLen;iPos++)
+ {
+ c = name[iPos];
+ if((c >= 48 && c <= 57) || (c == '.') )
+ {
+ // c is numeric or dot
+ if(c != '.')
+ {
+ // c is numeric
+ if(iNumPos > 3)
+ {
+ iHostType++;
+ break;
+ }
+ Num[iNumPos] = c;
+ Num[iNumPos + 1] = 0;
+ iNumPos ++;
+ }
+ else
+ {
+ iNumPos = 0;
+ iDots++;
+ iIPElement = atol(Num);
+ if(iIPElement > 256 || iDots > 3)
+ {
+ return 0; // error invalid IP
+ }
+ }
+ }
+ else
+ {
+ break; // this is an alpha numeric address type
+ }
+ }
+
+ if(c == 0 && iHostType == 0 && iDots == 3)
+ {
+ iIPElement = atol(Num);
+ if(iIPElement > 256)
+ {
+ return 0; // error invalid IP
+ }
+ }
+ else
+ {
+ iHostType++;
+ }
+
+ if(iHostType > 0)
+ {
+
+ HostEntry = gethostbyname(name);
+ if(HostEntry)
+ {
+ *(address) = *((u_long*)HostEntry->h_addr_list[0]);
+
+ //*(address) = (unsigned long)HostEntry->h_addr_list[0];
+ return 1; // Error
+ }
+ else
+ {
+ return 0; // OK
+ }
+ }
+
+ else // numeric address - no need for DNS resolve
+ {
+ *(address) = inet_addr(name);
+ return 1;
+
+ }
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTPWrapper_GetRandomeNumber
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : GetRandom number for Win32 & AMT
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void HTTPWrapperInitRandomeNumber()
+{
+ srand((unsigned int)time(NULL));
+}
+
+int HTTPWrapperGetRandomeNumber()
+{
+ int num;
+ num = (int)(((double) rand()/ ((double)RAND_MAX+1)) * 16);
+ return num;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : HTTPWrapper_GetRTC
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : Get uptime under Win32 & AMT
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+long HTTPWrapperGetUpTime()
+{
+
+ long lTime = 0;
+
+ lTime = (GetTickCount() / CLOCKS_PER_SEC);
+ return lTime;
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Section : TSL Wrapper
+// Last updated : 15/05/2005
+// Author Name : Eitan Michaelson
+// Notes : HTTPWrapper_Sec_Connect
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperSSLConnect(int s,const struct sockaddr *name,int namelen,char *hostname)
+{
+ return -1;
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperSSLNegotiate(int s,const struct sockaddr *name,int namelen,char *hostname)
+{
+ return -1;
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperSSLSend(int s,char *buf, int len,int flags)
+{
+ return -1;
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int HTTPWrapperSSLRecv(int s,char *buf, int len,int flags)
+{
+ return -1;
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+int HTTPWrapperSSLRecvPending(int s)
+{
+ return -1;
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+int HTTPWrapperSSLClose(int s)
+{
+ return -1;
+
+}
diff --git a/src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.h b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.h
new file mode 100644
index 000000000..617d918af
--- /dev/null
+++ b/src/thirdparty/ZenLib/HTTP_Client/HTTPClientWrapper.h
@@ -0,0 +1,111 @@
+
+#ifndef HTTP_CLIENT_WRAPPER
+#define HTTP_CLIENT_WRAPPER
+
+// Compilation mode
+#define _HTTP_BUILD_WIN32 // Set Windows Build flag
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Section : Microsoft Windows Support
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef _HTTP_BUILD_WIN32
+
+#if defined(_MSC_VER)
+ #pragma warning (disable: 4996) // 'function': was declared deprecated (VS 2005)
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#if defined(_WIN32) || defined(WIN32)
+ #include <winsock.h>
+#endif
+
+// Generic types
+typedef unsigned int UINT32;
+typedef int INT32;
+
+// Sockets (Winsock wrapper)
+#define HTTP_ECONNRESET (WSAECONNRESET)
+#define HTTP_EINPROGRESS (WSAEINPROGRESS)
+#define HTTP_EWOULDBLOCK (WSAEWOULDBLOCK)
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Section : Functions that are not supported by the AMT stdc framework
+// So they had to be specificaly added.
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // STDC Wrapper implimentation
+ int HTTPWrapperIsAscii (int c);
+ int HTTPWrapperToUpper (int c);
+ int HTTPWrapperToLower (int c);
+ int HTTPWrapperIsAlpha (int c);
+ int HTTPWrapperIsAlNum (int c);
+ char* HTTPWrapperItoa (char *buff,int i);
+ void HTTPWrapperInitRandomeNumber ();
+ long HTTPWrapperGetUpTime ();
+ int HTTPWrapperGetRandomeNumber ();
+ int HTTPWrapperGetSocketError (int s);
+ unsigned long HTTPWrapperGetHostByName (char *name,unsigned long *address);
+ int HTTPWrapperShutDown (int s,int in);
+ // SSL Wrapper prototypes
+ int HTTPWrapperSSLConnect (int s,const struct sockaddr *name,int namelen,char *hostname);
+ int HTTPWrapperSSLNegotiate (int s,const struct sockaddr *name,int namelen,char *hostname);
+ int HTTPWrapperSSLSend (int s,char *buf, int len,int flags);
+ int HTTPWrapperSSLRecv (int s,char *buf, int len,int flags);
+ int HTTPWrapperSSLClose (int s);
+ int HTTPWrapperSSLRecvPending (int s);
+ // Global wrapper Functions
+#define IToA HTTPWrapperItoa
+#define GetUpTime HTTPWrapperGetUpTime
+#define SocketGetErr HTTPWrapperGetSocketError
+#define HostByName HTTPWrapperGetHostByName
+#define InitRandomeNumber HTTPWrapperInitRandomeNumber
+#define GetRandomeNumber HTTPWrapperGetRandomeNumber
+
+#ifdef __cplusplus
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Section : Global type definitions
+// Last updated : 01/09/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#define VOID void
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+#define FALSE 0
+typedef char CHAR;
+typedef unsigned short UINT16;
+typedef int BOOL;
+typedef unsigned long ULONG;
+
+// Global socket structures and definitions
+#define HTTP_INVALID_SOCKET (-1)
+typedef struct sockaddr_in HTTP_SOCKADDR_IN;
+typedef struct timeval HTTP_TIMEVAL;
+typedef struct hostent HTTP_HOSTNET;
+typedef struct sockaddr HTTP_SOCKADDR;
+typedef struct in_addr HTTP_INADDR;
+
+
+#endif // HTTP_CLIENT_WRAPPER
diff --git a/src/thirdparty/ZenLib/InfoMap.cpp b/src/thirdparty/ZenLib/InfoMap.cpp
new file mode 100644
index 000000000..748e54f8c
--- /dev/null
+++ b/src/thirdparty/ZenLib/InfoMap.cpp
@@ -0,0 +1,177 @@
+// ZenLib::InfoMap - Helper for InfoMap
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifdef ZENLIB_USEWX
+ #include <wx/strconv.h>
+#endif //ZENLIB_USEWX
+#include <algorithm>
+#include "ZenLib/InfoMap.h"
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+const Ztring InfoMap_EmptyZtring_Const; //Use it when we can't return a reference to a true Ztring, const version
+//---------------------------------------------------------------------------
+
+//***************************************************************************
+// Constructors/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Constructors
+InfoMap::InfoMap()
+: std::multimap<ZenLib::Ztring, ZenLib::ZtringList> ()
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+}
+
+InfoMap::InfoMap(const Ztring &Source)
+: std::multimap<ZenLib::Ztring, ZenLib::ZtringList> ()
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Write(Source);
+}
+
+InfoMap::InfoMap(const Char *Source)
+: std::multimap<ZenLib::Ztring, ZenLib::ZtringList> ()
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Write(Source);
+}
+
+#ifdef _UNICODE
+InfoMap::InfoMap (const char* S)
+: std::multimap<ZenLib::Ztring, ZenLib::ZtringList> ()
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Write(Ztring(S));
+}
+#endif
+
+//***************************************************************************
+// In/Out
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+const Ztring &InfoMap::Get (const Ztring &Value, size_t Pos) const
+{
+ InfoMap::const_iterator List=find(Value);
+ if (List==end())
+ return InfoMap_EmptyZtring_Const; //Not found
+ if (Pos<List->second.size())
+ return List->second[Pos];
+ else
+ return InfoMap_EmptyZtring_Const; //Not found
+}
+
+//---------------------------------------------------------------------------
+const Ztring &InfoMap::Get (const Ztring &Value, size_t Pos, const Ztring &WithValue, size_t WithValue_Pos) const
+{
+ InfoMap::const_iterator List=find(Value);
+ if (List==end())
+ return InfoMap_EmptyZtring_Const; //Not found
+ if (Pos<List->second.size())
+ {
+ if (List->second[WithValue_Pos]==WithValue)
+ return List->second[Pos];
+ else
+ {
+ List++; //The second one, this is a stupid hack for a 2 value, should be changed later...
+ if (Pos<List->second.size())
+ {
+ if (List->second[WithValue_Pos]==WithValue)
+ return List->second[Pos];
+ else
+ return InfoMap_EmptyZtring_Const; //Not found
+ }
+ else
+ return InfoMap_EmptyZtring_Const; //Not found
+ }
+ }
+ else
+ return InfoMap_EmptyZtring_Const; //Not found
+}
+
+//---------------------------------------------------------------------------
+// Set
+void InfoMap::Write(const Ztring &NewInfoMap)
+{
+ clear();
+
+ if (!&NewInfoMap || !NewInfoMap.size())
+ return;
+
+ size_t Pos1=0, Pos2_EOL=0, Pos2_Separator=0;
+
+ while (Pos2_EOL!=(size_t)-1)
+ {
+ Pos2_EOL=NewInfoMap.find(_T('\n'), Pos1);
+ Pos2_Separator=NewInfoMap.find(_T(';'), Pos1);
+ if (Pos2_Separator<Pos2_EOL)
+ {
+ ZtringList List; List.Write(NewInfoMap.substr(Pos1, Pos2_EOL-Pos1));
+ insert (pair<Ztring, ZtringList>(NewInfoMap.substr(Pos1, Pos2_Separator-Pos1), List));
+ }
+ Pos1=Pos2_EOL+1;
+ }
+}
+
+//***************************************************************************
+// Configuration
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Separator
+void InfoMap::Separator_Set (size_type Level, const Ztring &NewSeparator)
+{
+ if (Level>1)
+ return;
+
+ Separator[Level]=NewSeparator;
+}
+
+//***************************************************************************
+// C++
+//***************************************************************************
+
+} //namespace
+
+
+
+
+
+
+
+
diff --git a/src/thirdparty/ZenLib/InfoMap.h b/src/thirdparty/ZenLib/InfoMap.h
new file mode 100644
index 000000000..18eb0eea4
--- /dev/null
+++ b/src/thirdparty/ZenLib/InfoMap.h
@@ -0,0 +1,77 @@
+// ZenLib::InfoMap - Helper for InfoMap
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+//
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_InfoMapH
+#define ZenLib_InfoMapH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/ZtringList.h"
+#include <map>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Helper for InfoMap
+//***************************************************************************
+
+class InfoMap : public std::multimap<Ztring, ZtringList>
+{
+public :
+ //Constructors/Destructor
+ InfoMap ();
+ InfoMap (const Ztring &Source);
+ InfoMap (const Char *Source);
+ #ifdef _UNICODE
+ InfoMap (const char *Source); //convert a UTF-8 string into Unicode
+ #endif
+
+ //In/Out
+ const Ztring &Get (const Ztring &Value, size_t Pos) const;
+ const Ztring &Get (const Ztring &Value, size_t Pos, const Ztring &WithValue, size_t WithValue_Pos) const;
+ void Write (const Ztring &NewLanguage);
+
+ //Configuration
+ /// @brief Set the Separator character
+ void Separator_Set (size_type Level, const Ztring &NewSeparator);
+ /// @brief Set the Quote character
+ /// During Read() or Write() method, if Separator is in the sequence, we must quote it
+ void Quote_Set (const Ztring &NewQuote);
+ /// @brief Set the Maximum number of element to read
+ /// During Read() or Write() method, if there is more elements, merge them with the last element
+ void Max_Set (size_type Level, size_type Max);
+
+protected :
+ Ztring Separator[2];
+ Ztring Quote;
+ size_type Max[2];
+};
+
+} //namespace
+#endif
+
diff --git a/src/thirdparty/ZenLib/MemoryDebug.cpp b/src/thirdparty/ZenLib/MemoryDebug.cpp
new file mode 100644
index 000000000..787521416
--- /dev/null
+++ b/src/thirdparty/ZenLib/MemoryDebug.cpp
@@ -0,0 +1,190 @@
+// ZenLib::MemoryDebug - To debug memory leaks
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#if defined(ZENLIB_DEBUG)
+//---------------------------------------------------------------------------
+#include <iomanip>
+#include <sstream>
+#include "ZenLib/MemoryDebug.h"
+#include "ZenLib/Ztring.h"
+#ifdef WINDOWS
+ #include <io.h>
+#else
+ #include <cstdio>
+#endif
+#include <fcntl.h>
+#include <sys/stat.h>
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructors/destructor
+//***************************************************************************
+
+MemoryDebug::MemoryDebug()
+{
+}
+
+MemoryDebug::~MemoryDebug()
+{
+ if (!m_Blocks.empty())
+ ReportLeaks();
+}
+
+//***************************************************************************
+// Instance
+//***************************************************************************
+
+MemoryDebug& MemoryDebug::Instance()
+{
+ static MemoryDebug Inst;
+ return Inst;
+}
+
+//***************************************************************************
+// Reports
+//***************************************************************************
+
+void MemoryDebug::ReportLeaks()
+{
+ Ztring m_File;
+ //std::ofstream m_File ("Debug_MemoryLeak.txt"); // Fichier de sortie
+
+ // Détail des fuites
+ std::size_t TotalSize = 0;
+ for (TBlockMap::iterator i = m_Blocks.begin(); i != m_Blocks.end(); ++i)
+ {
+ // Ajout de la taille du bloc au cumul
+ TotalSize += i->second.Size;
+
+ // Inscription dans le fichier des informations sur le bloc courant
+ /*
+ m_File << "-> 0x" << std::hex << i->first << std::dec
+ << " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(i->second.Size) << " bytes"
+ << " | " << i->second.File.c_str() << " (" << i->second.Line << ")" << std::endl;
+ */
+ m_File.append(_T("-> 0x"));
+ m_File.append(Ztring::ToZtring((size_t)i->first, 16));
+ m_File.append(_T(" | "));
+ Ztring Temp;
+ Temp.From_Number(static_cast<int>(i->second.Size));
+ while(Temp.size()<7)
+ Temp=_T(" ")+Temp;
+ m_File.append(Temp);
+ m_File.append(_T(" bytes"));
+ m_File.append(_T(" | "));
+ m_File.append(Ztring().From_Local(i->second.File.c_str()));
+ m_File.append(_T(" ("));
+ m_File.append(Ztring::ToZtring(i->second.Line));
+ m_File.append(_T(")"));
+ m_File.append(EOL);
+ }
+
+ // Affichage du cumul des fuites
+ /*
+ m_File << std::endl << std::endl << "-- "
+ << static_cast<int>(m_Blocks.size()) << " non-released blocs, "
+ << static_cast<int>(TotalSize) << " bytes --"
+ << std::endl;
+ */
+ m_File.append(EOL);
+ m_File.append(EOL);
+ m_File.append(_T("-- "));
+ m_File.append(Ztring::ToZtring(static_cast<int>(m_Blocks.size())));
+ m_File.append(_T(" non-released blocs, "));
+ m_File.append(Ztring::ToZtring(static_cast<int>(TotalSize)));
+ m_File.append(_T(" bytes --"));
+ m_File.append(EOL);
+
+ std::string ToWrite=m_File.To_Local().c_str();
+ int m_File_sav=open("Debug_MemoryLeak.txt", O_BINARY|O_RDWR |O_CREAT); // Fichier de sortie
+ write(m_File_sav, (int8u*)ToWrite.c_str(), ToWrite.size());
+ close(m_File_sav);
+}
+
+//***************************************************************************
+// Memory management
+//***************************************************************************
+
+void* MemoryDebug::Allocate(std::size_t Size, const char* File, int Line, bool Array)
+{
+ // Allocation de la mémoire
+ void* Ptr = malloc(Size);
+
+ // Ajout du bloc à la liste des blocs alloués
+ TBlock NewBlock;
+ NewBlock.Size = Size;
+ NewBlock.File = File;
+ NewBlock.Line = Line;
+ NewBlock.Array = Array;
+ m_Blocks[Ptr] = NewBlock;
+ return Ptr;
+}
+
+void MemoryDebug::Free(void* Ptr, bool Array)
+{
+ // Recherche de l'adresse dans les blocs alloués
+ TBlockMap::iterator It = m_Blocks.find(Ptr);
+
+ // Si le bloc n'a pas été alloué, on génère une erreur
+ if (It == m_Blocks.end())
+ {
+ // En fait ça arrive souvent, du fait que le delete surcharge est pris en compte meme la ou on n'inclue pas DebugNew.h,
+ // mais pas la macro pour le new
+ // Dans ce cas on détruit le bloc et on quitte immédiatement
+ free(Ptr);
+ return;
+ }
+
+ // Si le type d'allocation ne correspond pas, on génère une erreur
+ if (It->second.Array != Array)
+ {
+ //throw CBadDelete(Ptr, It->second.File.c_str(), It->second.Line, !Array);
+ }
+
+ // Finalement, si tout va bien, on supprime le bloc et on loggiz tout ça
+ m_Blocks.erase(It);
+ m_DeleteStack.pop();
+
+ // Libération de la mémoire
+ free(Ptr);
+}
+
+void MemoryDebug::NextDelete(const char* File, int Line)
+{
+ TBlock Delete;
+ Delete.File = File;
+ Delete.Line = Line;
+
+ m_DeleteStack.push(Delete);
+}
+
+//***************************************************************************
+//
+//***************************************************************************
+
+} //NameSpace
+
+#endif // defined(ZENLIB_DEBUG)
diff --git a/src/thirdparty/ZenLib/MemoryDebug.h b/src/thirdparty/ZenLib/MemoryDebug.h
new file mode 100644
index 000000000..589d50ccb
--- /dev/null
+++ b/src/thirdparty/ZenLib/MemoryDebug.h
@@ -0,0 +1,130 @@
+// ZenLib::MemoryDebug - To debug memory leaks
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// MemoryDebug
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Provide "new" and "delete" overloadings to be able to detect memory leaks
+// Based on http://loulou.developpez.com/tutoriels/moteur3d/partie1/ 2.2.1
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenMemoryDebugH
+#define ZenMemoryDebugH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#if defined(ZENLIB_DEBUG)
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include <fstream>
+#include <map>
+#include <stack>
+#include <string>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Class
+//***************************************************************************
+
+class MemoryDebug
+{
+public :
+ ~MemoryDebug();
+ static MemoryDebug& Instance();
+
+ void* Allocate(std::size_t Size, const char* File, int Line, bool Array);
+ void Free(void* Ptr, bool Array);
+ void NextDelete(const char*, int Line); //Sauvegarde les infos sur la désallocation courante
+
+private :
+ MemoryDebug();
+ void ReportLeaks();
+ struct TBlock
+ {
+ std::size_t Size; // Taille allouée
+ std::string File; // Fichier contenant l'allocation
+ int Line; // Ligne de l'allocation
+ bool Array; // Est-ce un objet ou un tableau ?
+ };
+ typedef std::map<void*, TBlock> TBlockMap;
+
+ TBlockMap m_Blocks; // Blocs de mémoire alloués
+ std::stack<TBlock> m_DeleteStack; // Pile dont le sommet contient la ligne et le fichier de la prochaine désallocation
+};
+
+} //NameSpace
+
+//***************************************************************************
+// operator overloadings
+//***************************************************************************
+
+inline void* operator new(std::size_t Size, const char* File, int Line)
+{
+ return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, false);
+}
+inline void* operator new[](std::size_t Size, const char* File, int Line)
+{
+ return ZenLib::MemoryDebug::Instance().Allocate(Size, File, Line, true);
+}
+
+inline void operator delete(void* Ptr)
+{
+ ZenLib::MemoryDebug::Instance().Free(Ptr, false);
+}
+
+inline void operator delete[](void* Ptr)
+{
+ ZenLib::MemoryDebug::Instance().Free(Ptr, true);
+}
+
+#if !defined(__BORLANDC__) // Borland does not support overloaded delete
+inline void operator delete(void* Ptr, const char* File, int Line)
+{
+ ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
+ ZenLib::MemoryDebug::Instance().Free(Ptr, false);
+}
+
+inline void operator delete[](void* Ptr, const char* File, int Line)
+{
+ ZenLib::MemoryDebug::Instance().NextDelete(File, Line);
+ ZenLib::MemoryDebug::Instance().Free(Ptr, true);
+}
+#endif
+
+#if !defined(__MINGW32__) //TODO: Does not work on MinGW, don't know why
+#ifndef new
+ #define new new(__FILE__, __LINE__)
+#endif
+#ifndef delete
+ #define delete ZenLib::MemoryDebug::Instance().NextDelete(__FILE__, __LINE__), delete
+#endif
+#endif // __MINGW32__
+
+#endif // defined(ZENLIB_DEBUG)
+
+#endif // ZenMemoryDebugH
+
+
diff --git a/src/thirdparty/ZenLib/OS_Utils.cpp b/src/thirdparty/ZenLib/OS_Utils.cpp
new file mode 100644
index 000000000..f14e840f9
--- /dev/null
+++ b/src/thirdparty/ZenLib/OS_Utils.cpp
@@ -0,0 +1,228 @@
+// ZenLib::OS_Utils - Cross platform OS utils
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifdef ZENLIB_USEWX
+#else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ #undef __TEXT
+ #include <windows.h>
+ #include <shlobj.h>
+ #endif
+#endif //ZENLIB_USEWX
+#include "ZenLib/OS_Utils.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// OS info
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool IsWin9X ()
+{
+ #ifdef ZENLIB_USEWX
+ return true;
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ if (GetVersion()<0x80000000)
+ return false;
+ else
+ return true;
+ #else //WINDOWS
+ return true;
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+// Shell
+//***************************************************************************
+
+void Shell_Execute(const Ztring &ToExecute)
+{
+ #ifdef ZENLIB_USEWX
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ #ifdef UNICODE
+ if (IsWin9X())
+ ShellExecuteA(NULL, "open", ToExecute.To_Local().c_str(), NULL, NULL, 0);
+ else
+ ShellExecute (NULL, _T("open"), ToExecute.c_str(), NULL, NULL, 0);
+ #else
+ ShellExecute(NULL, _T("open"), ToExecute.c_str(), NULL, NULL, 0);
+ #endif
+ #else
+ //Not supported
+ #endif
+ #endif //ZENLIB_USEWX
+}
+
+//***************************************************************************
+// Directories
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Select directory code
+// Extracted from TBffolder by Torsten Johann (t-johann@gmx.de)
+
+Ztring Directory_Select_Caption;
+
+#ifdef WINDOWS
+ #ifdef UNICODE
+ char InitDirA[MAX_PATH];
+ wchar_t InitDir [MAX_PATH];
+
+ int __stdcall ShowOpenFolder_CallbackProc (HWND hwnd, UINT uMsg, LPARAM, LPARAM)
+ {
+ if (uMsg==BFFM_INITIALIZED)
+ {
+ if (IsWin9X())
+ {
+ SetWindowTextA (hwnd, Directory_Select_Caption.To_Local().c_str()); // Caption
+ SendMessageA (hwnd, BFFM_ENABLEOK, 0, TRUE);
+ SendMessageA (hwnd, BFFM_SETSELECTION, true, (LPARAM)&InitDirA);
+ }
+ else
+ {
+ SetWindowText (hwnd, Directory_Select_Caption.c_str()); // Caption
+ SendMessage (hwnd, BFFM_ENABLEOK, 0, TRUE);
+ SendMessage (hwnd, BFFM_SETSELECTION, true, (LPARAM)&InitDir);
+ }
+ }
+ return 0;
+ }
+
+ Ztring OpenFolder_Show(void* Handle, const Ztring &Title, const Ztring &Caption)
+ {
+ //Caption
+ Directory_Select_Caption=Caption;
+
+ if (IsWin9X())
+ {
+ return Ztring(); //Not supported in Win9X
+ }
+ else
+ {
+ //Values
+ LPMALLOC Malloc;
+ LPSHELLFOLDER ShellFolder;
+ BROWSEINFO BrowseInfo;
+ LPITEMIDLIST ItemIdList;
+
+ //Initializing the SHBrowseForFolder function
+ if (SHGetMalloc(&Malloc)!=NOERROR)
+ return Ztring();
+ if (SHGetDesktopFolder(&ShellFolder)!=NOERROR)
+ return Ztring();
+ ZeroMemory(&BrowseInfo, sizeof(BROWSEINFOW));
+ BrowseInfo.ulFlags+=BIF_RETURNONLYFSDIRS;
+ BrowseInfo.hwndOwner=(HWND)Handle;
+ BrowseInfo.pszDisplayName=InitDir;
+ BrowseInfo.lpszTitle=Title.c_str();
+ BrowseInfo.lpfn=ShowOpenFolder_CallbackProc;
+
+ //Displaying
+ ItemIdList=SHBrowseForFolder(&BrowseInfo);
+
+ //Releasing
+ ShellFolder->Release();
+ if (ItemIdList!=NULL)
+ {
+ SHGetPathFromIDList(ItemIdList, InitDir);
+ Malloc->Free(ItemIdList);
+ Malloc->Release();
+
+ //The value
+ return InitDir;
+ }
+ else
+ return Ztring();
+ }
+ }
+
+ #else
+ char InitDirA[MAX_PATH];
+
+ int __stdcall ShowOpenFolder_CallbackProc (HWND hwnd, UINT uMsg, LPARAM, LPARAM)
+ {
+ if (uMsg==BFFM_INITIALIZED)
+ {
+ SetWindowText (hwnd, Directory_Select_Caption.c_str()); // Caption
+ SendMessage (hwnd, BFFM_ENABLEOK, 0, TRUE);
+ SendMessage (hwnd, BFFM_SETSELECTION, true, (LPARAM)&InitDirA);
+ }
+ return 0;
+ }
+
+ Ztring OpenFolder_Show(void* Handle, const Ztring &Title, const Ztring &Caption)
+ {
+ //Caption
+ Directory_Select_Caption=Caption;
+
+ //Values
+ LPMALLOC Malloc;
+ LPSHELLFOLDER ShellFolder;
+ BROWSEINFO BrowseInfo;
+ LPITEMIDLIST ItemIdList;
+
+ //Initializing the SHBrowseForFolder function
+ if (SHGetMalloc(&Malloc)!=NOERROR)
+ return Ztring();
+ if (SHGetDesktopFolder(&ShellFolder)!=NOERROR)
+ return Ztring();
+ ZeroMemory(&BrowseInfo, sizeof(BROWSEINFO));
+ BrowseInfo.ulFlags+=BIF_RETURNONLYFSDIRS;
+ BrowseInfo.hwndOwner=(HWND)Handle;
+ BrowseInfo.pszDisplayName=InitDirA;
+ BrowseInfo.lpszTitle=Title.c_str();
+ BrowseInfo.lpfn=ShowOpenFolder_CallbackProc;
+
+ //Displaying
+ ItemIdList=SHBrowseForFolder(&BrowseInfo);
+
+ //Releasing
+ ShellFolder->Release();
+ if (ItemIdList!=NULL)
+ {
+ SHGetPathFromIDList(ItemIdList, InitDirA);
+ Malloc->Free(ItemIdList);
+ Malloc->Release();
+
+ //The value
+ return InitDirA;
+ }
+ else
+ return Ztring();
+ }
+ #endif //UNICODE
+#endif //WINDOWS
+
+} //namespace ZenLib
diff --git a/src/thirdparty/ZenLib/OS_Utils.h b/src/thirdparty/ZenLib/OS_Utils.h
new file mode 100644
index 000000000..998963915
--- /dev/null
+++ b/src/thirdparty/ZenLib/OS_Utils.h
@@ -0,0 +1,56 @@
+// ZenLib::OS_Utils - Cross platform OS utils
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenOS_UtilsH
+#define ZenOS_UtilsH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/Ztring.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// OS Information
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool IsWin9X ();
+
+//***************************************************************************
+// Execute
+//***************************************************************************
+
+void Shell_Execute(const Ztring &ToExecute);
+
+//***************************************************************************
+// Directorues
+//***************************************************************************
+
+Ztring OpenFolder_Show(void* Handle, const Ztring &Title, const Ztring &Caption);
+
+} //namespace ZenLib
+#endif
diff --git a/src/thirdparty/ZenLib/Thread.cpp b/src/thirdparty/ZenLib/Thread.cpp
new file mode 100644
index 000000000..8e8241e40
--- /dev/null
+++ b/src/thirdparty/ZenLib/Thread.cpp
@@ -0,0 +1,650 @@
+// ZenLib::Thread - Thread functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Thread.h"
+#include <iostream>
+#include <ZenLib/Ztring.h>
+#include <ZenLib/CriticalSection.h>
+//---------------------------------------------------------------------------
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ZENLIB_USEWX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#ifdef ZENLIB_USEWX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include <wx/thread.h>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+class ThreadEntry : public wxThread
+{
+public :
+ ThreadEntry(Thread* Th_) : wxThread(wxTHREAD_JOINABLE)
+ {Th=Th_;};
+ void* Entry() {Th->Entry(); return NULL;}
+private :
+ Thread* Th;
+};
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Thread::Thread()
+{
+ ThreadPointer=(void*)new ThreadEntry(this);
+ ((ThreadEntry*)ThreadPointer)->Create();
+}
+
+//---------------------------------------------------------------------------
+Thread::~Thread()
+{
+ delete (ThreadEntry*)ThreadPointer;
+}
+
+//***************************************************************************
+// Main Entry
+//***************************************************************************
+
+void Thread::Entry()
+{
+}
+
+//***************************************************************************
+// Control
+//***************************************************************************
+
+void Thread::Run()
+{
+ ((ThreadEntry*)ThreadPointer)->Resume();
+}
+
+void Thread::Pause()
+{
+ ((ThreadEntry*)ThreadPointer)->Pause();
+}
+
+void Thread::Stop()
+{
+ ((ThreadEntry*)ThreadPointer)->Delete();
+}
+
+bool Thread::IsRunning()
+{
+ return ((ThreadEntry*)ThreadPointer)->IsRunning();
+}
+
+//***************************************************************************
+// Communicating
+//***************************************************************************
+
+void Thread::Sleep(size_t Millisecond)
+{
+ ((ThreadEntry*)ThreadPointer)->Sleep((unsigned long)Millisecond);
+}
+
+void Thread::Yield()
+{
+ ((ThreadEntry*)ThreadPointer)->Yield();
+}
+
+} //Namespace
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// WINDOWS
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#else //ZENLIB_USEWX
+#ifdef WINDOWS
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#undef __TEXT
+#include <windows.h>
+#undef Yield
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+//Config
+
+#ifndef _MT
+ #define _MT //Must have this symbol defined to get _beginthread/_endthread declarations
+#endif
+
+#ifdef __BORLANDC__
+ #if !defined(__MT__)
+ #define __MT__ //-tWM in the IDE is not always set
+ #endif
+
+ #if !defined(__MFC_COMPAT__)
+ #define __MFC_COMPAT__ // Needed to know about _beginthreadex etc..
+ #endif
+#endif //__BORLANDC__
+
+
+#if defined(__VISUALC__) || \
+ (defined(__GNUG__) && defined(__MSVCRT__)) || \
+ defined(__WATCOMC__) || \
+ defined(__MWERKS__)
+ //(defined(__BORLANDC__) && (__BORLANDC__ >= 0x500))
+
+ #ifndef __WXWINCE__
+ #define USING_BEGINTHREAD //Using _beginthreadex() instead of CreateThread() if possible (better, because of Win32 API has problems with memory leaks in C library)
+ #endif
+#endif
+
+#ifdef USING_BEGINTHREAD
+ #include <process.h>
+ typedef unsigned THREAD_RETVAL; //The return type of the thread function entry point
+ #define THREAD_CALLCONV __stdcall //The calling convention of the thread function entry point
+#else
+ // the settings for CreateThread()
+ typedef DWORD THREAD_RETVAL;
+ #define THREAD_CALLCONV WINAPI
+#endif
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+THREAD_RETVAL THREAD_CALLCONV Thread_Start(void *param)
+{
+ ((Thread*)param)->Entry();
+
+ ((Thread*)param)->Internal_Exit();
+
+ return 1;
+}
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Thread::Thread()
+{
+ C.Enter();
+
+ State=State_New;
+ ThreadPointer=NULL;
+
+ C.Leave();
+}
+
+//---------------------------------------------------------------------------
+Thread::~Thread()
+{
+ C.Enter();
+
+ if (ThreadPointer!=NULL)
+ CloseHandle((HANDLE)ThreadPointer); //ThreadPointer=NULL
+
+ C.Leave();
+}
+
+//***************************************************************************
+// Control
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Thread::returnvalue Thread::Run()
+{
+ C.Enter();
+
+ //Coherency
+ if (State!=State_New || ThreadPointer!=NULL)
+ {
+ C.Leave();
+ return Incoherent;
+ }
+
+ //Creating
+ #ifdef USING_BEGINTHREAD
+ #ifdef __WATCOMC__
+ const unsigned stksize=10240; //Watcom is reported to not like 0 stack size (which means "use default")
+ #else
+ const unsigned stksize=0; //Default
+ #endif //__WATCOMC__
+
+ ThreadPointer=(void*)_beginthreadex (NULL, stksize, Thread_Start, this, CREATE_SUSPENDED, NULL);
+ #else
+ ThreadPointer=(void*)CreateThread (NULL, 0, Thread_Start, this, CREATE_SUSPENDED, NULL);
+ #endif //USING_BEGINTHREAD
+ if (ThreadPointer==NULL)
+ {
+ C.Leave();
+ return Ressource;
+ }
+
+ //Running
+ ResumeThread((HANDLE)ThreadPointer);
+
+ //Configuring
+ State=State_Running;
+
+ C.Leave();
+ return Ok;
+}
+
+//---------------------------------------------------------------------------
+Thread::returnvalue Thread::RunAgain()
+{
+ //Coherency
+ C.Enter();
+
+ //Coherency
+ if (State!=State_New
+ && State!=State_Terminated)
+ {
+ C.Leave();
+ return Incoherent;
+ }
+
+ //Configuring
+ if (State==State_Terminated)
+ State=State_New;
+
+ C.Leave();
+
+ return Run();
+}
+
+//---------------------------------------------------------------------------
+Thread::returnvalue Thread::Pause()
+{
+ C.Enter();
+
+ //Pausing
+ SuspendThread((HANDLE)ThreadPointer);
+
+ //Configuring
+ State=State_Paused;
+
+ C.Leave();
+ return Ok;
+}
+
+//---------------------------------------------------------------------------
+Thread::returnvalue Thread::RequestTerminate()
+{
+ C.Enter();
+
+ //Coherency
+ if (State!=State_Running)
+ {
+ C.Leave();
+ return IsNotRunning;
+ }
+
+ //Configuring
+ State=State_Terminating;
+
+ C.Leave();
+ return Ok;
+}
+
+//---------------------------------------------------------------------------
+Thread::returnvalue Thread::ForceTerminate()
+{
+ C.Enter();
+
+ //Terminating (not clean)
+ TerminateThread((HANDLE)ThreadPointer, 1); ThreadPointer=NULL;
+
+ //Configuring
+ State=State_Terminated;
+
+ C.Leave();
+ return Ok;
+}
+
+//***************************************************************************
+// Status
+//***************************************************************************
+
+bool Thread::IsRunning()
+{
+ C.Enter();
+ bool ToReturn=State==State_Running;
+ C.Leave();
+ return ToReturn;
+}
+
+//---------------------------------------------------------------------------
+bool Thread::IsTerminating()
+{
+ C.Enter();
+ bool ToReturn=State==State_Terminating;
+ C.Leave();
+ return ToReturn;
+}
+
+//---------------------------------------------------------------------------
+bool Thread::IsExited()
+{
+ C.Enter();
+ bool ToReturn=State==State_New || State==State_Terminating;
+ C.Leave();
+ return ToReturn;
+}
+
+//***************************************************************************
+// Main Entry
+//***************************************************************************
+
+void Thread::Entry()
+{
+}
+
+//***************************************************************************
+// Communicating
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+void Thread::Sleep(size_t Millisecond)
+{
+ ::Sleep((DWORD)Millisecond);
+}
+
+//---------------------------------------------------------------------------
+void Thread::Yield()
+{
+ ::Sleep(0);
+}
+
+//***************************************************************************
+// Internal
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Thread::returnvalue Thread::Internal_Exit()
+{
+ C.Enter();
+
+ //Coherency
+ if (State!=State_Running
+ && State!=State_Terminating)
+ {
+ C.Leave();
+ return IsNotRunning;
+ }
+
+ //Closing old handle
+ CloseHandle((HANDLE)ThreadPointer); ThreadPointer=NULL;
+
+ //Configuring
+ State=State_Terminated;
+
+ C.Leave();
+ return Ok;
+}
+
+} //Namespace
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// UNIX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#else //WINDOWS
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+//Source: http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include <pthread.h>
+#include <unistd.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ #include <sched.h>
+#endif //_POSIX_PRIORITY_SCHEDULING
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+void *Thread_Start(void *param)
+{
+ ((Thread*)param)->Entry();
+ ((Thread*)param)->Internal_Exit();
+
+ return NULL;
+}
+
+//***************************************************************************
+// Constructor/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+Thread::Thread()
+{
+ C.Enter();
+
+ State=State_New;
+ ThreadPointer=NULL;
+
+ C.Leave();
+
+}
+
+//---------------------------------------------------------------------------
+Thread::~Thread()
+{
+}
+
+//***************************************************************************
+// Main Entry
+//***************************************************************************
+
+void Thread::Entry()
+{
+}
+
+//***************************************************************************
+// Control
+//***************************************************************************
+
+Thread::returnvalue Thread::Run()
+{
+ C.Enter();
+
+ //Coherency
+ if (State!=State_New || ThreadPointer!=NULL)
+ {
+ C.Leave();
+ return Incoherent;
+ }
+
+ //Creating
+ pthread_attr_t Attr;
+ pthread_attr_init(&Attr);
+ pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
+
+ //Running
+ pthread_create((pthread_t*)&ThreadPointer, &Attr, Thread_Start, (void*)this);
+
+ //Configuring
+ State=State_Running;
+
+ C.Leave();
+ return Ok;
+}
+
+Thread::returnvalue Thread::RunAgain()
+{
+ //Coherency
+ C.Enter();
+
+ //Coherency
+ if (State!=State_New
+ && State!=State_Terminated)
+ {
+ C.Leave();
+ return Incoherent;
+ }
+
+ //Configuring
+ if (State==State_Terminated)
+ State=State_New;
+
+ C.Leave();
+
+ return Run();
+}
+
+Thread::returnvalue Thread::Pause()
+{
+ //pthread_cond_wait
+ return Ok;
+}
+
+Thread::returnvalue Thread::RequestTerminate()
+{
+ C.Enter();
+
+ if (State!=State_Running)
+ {
+ C.Leave();
+ return IsNotRunning;
+ }
+
+ State=State_Terminating;
+
+ C.Leave();
+ return Ok;
+}
+
+Thread::returnvalue Thread::ForceTerminate()
+{
+ //Terminating (not clean)
+
+ //Configuring
+ State=State_Terminated;
+
+ return Ok;
+}
+
+//***************************************************************************
+// Status
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+bool Thread::IsRunning()
+{
+ C.Enter();
+ bool ToReturn=State==State_Running;
+ C.Leave();
+ return ToReturn;
+}
+
+//---------------------------------------------------------------------------
+bool Thread::IsTerminating()
+{
+ C.Enter();
+ bool ToReturn=State==State_Terminating;
+ C.Leave();
+ return ToReturn;
+}
+
+//---------------------------------------------------------------------------
+bool Thread::IsExited()
+{
+ C.Enter();
+ bool ToReturn=State==State_New || State==State_Terminating;
+ C.Leave();
+ return ToReturn;
+}
+
+//***************************************************************************
+// Communicating
+//***************************************************************************
+
+void Thread::Sleep(size_t)
+{
+}
+
+void Thread::Yield()
+{
+ #ifdef _POSIX_PRIORITY_SCHEDULING
+ sched_yield();
+ #endif //_POSIX_PRIORITY_SCHEDULING
+}
+
+//***************************************************************************
+// Internal
+//***************************************************************************
+
+Thread::returnvalue Thread::Internal_Exit()
+{
+ C.Enter();
+
+ //Coherency
+ if (State!=State_Running
+ && State!=State_Terminating)
+ {
+ C.Leave();
+ return IsNotRunning;
+ }
+
+ //Closing old handle
+ ; ThreadPointer=NULL;
+
+ //Configuring
+ State=State_Terminated;
+
+ C.Leave();
+ return Ok;
+}
+
+} //Namespace
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#endif //WINDOWS
+#endif //ZENLIB_USEWX
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
diff --git a/src/thirdparty/ZenLib/Thread.h b/src/thirdparty/ZenLib/Thread.h
new file mode 100644
index 000000000..0a810d0ef
--- /dev/null
+++ b/src/thirdparty/ZenLib/Thread.h
@@ -0,0 +1,105 @@
+// ZenLib::Thread - Thread functions
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Thread functions
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_ThreadH
+#define ZenLib_ThreadH
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/CriticalSection.h"
+#ifdef _WINDOWS
+ #undef Yield
+#endif
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Thread manipulation
+//***************************************************************************
+
+class Thread
+{
+public :
+ //Constructor/Destructor
+ Thread ();
+ virtual ~Thread ();
+
+ //Control
+ enum returnvalue
+ {
+ Ok,
+ IsNotRunning,
+ Incoherent,
+ Ressource,
+ };
+ returnvalue Run();
+ returnvalue RunAgain();
+ returnvalue Pause();
+ returnvalue RequestTerminate();
+ returnvalue ForceTerminate();
+
+ //Status
+ bool IsRunning();
+ bool IsTerminating();
+ bool IsExited();
+
+ //Configuration
+ void Priority_Set(int8s Priority); //-100 to +100
+
+ //Main Entry
+ virtual void Entry();
+
+ //Internal
+ returnvalue Internal_Exit(); //Do not use it
+
+protected :
+
+ //Communicating
+ void Sleep(size_t Millisecond);
+ void Yield();
+
+private :
+ //Internal
+ void* ThreadPointer;
+
+ //The possible states of the thread ("-->" shows all possible transitions from this state)
+ enum state
+ {
+ State_New, // didn't start execution yet (--> Running)
+ State_Running, // thread is running (--> Paused, Terminating)
+ State_Paused, // thread is temporarily suspended (--> Running)
+ State_Terminating, // thread should terminate a.s.a.p. (--> Terminated)
+ State_Terminated, // thread is terminated
+ };
+ state State;
+ CriticalSection C;
+};
+
+} //NameSpace
+
+#endif
diff --git a/src/thirdparty/ZenLib/TinyXml/tinyxml.cpp b/src/thirdparty/ZenLib/TinyXml/tinyxml.cpp
new file mode 100644
index 000000000..414f69aa8
--- /dev/null
+++ b/src/thirdparty/ZenLib/TinyXml/tinyxml.cpp
@@ -0,0 +1,1890 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+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.
+*/
+
+#define TIXML_USE_STL
+
+#include <ctype.h>
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+#include "ZenLib/TinyXml/tinyxml.h"
+
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+// Microsoft compiler security
+FILE* TiXmlFOpen( const char* filename, const char* mode )
+{
+ #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+ FILE* fp = 0;
+ errno_t err = fopen_s( &fp, filename, mode );
+ if ( !err && fp )
+ return fp;
+ return 0;
+ #else
+ return fopen( filename, mode );
+ #endif
+}
+
+void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+ int i=0;
+
+ while( i<(int)str.length() )
+ {
+ unsigned char c = (unsigned char) str[i];
+
+ if ( c == '&'
+ && i < ( (int)str.length() - 2 )
+ && str[i+1] == '#'
+ && str[i+2] == 'x' )
+ {
+ // Hexadecimal character reference.
+ // Pass through unchanged.
+ // &#xA9; -- copyright symbol, for example.
+ //
+ // The -1 is a bug fix from Rob Laveaux. It keeps
+ // an overflow from happening if there is no ';'.
+ // There are actually 2 ways to exit this loop -
+ // while fails (error case) and break (semicolon found).
+ // However, there is no mechanism (currently) for
+ // this function to return an error.
+ while ( i<(int)str.length()-1 )
+ {
+ outString->append( str.c_str() + i, 1 );
+ ++i;
+ if ( str[i] == ';' )
+ break;
+ }
+ }
+ else if ( c == '&' )
+ {
+ outString->append( entity[0].str, entity[0].strLength );
+ ++i;
+ }
+ else if ( c == '<' )
+ {
+ outString->append( entity[1].str, entity[1].strLength );
+ ++i;
+ }
+ else if ( c == '>' )
+ {
+ outString->append( entity[2].str, entity[2].strLength );
+ ++i;
+ }
+ else if ( c == '\"' )
+ {
+ outString->append( entity[3].str, entity[3].strLength );
+ ++i;
+ }
+ else if ( c == '\'' )
+ {
+ outString->append( entity[4].str, entity[4].strLength );
+ ++i;
+ }
+ else if ( c < 32 )
+ {
+ // Easy pass at non-alpha/numeric/symbol
+ // Below 32 is symbolic.
+ char buf[ 32 ];
+
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
+ #else
+ sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+ #endif
+
+ //*ME: warning C4267: convert 'size_t' to 'int'
+ //*ME: Int-Cast to make compiler happy ...
+ outString->append( buf, (int)strlen( buf ) );
+ ++i;
+ }
+ else
+ {
+ //char realc = (char) c;
+ //outString->append( &realc, 1 );
+ *outString += (char) c; // somewhat more efficient function call.
+ ++i;
+ }
+ }
+}
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+ parent = 0;
+ type = _type;
+ firstChild = 0;
+ lastChild = 0;
+ prev = 0;
+ next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+ target->SetValue (value.c_str() );
+ target->userData = userData;
+}
+
+
+void TiXmlNode::Clear()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+
+ firstChild = 0;
+ lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+ assert( node->parent == 0 || node->parent == this );
+ assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+ if ( node->Type() == TiXmlNode::DOCUMENT )
+ {
+ delete node;
+ if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ node->parent = this;
+
+ node->prev = lastChild;
+ node->next = 0;
+
+ if ( lastChild )
+ lastChild->next = node;
+ else
+ firstChild = node; // it was an empty list.
+
+ lastChild = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+ if ( addThis.Type() == TiXmlNode::DOCUMENT )
+ {
+ if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+
+ return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{
+ if ( !beforeThis || beforeThis->parent != this ) {
+ return 0;
+ }
+ if ( addThis.Type() == TiXmlNode::DOCUMENT )
+ {
+ if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->next = beforeThis;
+ node->prev = beforeThis->prev;
+ if ( beforeThis->prev )
+ {
+ beforeThis->prev->next = node;
+ }
+ else
+ {
+ assert( firstChild == beforeThis );
+ firstChild = node;
+ }
+ beforeThis->prev = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+ if ( !afterThis || afterThis->parent != this ) {
+ return 0;
+ }
+ if ( addThis.Type() == TiXmlNode::DOCUMENT )
+ {
+ if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->prev = afterThis;
+ node->next = afterThis->next;
+ if ( afterThis->next )
+ {
+ afterThis->next->prev = node;
+ }
+ else
+ {
+ assert( lastChild == afterThis );
+ lastChild = node;
+ }
+ afterThis->next = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+ if ( replaceThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = withThis.Clone();
+ if ( !node )
+ return 0;
+
+ node->next = replaceThis->next;
+ node->prev = replaceThis->prev;
+
+ if ( replaceThis->next )
+ replaceThis->next->prev = node;
+ else
+ lastChild = node;
+
+ if ( replaceThis->prev )
+ replaceThis->prev->next = node;
+ else
+ firstChild = node;
+
+ delete replaceThis;
+ node->parent = this;
+ return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+ if ( removeThis->parent != this )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ if ( removeThis->next )
+ removeThis->next->prev = removeThis->prev;
+ else
+ lastChild = removeThis->prev;
+
+ if ( removeThis->prev )
+ removeThis->prev->next = removeThis->next;
+ else
+ firstChild = removeThis->next;
+
+ delete removeThis;
+ return true;
+}
+
+const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = firstChild; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = lastChild; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild();
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling();
+ }
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild( val );
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling( val );
+ }
+}
+
+
+const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = next; node; node = node->next )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
+{
+ const TiXmlNode* node;
+ for ( node = prev; node; node = node->prev )
+ {
+ if ( strcmp( node->Value(), _value ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+ #ifdef TIXML_USE_STL
+ TIXML_STRING str( name );
+ TiXmlAttribute* node = attributeSet.Find( str );
+ #else
+ TiXmlAttribute* node = attributeSet.Find( name );
+ #endif
+ if ( node )
+ {
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+const TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+ const TiXmlNode* node;
+
+ for ( node = FirstChild();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
+{
+ const TiXmlNode* node;
+
+ for ( node = FirstChild( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+ const TiXmlNode* node;
+
+ for ( node = NextSibling();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
+{
+ const TiXmlNode* node;
+
+ for ( node = NextSibling( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+const TiXmlDocument* TiXmlNode::GetDocument() const
+{
+ const TiXmlNode* node;
+
+ for( node = this; node; node = node->parent )
+ {
+ if ( node->ToDocument() )
+ return node->ToDocument();
+ }
+ return 0;
+}
+
+
+TiXmlElement::TiXmlElement (const char * _value)
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value )
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ copy.CopyTo( this );
+}
+
+
+void TiXmlElement::operator=( const TiXmlElement& base )
+{
+ ClearThis();
+ base.CopyTo( this );
+}
+
+
+TiXmlElement::~TiXmlElement()
+{
+ ClearThis();
+}
+
+
+void TiXmlElement::ClearThis()
+{
+ Clear();
+ while( attributeSet.First() )
+ {
+ TiXmlAttribute* node = attributeSet.First();
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+
+const char* TiXmlElement::Attribute( const char* name ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ return node->Value();
+ return 0;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ return &node->ValueStr();
+ return 0;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, int* i ) const
+{
+ const char* s = Attribute( name );
+ if ( i )
+ {
+ if ( s ) {
+ *i = atoi( s );
+ }
+ else {
+ *i = 0;
+ }
+ }
+ return s;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
+{
+ const std::string* s = Attribute( name );
+ if ( i )
+ {
+ if ( s ) {
+ *i = atoi( s->c_str() );
+ }
+ else {
+ *i = 0;
+ }
+ }
+ return s;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, double* d ) const
+{
+ const char* s = Attribute( name );
+ if ( d )
+ {
+ if ( s ) {
+ *d = atof( s );
+ }
+ else {
+ *d = 0;
+ }
+ }
+ return s;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
+{
+ const std::string* s = Attribute( name );
+ if ( d )
+ {
+ if ( s ) {
+ *d = atof( s->c_str() );
+ }
+ else {
+ *d = 0;
+ }
+ }
+ return s;
+}
+#endif
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+ return node->QueryIntValue( ival );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+ return node->QueryIntValue( ival );
+}
+#endif
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+ return node->QueryDoubleValue( dval );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
+{
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+ return node->QueryDoubleValue( dval );
+}
+#endif
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{
+ char buf[64];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
+ #else
+ sprintf( buf, "%d", val );
+ #endif
+ SetAttribute( name, buf );
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{
+ std::ostringstream oss;
+ oss << val;
+ SetAttribute( name, oss.str() );
+}
+#endif
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{
+ char buf[256];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
+ #else
+ sprintf( buf, "%f", val );
+ #endif
+ SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
+{
+ #ifdef TIXML_USE_STL
+ TIXML_STRING _name( cname );
+ TIXML_STRING _value( cvalue );
+ #else
+ const char* _name = cname;
+ const char* _value = cvalue;
+ #endif
+
+ TiXmlAttribute* node = attributeSet.Find( _name );
+ if ( node )
+ {
+ node->SetValue( _value );
+ return;
+ }
+
+ TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
+ if ( attrib )
+ {
+ attributeSet.Add( attrib );
+ }
+ else
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ {
+ node->SetValue( _value );
+ return;
+ }
+
+ TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
+ if ( attrib )
+ {
+ attributeSet.Add( attrib );
+ }
+ else
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+}
+#endif
+
+
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+ int i;
+ assert( cfile );
+ for ( i=0; i<depth; i++ ) {
+ fprintf( cfile, " " );
+ }
+
+ fprintf( cfile, "<%s", value.c_str() );
+
+ const TiXmlAttribute* attrib;
+ for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+ {
+ fprintf( cfile, " " );
+ attrib->Print( cfile, depth );
+ }
+
+ // There are 3 different formatting approaches:
+ // 1) An element without children is printed as a <foo /> node
+ // 2) An element with only a text child is printed as <foo> text </foo>
+ // 3) An element with children is printed on multiple lines.
+ TiXmlNode* node;
+ if ( !firstChild )
+ {
+ fprintf( cfile, " />" );
+ }
+ else if ( firstChild == lastChild && firstChild->ToText() )
+ {
+ fprintf( cfile, ">" );
+ firstChild->Print( cfile, depth + 1 );
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+ else
+ {
+ fprintf( cfile, ">" );
+
+ for ( node = firstChild; node; node=node->NextSibling() )
+ {
+ if ( !node->ToText() )
+ {
+ fprintf( cfile, "\n" );
+ }
+ node->Print( cfile, depth+1 );
+ }
+ fprintf( cfile, "\n" );
+ for( i=0; i<depth; ++i ) {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+}
+
+
+void TiXmlElement::CopyTo( TiXmlElement* target ) const
+{
+ // superclass:
+ TiXmlNode::CopyTo( target );
+
+ // Element class:
+ // Clone the attributes, then clone the children.
+ const TiXmlAttribute* attribute = 0;
+ for( attribute = attributeSet.First();
+ attribute;
+ attribute = attribute->Next() )
+ {
+ target->SetAttribute( attribute->Name(), attribute->Value() );
+ }
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
+{
+ if ( visitor->VisitEnter( *this, attributeSet.First() ) )
+ {
+ for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+ {
+ if ( !node->Accept( visitor ) )
+ break;
+ }
+ }
+ return visitor->VisitExit( *this );
+}
+
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+ TiXmlElement* clone = new TiXmlElement( Value() );
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+const char* TiXmlElement::GetText() const
+{
+ const TiXmlNode* child = this->FirstChild();
+ if ( child ) {
+ const TiXmlText* childText = child->ToText();
+ if ( childText ) {
+ return childText->Value();
+ }
+ }
+ return 0;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ value = documentName;
+ ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ useMicrosoftBOM = false;
+ value = documentName;
+ ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+ // See STL_STRING_BUG below.
+ //StringToBuffer buf( value );
+
+ return LoadFile( Value(), encoding );
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+ // See STL_STRING_BUG below.
+// StringToBuffer buf( value );
+//
+// if ( buf.buffer && SaveFile( buf.buffer ) )
+// return true;
+//
+// return false;
+ return SaveFile( Value() );
+}
+
+bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
+{
+ // There was a really terrifying little bug here. The code:
+ // value = filename
+ // in the STL case, cause the assignment method of the std::string to
+ // be called. What is strange, is that the std::string had the same
+ // address as it's c_str() method, and so bad things happen. Looks
+ // like a bug in the Microsoft STL implementation.
+ // Add an extra string to avoid the crash.
+ TIXML_STRING filename( _filename );
+ value = filename;
+
+ // reading in binary mode so that tinyxml can normalize the EOL
+ FILE* file = TiXmlFOpen( value.c_str (), "rb" );
+
+ if ( file )
+ {
+ bool result = LoadFile( file, encoding );
+ fclose( file );
+ return result;
+ }
+ else
+ {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+}
+
+bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
+{
+ if ( !file )
+ {
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // Delete the existing data:
+ Clear();
+ location.Clear();
+
+ // Get the file size, so we can pre-allocate the string. HUGE speed impact.
+ long length = 0;
+ fseek( file, 0, SEEK_END );
+ length = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ // Strange case, but good to handle up front.
+ if ( length <= 0 )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ // If we have a file, assume it is all one big XML file, and read it in.
+ // The document parser may decide the document ends sooner than the entire file, however.
+ TIXML_STRING data;
+ data.reserve( length );
+
+ // Subtle bug here. TinyXml did use fgets. But from the XML spec:
+ // 2.11 End-of-Line Handling
+ // <snip>
+ // <quote>
+ // ...the XML processor MUST behave as if it normalized all line breaks in external
+ // parsed entities (including the document entity) on input, before parsing, by translating
+ // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
+ // a single #xA character.
+ // </quote>
+ //
+ // It is not clear fgets does that, and certainly isn't clear it works cross platform.
+ // Generally, you expect fgets to translate from the convention of the OS to the c/unix
+ // convention, and not work generally.
+
+ /*
+ while( fgets( buf, sizeof(buf), file ) )
+ {
+ data += buf;
+ }
+ */
+
+ char* buf = new char[ length+1 ];
+ buf[0] = 0;
+
+ if ( fread( buf, length, 1, file ) != 1 ) {
+ delete [] buf;
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+ }
+
+ const char* lastPos = buf;
+ const char* p = buf;
+
+ buf[length] = 0;
+ while( *p ) {
+ assert( p < (buf+length) );
+ if ( *p == 0xa ) {
+ // Newline character. No special rules for this. Append all the characters
+ // since the last string, and include the newline.
+ data.append( lastPos, (p-lastPos+1) ); // append, include the newline
+ ++p; // move past the newline
+ lastPos = p; // and point to the new buffer (may be 0)
+ assert( p <= (buf+length) );
+ }
+ else if ( *p == 0xd ) {
+ // Carriage return. Append what we have so far, then
+ // handle moving forward in the buffer.
+ if ( (p-lastPos) > 0 ) {
+ data.append( lastPos, p-lastPos ); // do not add the CR
+ }
+ data += (char)0xa; // a proper newline
+
+ if ( *(p+1) == 0xa ) {
+ // Carriage return - new line sequence
+ p += 2;
+ lastPos = p;
+ assert( p <= (buf+length) );
+ }
+ else {
+ // it was followed by something else...that is presumably characters again.
+ ++p;
+ lastPos = p;
+ assert( p <= (buf+length) );
+ }
+ }
+ else {
+ ++p;
+ }
+ }
+ // Handle any left over characters.
+ if ( p-lastPos ) {
+ data.append( lastPos, p-lastPos );
+ }
+ delete [] buf;
+ buf = 0;
+
+ Parse( data.c_str(), 0, encoding );
+
+ if ( Error() )
+ return false;
+ else
+ return true;
+}
+
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+ // The old c stuff lives on...
+ FILE* fp = TiXmlFOpen( filename, "w" );
+ if ( fp )
+ {
+ bool result = SaveFile( fp );
+ fclose( fp );
+ return result;
+ }
+ return false;
+}
+
+
+bool TiXmlDocument::SaveFile( FILE* fp ) const
+{
+ if ( useMicrosoftBOM )
+ {
+ const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+ const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+ const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+ fputc( TIXML_UTF_LEAD_0, fp );
+ fputc( TIXML_UTF_LEAD_1, fp );
+ fputc( TIXML_UTF_LEAD_2, fp );
+ }
+ Print( fp, 0 );
+ return (ferror(fp) == 0);
+}
+
+
+void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->error = error;
+ target->errorId = errorId;
+ target->errorDesc = errorDesc;
+ target->tabsize = tabsize;
+ target->errorLocation = errorLocation;
+ target->useMicrosoftBOM = useMicrosoftBOM;
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+ TiXmlDocument* clone = new TiXmlDocument();
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+ assert( cfile );
+ for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+ {
+ node->Print( cfile, depth );
+ fprintf( cfile, "\n" );
+ }
+}
+
+
+bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
+{
+ if ( visitor->VisitEnter( *this ) )
+ {
+ for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+ {
+ if ( !node->Accept( visitor ) )
+ break;
+ }
+ }
+ return visitor->VisitExit( *this );
+}
+
+
+const TiXmlAttribute* TiXmlAttribute::Next() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Next()
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+*/
+
+const TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Previous()
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+*/
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+ TIXML_STRING n, v;
+
+ EncodeString( name, &n );
+ EncodeString( value, &v );
+
+ if (value.find ('\"') == TIXML_STRING::npos) {
+ if ( cfile ) {
+ fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+ }
+ if ( str ) {
+ (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
+ }
+ }
+ else {
+ if ( cfile ) {
+ fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+ }
+ if ( str ) {
+ (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
+ }
+ }
+}
+
+
+int TiXmlAttribute::QueryIntValue( int* ival ) const
+{
+ if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+int TiXmlAttribute::QueryDoubleValue( double* dval ) const
+{
+ if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+void TiXmlAttribute::SetIntValue( int _value )
+{
+ char buf [64];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
+ #else
+ sprintf (buf, "%d", _value);
+ #endif
+ SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double _value )
+{
+ char buf [256];
+ #if defined(TIXML_SNPRINTF)
+ TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
+ #else
+ sprintf (buf, "%lf", _value);
+ #endif
+ SetValue (buf);
+}
+
+int TiXmlAttribute::IntValue() const
+{
+ return atoi (value.c_str ());
+}
+
+double TiXmlAttribute::DoubleValue() const
+{
+ return atof (value.c_str ());
+}
+
+
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlComment::operator=( const TiXmlComment& base )
+{
+ Clear();
+ base.CopyTo( this );
+}
+
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+ assert( cfile );
+ for ( int i=0; i<depth; i++ )
+ {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+
+void TiXmlComment::CopyTo( TiXmlComment* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+ TiXmlComment* clone = new TiXmlComment();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int depth ) const
+{
+ assert( cfile );
+ if ( cdata )
+ {
+ int i;
+ fprintf( cfile, "\n" );
+ for ( i=0; i<depth; i++ ) {
+ fprintf( cfile, " " );
+ }
+ fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
+ }
+ else
+ {
+ TIXML_STRING buffer;
+ EncodeString( value, &buffer );
+ fprintf( cfile, "%s", buffer.c_str() );
+ }
+}
+
+
+void TiXmlText::CopyTo( TiXmlText* target ) const
+{
+ TiXmlNode::CopyTo( target );
+ target->cdata = cdata;
+}
+
+
+bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{
+ TiXmlText* clone = 0;
+ clone = new TiXmlText( "" );
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+ const char * _encoding,
+ const char * _standalone )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+ if ( cfile ) fprintf( cfile, "<?xml " );
+ if ( str ) (*str) += "<?xml ";
+
+ if ( !version.empty() ) {
+ if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
+ if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
+ }
+ if ( !encoding.empty() ) {
+ if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+ if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
+ }
+ if ( !standalone.empty() ) {
+ if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+ if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
+ }
+ if ( cfile ) fprintf( cfile, "?>" );
+ if ( str ) (*str) += "?>";
+}
+
+
+void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->version = version;
+ target->encoding = encoding;
+ target->standalone = standalone;
+}
+
+
+bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{
+ TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+ for ( int i=0; i<depth; i++ )
+ fprintf( cfile, " " );
+ fprintf( cfile, "<%s>", value.c_str() );
+}
+
+
+void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
+{
+ return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+ TiXmlUnknown* clone = new TiXmlUnknown();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+ sentinel.next = &sentinel;
+ sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+ assert( sentinel.next == &sentinel );
+ assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+ #ifdef TIXML_USE_STL
+ assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
+ #else
+ assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
+ #endif
+
+ addMe->next = &sentinel;
+ addMe->prev = sentinel.prev;
+
+ sentinel.prev->next = addMe;
+ sentinel.prev = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+ TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node == removeMe )
+ {
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ node->next = 0;
+ node->prev = 0;
+ return;
+ }
+ }
+ assert( 0 ); // we tried to remove a non-linked attribute.
+}
+
+
+#ifdef TIXML_USE_STL
+const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
+{
+ for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node->name == name )
+ return node;
+ }
+ return 0;
+}
+
+/*
+TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
+{
+ for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node->name == name )
+ return node;
+ }
+ return 0;
+}
+*/
+#endif
+
+
+const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
+{
+ for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( strcmp( node->name.c_str(), name ) == 0 )
+ return node;
+ }
+ return 0;
+}
+
+/*
+TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
+{
+ for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( strcmp( node->name.c_str(), name ) == 0 )
+ return node;
+ }
+ return 0;
+}
+*/
+
+#ifdef TIXML_USE_STL
+std::istream& operator>> (std::istream & in, TiXmlNode & base)
+{
+ TIXML_STRING tag;
+ tag.reserve( 8 * 1000 );
+ base.StreamIn( &in, &tag );
+
+ base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
+ return in;
+}
+#endif
+
+
+#ifdef TIXML_USE_STL
+std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
+{
+ TiXmlPrinter printer;
+ printer.SetStreamPrinting();
+ base.Accept( &printer );
+ out << printer.Str();
+
+ return out;
+}
+
+
+std::string& operator<< (std::string& out, const TiXmlNode& base )
+{
+ TiXmlPrinter printer;
+ printer.SetStreamPrinting();
+ base.Accept( &printer );
+ out.append( printer.Str() );
+
+ return out;
+}
+#endif
+
+
+TiXmlHandle TiXmlHandle::FirstChild() const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement() const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
+{
+ return true;
+}
+
+bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
+{
+ return true;
+}
+
+bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
+{
+ DoIndent();
+ buffer += "<";
+ buffer += element.Value();
+
+ for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
+ {
+ buffer += " ";
+ attrib->Print( 0, 0, &buffer );
+ }
+
+ if ( !element.FirstChild() )
+ {
+ buffer += " />";
+ DoLineBreak();
+ }
+ else
+ {
+ buffer += ">";
+ if ( element.FirstChild()->ToText()
+ && element.LastChild() == element.FirstChild()
+ && element.FirstChild()->ToText()->CDATA() == false )
+ {
+ simpleTextPrint = true;
+ // no DoLineBreak()!
+ }
+ else
+ {
+ DoLineBreak();
+ }
+ }
+ ++depth;
+ return true;
+}
+
+
+bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
+{
+ --depth;
+ if ( !element.FirstChild() )
+ {
+ // nothing.
+ }
+ else
+ {
+ if ( simpleTextPrint )
+ {
+ simpleTextPrint = false;
+ }
+ else
+ {
+ DoIndent();
+ }
+ buffer += "</";
+ buffer += element.Value();
+ buffer += ">";
+ DoLineBreak();
+ }
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlText& text )
+{
+ if ( text.CDATA() )
+ {
+ DoIndent();
+ buffer += "<![CDATA[";
+ buffer += text.Value();
+ buffer += "]]>";
+ DoLineBreak();
+ }
+ else if ( simpleTextPrint )
+ {
+ TIXML_STRING str;
+ TiXmlBase::EncodeString( text.ValueTStr(), &str );
+ buffer += str;
+ }
+ else
+ {
+ DoIndent();
+ TIXML_STRING str;
+ TiXmlBase::EncodeString( text.ValueTStr(), &str );
+ buffer += str;
+ DoLineBreak();
+ }
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
+{
+ DoIndent();
+ declaration.Print( 0, 0, &buffer );
+ DoLineBreak();
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlComment& comment )
+{
+ DoIndent();
+ buffer += "<!--";
+ buffer += comment.Value();
+ buffer += "-->";
+ DoLineBreak();
+ return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
+{
+ DoIndent();
+ buffer += "<";
+ buffer += unknown.Value();
+ buffer += ">";
+ DoLineBreak();
+ return true;
+}
+
diff --git a/src/thirdparty/ZenLib/TinyXml/tinyxml.h b/src/thirdparty/ZenLib/TinyXml/tinyxml.h
new file mode 100644
index 000000000..2108c8ee9
--- /dev/null
+++ b/src/thirdparty/ZenLib/TinyXml/tinyxml.h
@@ -0,0 +1,1804 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+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.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#define TIXML_USE_STL
+
+#ifdef TIXML_USE_STL
+ #include <string>
+ #include <iostream>
+ #include <sstream>
+ #define TIXML_STRING std::string
+#else
+ #include "tinystr.h"
+ #define TIXML_STRING TiXmlString
+#endif
+
+// Deprecated library function hell. Compilers want to use the
+// new safe versions. This probably doesn't fully address the problem,
+// but it gets closer. There are too many compilers for me to fully
+// test. If you get compilation troubles, undefine TIXML_SAFE
+#define TIXML_SAFE
+
+#ifdef TIXML_SAFE
+ #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+ // Microsoft visual studio, version 2005 and higher.
+ #define TIXML_SNPRINTF _snprintf_s
+ #define TIXML_SNSCANF _snscanf_s
+ #define TIXML_SSCANF sscanf_s
+ #elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
+ // Microsoft visual studio, version 6 and higher.
+ //#pragma message( "Using _sn* functions." )
+ #define TIXML_SNPRINTF _snprintf
+ #define TIXML_SNSCANF _snscanf
+ #define TIXML_SSCANF sscanf
+ #elif defined(__GNUC__) && (__GNUC__ >= 3 )
+ // GCC version 3 and higher.s
+ //#warning( "Using sn* functions." )
+ #define TIXML_SNPRINTF snprintf
+ #define TIXML_SNSCANF snscanf
+ #define TIXML_SSCANF sscanf
+ #else
+ #define TIXML_SSCANF sscanf
+ #endif
+#endif
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlParsingData;
+
+const int TIXML_MAJOR_VERSION = 2;
+const int TIXML_MINOR_VERSION = 5;
+const int TIXML_PATCH_VERSION = 3;
+
+/* Internal structure for tracking location of items
+ in the XML file.
+*/
+struct TiXmlCursor
+{
+ TiXmlCursor() { Clear(); }
+ void Clear() { row = col = -1; }
+
+ int row; // 0 based.
+ int col; // 0 based.
+};
+
+
+/**
+ If you call the Accept() method, it requires being passed a TiXmlVisitor
+ class to handle callbacks. For nodes that contain other nodes (Document, Element)
+ you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
+ are simple called with Visit().
+
+ If you return 'true' from a Visit method, recursive parsing will continue. If you return
+ false, <b>no children of this node or its sibilings</b> will be Visited.
+
+ All flavors of Visit methods have a default implementation that returns 'true' (continue
+ visiting). You need to only override methods that are interesting to you.
+
+ Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
+
+ You should never change the document from a callback.
+
+ @sa TiXmlNode::Accept()
+*/
+class TiXmlVisitor
+{
+public:
+ virtual ~TiXmlVisitor() {}
+
+ /// Visit a document.
+ virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; }
+ /// Visit a document.
+ virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; }
+
+ /// Visit an element.
+ virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; }
+ /// Visit an element.
+ virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; }
+
+ /// Visit a declaration
+ virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; }
+ /// Visit a text node
+ virtual bool Visit( const TiXmlText& /*text*/ ) { return true; }
+ /// Visit a comment node
+ virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; }
+ /// Visit an unknow node
+ virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; }
+};
+
+// Only used by Attribute::Query functions
+enum
+{
+ TIXML_SUCCESS,
+ TIXML_NO_ATTRIBUTE,
+ TIXML_WRONG_TYPE
+};
+
+
+// Used by the parsing routines.
+enum TiXmlEncoding
+{
+ TIXML_ENCODING_UNKNOWN,
+ TIXML_ENCODING_UTF8,
+ TIXML_ENCODING_LEGACY
+};
+
+const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
+
+/** TiXmlBase is a base class for every class in TinyXml.
+ It does little except to establish that TinyXml classes
+ can be printed and provide some utility functions.
+
+ In XML, the document and elements can contain
+ other elements and other types of nodes.
+
+ @verbatim
+ A Document can contain: Element (container or leaf)
+ Comment (leaf)
+ Unknown (leaf)
+ Declaration( leaf )
+
+ An Element can contain: Element (container or leaf)
+ Text (leaf)
+ Attributes (not on tree)
+ Comment (leaf)
+ Unknown (leaf)
+
+ A Decleration contains: Attributes (not on tree)
+ @endverbatim
+*/
+class TiXmlBase
+{
+ friend class TiXmlNode;
+ friend class TiXmlElement;
+ friend class TiXmlDocument;
+
+public:
+ TiXmlBase() : userData(0) {}
+ virtual ~TiXmlBase() {}
+
+ /** All TinyXml classes can print themselves to a filestream
+ or the string class (TiXmlString in non-STL mode, std::string
+ in STL mode.) Either or both cfile and str can be null.
+
+ This is a formatted print, and will insert
+ tabs and newlines.
+
+ (For an unformatted stream, use the << operator.)
+ */
+ virtual void Print( FILE* cfile, int depth ) const = 0;
+
+ /** The world does not agree on whether white space should be kept or
+ not. In order to make everyone happy, these global, static functions
+ are provided to set whether or not TinyXml will condense all white space
+ into a single space or not. The default is to condense. Note changing this
+ value is not thread safe.
+ */
+ static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; }
+
+ /// Return the current white space setting.
+ static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; }
+
+ /** Return the position, in the original source file, of this node or attribute.
+ The row and column are 1-based. (That is the first row and first column is
+ 1,1). If the returns values are 0 or less, then the parser does not have
+ a row and column value.
+
+ Generally, the row and column value will be set when the TiXmlDocument::Load(),
+ TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
+ when the DOM was created from operator>>.
+
+ The values reflect the initial load. Once the DOM is modified programmatically
+ (by adding or changing nodes and attributes) the new values will NOT update to
+ reflect changes in the document.
+
+ There is a minor performance cost to computing the row and column. Computation
+ can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
+
+ @sa TiXmlDocument::SetTabSize()
+ */
+ int Row() const { return location.row + 1; }
+ int Column() const { return location.col + 1; } ///< See Row()
+
+ void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data.
+ void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data.
+ const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data.
+
+ // Table that returs, for a given lead byte, the total number of bytes
+ // in the UTF-8 sequence.
+ static const int utf8ByteTable[256];
+
+ virtual const char* Parse( const char* p,
+ TiXmlParsingData* data,
+ TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
+
+ /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc,
+ or they will be transformed into entities!
+ */
+ static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out );
+
+ enum
+ {
+ TIXML_NO_ERROR = 0,
+ TIXML_ERROR,
+ TIXML_ERROR_OPENING_FILE,
+ TIXML_ERROR_OUT_OF_MEMORY,
+ TIXML_ERROR_PARSING_ELEMENT,
+ TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+ TIXML_ERROR_READING_ELEMENT_VALUE,
+ TIXML_ERROR_READING_ATTRIBUTES,
+ TIXML_ERROR_PARSING_EMPTY,
+ TIXML_ERROR_READING_END_TAG,
+ TIXML_ERROR_PARSING_UNKNOWN,
+ TIXML_ERROR_PARSING_COMMENT,
+ TIXML_ERROR_PARSING_DECLARATION,
+ TIXML_ERROR_DOCUMENT_EMPTY,
+ TIXML_ERROR_EMBEDDED_NULL,
+ TIXML_ERROR_PARSING_CDATA,
+ TIXML_ERROR_DOCUMENT_TOP_ONLY,
+
+ TIXML_ERROR_STRING_COUNT
+ };
+
+protected:
+
+ static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
+ inline static bool IsWhiteSpace( char c )
+ {
+ return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
+ }
+ inline static bool IsWhiteSpace( int c )
+ {
+ if ( c < 256 )
+ return IsWhiteSpace( (char) c );
+ return false; // Again, only truly correct for English/Latin...but usually works.
+ }
+
+ #ifdef TIXML_USE_STL
+ static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag );
+ static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag );
+ #endif
+
+ /* Reads an XML name into the string provided. Returns
+ a pointer just past the last character of the name,
+ or 0 if the function has an error.
+ */
+ static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
+
+ /* Reads text. Returns a pointer past the given end tag.
+ Wickedly complex options, but it keeps the (sensitive) code in one place.
+ */
+ static const char* ReadText( const char* in, // where to start
+ TIXML_STRING* text, // the string read
+ bool ignoreWhiteSpace, // whether to keep the white space
+ const char* endTag, // what ends this text
+ bool ignoreCase, // whether to ignore case in the end tag
+ TiXmlEncoding encoding ); // the current encoding
+
+ // If an entity has been found, transform it into a character.
+ static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
+
+ // Get a character, while interpreting entities.
+ // The length can be from 0 to 4 bytes.
+ inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
+ {
+ assert( p );
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ *length = utf8ByteTable[ *((const unsigned char*)p) ];
+ assert( *length >= 0 && *length < 5 );
+ }
+ else
+ {
+ *length = 1;
+ }
+
+ if ( *length == 1 )
+ {
+ if ( *p == '&' )
+ return GetEntity( p, _value, length, encoding );
+ *_value = *p;
+ return p+1;
+ }
+ else if ( *length )
+ {
+ //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe),
+ // and the null terminator isn't needed
+ for( int i=0; p[i] && i<*length; ++i ) {
+ _value[i] = p[i];
+ }
+ return p + (*length);
+ }
+ else
+ {
+ // Not valid text.
+ return 0;
+ }
+ }
+
+ // Return true if the next characters in the stream are any of the endTag sequences.
+ // Ignore case only works for english, and should only be relied on when comparing
+ // to English words: StringEqual( p, "version", true ) is fine.
+ static bool StringEqual( const char* p,
+ const char* endTag,
+ bool ignoreCase,
+ TiXmlEncoding encoding );
+
+ static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+ TiXmlCursor location;
+
+ /// Field containing a generic user pointer
+ void* userData;
+
+ // None of these methods are reliable for any language except English.
+ // Good for approximation, not great for accuracy.
+ static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
+ static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
+ inline static int ToLower( int v, TiXmlEncoding encoding )
+ {
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( v < 128 ) return tolower( v );
+ return v;
+ }
+ else
+ {
+ return tolower( v );
+ }
+ }
+ static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+private:
+ TiXmlBase( const TiXmlBase& ); // not implemented.
+ void operator=( const TiXmlBase& base ); // not allowed.
+
+ struct Entity
+ {
+ const char* str;
+ unsigned int strLength;
+ char chr;
+ };
+ enum
+ {
+ NUM_ENTITY = 5,
+ MAX_ENTITY_LENGTH = 6
+
+ };
+ static Entity entity[ NUM_ENTITY ];
+ static bool condenseWhiteSpace;
+};
+
+
+/** The parent class for everything in the Document Object Model.
+ (Except for attributes).
+ Nodes have siblings, a parent, and children. A node can be
+ in a document, or stand on its own. The type of a TiXmlNode
+ can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+ friend class TiXmlDocument;
+ friend class TiXmlElement;
+
+public:
+ #ifdef TIXML_USE_STL
+
+ /** An input stream operator, for every class. Tolerant of newlines and
+ formatting, but doesn't expect them.
+ */
+ friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+ /** An output stream operator, for every class. Note that this outputs
+ without any newlines or formatting, as opposed to Print(), which
+ includes tabs and new lines.
+
+ The operator<< and operator>> are not completely symmetric. Writing
+ a node to a stream is very well defined. You'll get a nice stream
+ of output, without any extra whitespace or newlines.
+
+ But reading is not as well defined. (As it always is.) If you create
+ a TiXmlElement (for example) and read that from an input stream,
+ the text needs to define an element or junk will result. This is
+ true of all input streams, but it's worth keeping in mind.
+
+ A TiXmlDocument will read nodes until it reads a root element, and
+ all the children of that root element.
+ */
+ friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
+
+ /// Appends the XML node or attribute to a std::string.
+ friend std::string& operator<< (std::string& out, const TiXmlNode& base );
+
+ #endif
+
+ /** The types of XML nodes supported by TinyXml. (All the
+ unsupported types are picked up by UNKNOWN.)
+ */
+ enum NodeType
+ {
+ DOCUMENT,
+ ELEMENT,
+ COMMENT,
+ UNKNOWN,
+ TEXT,
+ DECLARATION,
+ TYPECOUNT
+ };
+
+ virtual ~TiXmlNode();
+
+ /** The meaning of 'value' changes for the specific type of
+ TiXmlNode.
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+
+ The subclasses will wrap this function.
+ */
+ const char *Value() const { return value.c_str (); }
+
+ #ifdef TIXML_USE_STL
+ /** Return Value() as a std::string. If you only use STL,
+ this is more efficient than calling Value().
+ Only available in STL mode.
+ */
+ const std::string& ValueStr() const { return value; }
+ #endif
+
+ const TIXML_STRING& ValueTStr() const { return value; }
+
+ /** Changes the value of the node. Defined as:
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+ */
+ void SetValue(const char * _value) { value = _value;}
+
+ #ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetValue( const std::string& _value ) { value = _value; }
+ #endif
+
+ /// Delete all the children of this node. Does not affect 'this'.
+ void Clear();
+
+ /// One step up the DOM.
+ TiXmlNode* Parent() { return parent; }
+ const TiXmlNode* Parent() const { return parent; }
+
+ const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
+ TiXmlNode* FirstChild() { return firstChild; }
+ const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
+ /// The first child of this node with the matching 'value'. Will be null if none found.
+ TiXmlNode* FirstChild( const char * _value ) {
+ // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe)
+ // call the method, cast the return back to non-const.
+ return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value ));
+ }
+ const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
+ TiXmlNode* LastChild() { return lastChild; }
+
+ const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
+ TiXmlNode* LastChild( const char * _value ) {
+ return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value ));
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form.
+ const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /** An alternate way to walk the children of a node.
+ One way to iterate over nodes is:
+ @verbatim
+ for( child = parent->FirstChild(); child; child = child->NextSibling() )
+ @endverbatim
+
+ IterateChildren does the same thing with the syntax:
+ @verbatim
+ child = 0;
+ while( child = parent->IterateChildren( child ) )
+ @endverbatim
+
+ IterateChildren takes the previous child as input and finds
+ the next one. If the previous child is null, it returns the
+ first. IterateChildren will return null when done.
+ */
+ const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
+ TiXmlNode* IterateChildren( const TiXmlNode* previous ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) );
+ }
+
+ /// This flavor of IterateChildren searches for children with a particular 'value'
+ const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
+ TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
+ TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form.
+ #endif
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+
+ NOTE: the node to be added is passed by pointer, and will be
+ henceforth owned (and deleted) by tinyXml. This method is efficient
+ and avoids an extra copy, but should be used with care as it
+ uses a different memory model than the other insert functions.
+
+ @sa InsertEndChild
+ */
+ TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+ /** Add a new node related to this. Adds a child before the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+ /** Add a new node related to this. Adds a child after the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+ /** Replace a child of this node.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+ /// Delete a child of this node.
+ bool RemoveChild( TiXmlNode* removeThis );
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* PreviousSibling() const { return prev; }
+ TiXmlNode* PreviousSibling() { return prev; }
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* PreviousSibling( const char * ) const;
+ TiXmlNode* PreviousSibling( const char *_prev ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form.
+ const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form.
+ TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /// Navigate to a sibling node.
+ const TiXmlNode* NextSibling() const { return next; }
+ TiXmlNode* NextSibling() { return next; }
+
+ /// Navigate to a sibling node with the given 'value'.
+ const TiXmlNode* NextSibling( const char * ) const;
+ TiXmlNode* NextSibling( const char* _next ) {
+ return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) );
+ }
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ const TiXmlElement* NextSiblingElement() const;
+ TiXmlElement* NextSiblingElement() {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() );
+ }
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ const TiXmlElement* NextSiblingElement( const char * ) const;
+ TiXmlElement* NextSiblingElement( const char *_next ) {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
+ TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /// Convenience function to get through elements.
+ const TiXmlElement* FirstChildElement() const;
+ TiXmlElement* FirstChildElement() {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() );
+ }
+
+ /// Convenience function to get through elements.
+ const TiXmlElement* FirstChildElement( const char * _value ) const;
+ TiXmlElement* FirstChildElement( const char * _value ) {
+ return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) );
+ }
+
+ #ifdef TIXML_USE_STL
+ const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
+ TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form.
+ #endif
+
+ /** Query the type (as an enumerated value, above) of this node.
+ The possible types are: DOCUMENT, ELEMENT, COMMENT,
+ UNKNOWN, TEXT, and DECLARATION.
+ */
+ int Type() const { return type; }
+
+ /** Return a pointer to the Document this node lives in.
+ Returns null if not in a document.
+ */
+ const TiXmlDocument* GetDocument() const;
+ TiXmlDocument* GetDocument() {
+ return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() );
+ }
+
+ /// Returns true if this node has no children.
+ bool NoChildren() const { return !firstChild; }
+
+ virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+ virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+ virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+ /** Create an exact duplicate of this node and return it. The memory must be deleted
+ by the caller.
+ */
+ virtual TiXmlNode* Clone() const = 0;
+
+ /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
+ XML tree will be conditionally visited and the host will be called back
+ via the TiXmlVisitor interface.
+
+ This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
+ the XML for the callbacks, so the performance of TinyXML is unchanged by using this
+ interface versus any other.)
+
+ The interface has been based on ideas from:
+
+ - http://www.saxproject.org/
+ - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
+
+ Which are both good references for "visiting".
+
+ An example of using Accept():
+ @verbatim
+ TiXmlPrinter printer;
+ tinyxmlDoc.Accept( &printer );
+ const char* xmlcstr = printer.CStr();
+ @endverbatim
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const = 0;
+
+protected:
+ TiXmlNode( NodeType _type );
+
+ // Copy to the allocated object. Shared functionality between Clone, Copy constructor,
+ // and the assignment operator.
+ void CopyTo( TiXmlNode* target ) const;
+
+ #ifdef TIXML_USE_STL
+ // The real work of the input operator.
+ virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0;
+ #endif
+
+ // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+ TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
+
+ TiXmlNode* parent;
+ NodeType type;
+
+ TiXmlNode* firstChild;
+ TiXmlNode* lastChild;
+
+ TIXML_STRING value;
+
+ TiXmlNode* prev;
+ TiXmlNode* next;
+
+private:
+ TiXmlNode( const TiXmlNode& ); // not implemented.
+ void operator=( const TiXmlNode& base ); // not allowed.
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+ number of attributes, each with a unique name.
+
+ @note The attributes are not TiXmlNodes, since they are not
+ part of the tinyXML document object model. There are other
+ suggested ways to look at this problem.
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+ friend class TiXmlAttributeSet;
+
+public:
+ /// Construct an empty attribute.
+ TiXmlAttribute() : TiXmlBase()
+ {
+ document = 0;
+ prev = next = 0;
+ }
+
+ #ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlAttribute( const std::string& _name, const std::string& _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+ #endif
+
+ /// Construct an attribute with a name and value.
+ TiXmlAttribute( const char * _name, const char * _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+
+ const char* Name() const { return name.c_str(); } ///< Return the name of this attribute.
+ const char* Value() const { return value.c_str(); } ///< Return the value of this attribute.
+ #ifdef TIXML_USE_STL
+ const std::string& ValueStr() const { return value; } ///< Return the value of this attribute.
+ #endif
+ int IntValue() const; ///< Return the value of this attribute, converted to an integer.
+ double DoubleValue() const; ///< Return the value of this attribute, converted to a double.
+
+ // Get the tinyxml string representation
+ const TIXML_STRING& NameTStr() const { return name; }
+
+ /** QueryIntValue examines the value string. It is an alternative to the
+ IntValue() method with richer error checking.
+ If the value is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE.
+
+ A specialized but useful call. Note that for success it returns 0,
+ which is the opposite of almost all other TinyXml calls.
+ */
+ int QueryIntValue( int* _value ) const;
+ /// QueryDoubleValue examines the value string. See QueryIntValue().
+ int QueryDoubleValue( double* _value ) const;
+
+ void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute.
+ void SetValue( const char* _value ) { value = _value; } ///< Set the value.
+
+ void SetIntValue( int _value ); ///< Set the value from an integer.
+ void SetDoubleValue( double _value ); ///< Set the value from a double.
+
+ #ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetName( const std::string& _name ) { name = _name; }
+ /// STL std::string form.
+ void SetValue( const std::string& _value ) { value = _value; }
+ #endif
+
+ /// Get the next sibling attribute in the DOM. Returns null at end.
+ const TiXmlAttribute* Next() const;
+ TiXmlAttribute* Next() {
+ return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() );
+ }
+
+ /// Get the previous sibling attribute in the DOM. Returns null at beginning.
+ const TiXmlAttribute* Previous() const;
+ TiXmlAttribute* Previous() {
+ return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() );
+ }
+
+ bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
+ bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; }
+ bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; }
+
+ /* Attribute parsing starts: first letter of the name
+ returns: the next char after the value end quote
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ // Prints this Attribute to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const {
+ Print( cfile, depth, 0 );
+ }
+ void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+
+ // [internal use]
+ // Set the document pointer so the attribute can report errors.
+ void SetDocument( TiXmlDocument* doc ) { document = doc; }
+
+private:
+ TiXmlAttribute( const TiXmlAttribute& ); // not implemented.
+ void operator=( const TiXmlAttribute& base ); // not allowed.
+
+ TiXmlDocument* document; // A pointer back to a document, for error reporting.
+ TIXML_STRING name;
+ TIXML_STRING value;
+ TiXmlAttribute* prev;
+ TiXmlAttribute* next;
+};
+
+
+/* A class used to manage a group of attributes.
+ It is only used internally, both by the ELEMENT and the DECLARATION.
+
+ The set can be changed transparent to the Element and Declaration
+ classes that use it, but NOT transparent to the Attribute
+ which has to implement a next() and previous() method. Which makes
+ it a bit problematic and prevents the use of STL.
+
+ This version is implemented with circular lists because:
+ - I like circular lists
+ - it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+ TiXmlAttributeSet();
+ ~TiXmlAttributeSet();
+
+ void Add( TiXmlAttribute* attribute );
+ void Remove( TiXmlAttribute* attribute );
+
+ const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+ TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+ const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+ TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+
+ const TiXmlAttribute* Find( const char* _name ) const;
+ TiXmlAttribute* Find( const char* _name ) {
+ return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
+ }
+ #ifdef TIXML_USE_STL
+ const TiXmlAttribute* Find( const std::string& _name ) const;
+ TiXmlAttribute* Find( const std::string& _name ) {
+ return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
+ }
+
+ #endif
+
+private:
+ //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
+ //*ME: this class must be also use a hidden/disabled copy-constructor !!!
+ TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed
+ void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute)
+
+ TiXmlAttribute sentinel;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+ and can contain other elements, text, comments, and unknowns.
+ Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+ /// Construct an element.
+ TiXmlElement (const char * in_value);
+
+ #ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlElement( const std::string& _value );
+ #endif
+
+ TiXmlElement( const TiXmlElement& );
+
+ void operator=( const TiXmlElement& base );
+
+ virtual ~TiXmlElement();
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ */
+ const char* Attribute( const char* name ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an integer,
+ the integer value will be put in the return 'i', if 'i'
+ is non-null.
+ */
+ const char* Attribute( const char* name, int* i ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an double,
+ the double value will be put in the return 'd', if 'd'
+ is non-null.
+ */
+ const char* Attribute( const char* name, double* d ) const;
+
+ /** QueryIntAttribute examines the attribute - it is an alternative to the
+ Attribute() method with richer error checking.
+ If the attribute is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE. If the attribute
+ does not exist, then TIXML_NO_ATTRIBUTE is returned.
+ */
+ int QueryIntAttribute( const char* name, int* _value ) const;
+ /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
+ int QueryDoubleAttribute( const char* name, double* _value ) const;
+ /// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
+ int QueryFloatAttribute( const char* name, float* _value ) const {
+ double d;
+ int result = QueryDoubleAttribute( name, &d );
+ if ( result == TIXML_SUCCESS ) {
+ *_value = (float)d;
+ }
+ return result;
+ }
+
+ #ifdef TIXML_USE_STL
+ /** Template form of the attribute query which will try to read the
+ attribute into the specified type. Very easy, very powerful, but
+ be careful to make sure to call this with the correct type.
+
+ NOTE: This method doesn't work correctly for 'string' types.
+
+ @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE
+ */
+ template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const
+ {
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ std::stringstream sstream( node->ValueStr() );
+ sstream >> *outValue;
+ if ( !sstream.fail() )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+ }
+ /*
+ This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string"
+ but template specialization is hard to get working cross-compiler. Leaving the bug for now.
+
+ // The above will fail for std::string because the space character is used as a seperator.
+ // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string
+ template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const
+ {
+ const TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+ *outValue = node->ValueStr();
+ return TIXML_SUCCESS;
+ }
+ */
+ #endif
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char* name, const char * _value );
+
+ #ifdef TIXML_USE_STL
+ const std::string* Attribute( const std::string& name ) const;
+ const std::string* Attribute( const std::string& name, int* i ) const;
+ const std::string* Attribute( const std::string& name, double* d ) const;
+ int QueryIntAttribute( const std::string& name, int* _value ) const;
+ int QueryDoubleAttribute( const std::string& name, double* _value ) const;
+
+ /// STL std::string form.
+ void SetAttribute( const std::string& name, const std::string& _value );
+ ///< STL std::string form.
+ void SetAttribute( const std::string& name, int _value );
+ #endif
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char * name, int value );
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetDoubleAttribute( const char * name, double value );
+
+ /** Deletes an attribute with the given name.
+ */
+ void RemoveAttribute( const char * name );
+ #ifdef TIXML_USE_STL
+ void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form.
+ #endif
+
+ const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element.
+ TiXmlAttribute* FirstAttribute() { return attributeSet.First(); }
+ const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element.
+ TiXmlAttribute* LastAttribute() { return attributeSet.Last(); }
+
+ /** Convenience function for easy access to the text inside an element. Although easy
+ and concise, GetText() is limited compared to getting the TiXmlText child
+ and accessing it directly.
+
+ If the first child of 'this' is a TiXmlText, the GetText()
+ returns the character string of the Text node, else null is returned.
+
+ This is a convenient method for getting the text of simple contained text:
+ @verbatim
+ <foo>This is text</foo>
+ const char* str = fooElement->GetText();
+ @endverbatim
+
+ 'str' will be a pointer to "This is text".
+
+ Note that this function can be misleading. If the element foo was created from
+ this XML:
+ @verbatim
+ <foo><b>This is text</b></foo>
+ @endverbatim
+
+ then the value of str would be null. The first child node isn't a text node, it is
+ another element. From this XML:
+ @verbatim
+ <foo>This is <b>text</b></foo>
+ @endverbatim
+ GetText() will return "This is ".
+
+ WARNING: GetText() accesses a child node - don't become confused with the
+ similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are
+ safe type casts on the referenced node.
+ */
+ const char* GetText() const;
+
+ /// Creates a new Element and returns it - the returned element is a copy.
+ virtual TiXmlNode* Clone() const;
+ // Print the Element to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: next char past '<'
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+
+ void CopyTo( TiXmlElement* target ) const;
+ void ClearThis(); // like clear, but initializes 'this' object as well
+
+ // Used to be public [internal use]
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+ /* [internal use]
+ Reads the "value" of the element -- another element, or text.
+ This should terminate with the current end tag.
+ */
+ const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+private:
+
+ TiXmlAttributeSet attributeSet;
+};
+
+
+/** An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+ /// Constructs an empty comment.
+ TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
+ /// Construct a comment from text.
+ TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) {
+ SetValue( _value );
+ }
+ TiXmlComment( const TiXmlComment& );
+ void operator=( const TiXmlComment& base );
+
+ virtual ~TiXmlComment() {}
+
+ /// Returns a copy of this Comment.
+ virtual TiXmlNode* Clone() const;
+ // Write this Comment to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: at the ! of the !--
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+ void CopyTo( TiXmlComment* target ) const;
+
+ // used to be public
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+// virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** XML text. A text node can have 2 ways to output the next. "normal" output
+ and CDATA. It will default to the mode it was parsed from the XML file and
+ you generally want to leave it alone, but you can change the output mode with
+ SetCDATA() and query it with CDATA().
+*/
+class TiXmlText : public TiXmlNode
+{
+ friend class TiXmlElement;
+public:
+ /** Constructor for text element. By default, it is treated as
+ normal, encoded text. If you want it be output as a CDATA text
+ element, set the parameter _cdata to 'true'
+ */
+ TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
+ {
+ SetValue( initValue );
+ cdata = false;
+ }
+ virtual ~TiXmlText() {}
+
+ #ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
+ {
+ SetValue( initValue );
+ cdata = false;
+ }
+ #endif
+
+ TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); }
+ void operator=( const TiXmlText& base ) { base.CopyTo( this ); }
+
+ // Write this text object to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /// Queries whether this represents text using a CDATA section.
+ bool CDATA() const { return cdata; }
+ /// Turns on or off a CDATA representation of text.
+ void SetCDATA( bool _cdata ) { cdata = _cdata; }
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+ /// [internal use] Creates a new Element and returns it.
+ virtual TiXmlNode* Clone() const;
+ void CopyTo( TiXmlText* target ) const;
+
+ bool Blank() const; // returns true if all white space and new lines
+ // [internal use]
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+ bool cdata; // true if this should be input and output as a CDATA style text element
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+ @verbatim
+ <?xml version="1.0" standalone="yes"?>
+ @endverbatim
+
+ TinyXml will happily read or write files without a declaration,
+ however. There are 3 possible attributes to the declaration:
+ version, encoding, and standalone.
+
+ Note: In this version of the code, the attributes are
+ handled as special cases, not generic attributes, simply
+ because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+ /// Construct an empty declaration.
+ TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {}
+
+#ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone );
+#endif
+
+ /// Construct.
+ TiXmlDeclaration( const char* _version,
+ const char* _encoding,
+ const char* _standalone );
+
+ TiXmlDeclaration( const TiXmlDeclaration& copy );
+ void operator=( const TiXmlDeclaration& copy );
+
+ virtual ~TiXmlDeclaration() {}
+
+ /// Version. Will return an empty string if none was found.
+ const char *Version() const { return version.c_str (); }
+ /// Encoding. Will return an empty string if none was found.
+ const char *Encoding() const { return encoding.c_str (); }
+ /// Is this a standalone document?
+ const char *Standalone() const { return standalone.c_str (); }
+
+ /// Creates a copy of this Declaration and returns it.
+ virtual TiXmlNode* Clone() const;
+ // Print this declaration to a FILE stream.
+ virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+ virtual void Print( FILE* cfile, int depth ) const {
+ Print( cfile, depth, 0 );
+ }
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+ void CopyTo( TiXmlDeclaration* target ) const;
+ // used to be public
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+
+ TIXML_STRING version;
+ TIXML_STRING encoding;
+ TIXML_STRING standalone;
+};
+
+
+/** Any tag that tinyXml doesn't recognize is saved as an
+ unknown. It is a tag of text, but should not be modified.
+ It will be written back to the XML, unchanged, when the file
+ is saved.
+
+ DTD tags get thrown into TiXmlUnknowns.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+ TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
+ virtual ~TiXmlUnknown() {}
+
+ TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); }
+ void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); }
+
+ /// Creates a copy of this Unknown and returns it.
+ virtual TiXmlNode* Clone() const;
+ // Print this Unknown to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected:
+ void CopyTo( TiXmlUnknown* target ) const;
+
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+
+};
+
+
+/** Always the top level node. A document binds together all the
+ XML pieces. It can be saved, loaded, and printed to the screen.
+ The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+ /// Create an empty document, that has no name.
+ TiXmlDocument();
+ /// Create a document with a name. The name of the document is also the filename of the xml.
+ TiXmlDocument( const char * documentName );
+
+ #ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDocument( const std::string& documentName );
+ #endif
+
+ TiXmlDocument( const TiXmlDocument& copy );
+ void operator=( const TiXmlDocument& copy );
+
+ virtual ~TiXmlDocument() {}
+
+ /** Load a file using the current document value.
+ Returns true if successful. Will delete any existing
+ document data before loading.
+ */
+ bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the current document value. Returns true if successful.
+ bool SaveFile() const;
+ /// Load a file using the given filename. Returns true if successful.
+ bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given filename. Returns true if successful.
+ bool SaveFile( const char * filename ) const;
+ /** Load a file using the given FILE*. Returns true if successful. Note that this method
+ doesn't stream - the entire object pointed at by the FILE*
+ will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
+ file location. Streaming may be added in the future.
+ */
+ bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given FILE*. Returns true if successful.
+ bool SaveFile( FILE* ) const;
+
+ #ifdef TIXML_USE_STL
+ bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
+ {
+// StringToBuffer f( filename );
+// return ( f.buffer && LoadFile( f.buffer, encoding ));
+ return LoadFile( filename.c_str(), encoding );
+ }
+ bool SaveFile( const std::string& filename ) const ///< STL std::string version.
+ {
+// StringToBuffer f( filename );
+// return ( f.buffer && SaveFile( f.buffer ));
+ return SaveFile( filename.c_str() );
+ }
+ #endif
+
+ /** Parse the given null terminated block of xml data. Passing in an encoding to this
+ method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
+ to use that encoding, regardless of what TinyXml might otherwise try to detect.
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+ /** Get the root element -- the only top level element -- of the document.
+ In well formed XML, there should only be one. TinyXml is tolerant of
+ multiple elements at the document level.
+ */
+ const TiXmlElement* RootElement() const { return FirstChildElement(); }
+ TiXmlElement* RootElement() { return FirstChildElement(); }
+
+ /** If an error occurs, Error will be set to true. Also,
+ - The ErrorId() will contain the integer identifier of the error (not generally useful)
+ - The ErrorDesc() method will return the name of the error. (very useful)
+ - The ErrorRow() and ErrorCol() will return the location of the error (if known)
+ */
+ bool Error() const { return error; }
+
+ /// Contains a textual (english) description of the error if one occurs.
+ const char * ErrorDesc() const { return errorDesc.c_str (); }
+
+ /** Generally, you probably want the error string ( ErrorDesc() ). But if you
+ prefer the ErrorId, this function will fetch it.
+ */
+ int ErrorId() const { return errorId; }
+
+ /** Returns the location (if known) of the error. The first column is column 1,
+ and the first row is row 1. A value of 0 means the row and column wasn't applicable
+ (memory errors, for example, have no row/column) or the parser lost the error. (An
+ error in the error reporting, in that case.)
+
+ @sa SetTabSize, Row, Column
+ */
+ int ErrorRow() const { return errorLocation.row+1; }
+ int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
+
+ /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
+ to report the correct values for row and column. It does not change the output
+ or input in any way.
+
+ By calling this method, with a tab size
+ greater than 0, the row and column of each node and attribute is stored
+ when the file is loaded. Very useful for tracking the DOM back in to
+ the source file.
+
+ The tab size is required for calculating the location of nodes. If not
+ set, the default of 4 is used. The tabsize is set per document. Setting
+ the tabsize to 0 disables row/column tracking.
+
+ Note that row and column tracking is not supported when using operator>>.
+
+ The tab size needs to be enabled before the parse or load. Correct usage:
+ @verbatim
+ TiXmlDocument doc;
+ doc.SetTabSize( 8 );
+ doc.Load( "myfile.xml" );
+ @endverbatim
+
+ @sa Row, Column
+ */
+ void SetTabSize( int _tabsize ) { tabsize = _tabsize; }
+
+ int TabSize() const { return tabsize; }
+
+ /** If you have handled the error, it can be reset with this call. The error
+ state is automatically cleared if you Parse a new XML block.
+ */
+ void ClearError() { error = false;
+ errorId = 0;
+ errorDesc = "";
+ errorLocation.row = errorLocation.col = 0;
+ //errorLocation.last = 0;
+ }
+
+ /** Write the document to standard out using formatted printing ("pretty print"). */
+ void Print() const { Print( stdout, 0 ); }
+
+ /* Write the document to a string using formatted printing ("pretty print"). This
+ will allocate a character array (new char[]) and return it as a pointer. The
+ calling code pust call delete[] on the return char* to avoid a memory leak.
+ */
+ //char* PrintToMemory() const;
+
+ /// Print this Document to a FILE stream.
+ virtual void Print( FILE* cfile, int depth = 0 ) const;
+ // [internal use]
+ void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+ virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+ virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Walk the XML tree visiting this node and all of its children.
+ */
+ virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+ // [internal use]
+ virtual TiXmlNode* Clone() const;
+ #ifdef TIXML_USE_STL
+ virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+ #endif
+
+private:
+ void CopyTo( TiXmlDocument* target ) const;
+
+ bool error;
+ int errorId;
+ TIXML_STRING errorDesc;
+ int tabsize;
+ TiXmlCursor errorLocation;
+ bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write.
+};
+
+
+/**
+ A TiXmlHandle is a class that wraps a node pointer with null checks; this is
+ an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
+ DOM structure. It is a separate utility class.
+
+ Take an example:
+ @verbatim
+ <Document>
+ <Element attributeA = "valueA">
+ <Child attributeB = "value1" />
+ <Child attributeB = "value2" />
+ </Element>
+ <Document>
+ @endverbatim
+
+ Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
+ easy to write a *lot* of code that looks like:
+
+ @verbatim
+ TiXmlElement* root = document.FirstChildElement( "Document" );
+ if ( root )
+ {
+ TiXmlElement* element = root->FirstChildElement( "Element" );
+ if ( element )
+ {
+ TiXmlElement* child = element->FirstChildElement( "Child" );
+ if ( child )
+ {
+ TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+ if ( child2 )
+ {
+ // Finally do something useful.
+ @endverbatim
+
+ And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
+ of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
+ and correct to use:
+
+ @verbatim
+ TiXmlHandle docHandle( &document );
+ TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+ if ( child2 )
+ {
+ // do something useful
+ @endverbatim
+
+ Which is MUCH more concise and useful.
+
+ It is also safe to copy handles - internally they are nothing more than node pointers.
+ @verbatim
+ TiXmlHandle handleCopy = handle;
+ @endverbatim
+
+ What they should not be used for is iteration:
+
+ @verbatim
+ int i=0;
+ while ( true )
+ {
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement();
+ if ( !child )
+ break;
+ // do something
+ ++i;
+ }
+ @endverbatim
+
+ It seems reasonable, but it is in fact two embedded while loops. The Child method is
+ a linear walk to find the element, so this code would iterate much more than it needs
+ to. Instead, prefer:
+
+ @verbatim
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement();
+
+ for( child; child; child=child->NextSiblingElement() )
+ {
+ // do something
+ }
+ @endverbatim
+*/
+class TiXmlHandle
+{
+public:
+ /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+ TiXmlHandle( TiXmlNode* _node ) { this->node = _node; }
+ /// Copy constructor
+ TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; }
+ TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
+
+ /// Return a handle to the first child node.
+ TiXmlHandle FirstChild() const;
+ /// Return a handle to the first child node with the given name.
+ TiXmlHandle FirstChild( const char * value ) const;
+ /// Return a handle to the first child element.
+ TiXmlHandle FirstChildElement() const;
+ /// Return a handle to the first child element with the given name.
+ TiXmlHandle FirstChildElement( const char * value ) const;
+
+ /** Return a handle to the "index" child with the given name.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( const char* value, int index ) const;
+ /** Return a handle to the "index" child.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( int index ) const;
+ /** Return a handle to the "index" child element with the given name.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( const char* value, int index ) const;
+ /** Return a handle to the "index" child element.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( int index ) const;
+
+ #ifdef TIXML_USE_STL
+ TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); }
+ TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); }
+
+ TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); }
+ TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); }
+ #endif
+
+ /** Return the handle as a TiXmlNode. This may return null.
+ */
+ TiXmlNode* ToNode() const { return node; }
+ /** Return the handle as a TiXmlElement. This may return null.
+ */
+ TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+ /** Return the handle as a TiXmlText. This may return null.
+ */
+ TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+ /** Return the handle as a TiXmlUnknown. This may return null.
+ */
+ TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+
+ /** @deprecated use ToNode.
+ Return the handle as a TiXmlNode. This may return null.
+ */
+ TiXmlNode* Node() const { return ToNode(); }
+ /** @deprecated use ToElement.
+ Return the handle as a TiXmlElement. This may return null.
+ */
+ TiXmlElement* Element() const { return ToElement(); }
+ /** @deprecated use ToText()
+ Return the handle as a TiXmlText. This may return null.
+ */
+ TiXmlText* Text() const { return ToText(); }
+ /** @deprecated use ToUnknown()
+ Return the handle as a TiXmlUnknown. This may return null.
+ */
+ TiXmlUnknown* Unknown() const { return ToUnknown(); }
+
+private:
+ TiXmlNode* node;
+};
+
+
+/** Print to memory functionality. The TiXmlPrinter is useful when you need to:
+
+ -# Print to memory (especially in non-STL mode)
+ -# Control formatting (line endings, etc.)
+
+ When constructed, the TiXmlPrinter is in its default "pretty printing" mode.
+ Before calling Accept() you can call methods to control the printing
+ of the XML document. After TiXmlNode::Accept() is called, the printed document can
+ be accessed via the CStr(), Str(), and Size() methods.
+
+ TiXmlPrinter uses the Visitor API.
+ @verbatim
+ TiXmlPrinter printer;
+ printer.SetIndent( "\t" );
+
+ doc.Accept( &printer );
+ fprintf( stdout, "%s", printer.CStr() );
+ @endverbatim
+*/
+class TiXmlPrinter : public TiXmlVisitor
+{
+public:
+ TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ),
+ buffer(), indent( " " ), lineBreak( "\n" ) {}
+
+ virtual bool VisitEnter( const TiXmlDocument& doc );
+ virtual bool VisitExit( const TiXmlDocument& doc );
+
+ virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
+ virtual bool VisitExit( const TiXmlElement& element );
+
+ virtual bool Visit( const TiXmlDeclaration& declaration );
+ virtual bool Visit( const TiXmlText& text );
+ virtual bool Visit( const TiXmlComment& comment );
+ virtual bool Visit( const TiXmlUnknown& unknown );
+
+ /** Set the indent characters for printing. By default 4 spaces
+ but tab (\t) is also useful, or null/empty string for no indentation.
+ */
+ void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; }
+ /// Query the indention string.
+ const char* Indent() { return indent.c_str(); }
+ /** Set the line breaking string. By default set to newline (\n).
+ Some operating systems prefer other characters, or can be
+ set to the null/empty string for no indenation.
+ */
+ void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; }
+ /// Query the current line breaking string.
+ const char* LineBreak() { return lineBreak.c_str(); }
+
+ /** Switch over to "stream printing" which is the most dense formatting without
+ linebreaks. Common when the XML is needed for network transmission.
+ */
+ void SetStreamPrinting() { indent = "";
+ lineBreak = "";
+ }
+ /// Return the result.
+ const char* CStr() { return buffer.c_str(); }
+ /// Return the length of the result string.
+ size_t Size() { return buffer.size(); }
+
+ #ifdef TIXML_USE_STL
+ /// Return the result.
+ const std::string& Str() { return buffer; }
+ #endif
+
+private:
+ void DoIndent() {
+ for( int i=0; i<depth; ++i )
+ buffer += indent;
+ }
+ void DoLineBreak() {
+ buffer += lineBreak;
+ }
+
+ int depth;
+ bool simpleTextPrint;
+ TIXML_STRING buffer;
+ TIXML_STRING indent;
+ TIXML_STRING lineBreak;
+};
+
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
+
diff --git a/src/thirdparty/ZenLib/TinyXml/tinyxmlerror.cpp b/src/thirdparty/ZenLib/TinyXml/tinyxmlerror.cpp
new file mode 100644
index 000000000..ff4148dd5
--- /dev/null
+++ b/src/thirdparty/ZenLib/TinyXml/tinyxmlerror.cpp
@@ -0,0 +1,55 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+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.
+*/
+
+#define TIXML_USE_STL
+
+#include "ZenLib/TinyXml/tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// english error messages, but the could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
+{
+ "No error",
+ "Error",
+ "Failed to open file",
+ "Memory allocation failed.",
+ "Error parsing Element.",
+ "Failed to read Element name",
+ "Error reading Element value.",
+ "Error reading Attributes.",
+ "Error: empty tag.",
+ "Error reading end tag.",
+ "Error parsing Unknown.",
+ "Error parsing Comment.",
+ "Error parsing Declaration.",
+ "Error document empty.",
+ "Error null (0) or unexpected EOF found in input stream.",
+ "Error parsing CDATA.",
+ "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
+};
diff --git a/src/thirdparty/ZenLib/TinyXml/tinyxmlparser.cpp b/src/thirdparty/ZenLib/TinyXml/tinyxmlparser.cpp
new file mode 100644
index 000000000..00a87fd1e
--- /dev/null
+++ b/src/thirdparty/ZenLib/TinyXml/tinyxmlparser.cpp
@@ -0,0 +1,1640 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+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.
+*/
+
+#define TIXML_USE_STL
+
+#include <ctype.h>
+#include <stddef.h>
+
+#include "ZenLib/TinyXml/tinyxml.h"
+
+//#define DEBUG_PARSER
+#if defined( DEBUG_PARSER )
+# if defined( DEBUG ) && defined( _MSC_VER )
+# include <windows.h>
+# define TIXML_LOG OutputDebugString
+# else
+# define TIXML_LOG printf
+# endif
+#endif
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.
+TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
+{
+ { "&amp;", 5, '&' },
+ { "&lt;", 4, '<' },
+ { "&gt;", 4, '>' },
+ { "&quot;", 6, '\"' },
+ { "&apos;", 6, '\'' }
+};
+
+// Bunch of unicode info at:
+// http://www.unicode.org/faq/utf_bom.html
+// Including the basic of this table, which determines the #bytes in the
+// sequence from the lead byte. 1 placed for invalid sequences --
+// although the result will be junk, pass it through as much as possible.
+// Beware of the non-characters in UTF-8:
+// ef bb bf (Microsoft "lead bytes")
+// ef bf be
+// ef bf bf
+
+const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+const int TiXmlBase::utf8ByteTable[256] =
+{
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
+ 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+
+
+void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
+{
+ const unsigned long BYTE_MASK = 0xBF;
+ const unsigned long BYTE_MARK = 0x80;
+ const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+ if (input < 0x80)
+ *length = 1;
+ else if ( input < 0x800 )
+ *length = 2;
+ else if ( input < 0x10000 )
+ *length = 3;
+ else if ( input < 0x200000 )
+ *length = 4;
+ else
+ { *length = 0; return; } // This code won't covert this correctly anyway.
+
+ output += *length;
+
+ // Scary scary fall throughs.
+ switch (*length)
+ {
+ case 4:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 3:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 2:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 1:
+ --output;
+ *output = (char)(input | FIRST_BYTE_MARK[*length]);
+ }
+}
+
+
+/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+// if ( encoding == TIXML_ENCODING_UTF8 )
+// {
+ if ( anyByte < 127 )
+ return isalpha( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+// }
+// else
+// {
+// return isalpha( anyByte );
+// }
+}
+
+
+/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+// if ( encoding == TIXML_ENCODING_UTF8 )
+// {
+ if ( anyByte < 127 )
+ return isalnum( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+// }
+// else
+// {
+// return isalnum( anyByte );
+// }
+}
+
+
+class TiXmlParsingData
+{
+ friend class TiXmlDocument;
+ public:
+ void Stamp( const char* now, TiXmlEncoding encoding );
+
+ const TiXmlCursor& Cursor() { return cursor; }
+
+ private:
+ // Only used by the document!
+ TiXmlParsingData( const char* start, int _tabsize, int row, int col )
+ {
+ assert( start );
+ stamp = start;
+ tabsize = _tabsize;
+ cursor.row = row;
+ cursor.col = col;
+ }
+
+ TiXmlCursor cursor;
+ const char* stamp;
+ int tabsize;
+};
+
+
+void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
+{
+ assert( now );
+
+ // Do nothing if the tabsize is 0.
+ if ( tabsize < 1 )
+ {
+ return;
+ }
+
+ // Get the current row, column.
+ int row = cursor.row;
+ int col = cursor.col;
+ const char* p = stamp;
+ assert( p );
+
+ while ( p < now )
+ {
+ // Treat p as unsigned, so we have a happy compiler.
+ const unsigned char* pU = (const unsigned char*)p;
+
+ // Code contributed by Fletcher Dunn: (modified by lee)
+ switch (*pU) {
+ case 0:
+ // We *should* never get here, but in case we do, don't
+ // advance past the terminating null character, ever
+ return;
+
+ case '\r':
+ // bump down to the next line
+ ++row;
+ col = 0;
+ // Eat the character
+ ++p;
+
+ // Check for \r\n sequence, and treat this as a single character
+ if (*p == '\n') {
+ ++p;
+ }
+ break;
+
+ case '\n':
+ // bump down to the next line
+ ++row;
+ col = 0;
+
+ // Eat the character
+ ++p;
+
+ // Check for \n\r sequence, and treat this as a single
+ // character. (Yes, this bizarre thing does occur still
+ // on some arcane platforms...)
+ if (*p == '\r') {
+ ++p;
+ }
+ break;
+
+ case '\t':
+ // Eat the character
+ ++p;
+
+ // Skip to next tab stop
+ col = (col / tabsize + 1) * tabsize;
+ break;
+
+ case TIXML_UTF_LEAD_0:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( *(p+1) && *(p+2) )
+ {
+ // In these cases, don't advance the column. These are
+ // 0-width spaces.
+ if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
+ p += 3;
+ else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
+ p += 3;
+ else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
+ p += 3;
+ else
+ { p +=3; ++col; } // A normal character.
+ }
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+
+ default:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // Eat the 1 to 4 byte utf8 character.
+ int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
+ if ( step == 0 )
+ step = 1; // Error case from bad encoding, but handle gracefully.
+ p += step;
+
+ // Just advance one column, of course.
+ ++col;
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+ }
+ }
+ cursor.row = row;
+ cursor.col = col;
+ assert( cursor.row >= -1 );
+ assert( cursor.col >= -1 );
+ stamp = p;
+ assert( stamp );
+}
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
+{
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ while ( *p )
+ {
+ const unsigned char* pU = (const unsigned char*)p;
+
+ // Skip the stupid Microsoft UTF-8 Byte order marks
+ if ( *(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==TIXML_UTF_LEAD_1
+ && *(pU+2)==TIXML_UTF_LEAD_2 )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==0xbfU
+ && *(pU+2)==0xbeU )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(pU+0)==TIXML_UTF_LEAD_0
+ && *(pU+1)==0xbfU
+ && *(pU+2)==0xbfU )
+ {
+ p += 3;
+ continue;
+ }
+
+ if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
+ ++p;
+ else
+ break;
+ }
+ }
+ else
+ {
+ while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )
+ ++p;
+ }
+
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
+{
+ for( ;; )
+ {
+ if ( !in->good() ) return false;
+
+ int c = in->peek();
+ // At this scope, we can't get to a document. So fail silently.
+ if ( !IsWhiteSpace( c ) || c <= 0 )
+ return true;
+
+ *tag += (char) in->get();
+ }
+}
+
+/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
+{
+ //assert( character > 0 && character < 128 ); // else it won't work in utf-8
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( c == character )
+ return true;
+ if ( c <= 0 ) // Silent failure: can't get document at this scope
+ return false;
+
+ in->get();
+ *tag += (char) c;
+ }
+ return false;
+}
+#endif
+
+// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The
+// "assign" optimization removes over 10% of the execution time.
+//
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
+{
+ // Oddly, not supported on some comilers,
+ //name->clear();
+ // So use this:
+ *name = "";
+ assert( p );
+
+ // Names start with letters or underscores.
+ // Of course, in unicode, tinyxml has no idea what a letter *is*. The
+ // algorithm is generous.
+ //
+ // After that, they can be letters, underscores, numbers,
+ // hyphens, or colons. (Colons are valid ony for namespaces,
+ // but tinyxml can't tell namespaces from names.)
+ if ( p && *p
+ && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
+ {
+ const char* start = p;
+ while( p && *p
+ && ( IsAlphaNum( (unsigned char ) *p, encoding )
+ || *p == '_'
+ || *p == '-'
+ || *p == '.'
+ || *p == ':' ) )
+ {
+ //(*name) += *p; // expensive
+ ++p;
+ }
+ if ( p-start > 0 ) {
+ name->assign( start, p-start );
+ }
+ return p;
+ }
+ return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
+{
+ // Presume an entity, and pull it out.
+ TIXML_STRING ent;
+ int i;
+ *length = 0;
+
+ if ( *(p+1) && *(p+1) == '#' && *(p+2) )
+ {
+ unsigned long ucs = 0;
+ ptrdiff_t delta = 0;
+ unsigned mult = 1;
+
+ if ( *(p+2) == 'x' )
+ {
+ // Hexadecimal.
+ if ( !*(p+3) ) return 0;
+
+ const char* q = p+3;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q ) return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != 'x' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else if ( *q >= 'a' && *q <= 'f' )
+ ucs += mult * (*q - 'a' + 10);
+ else if ( *q >= 'A' && *q <= 'F' )
+ ucs += mult * (*q - 'A' + 10 );
+ else
+ return 0;
+ mult *= 16;
+ --q;
+ }
+ }
+ else
+ {
+ // Decimal.
+ if ( !*(p+2) ) return 0;
+
+ const char* q = p+2;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q ) return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != '#' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else
+ return 0;
+ mult *= 10;
+ --q;
+ }
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // convert the UCS to UTF-8
+ ConvertUTF32ToUTF8( ucs, value, length );
+ }
+ else
+ {
+ *value = (char)ucs;
+ *length = 1;
+ }
+ return p + delta + 1;
+ }
+
+ // Now try to match it.
+ for( i=0; i<NUM_ENTITY; ++i )
+ {
+ if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+ {
+ assert( strlen( entity[i].str ) == entity[i].strLength );
+ *value = entity[i].chr;
+ *length = 1;
+ return ( p + entity[i].strLength );
+ }
+ }
+
+ // So it wasn't an entity, its unrecognized, or something like that.
+ *value = *p; // Don't put back the last one, since we return it!
+ //*length = 1; // Leave unrecognized entities - this doesn't really work.
+ // Just writes strange XML.
+ return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+ const char* tag,
+ bool ignoreCase,
+ TiXmlEncoding encoding )
+{
+ assert( p );
+ assert( tag );
+ if ( !p || !*p )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ const char* q = p;
+
+ if ( ignoreCase )
+ {
+ while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 )
+ return true;
+ }
+ else
+ {
+ while ( *q && *tag && *q == *tag )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
+ return true;
+ }
+ return false;
+}
+
+const char* TiXmlBase::ReadText( const char* p,
+ TIXML_STRING * text,
+ bool trimWhiteSpace,
+ const char* endTag,
+ bool caseInsensitive,
+ TiXmlEncoding encoding )
+{
+ *text = "";
+ if ( !trimWhiteSpace // certain tags always keep whitespace
+ || !condenseWhiteSpace ) // if true, whitespace is always kept
+ {
+ // Keep all the white space.
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding )
+ )
+ {
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ text->append( cArr, len );
+ }
+ }
+ else
+ {
+ bool whitespace = false;
+
+ // Remove leading white space:
+ p = SkipWhiteSpace( p, encoding );
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding ) )
+ {
+ if ( *p == '\r' || *p == '\n' )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else if ( IsWhiteSpace( *p ) )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else
+ {
+ // If we've found whitespace, add it before the
+ // new character. Any whitespace just becomes a space.
+ if ( whitespace )
+ {
+ (*text) += ' ';
+ whitespace = false;
+ }
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ if ( len == 1 )
+ (*text) += cArr[0]; // more efficient
+ else
+ text->append( cArr, len );
+ }
+ }
+ }
+ if ( p )
+ p += strlen( endTag );
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ // The basic issue with a document is that we don't know what we're
+ // streaming. Read something presumed to be a tag (and hope), then
+ // identify it, and call the appropriate stream method on the tag.
+ //
+ // This "pre-streaming" will never read the closing ">" so the
+ // sub-tag can orient itself.
+
+ if ( !StreamTo( in, '<', tag ) )
+ {
+ SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ while ( in->good() )
+ {
+ int tagIndex = (int) tag->length();
+ while ( in->good() && in->peek() != '>' )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ break;
+ }
+ (*tag) += (char) c;
+ }
+
+ if ( in->good() )
+ {
+ // We now have something we presume to be a node of
+ // some sort. Identify it, and call the node to
+ // continue streaming.
+ TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
+
+ if ( node )
+ {
+ node->StreamIn( in, tag );
+ bool isElement = node->ToElement() != 0;
+ delete node;
+ node = 0;
+
+ // If this is the root element, we're done. Parsing will be
+ // done by the >> operator.
+ if ( isElement )
+ {
+ return;
+ }
+ }
+ else
+ {
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ }
+ }
+ // We should have returned sooner.
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
+{
+ ClearError();
+
+ // Parse away, at the document level. Since a document
+ // contains nothing but other tags, most of what happens
+ // here is skipping white space.
+ if ( !p || !*p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ // Note that, for a document, this needs to come
+ // before the while space skip, so that parsing
+ // starts from the pointer we are given.
+ location.Clear();
+ if ( prevData )
+ {
+ location.row = prevData->cursor.row;
+ location.col = prevData->cursor.col;
+ }
+ else
+ {
+ location.row = 0;
+ location.col = 0;
+ }
+ TiXmlParsingData data( p, TabSize(), location.row, location.col );
+ location = data.Cursor();
+
+ if ( encoding == TIXML_ENCODING_UNKNOWN )
+ {
+ // Check for the Microsoft UTF-8 lead bytes.
+ const unsigned char* pU = (const unsigned char*)p;
+ if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
+ && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
+ && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
+ {
+ encoding = TIXML_ENCODING_UTF8;
+ useMicrosoftBOM = true;
+ }
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ while ( p && *p )
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, &data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ break;
+ }
+
+ // Did we get encoding info?
+ if ( encoding == TIXML_ENCODING_UNKNOWN
+ && node->ToDeclaration() )
+ {
+ TiXmlDeclaration* dec = node->ToDeclaration();
+ const char* enc = dec->Encoding();
+ assert( enc );
+
+ if ( *enc == 0 )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
+ else
+ encoding = TIXML_ENCODING_LEGACY;
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ // Was this empty?
+ if ( !firstChild ) {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
+ return 0;
+ }
+
+ // All is well.
+ return p;
+}
+
+void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ // The first error in a chain is more accurate - don't set again!
+ if ( error )
+ return;
+
+ assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+ error = true;
+ errorId = err;
+ errorDesc = errorString[ errorId ];
+
+ errorLocation.Clear();
+ if ( pError && data )
+ {
+ data->Stamp( pError, encoding );
+ errorLocation = data->Cursor();
+ }
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
+{
+ TiXmlNode* returnNode = 0;
+
+ p = SkipWhiteSpace( p, encoding );
+ if( !p || !*p || *p != '<' )
+ {
+ return 0;
+ }
+
+ TiXmlDocument* doc = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+
+ // What is this thing?
+ // - Elements start with a letter or underscore, but xml is reserved.
+ // - Comments: <!--
+ // - Decleration: <?xml
+ // - Everthing else is unknown to tinyxml.
+ //
+
+ const char* xmlHeader = { "<?xml" };
+ const char* commentHeader = { "<!--" };
+ const char* dtdHeader = { "<!" };
+ const char* cdataHeader = { "<![CDATA[" };
+
+ if ( StringEqual( p, xmlHeader, true, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Declaration\n" );
+ #endif
+ returnNode = new TiXmlDeclaration();
+ }
+ else if ( StringEqual( p, commentHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Comment\n" );
+ #endif
+ returnNode = new TiXmlComment();
+ }
+ else if ( StringEqual( p, cdataHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing CDATA\n" );
+ #endif
+ TiXmlText* text = new TiXmlText( "" );
+ text->SetCDATA( true );
+ returnNode = text;
+ }
+ else if ( StringEqual( p, dtdHeader, false, encoding ) )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(1)\n" );
+ #endif
+ returnNode = new TiXmlUnknown();
+ }
+ else if ( IsAlpha( *(p+1), encoding )
+ || *(p+1) == '_' )
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Element\n" );
+ #endif
+ returnNode = new TiXmlElement( "" );
+ }
+ else
+ {
+ #ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(2)\n" );
+ #endif
+ returnNode = new TiXmlUnknown();
+ }
+
+ if ( returnNode )
+ {
+ // Set the parent, so it can report errors
+ returnNode->parent = this;
+ }
+ else
+ {
+ if ( doc )
+ doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+ return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
+{
+ // We're called with some amount of pre-parsing. That is, some of "this"
+ // element is in "tag". Go ahead and stream to the closing ">"
+ while( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c ;
+
+ if ( c == '>' )
+ break;
+ }
+
+ if ( tag->length() < 3 ) return;
+
+ // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+ // If not, identify and stream.
+
+ if ( tag->at( tag->length() - 1 ) == '>'
+ && tag->at( tag->length() - 2 ) == '/' )
+ {
+ // All good!
+ return;
+ }
+ else if ( tag->at( tag->length() - 1 ) == '>' )
+ {
+ // There is more. Could be:
+ // text
+ // cdata text (which looks like another node)
+ // closing tag
+ // another node.
+ for ( ;; )
+ {
+ StreamWhiteSpace( in, tag );
+
+ // Do we have text?
+ if ( in->good() && in->peek() != '<' )
+ {
+ // Yep, text.
+ TiXmlText text( "" );
+ text.StreamIn( in, tag );
+
+ // What follows text is a closing tag or another node.
+ // Go around again and figure it out.
+ continue;
+ }
+
+ // We now have either a closing tag...or another node.
+ // We should be at a "<", regardless.
+ if ( !in->good() ) return;
+ assert( in->peek() == '<' );
+ int tagIndex = (int) tag->length();
+
+ bool closingTag = false;
+ bool firstCharFound = false;
+
+ for( ;; )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->peek();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ if ( c == '>' )
+ break;
+
+ *tag += (char) c;
+ in->get();
+
+ // Early out if we find the CDATA id.
+ if ( c == '[' && tag->size() >= 9 )
+ {
+ size_t len = tag->size();
+ const char* start = tag->c_str() + len - 9;
+ if ( strcmp( start, "<![CDATA[" ) == 0 ) {
+ assert( !closingTag );
+ break;
+ }
+ }
+
+ if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+ {
+ firstCharFound = true;
+ if ( c == '/' )
+ closingTag = true;
+ }
+ }
+ // If it was a closing tag, then read in the closing '>' to clean up the input stream.
+ // If it was not, the streaming will be done by the tag.
+ if ( closingTag )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ assert( c == '>' );
+ *tag += (char) c;
+
+ // We are done, once we've found our closing tag.
+ return;
+ }
+ else
+ {
+ // If not a closing tag, id it, and stream.
+ const char* tagloc = tag->c_str() + tagIndex;
+ TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
+ if ( !node )
+ return;
+ node->StreamIn( in, tag );
+ delete node;
+ node = 0;
+
+ // No return: go around from the beginning: text, closing tag, or node.
+ }
+ }
+ }
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ TiXmlDocument* document = GetDocument();
+
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
+ return 0;
+ }
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ if ( *p != '<' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
+ return 0;
+ }
+
+ p = SkipWhiteSpace( p+1, encoding );
+
+ // Read the name.
+ const char* pErr = p;
+
+ p = ReadName( p, &value, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
+ return 0;
+ }
+
+ TIXML_STRING endTag ("</");
+ endTag += value;
+ endTag += ">";
+
+ // Check for and read attributes. Also look for an empty
+ // tag or an end tag.
+ while ( p && *p )
+ {
+ pErr = p;
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ if ( *p == '/' )
+ {
+ ++p;
+ // Empty tag.
+ if ( *p != '>' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
+ return 0;
+ }
+ return (p+1);
+ }
+ else if ( *p == '>' )
+ {
+ // Done with attributes (if there were any.)
+ // Read the value -- which can include other
+ // elements -- read the end tag, and return.
+ ++p;
+ p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
+ if ( !p || !*p ) {
+ // We were looking for the end tag, but found nothing.
+ // Fix for [ 1663758 ] Failure to report error on bad XML
+ if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+
+ // We should find the end tag now
+ if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+ {
+ p += endTag.length();
+ return p;
+ }
+ else
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+ }
+ else
+ {
+ // Try to read an attribute:
+ TiXmlAttribute* attrib = new TiXmlAttribute();
+ if ( !attrib )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
+ return 0;
+ }
+
+ attrib->SetDocument( document );
+ pErr = p;
+ p = attrib->Parse( p, data, encoding );
+
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+ delete attrib;
+ return 0;
+ }
+
+ // Handle the strange case of double attributes:
+ #ifdef TIXML_USE_STL
+ TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
+ #else
+ TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
+ #endif
+ if ( node )
+ {
+ node->SetValue( attrib->Value() );
+ delete attrib;
+ return 0;
+ }
+
+ attributeSet.Add( attrib );
+ }
+ }
+ return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+
+ // Read in text and elements in any order.
+ const char* pWithWhiteSpace = p;
+ p = SkipWhiteSpace( p, encoding );
+
+ while ( p && *p )
+ {
+ if ( *p != '<' )
+ {
+ // Take what we have, make a text element.
+ TiXmlText* textNode = new TiXmlText( "" );
+
+ if ( !textNode )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
+ return 0;
+ }
+
+ if ( TiXmlBase::IsWhiteSpaceCondensed() )
+ {
+ p = textNode->Parse( p, data, encoding );
+ }
+ else
+ {
+ // Special case: we want to keep the white space
+ // so that leading spaces aren't removed.
+ p = textNode->Parse( pWithWhiteSpace, data, encoding );
+ }
+
+ if ( !textNode->Blank() )
+ LinkEndChild( textNode );
+ else
+ delete textNode;
+ }
+ else
+ {
+ // We hit a '<'
+ // Have we hit a new element or an end tag? This could also be
+ // a TiXmlText in the "CDATA" style.
+ if ( StringEqual( p, "</", false, encoding ) )
+ {
+ return p;
+ }
+ else
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ pWithWhiteSpace = p;
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ if ( !p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
+ }
+ return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ if ( !p || !*p || *p != '<' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
+ return 0;
+ }
+ ++p;
+ value = "";
+
+ while ( p && *p && *p != '>' )
+ {
+ value += *p;
+ ++p;
+ }
+
+ if ( !p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
+ }
+ if ( *p == '>' )
+ return p+1;
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+
+ if ( c == '>'
+ && tag->at( tag->length() - 2 ) == '-'
+ && tag->at( tag->length() - 3 ) == '-' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ value = "";
+
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ const char* startTag = "<!--";
+ const char* endTag = "-->";
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+
+ // [ 1475201 ] TinyXML parses entities in comments
+ // Oops - ReadText doesn't work, because we don't want to parse the entities.
+ // p = ReadText( p, &value, false, endTag, false, encoding );
+ //
+ // from the XML spec:
+ /*
+ [Definition: Comments may appear anywhere in a document outside other markup; in addition,
+ they may appear within the document type declaration at places allowed by the grammar.
+ They are not part of the document's character data; an XML processor MAY, but need not,
+ make it possible for an application to retrieve the text of comments. For compatibility,
+ the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity
+ references MUST NOT be recognized within comments.
+
+ An example of a comment:
+
+ <!-- declarations for <head> & <body> -->
+ */
+
+ value = "";
+ // Keep all the white space.
+ while ( p && *p && !StringEqual( p, endTag, false, encoding ) )
+ {
+ value.append( p, 1 );
+ ++p;
+ }
+ if ( p )
+ p += strlen( endTag );
+
+ return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p ) return 0;
+
+// int tabsize = 4;
+// if ( document )
+// tabsize = document->TabSize();
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ // Read the name, the '=' and the value.
+ const char* pErr = p;
+ p = ReadName( p, &name, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p || *p != '=' )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ ++p; // skip '='
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ const char* end;
+ const char SINGLE_QUOTE = '\'';
+ const char DOUBLE_QUOTE = '\"';
+
+ if ( *p == SINGLE_QUOTE )
+ {
+ ++p;
+ end = "\'"; // single quote in string
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else if ( *p == DOUBLE_QUOTE )
+ {
+ ++p;
+ end = "\""; // double quote in string
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else
+ {
+ // All attribute values should be in single or double quotes.
+ // But this is such a common error that the parser will try
+ // its best, even without them.
+ value = "";
+ while ( p && *p // existence
+ && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
+ && *p != '/' && *p != '>' ) // tag end
+ {
+ if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
+ // [ 1451649 ] Attribute values with trailing quotes not handled correctly
+ // We did not have an opening quote but seem to have a
+ // closing one. Give up and throw an error.
+ if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+ value += *p;
+ ++p;
+ }
+ }
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( !cdata && (c == '<' ) )
+ {
+ return;
+ }
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+ in->get(); // "commits" the peek made above
+
+ if ( cdata && c == '>' && tag->size() >= 3 ) {
+ size_t len = tag->size();
+ if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
+ // terminator of cdata.
+ return;
+ }
+ }
+ }
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ value = "";
+ TiXmlDocument* document = GetDocument();
+
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ const char* const startTag = "<![CDATA[";
+ const char* const endTag = "]]>";
+
+ if ( cdata || StringEqual( p, startTag, false, encoding ) )
+ {
+ cdata = true;
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+
+ // Keep all the white space, ignore the encoding, etc.
+ while ( p && *p
+ && !StringEqual( p, endTag, false, encoding )
+ )
+ {
+ value += *p;
+ ++p;
+ }
+
+ TIXML_STRING dummy;
+ p = ReadText( p, &dummy, false, endTag, false, encoding );
+ return p;
+ }
+ else
+ {
+ bool ignoreWhite = true;
+
+ const char* end = "<";
+ p = ReadText( p, &value, ignoreWhite, end, false, encoding );
+ if ( p )
+ return p-1; // don't truncate the '<'
+ return 0;
+ }
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+ p = SkipWhiteSpace( p, _encoding );
+ // Find the beginning, find the end, and look for
+ // the stuff in-between.
+ TiXmlDocument* document = GetDocument();
+ if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
+ {
+ if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+ return 0;
+ }
+ if ( data )
+ {
+ data->Stamp( p, _encoding );
+ location = data->Cursor();
+ }
+ p += 5;
+
+ version = "";
+ encoding = "";
+ standalone = "";
+
+ while ( p && *p )
+ {
+ if ( *p == '>' )
+ {
+ ++p;
+ return p;
+ }
+
+ p = SkipWhiteSpace( p, _encoding );
+ if ( StringEqual( p, "version", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ version = attrib.Value();
+ }
+ else if ( StringEqual( p, "encoding", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ encoding = attrib.Value();
+ }
+ else if ( StringEqual( p, "standalone", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ standalone = attrib.Value();
+ }
+ else
+ {
+ // Read over whatever it is.
+ while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+ ++p;
+ }
+ }
+ return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+ for ( unsigned i=0; i<value.length(); i++ )
+ if ( !IsWhiteSpace( value[i] ) )
+ return false;
+ return true;
+}
+
diff --git a/src/thirdparty/ZenLib/Trace.h b/src/thirdparty/ZenLib/Trace.h
new file mode 100644
index 000000000..556b03b79
--- /dev/null
+++ b/src/thirdparty/ZenLib/Trace.h
@@ -0,0 +1,77 @@
+// ZenLib::Trace - To trace (in files)
+// Copyright (C) 2006-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Trace
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Provide a direct to file trace
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenTraceH
+#define ZenTraceH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include <fstream>
+#include "ZenLib/Ztring.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+
+static std::FILE* Trace_F;
+static ZenLib::Ztring Trace;
+static ZenLib::Ztring Trace2;
+
+#ifdef TRACE
+ #undef TRACE
+#endif //TRACE
+
+#if 1
+#define TRACE(_TOAPPEND)
+#else
+#define TRACE(_TOAPPEND) \
+Trace.clear(); \
+Trace2.clear(); \
+_TOAPPEND; \
+if (!Trace2.empty()) \
+{ \
+ Trace+=_T(" - "); \
+ Trace+=Trace2; \
+} \
+Trace+=_T("\r\n"); \
+Trace_F=std::fopen("Trace.txt", "a+t"); \
+std::fwrite(Trace.To_Local().c_str(), Trace.size(), 1, Trace_F); \
+std::fclose(Trace_F);
+#endif
+
+//***************************************************************************
+
+
+} //NameSpace
+
+#endif // ZenTraceH
+
+
diff --git a/src/thirdparty/ZenLib/Translation.cpp b/src/thirdparty/ZenLib/Translation.cpp
new file mode 100644
index 000000000..0d62efc20
--- /dev/null
+++ b/src/thirdparty/ZenLib/Translation.cpp
@@ -0,0 +1,169 @@
+// ZenLib::Translation - Helper for translation
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifdef ZENLIB_USEWX
+ #include <wx/strconv.h>
+#endif //ZENLIB_USEWX
+#include <algorithm>
+#include "ZenLib/Translation.h"
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Constructors/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Constructors
+Translation::Translation()
+: std::map<ZenLib::Ztring, ZenLib::Ztring> ()
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+}
+
+Translation::Translation(const Ztring &Source)
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Write(Source);
+}
+
+Translation::Translation(const Char *Source)
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Write(Source);
+}
+
+#ifdef _UNICODE
+Translation::Translation (const char* S)
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Write(Ztring(S));
+}
+#endif
+
+//***************************************************************************
+// In/Out
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Get
+Ztring Translation::Get () const
+{
+ Ztring ToReturn;
+ const_iterator Temp=begin();
+ while (Temp!=end())
+ {
+ ToReturn+=Temp->first;
+ ToReturn+=Separator[1];
+ ToReturn+=Temp->second;
+ ToReturn+=Separator[0];
+ Temp++;
+ }
+ return ToReturn;
+}
+
+const Ztring &Translation::Get (const Ztring &Value)
+{
+ iterator Pos=find(Value);
+ if (Pos==end())
+ operator[](Value)=Value;
+ return operator[](Value);
+}
+
+Ztring Translation::Get (const Ztring &Value, const Ztring &Default)
+{
+ iterator Pos=find(Value);
+ if (Pos==end())
+ operator[](Value)=Default;
+ return operator[](Value);
+}
+
+//---------------------------------------------------------------------------
+// Set
+void Translation::Write(const Ztring &NewLanguage)
+{
+ clear();
+
+ if (!&NewLanguage || !NewLanguage.size())
+ return;
+
+ size_t Pos1=0, Pos2_EOL=0, Pos2_Separator=0;
+
+ while (Pos2_EOL!=(size_t)-1)
+ {
+ Pos2_EOL=NewLanguage.find(_T('\n'), Pos1);
+ Pos2_Separator=NewLanguage.find(_T(';'), Pos1);
+ if (Pos2_Separator<Pos2_EOL)
+ {
+ operator[](NewLanguage.substr(Pos1, Pos2_Separator-Pos1))=NewLanguage.substr(Pos2_Separator+1, Pos2_EOL-Pos2_Separator-1);
+ }
+ Pos1=Pos2_EOL+1;
+ }
+}
+
+//---------------------------------------------------------------------------
+// Set
+void Translation::Write(const Ztring &Value, const Ztring &NewLanguage)
+{
+ operator[](Value)=NewLanguage;
+}
+
+//***************************************************************************
+// Configuration
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Separator
+void Translation::Separator_Set (size_type Level, const Ztring &NewSeparator)
+{
+ if (Level>1)
+ return;
+
+ Separator[Level]=NewSeparator;
+}
+
+//***************************************************************************
+// C++
+//***************************************************************************
+
+} //namespace
+
+
+
+
+
+
+
+
diff --git a/src/thirdparty/ZenLib/Translation.h b/src/thirdparty/ZenLib/Translation.h
new file mode 100644
index 000000000..a943e9a71
--- /dev/null
+++ b/src/thirdparty/ZenLib/Translation.h
@@ -0,0 +1,79 @@
+// ZenLib::Translation - Helper for translation
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+//
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_TranslationH
+#define ZenLib_TranslationH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Ztring.h"
+#include <map>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Helper for translation
+//***************************************************************************
+
+class Translation : public std::map<Ztring, Ztring>
+{
+public :
+ //Constructors/Destructor
+ Translation ();
+ Translation (const Ztring &Source);
+ Translation (const Char *Source);
+ #ifdef _UNICODE
+ Translation (const char *Source); //convert a UTF-8 string into Unicode
+ #endif
+
+ //In/Out
+ Ztring Get () const;
+ const Ztring &Get (const Ztring &Value);
+ Ztring Get (const Ztring &Count, const Ztring &Value);
+ void Write (const Ztring &NewLanguage); //All language in one
+ void Write (const Ztring &Value, const Ztring &NewLanguage); //Per item
+
+ //Configuration
+ /// @brief Set the Separator character
+ void Separator_Set (size_type Level, const Ztring &NewSeparator);
+ /// @brief Set the Quote character
+ /// During Read() or Write() method, if Separator is in the sequence, we must quote it
+ void Quote_Set (const Ztring &NewQuote);
+ /// @brief Set the Maximum number of element to read
+ /// During Read() or Write() method, if there is more elements, merge them with the last element
+ void Max_Set (size_type Level, size_type Max);
+
+protected :
+ Ztring Separator[2];
+ Ztring Quote;
+ size_type Max[2];
+};
+
+} //namespace
+#endif
+
diff --git a/src/thirdparty/ZenLib/Utils.cpp b/src/thirdparty/ZenLib/Utils.cpp
new file mode 100644
index 000000000..9190d651a
--- /dev/null
+++ b/src/thirdparty/ZenLib/Utils.cpp
@@ -0,0 +1,921 @@
+// ZenLib::Utils - Very small utilities
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/Utils.h"
+#include <complex>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Transformations - Little Endian to something
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Little Endian - 8 bits
+int8s LittleEndian2int8s (const char* Liste)
+{
+ return (int8s)Liste[0];
+}
+
+int8u LittleEndian2int8u (const char* Liste)
+{
+ return (int8u)Liste[0];
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 16 bits
+int16s LittleEndian2int16s (const char* Liste)
+{
+ int16s Retour= (int8s)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int16u LittleEndian2int16u (const char* Liste)
+{
+ int16u Retour= (int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 24 bits
+int32s LittleEndian2int24s (const char* Liste)
+{
+ int32s Retour= (int8s)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int32u LittleEndian2int24u (const char* Liste)
+{
+ int32u Retour= (int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 32 bits
+int32s LittleEndian2int32s (const char* Liste)
+{
+ int32s Retour= (int8s)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int32u LittleEndian2int32u (const char* Liste)
+{
+ int32u Retour= (int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 40 bits
+int64s LittleEndian2int40s (const char* Liste)
+{
+ int64s Retour= (int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int64u LittleEndian2int40u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 48 bits
+int64s LittleEndian2int48s (const char* Liste)
+{
+ int64s Retour= (int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int64u LittleEndian2int48u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 56 bits
+int64s LittleEndian2int56s (const char* Liste)
+{
+ int64s Retour= (int8u)Liste[6];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int64u LittleEndian2int56u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[6];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 64 bits
+int64s LittleEndian2int64s (const char* Liste)
+{
+ int64s Retour= (int8s)Liste[7];
+ Retour=(Retour<<8)|(int8u)Liste[6];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+int64u LittleEndian2int64u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[7];
+ Retour=(Retour<<8)|(int8u)Liste[6];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[0];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 128 bits
+int128u LittleEndian2int128u(const char* Liste)
+{
+ int128u Retour;
+ Retour.lo=LittleEndian2int64u(Liste);
+ Retour.hi=LittleEndian2int64u(Liste+8);
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - float 32 bits
+float32 LittleEndian2float32(const char*)
+{
+ return 0.0; //Does it exist?
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - float 64 bits
+float64 LittleEndian2float64(const char*)
+{
+ return 0.0; //Does it exist?
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - float 80 bits
+float80 LittleEndian2float80(const char*)
+{
+ return 0.0; //Does it exist?
+}
+
+//***************************************************************************
+// Transformations - Something to Little Endian
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Little Endian - 8 bits
+void int8s2LittleEndian (char* List, int8s Value)
+{
+ List[0]=(char)Value;
+}
+
+void int8u2LittleEndian (char* List, int8u Value)
+{
+ List[0]=(char)Value;
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 16 bits
+void int16s2LittleEndian (char* List, int16s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+}
+
+void int16u2LittleEndian (char* List, int16u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 24 bits
+void int24s2LittleEndian (char* List, int32s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+}
+
+void int24u2LittleEndian (char* List, int32u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 32 bits
+void int32s2LittleEndian (char* List, int32s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+}
+
+void int32u2LittleEndian (char* List, int32u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 40 bits
+void int40s2LittleEndian (char* List, int64s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+}
+
+void int40u2LittleEndian (char* List, int64u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 48 bits
+void int48s2LittleEndian (char* List, int64s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+ List[5]=(char)(Value>>40);
+}
+
+void int48u2LittleEndian (char* List, int64u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+ List[5]=(char)(Value>>40);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 56 bits
+void int56s2LittleEndian (char* List, int64s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+ List[5]=(char)(Value>>40);
+ List[6]=(char)(Value>>48);
+}
+
+void int56u2LittleEndian (char* List, int64u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+ List[5]=(char)(Value>>40);
+ List[6]=(char)(Value>>48);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 64 bits
+void int64s2LittleEndian (char* List, int64s Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+ List[5]=(char)(Value>>40);
+ List[6]=(char)(Value>>48);
+ List[7]=(char)(Value>>56);
+}
+
+void int64u2LittleEndian (char* List, int64u Value)
+{
+ List[0]=(char) Value;
+ List[1]=(char)(Value>> 8);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>32);
+ List[5]=(char)(Value>>40);
+ List[6]=(char)(Value>>48);
+ List[7]=(char)(Value>>56);
+}
+
+//---------------------------------------------------------------------------
+// Little Endian - 128 bits
+void int128u2LittleEndian(char* List, int128u Value)
+{
+ int64u2LittleEndian(List+8, Value.lo);
+ int64u2LittleEndian(List , Value.hi);
+}
+
+//***************************************************************************
+// Transformations - Big Endian to something
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Big Endian - 8 bits
+int8s BigEndian2int8s (const char* Liste)
+{
+ return (int8s)Liste[0];
+}
+
+int8u BigEndian2int8u (const char* Liste)
+{
+ return (int8u)Liste[0];
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 16 bits
+int16s BigEndian2int16s (const char* Liste)
+{
+ int16s Retour= (int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ return Retour;
+}
+
+int16u BigEndian2int16u (const char* Liste)
+{
+ int16u Retour= (int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 24 bits
+int32s BigEndian2int24s (const char* Liste)
+{
+ int32s Retour= (int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ return Retour;
+}
+
+int32u BigEndian2int24u (const char* Liste)
+{
+ int32u Retour= (int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 32 bits
+int32s BigEndian2int32s (const char* Liste)
+{
+ int32s Retour= (int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ return Retour;
+}
+
+int32u BigEndian2int32u (const char* Liste)
+{
+ int32u Retour= (int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 40 bits
+int64s BigEndian2int40s (const char* Liste)
+{
+ int64s Retour= (int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ return Retour;
+}
+
+int64u BigEndian2int40u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 48 bits
+int64s BigEndian2int48s (const char* Liste)
+{
+ int64s Retour= (int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ return Retour;
+}
+
+int64u BigEndian2int48u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 56 bits
+int64s BigEndian2int56s (const char* Liste)
+{
+ int64s Retour= (int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[6];
+ return Retour;
+}
+
+int64u BigEndian2int56u (const char* Liste)
+{
+ int64u Retour= (int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[6];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 64 bits
+int64s BigEndian2int64s (const char* Liste)
+{
+ int64s Retour=(int8s)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[6];
+ Retour=(Retour<<8)|(int8u)Liste[7];
+ return Retour;
+}
+
+int64u BigEndian2int64u (const char* Liste)
+{
+ int64u Retour=(int8u)Liste[0];
+ Retour=(Retour<<8)|(int8u)Liste[1];
+ Retour=(Retour<<8)|(int8u)Liste[2];
+ Retour=(Retour<<8)|(int8u)Liste[3];
+ Retour=(Retour<<8)|(int8u)Liste[4];
+ Retour=(Retour<<8)|(int8u)Liste[5];
+ Retour=(Retour<<8)|(int8u)Liste[6];
+ Retour=(Retour<<8)|(int8u)Liste[7];
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 128 bits
+int128u BigEndian2int128u(const char* Liste)
+{
+ int128u Retour;
+ Retour.hi=BigEndian2int64u(Liste);
+ Retour.lo=BigEndian2int64u(Liste+8);
+ return Retour;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - float 32 bits
+float32 BigEndian2float32(const char* Liste)
+{
+ //sign 1 bit
+ //exponent 8 bit
+ //significand 23 bit
+
+ //Retrieving data
+ int32u Integer=BigEndian2int32u(Liste);
+
+ //Retrieving elements
+ bool Sign =(Integer&0x80000000)?true:false;
+ int32u Exponent=(Integer>>23)&0xFF;
+ int32u Mantissa= Integer&0x007FFFFF;
+
+ //Some computing
+ if (Exponent==0 || Exponent==0xFF)
+ return 0; //These are denormalised numbers, NANs, and other horrible things
+ Exponent-=0x7F; //Bias
+ float64 Answer=(((float64)Mantissa)/8388608+1.0)*std::pow((float64)2, (int)Exponent); //(1+Mantissa) * 2^Exponent
+ if (Sign)
+ Answer=-Answer;
+
+ return (float32)Answer;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - float 64 bits
+float64 BigEndian2float64(const char* Liste)
+{
+ //sign 1 bit
+ //exponent 11 bit
+ //significand 52 bit
+
+ //Retrieving data
+ int64u Integer=BigEndian2int64u(Liste);
+
+ //Retrieving elements
+ bool Sign =(Integer&0x8000000000000000LL)?true:false;
+ int64u Exponent=(Integer>>52)&0x7FF;
+ int64u Mantissa= Integer&0xFFFFFFFFFFFFFLL;
+
+ //Some computing
+ if (Exponent==0 || Exponent==0x7FF)
+ return 0; //These are denormalised numbers, NANs, and other horrible things
+ Exponent-=0x3FF; //Bias
+ float64 Answer=(((float64)Mantissa)/4503599627370496.0+1.0)*std::pow((float64)2, (int)Exponent); //(1+Mantissa) * 2^Exponent
+ if (Sign)
+ Answer=-Answer;
+
+ return (float32)Answer;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - float 80 bits
+float80 BigEndian2float80(const char* Liste)
+{
+ //sign 1 bit
+ //exponent 15 bit
+ //integer? 1 bit
+ //significand 63 bit
+
+ //Retrieving data
+ int16u Integer1=BigEndian2int16u(Liste);
+ int64u Integer2=BigEndian2int64u(Liste+2);
+
+ //Retrieving elements
+ bool Sign =(Integer1&0x8000)?true:false;
+ int16u Exponent= Integer1&0x7FFF;
+ int64u Mantissa= Integer2&0x7FFFFFFFFFFFFFFFLL; //Only 63 bits, 1 most significant bit is explicit
+ //Some computing
+ if (Exponent==0 || Exponent==0x7FFF)
+ return 0; //These are denormalised numbers, NANs, and other horrible things
+ Exponent-=0x3FFF; //Bias
+ float80 Answer=(((float80)Mantissa)/9223372036854775808.0+1.0)*std::pow((float80)2, (int)Exponent); //(1+Mantissa) * 2^Exponent
+ if (Sign)
+ Answer=-Answer;
+
+ return (float80)Answer;
+}
+
+//***************************************************************************
+// Transformations - Something to Big Endian
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Big Endian - 8 bits
+void int8s2BigEndian (char* List, int8s Value)
+{
+ List[0]=(char)Value;
+}
+
+void int8u2BigEndian (char* List, int8u Value)
+{
+ List[0]=(char)Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 16 bits
+void int16s2BigEndian (char* List, int16s Value)
+{
+ List[0]=(char)(Value>> 8);
+ List[1]=(char) Value;
+}
+
+void int16u2BigEndian (char* List, int16u Value)
+{
+ List[0]=(char)(Value>> 8);
+ List[1]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 24 bits
+void int24s2BigEndian (char* List, int32s Value)
+{
+ List[0]=(char)(Value>>16);
+ List[1]=(char)(Value>> 8);
+ List[2]=(char) Value;
+}
+
+void int24u2BigEndian (char* List, int32u Value)
+{
+ List[0]=(char)(Value>>16);
+ List[1]=(char)(Value>> 8);
+ List[2]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 32 bits
+void int32s2BigEndian (char* List, int32s Value)
+{
+ List[0]=(char)(Value>>24);
+ List[1]=(char)(Value>>16);
+ List[2]=(char)(Value>> 8);
+ List[3]=(char) Value;
+}
+
+void int32u2BigEndian (char* List, int32u Value)
+{
+ List[0]=(char)(Value>>24);
+ List[1]=(char)(Value>>16);
+ List[2]=(char)(Value>> 8);
+ List[3]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 40 bits
+void int40s2BigEndian (char* List, int64s Value)
+{
+ List[0]=(char)(Value>>32);
+ List[1]=(char)(Value>>24);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>> 8);
+ List[4]=(char) Value;
+}
+
+void int40u2BigEndian (char* List, int64u Value)
+{
+ List[0]=(char)(Value>>32);
+ List[1]=(char)(Value>>24);
+ List[2]=(char)(Value>>16);
+ List[3]=(char)(Value>> 8);
+ List[4]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 48 bits
+void int48s2BigEndian (char* List, int64s Value)
+{
+ List[0]=(char)(Value>>40);
+ List[1]=(char)(Value>>32);
+ List[2]=(char)(Value>>24);
+ List[3]=(char)(Value>>16);
+ List[4]=(char)(Value>> 8);
+ List[5]=(char) Value;
+}
+
+void int48u2BigEndian (char* List, int64u Value)
+{
+ List[0]=(char)(Value>>40);
+ List[1]=(char)(Value>>32);
+ List[2]=(char)(Value>>24);
+ List[3]=(char)(Value>>16);
+ List[4]=(char)(Value>> 8);
+ List[5]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 56 bits
+void int56s2BigEndian (char* List, int64s Value)
+{
+ List[0]=(char)(Value>>48);
+ List[1]=(char)(Value>>40);
+ List[2]=(char)(Value>>32);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>16);
+ List[5]=(char)(Value>> 8);
+ List[6]=(char) Value;
+}
+
+void int56u2BigEndian (char* List, int64u Value)
+{
+ List[0]=(char)(Value>>48);
+ List[1]=(char)(Value>>40);
+ List[2]=(char)(Value>>32);
+ List[3]=(char)(Value>>24);
+ List[4]=(char)(Value>>16);
+ List[5]=(char)(Value>> 8);
+ List[6]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 64 bits
+void int64s2BigEndian (char* List, int64s Value)
+{
+ List[0]=(char)(Value>>56);
+ List[1]=(char)(Value>>48);
+ List[2]=(char)(Value>>40);
+ List[3]=(char)(Value>>32);
+ List[4]=(char)(Value>>24);
+ List[5]=(char)(Value>>16);
+ List[6]=(char)(Value>> 8);
+ List[7]=(char) Value;
+}
+
+void int64u2BigEndian (char* List, int64u Value)
+{
+ List[0]=(char)(Value>>56);
+ List[1]=(char)(Value>>48);
+ List[2]=(char)(Value>>40);
+ List[3]=(char)(Value>>32);
+ List[4]=(char)(Value>>24);
+ List[5]=(char)(Value>>16);
+ List[6]=(char)(Value>> 8);
+ List[7]=(char) Value;
+}
+
+//---------------------------------------------------------------------------
+// Big Endian - 128 bits
+void int128u2BigEndian(char* List, int128u Value)
+{
+ int64u2BigEndian(List, Value.hi);
+ int64u2BigEndian(List+8, Value.lo);
+}
+
+//***************************************************************************
+// Int to Int
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// int32 - int64
+int64s int32s_int64s ( int32s High, int32u Low)
+{
+ return ((((int64s)High)<<32) | Low);
+}
+
+int64u int32u_int64u ( int32u High, int32u Low)
+{
+ return ((((int64s)High)<<32) | Low);
+}
+
+void int32s_int64s (int64s &BigInt, int32s High, int32u Low)
+{
+ BigInt= ((((int64s)High)<<32) | Low);
+}
+void int32u_int64u (int64s &BigInt, int32u High, int32u Low)
+{
+ BigInt= ((((int64s)High)<<32) | Low);
+}
+
+void int64s_int32s (int64s BigInt, int32s &High, int32u &Low)
+{
+ High = (int32s) ((BigInt & 0xFFFFFFFF00000000LL)>>32);
+ Low = (int32u) ( BigInt & 0x00000000FFFFFFFF);
+}
+
+void int64u_int32u (int64u BigInt, int32u &High, int32u &Low)
+{
+ High = (int32u) ((BigInt & 0xFFFFFFFF00000000LL)>>32);
+ Low = (int32u) ( BigInt & 0x00000000FFFFFFFF);
+}
+
+//---------------------------------------------------------------------------
+// Floats and ints
+int32s float32_int32s (float32 F, bool Rounded)
+{
+ //Not rounded
+ if (!Rounded)
+ return (int32s)F;
+ //Rounded
+ int I1=(int)F;
+ if (F-I1>=0.5)
+ return I1+1;
+ else
+ return I1;
+}
+
+int64s float32_int64s (float32 F, bool Rounded)
+{
+ //Not rounded
+ if (!Rounded)
+ return (int64s)F;
+ //Rounded
+ int I1=(int)F;
+ if (F-I1>=0.5)
+ return I1+1;
+ else
+ return I1;
+}
+
+int32s float64_int32s (float64 F, bool Rounded)
+{
+ //Not rounded
+ if (!Rounded)
+ return (int32s)F;
+ //Rounded
+ int32s I1=(int32s)F;
+ if (F-I1>=0.5)
+ return I1+1;
+ else
+ return I1;
+}
+
+int64s float64_int64s (float64 F, bool Rounded)
+{
+ //Not rounded
+ if (!Rounded)
+ return (int64s)F;
+ //Rounded
+ int64s I1=(int64s)F;
+ if (F-I1>=0.5)
+ return I1+1;
+ else
+ return I1;
+}
+
+} //namespace ZenLib
+
+
diff --git a/src/thirdparty/ZenLib/Utils.h b/src/thirdparty/ZenLib/Utils.h
new file mode 100644
index 000000000..2abcef139
--- /dev/null
+++ b/src/thirdparty/ZenLib/Utils.h
@@ -0,0 +1,318 @@
+// ZenLib::Utils - Very small utilities
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Integer and float manipulation
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenUtilsH
+#define ZenUtilsH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/int128u.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+// Integer transformations
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Little Endians
+int8s LittleEndian2int8s (const char* List);
+int8u LittleEndian2int8u (const char* List);
+int16s LittleEndian2int16s (const char* List);
+int16u LittleEndian2int16u (const char* List);
+int32s LittleEndian2int24s (const char* List);
+int32u LittleEndian2int24u (const char* List);
+int32s LittleEndian2int32s (const char* List);
+int32u LittleEndian2int32u (const char* List);
+#if (MAXTYPE_INT >= 64)
+int64s LittleEndian2int40s (const char* List);
+int64u LittleEndian2int40u (const char* List);
+int64s LittleEndian2int48s (const char* List);
+int64u LittleEndian2int48u (const char* List);
+int64s LittleEndian2int56s (const char* List);
+int64u LittleEndian2int56u (const char* List);
+int64s LittleEndian2int64s (const char* List);
+int64u LittleEndian2int64u (const char* List);
+int128u LittleEndian2int128u (const char* List);
+#endif
+float32 LittleEndian2float32 (const char* List);
+float64 LittleEndian2float64 (const char* List);
+float80 LittleEndian2float80 (const char* List);
+
+void int8s2LittleEndian (char* List, int8s Value);
+void int8u2LittleEndian (char* List, int8u Value);
+void int16s2LittleEndian (char* List, int16s Value);
+void int16u2LittleEndian (char* List, int16u Value);
+void int24s2LittleEndian (char* List, int32s Value);
+void int24u2LittleEndian (char* List, int32u Value);
+void int32s2LittleEndian (char* List, int32s Value);
+void int32u2LittleEndian (char* List, int32u Value);
+#if (MAXTYPE_INT >= 64)
+void int40s2LittleEndian (char* List, int64s Value);
+void int40u2LittleEndian (char* List, int64u Value);
+void int48s2LittleEndian (char* List, int64s Value);
+void int48u2LittleEndian (char* List, int64u Value);
+void int56s2LittleEndian (char* List, int64s Value);
+void int56u2LittleEndian (char* List, int64u Value);
+void int64s2LittleEndian (char* List, int64s Value);
+void int64u2LittleEndian (char* List, int64u Value);
+void int128u2LittleEndian (char* List, int128u Value);
+#endif
+void float322LittleEndian (char* List, float32 Value);
+void float642LittleEndian (char* List, float64 Value);
+void float802LittleEndian (char* List, float80 Value);
+
+#ifndef __BORLANDC__
+inline int8s LittleEndian2int8s (const int8u* List) {return LittleEndian2int8s ((const char*)List);}
+inline int8u LittleEndian2int8u (const int8u* List) {return LittleEndian2int8u ((const char*)List);}
+inline int16s LittleEndian2int16s (const int8u* List) {return LittleEndian2int16s ((const char*)List);}
+inline int16u LittleEndian2int16u (const int8u* List) {return LittleEndian2int16u ((const char*)List);}
+inline int32s LittleEndian2int24s (const int8u* List) {return LittleEndian2int24s ((const char*)List);}
+inline int32u LittleEndian2int24u (const int8u* List) {return LittleEndian2int24u ((const char*)List);}
+inline int32s LittleEndian2int32s (const int8u* List) {return LittleEndian2int32s ((const char*)List);}
+inline int32u LittleEndian2int32u (const int8u* List) {return LittleEndian2int32u ((const char*)List);}
+#if (MAXTYPE_INT >= 64)
+inline int64s LittleEndian2int40s (const int8u* List) {return LittleEndian2int40s ((const char*)List);}
+inline int64u LittleEndian2int40u (const int8u* List) {return LittleEndian2int40u ((const char*)List);}
+inline int64s LittleEndian2int48s (const int8u* List) {return LittleEndian2int48s ((const char*)List);}
+inline int64u LittleEndian2int48u (const int8u* List) {return LittleEndian2int48u ((const char*)List);}
+inline int64s LittleEndian2int56s (const int8u* List) {return LittleEndian2int56s ((const char*)List);}
+inline int64u LittleEndian2int56u (const int8u* List) {return LittleEndian2int56u ((const char*)List);}
+inline int64s LittleEndian2int64s (const int8u* List) {return LittleEndian2int64s ((const char*)List);}
+inline int64u LittleEndian2int64u (const int8u* List) {return LittleEndian2int64u ((const char*)List);}
+inline int128u LittleEndian2int128u (const int8u* List) {return LittleEndian2int64u ((const char*)List);}
+#endif
+inline float32 LittleEndian2float32 (const int8u* List) {return LittleEndian2float32 ((const char*)List);}
+inline float64 LittleEndian2float64 (const int8u* List) {return LittleEndian2float64 ((const char*)List);}
+inline float80 LittleEndian2float80 (const int8u* List) {return LittleEndian2float80 ((const char*)List);}
+
+inline void int8s2LittleEndian (int8u* List, int8s Value) {return int8s2LittleEndian ((char*)List, Value);}
+inline void int8u2LittleEndian (int8u* List, int8u Value) {return int8u2LittleEndian ((char*)List, Value);}
+inline void int16s2LittleEndian (int8u* List, int16s Value) {return int16s2LittleEndian ((char*)List, Value);}
+inline void int16u2LittleEndian (int8u* List, int16u Value) {return int16u2LittleEndian ((char*)List, Value);}
+inline void int24s2LittleEndian (int8u* List, int32s Value) {return int24s2LittleEndian ((char*)List, Value);}
+inline void int24u2LittleEndian (int8u* List, int32u Value) {return int24u2LittleEndian ((char*)List, Value);}
+inline void int32s2LittleEndian (int8u* List, int32s Value) {return int32s2LittleEndian ((char*)List, Value);}
+inline void int32u2LittleEndian (int8u* List, int32u Value) {return int32u2LittleEndian ((char*)List, Value);}
+#if (MAXTYPE_INT >= 64)
+inline void int40s2LittleEndian (int8u* List, int64s Value) {return int40s2LittleEndian ((char*)List, Value);}
+inline void int40u2LittleEndian (int8u* List, int64u Value) {return int40u2LittleEndian ((char*)List, Value);}
+inline void int48s2LittleEndian (int8u* List, int64s Value) {return int48s2LittleEndian ((char*)List, Value);}
+inline void int48u2LittleEndian (int8u* List, int64u Value) {return int48u2LittleEndian ((char*)List, Value);}
+inline void int56s2LittleEndian (int8u* List, int64s Value) {return int56s2LittleEndian ((char*)List, Value);}
+inline void int56u2LittleEndian (int8u* List, int64u Value) {return int56u2LittleEndian ((char*)List, Value);}
+inline void int64s2LittleEndian (int8u* List, int64s Value) {return int64s2LittleEndian ((char*)List, Value);}
+inline void int64u2LittleEndian (int8u* List, int64u Value) {return int64u2LittleEndian ((char*)List, Value);}
+inline void int128u2LittleEndian (int8u* List, int128u Value) {return int128u2LittleEndian ((char*)List, Value);}
+#endif
+inline void float322LittleEndian (int8u* List, float32 Value) {return float322LittleEndian ((char*)List, Value);}
+inline void float642LittleEndian (int8u* List, float64 Value) {return float642LittleEndian ((char*)List, Value);}
+inline void float802LittleEndian (int8u* List, float80 Value) {return float802LittleEndian ((char*)List, Value);}
+#endif //__BORLANDC__
+
+//---------------------------------------------------------------------------
+//Big Endians
+int8s BigEndian2int8s (const char* List);
+int8u BigEndian2int8u (const char* List);
+int16s BigEndian2int16s (const char* List);
+int16u BigEndian2int16u (const char* List);
+int32s BigEndian2int24s (const char* List);
+int32u BigEndian2int24u (const char* List);
+int32s BigEndian2int32s (const char* List);
+int32u BigEndian2int32u (const char* List);
+#if (MAXTYPE_INT >= 64)
+int64s BigEndian2int40s (const char* List);
+int64u BigEndian2int40u (const char* List);
+int64s BigEndian2int48s (const char* List);
+int64u BigEndian2int48u (const char* List);
+int64s BigEndian2int56s (const char* List);
+int64u BigEndian2int56u (const char* List);
+int64s BigEndian2int64s (const char* List);
+int64u BigEndian2int64u (const char* List);
+int128u BigEndian2int128u (const char* List);
+#endif
+float32 BigEndian2float32 (const char* List);
+float64 BigEndian2float64 (const char* List);
+float80 BigEndian2float80 (const char* List);
+
+void int8s2BigEndian (char* List, int8s Value);
+void int8u2BigEndian (char* List, int8u Value);
+void int16s2BigEndian (char* List, int16s Value);
+void int16u2BigEndian (char* List, int16u Value);
+void int24s2BigEndian (char* List, int32s Value);
+void int24u2BigEndian (char* List, int32u Value);
+void int32s2BigEndian (char* List, int32s Value);
+void int32u2BigEndian (char* List, int32u Value);
+#if (MAXTYPE_INT >= 64)
+void int40s2BigEndian (char* List, int64s Value);
+void int40u2BigEndian (char* List, int64u Value);
+void int48s2BigEndian (char* List, int64s Value);
+void int48u2BigEndian (char* List, int64u Value);
+void int56s2BigEndian (char* List, int64s Value);
+void int56u2BigEndian (char* List, int64u Value);
+void int64s2BigEndian (char* List, int64s Value);
+void int64u2BigEndian (char* List, int64u Value);
+void int128u2BigEndian (char* List, int128u Value);
+#endif
+void float322BigEndian (char* List, float32 Value);
+void float642BigEndian (char* List, float64 Value);
+void float802BigEndian (char* List, float80 Value);
+
+#ifndef __BORLANDC__
+inline int8s BigEndian2int8s (const int8u* List) {return BigEndian2int8s ((const char*)List);}
+inline int8u BigEndian2int8u (const int8u* List) {return BigEndian2int8u ((const char*)List);}
+inline int16s BigEndian2int16s (const int8u* List) {return BigEndian2int16s ((const char*)List);}
+inline int16u BigEndian2int16u (const int8u* List) {return BigEndian2int16u ((const char*)List);}
+inline int32s BigEndian2int32s (const int8u* List) {return BigEndian2int32s ((const char*)List);}
+inline int32u BigEndian2int24u (const int8u* List) {return BigEndian2int24u ((const char*)List);}
+inline int32s BigEndian2int24s (const int8u* List) {return BigEndian2int24s ((const char*)List);}
+inline int32u BigEndian2int32u (const int8u* List) {return BigEndian2int32u ((const char*)List);}
+#if (MAXTYPE_INT >= 64)
+inline int64s BigEndian2int40s (const int8u* List) {return BigEndian2int40s ((const char*)List);}
+inline int64u BigEndian2int40u (const int8u* List) {return BigEndian2int40u ((const char*)List);}
+inline int64s BigEndian2int48s (const int8u* List) {return BigEndian2int48s ((const char*)List);}
+inline int64u BigEndian2int48u (const int8u* List) {return BigEndian2int48u ((const char*)List);}
+inline int64s BigEndian2int56s (const int8u* List) {return BigEndian2int56s ((const char*)List);}
+inline int64u BigEndian2int56u (const int8u* List) {return BigEndian2int56u ((const char*)List);}
+inline int64s BigEndian2int64s (const int8u* List) {return BigEndian2int64s ((const char*)List);}
+inline int64u BigEndian2int64u (const int8u* List) {return BigEndian2int64u ((const char*)List);}
+inline int128u BigEndian2int128u (const int8u* List) {return BigEndian2int128u ((const char*)List);}
+#endif
+inline float32 BigEndian2float32 (const int8u* List) {return BigEndian2float32 ((const char*)List);}
+inline float64 BigEndian2float64 (const int8u* List) {return BigEndian2float64 ((const char*)List);}
+inline float80 BigEndian2float80 (const int8u* List) {return BigEndian2float80 ((const char*)List);}
+
+inline void int8s2BigEndian (int8u* List, int8s Value) {return int8s2BigEndian ((char*)List, Value);}
+inline void int8u2BigEndian (int8u* List, int8u Value) {return int8u2BigEndian ((char*)List, Value);}
+inline void int16s2BigEndian (int8u* List, int16s Value) {return int16s2BigEndian ((char*)List, Value);}
+inline void int16u2BigEndian (int8u* List, int16u Value) {return int16u2BigEndian ((char*)List, Value);}
+inline void int24s2BigEndian (int8u* List, int32s Value) {return int24s2BigEndian ((char*)List, Value);}
+inline void int24u2BigEndian (int8u* List, int32u Value) {return int24u2BigEndian ((char*)List, Value);}
+inline void int32s2BigEndian (int8u* List, int32s Value) {return int32s2BigEndian ((char*)List, Value);}
+inline void int32u2BigEndian (int8u* List, int32u Value) {return int32u2BigEndian ((char*)List, Value);}
+#if (MAXTYPE_INT >= 64)
+inline void int40s2BigEndian (int8u* List, int64s Value) {return int40s2BigEndian ((char*)List, Value);}
+inline void int40u2BigEndian (int8u* List, int64u Value) {return int40u2BigEndian ((char*)List, Value);}
+inline void int48s2BigEndian (int8u* List, int64s Value) {return int48s2BigEndian ((char*)List, Value);}
+inline void int48u2BigEndian (int8u* List, int64u Value) {return int48u2BigEndian ((char*)List, Value);}
+inline void int56s2BigEndian (int8u* List, int64s Value) {return int56s2BigEndian ((char*)List, Value);}
+inline void int56u2BigEndian (int8u* List, int64u Value) {return int56u2BigEndian ((char*)List, Value);}
+inline void int64s2BigEndian (int8u* List, int64s Value) {return int64s2BigEndian ((char*)List, Value);}
+inline void int64u2BigEndian (int8u* List, int64u Value) {return int64u2BigEndian ((char*)List, Value);}
+inline void int128u2BigEndian (int8u* List, int128u Value) {return int128u2BigEndian ((char*)List, Value);}
+#endif
+inline void float322BigEndian (int8u* List, float32 Value) {return float322BigEndian ((char*)List, Value);}
+inline void float642BigEndian (int8u* List, float64 Value) {return float642BigEndian ((char*)List, Value);}
+inline void float802BigEndian (int8u* List, float80 Value) {return float802BigEndian ((char*)List, Value);}
+#endif //__BORLANDC__
+
+//---------------------------------------------------------------------------
+// int32 - int64
+int64s int32s_int64s ( int32s High, int32u Low);
+int64u int32u_int64u ( int32u High, int32u Low);
+void int32s_int64s (int64s &BigInt, int32s High, int32u Low);
+void int32u_int64u (int64s &BigInt, int32u High, int32u Low);
+void int64s_int32s (int64s BigInt, int32s &High, int32u &Low);
+void int64u_int32u (int64u BigInt, int32u &High, int32u &Low);
+
+//---------------------------------------------------------------------------
+// Floats and ints
+int32s float32_int32s (float32 F, bool Rounded=true);
+int64s float32_int64s (float32 F, bool Rounded=true);
+int32s float64_int32s (float64 F, bool Rounded=true);
+int64s float64_int64s (float64 F, bool Rounded=true);
+
+// These functions are used because MSVC6 isn't able to convert an unsigned int64 to a floating-point value, and I couldn't think of a cleaner way to handle it.
+#if defined(_MSC_VER) && _MSC_VER<=1200
+ inline float32 int64u_float32 (int64u v) {return static_cast<float32>(static_cast<int64s>(v>>1))*2.0f + static_cast<float32>(static_cast<int64s>(v & 1));}
+ inline float64 int64u_float64 (int64u v) {return static_cast<float64>(static_cast<int64s>(v>>1))*2.0f + static_cast<float32>(static_cast<int64s>(v & 1));}
+#else
+ #if defined(_MSC_VER)
+ #pragma warning( disable : 4244 )
+ #endif
+ inline float32 int64u_float32 (int64u v) {return v;}
+ inline float64 int64u_float64 (int64u v) {return v;}
+ #if defined(_MSC_VER)
+ #pragma warning( default : 4244 )
+ #endif
+#endif // defined(_MSC_VER) && _MSC_VER<=1200
+
+//---------------------------------------------------------------------------
+// CC (often used in all containers to identify a stream
+inline int64u CC8(const char* C) {return BigEndian2int64u(C);}
+inline int64u CC7(const char* C) {return BigEndian2int56u(C);}
+inline int64u CC6(const char* C) {return BigEndian2int48u(C);}
+inline int64u CC5(const char* C) {return BigEndian2int40u(C);}
+inline int32u CC4(const char* C) {return BigEndian2int32u(C);}
+inline int32u CC3(const char* C) {return BigEndian2int24u(C);}
+inline int16u CC2(const char* C) {return BigEndian2int16u(C);}
+inline int8u CC1(const char* C) {return BigEndian2int8u (C);}
+#ifndef __BORLANDC__
+inline int64u CC8(const int8u* C) {return BigEndian2int64u(C);}
+inline int64u CC7(const int8u* C) {return BigEndian2int56u(C);}
+inline int64u CC6(const int8u* C) {return BigEndian2int48u(C);}
+inline int64u CC5(const int8u* C) {return BigEndian2int40u(C);}
+inline int32u CC4(const int8u* C) {return BigEndian2int32u(C);}
+inline int32u CC3(const int8u* C) {return BigEndian2int24u(C);}
+inline int16u CC2(const int8u* C) {return BigEndian2int16u(C);}
+inline int8u CC1(const int8u* C) {return BigEndian2int8u (C);}
+#endif // __BORLANDC__
+
+//---------------------------------------------------------------------------
+// turn a numeric literal into a hex constant
+// (avoids problems with leading zeroes)
+// 8-bit constants max value 0x11111111, always fits in unsigned long
+#define HEX__(n) 0x##n##LU
+
+// 8-bit conversion function
+#define B8__(x) ((x&0x0000000FLU)?0x01:0) \
+ +((x&0x000000F0LU)?0x02:0) \
+ +((x&0x00000F00LU)?0x04:0) \
+ +((x&0x0000F000LU)?0x08:0) \
+ +((x&0x000F0000LU)?0x10:0) \
+ +((x&0x00F00000LU)?0x20:0) \
+ +((x&0x0F000000LU)?0x40:0) \
+ +((x&0xF0000000LU)?0x80:0)
+
+// for upto 8-bit binary constants
+#define B8(d) ((int8u)B8__(HEX__(d)))
+
+// for upto 16-bit binary constants, MSB first
+#define B16(dmsb, dlsb) (((int16u)B8(dmsb)<<8) \
+ + ((int16u)B8(dlsb)<<0))
+
+// for upto 32-bit binary constants, MSB first
+#define B32(dmsb, db2, db3, dlsb) (((int32u)B8(dmsb)<<24) \
+ + ((int32u)B8( db2)<<16) \
+ + ((int32u)B8( db3)<< 8) \
+ + ((int32u)B8(dlsb)<< 0))
+
+} //namespace ZenLib
+#endif
diff --git a/src/thirdparty/ZenLib/ZenLib.vcproj b/src/thirdparty/ZenLib/ZenLib.vcproj
new file mode 100644
index 000000000..5ed41f5b3
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZenLib.vcproj
@@ -0,0 +1,599 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="ZenLib"
+ ProjectGUID="{0DA1DA7D-F393-4E7C-A7CE-CB5C6A67BC94}"
+ RootNamespace="ZenLib"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\common.vsprops;..\..\debug.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/MP"
+ AdditionalIncludeDirectories="..;../zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalOptions="/IGNORE:4221"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\common.vsprops;..\..\debug.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/MP"
+ AdditionalIncludeDirectories="..;../zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WSTRING_MISSING"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalOptions="/IGNORE:4221"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\common.vsprops;..\..\release.vsprops"
+ UseOfMFC="1"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/MP"
+ AdditionalIncludeDirectories="..;../zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalOptions="/IGNORE:4221"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\common.vsprops;..\..\release.vsprops"
+ UseOfMFC="1"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/MP"
+ AdditionalIncludeDirectories="..;../zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ EnableEnhancedInstructionSet="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalOptions="/IGNORE:4221"
+ />
+ <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;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Conf.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\CriticalSection.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Dir.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\File.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\FileName.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\HTTP_Client.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\InfoMap.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\int128s.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4127"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4127"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\int128u.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4127"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4127"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\MemoryDebug.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\OS_Utils.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Thread.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Translation.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Utils.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Ztring.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ZtringList.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ZtringListList.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ZtringListListF.cpp"
+ >
+ </File>
+ <Filter
+ Name="Format"
+ >
+ <Filter
+ Name="Http"
+ >
+ <File
+ RelativePath=".\Format\Http\Http_Cookies.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4996"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4996"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4996"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4996"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Format\Http\Http_Handler.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Http\Http_Request.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Http\Http_Utils.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Html"
+ >
+ <File
+ RelativePath=".\Format\Html\Html_Handler.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Html\Html_Request.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="TinyXml"
+ >
+ <File
+ RelativePath=".\TinyXml\tinyxml.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\TinyXml\tinyxmlerror.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\TinyXml\tinyxmlparser.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\BitStream.h"
+ >
+ </File>
+ <File
+ RelativePath=".\BitStream_LE.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Conf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ConvertUTF.h"
+ >
+ </File>
+ <File
+ RelativePath=".\CriticalSection.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Dir.h"
+ >
+ </File>
+ <File
+ RelativePath=".\File.h"
+ >
+ </File>
+ <File
+ RelativePath=".\FileName.h"
+ >
+ </File>
+ <File
+ RelativePath=".\HTTP_Client.h"
+ >
+ </File>
+ <File
+ RelativePath=".\InfoMap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\int128s.h"
+ >
+ </File>
+ <File
+ RelativePath=".\int128u.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MemoryDebug.h"
+ >
+ </File>
+ <File
+ RelativePath=".\OS_Utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Thread.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Trace.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Translation.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ztring.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ZtringList.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ZtringListList.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ZtringListListF.h"
+ >
+ </File>
+ <Filter
+ Name="Format"
+ >
+ <Filter
+ Name="Html"
+ >
+ <File
+ RelativePath=".\Format\Html\Html_Handler.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Html\Html_Request.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Http"
+ >
+ <File
+ RelativePath=".\Format\Http\Http_Cookies.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Http\Http_Handler.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Http\Http_Request.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Format\Http\Http_Utils.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="TinyXml"
+ >
+ <File
+ RelativePath=".\TinyXml\tinyxml.h"
+ >
+ </File>
+ </Filter>
+ </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>
diff --git a/src/thirdparty/ZenLib/ZenLib.vcxproj b/src/thirdparty/ZenLib/ZenLib.vcxproj
new file mode 100644
index 000000000..a56a09eb4
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZenLib.vcxproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{0DA1DA7D-F393-4E7C-A7CE-CB5C6A67BC94}</ProjectGuid>
+ <RootNamespace>ZenLib</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>Static</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>Static</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\common.props" />
+ <Import Project="..\..\release.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\common.props" />
+ <Import Project="..\..\debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\common.props" />
+ <Import Project="..\..\release.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\common.props" />
+ <Import Project="..\..\debug.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..;../zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <AdditionalOptions>/IGNORE:4221 %(AdditionalOptions)</AdditionalOptions>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..;../zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;WSTRING_MISSING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <EnablePREfast>false</EnablePREfast>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Lib>
+ <AdditionalOptions>/IGNORE:4221 %(AdditionalOptions)</AdditionalOptions>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..;../zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Lib>
+ <AdditionalOptions>/IGNORE:4221 %(AdditionalOptions)</AdditionalOptions>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..;../zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Lib>
+ <AdditionalOptions>/IGNORE:4221 %(AdditionalOptions)</AdditionalOptions>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="Conf.cpp" />
+ <ClCompile Include="CriticalSection.cpp" />
+ <ClCompile Include="Dir.cpp" />
+ <ClCompile Include="File.cpp" />
+ <ClCompile Include="FileName.cpp" />
+ <ClCompile Include="HTTP_Client.cpp" />
+ <ClCompile Include="InfoMap.cpp" />
+ <ClCompile Include="int128s.cpp">
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ClCompile Include="int128u.cpp">
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ClCompile Include="MemoryDebug.cpp" />
+ <ClCompile Include="OS_Utils.cpp" />
+ <ClCompile Include="Thread.cpp" />
+ <ClCompile Include="Translation.cpp" />
+ <ClCompile Include="Utils.cpp" />
+ <ClCompile Include="Ztring.cpp" />
+ <ClCompile Include="ZtringList.cpp" />
+ <ClCompile Include="ZtringListList.cpp" />
+ <ClCompile Include="ZtringListListF.cpp" />
+ <ClCompile Include="Format\Http\Http_Cookies.cpp">
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ClCompile Include="Format\Http\Http_Handler.cpp" />
+ <ClCompile Include="Format\Http\Http_Request.cpp" />
+ <ClCompile Include="Format\Http\Http_Utils.cpp" />
+ <ClCompile Include="Format\Html\Html_Handler.cpp" />
+ <ClCompile Include="Format\Html\Html_Request.cpp" />
+ <ClCompile Include="TinyXml\tinyxml.cpp" />
+ <ClCompile Include="TinyXml\tinyxmlerror.cpp" />
+ <ClCompile Include="TinyXml\tinyxmlparser.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="BitStream.h" />
+ <ClInclude Include="BitStream_LE.h" />
+ <ClInclude Include="Conf.h" />
+ <ClInclude Include="ConvertUTF.h" />
+ <ClInclude Include="CriticalSection.h" />
+ <ClInclude Include="Dir.h" />
+ <ClInclude Include="File.h" />
+ <ClInclude Include="FileName.h" />
+ <ClInclude Include="HTTP_Client.h" />
+ <ClInclude Include="InfoMap.h" />
+ <ClInclude Include="int128s.h" />
+ <ClInclude Include="int128u.h" />
+ <ClInclude Include="MemoryDebug.h" />
+ <ClInclude Include="OS_Utils.h" />
+ <ClInclude Include="Thread.h" />
+ <ClInclude Include="Trace.h" />
+ <ClInclude Include="Translation.h" />
+ <ClInclude Include="Utils.h" />
+ <ClInclude Include="Ztring.h" />
+ <ClInclude Include="ZtringList.h" />
+ <ClInclude Include="ZtringListList.h" />
+ <ClInclude Include="ZtringListListF.h" />
+ <ClInclude Include="Format\Html\Html_Handler.h" />
+ <ClInclude Include="Format\Html\Html_Request.h" />
+ <ClInclude Include="Format\Http\Http_Cookies.h" />
+ <ClInclude Include="Format\Http\Http_Handler.h" />
+ <ClInclude Include="Format\Http\Http_Request.h" />
+ <ClInclude Include="Format\Http\Http_Utils.h" />
+ <ClInclude Include="TinyXml\tinyxml.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/thirdparty/ZenLib/ZenLib.vcxproj.filters b/src/thirdparty/ZenLib/ZenLib.vcxproj.filters
new file mode 100644
index 000000000..a23900972
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZenLib.vcxproj.filters
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Format">
+ <UniqueIdentifier>{e294e00a-2def-47ce-9e5f-1b01c58d9c9e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Format\Http">
+ <UniqueIdentifier>{66c17032-cb7b-4c8b-9a6c-ebc78ebfb6fd}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Format\Html">
+ <UniqueIdentifier>{d9df8c89-24c5-4fa0-a091-ab35f334de6a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\TinyXml">
+ <UniqueIdentifier>{e6a58e0d-012d-4129-9a52-4f93e8afa7fc}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Header Files\Format">
+ <UniqueIdentifier>{bc5887e0-d9e5-4186-9b1a-4993a5a940e0}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Format\Html">
+ <UniqueIdentifier>{4f1c0bf7-3263-461e-822a-376a630b84fc}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Format\Http">
+ <UniqueIdentifier>{67c60fa1-1fe7-4f24-bd24-8a7846d1dc28}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\TinyXml">
+ <UniqueIdentifier>{10a4ea7b-a241-4ba2-b474-f7af040615ef}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Conf.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CriticalSection.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Dir.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="File.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="FileName.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="HTTP_Client.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="InfoMap.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="int128s.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="int128u.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="MemoryDebug.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="OS_Utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Thread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Translation.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Ztring.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ZtringList.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ZtringListList.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ZtringListListF.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Format\Http\Http_Cookies.cpp">
+ <Filter>Source Files\Format\Http</Filter>
+ </ClCompile>
+ <ClCompile Include="Format\Http\Http_Handler.cpp">
+ <Filter>Source Files\Format\Http</Filter>
+ </ClCompile>
+ <ClCompile Include="Format\Http\Http_Request.cpp">
+ <Filter>Source Files\Format\Http</Filter>
+ </ClCompile>
+ <ClCompile Include="Format\Http\Http_Utils.cpp">
+ <Filter>Source Files\Format\Http</Filter>
+ </ClCompile>
+ <ClCompile Include="Format\Html\Html_Handler.cpp">
+ <Filter>Source Files\Format\Html</Filter>
+ </ClCompile>
+ <ClCompile Include="Format\Html\Html_Request.cpp">
+ <Filter>Source Files\Format\Html</Filter>
+ </ClCompile>
+ <ClCompile Include="TinyXml\tinyxml.cpp">
+ <Filter>Source Files\TinyXml</Filter>
+ </ClCompile>
+ <ClCompile Include="TinyXml\tinyxmlerror.cpp">
+ <Filter>Source Files\TinyXml</Filter>
+ </ClCompile>
+ <ClCompile Include="TinyXml\tinyxmlparser.cpp">
+ <Filter>Source Files\TinyXml</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="BitStream.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="BitStream_LE.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Conf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ConvertUTF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CriticalSection.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Dir.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="File.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="FileName.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="HTTP_Client.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="InfoMap.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="int128s.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="int128u.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="MemoryDebug.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="OS_Utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Thread.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Trace.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Translation.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Ztring.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ZtringList.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ZtringListList.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ZtringListListF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Format\Html\Html_Handler.h">
+ <Filter>Header Files\Format\Html</Filter>
+ </ClInclude>
+ <ClInclude Include="Format\Html\Html_Request.h">
+ <Filter>Header Files\Format\Html</Filter>
+ </ClInclude>
+ <ClInclude Include="Format\Http\Http_Cookies.h">
+ <Filter>Header Files\Format\Http</Filter>
+ </ClInclude>
+ <ClInclude Include="Format\Http\Http_Handler.h">
+ <Filter>Header Files\Format\Http</Filter>
+ </ClInclude>
+ <ClInclude Include="Format\Http\Http_Request.h">
+ <Filter>Header Files\Format\Http</Filter>
+ </ClInclude>
+ <ClInclude Include="Format\Http\Http_Utils.h">
+ <Filter>Header Files\Format\Http</Filter>
+ </ClInclude>
+ <ClInclude Include="TinyXml\tinyxml.h">
+ <Filter>Header Files\TinyXml</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/src/thirdparty/ZenLib/Ztring.cpp b/src/thirdparty/ZenLib/Ztring.cpp
new file mode 100644
index 000000000..8a792e21c
--- /dev/null
+++ b/src/thirdparty/ZenLib/Ztring.cpp
@@ -0,0 +1,2157 @@
+// ZenLib::Ztring - std::(w)string is better
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// More methods for std::(w)string
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#ifdef ZENLIB_USEWX
+ #include <wx/strconv.h>
+ #include <wx/datetime.h>
+#else //ZENLIB_USEWX
+ #ifdef ZENLIB_STANDARD
+ #undef WINDOWS
+ #endif
+ #ifdef WINDOWS
+ #undef __TEXT
+ #include <windows.h>
+ #include <tchar.h>
+ #endif
+#endif //ZENLIB_USEWX
+#ifdef __MINGW32__
+ #include <windows.h>
+#endif //__MINGW32__
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#ifdef SS
+ #undef SS //Solaris defines this in cstdlib
+#endif
+#include <ctime>
+#include <algorithm>
+#include <sstream>
+#include <iomanip>
+#include <cmath>
+#include "ZenLib/Ztring.h"
+#include "ZenLib/OS_Utils.h"
+#include "ZenLib/File.h"
+using namespace std;
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+Ztring EmptyZtring;
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#if defined(__MINGW32__) || defined(__sun__) || defined(__mips__) || defined(__mipsel__)
+ #if defined (_UNICODE)
+ #define _tnprintf snwprintf
+ #else
+ #define _tnprintf snprintf
+ #endif
+#endif
+typedef basic_stringstream<Char> tStringStream;
+typedef basic_istringstream<Char> tiStringStream;
+typedef basic_ostringstream<Char> toStringStream;
+//---------------------------------------------------------------------------
+
+//***************************************************************************
+// Operators
+//***************************************************************************
+
+Char &Ztring::operator() (size_type Pos)
+{
+ if (Pos>size())
+ resize(Pos);
+ return operator[] (Pos);
+}
+
+//***************************************************************************
+// Assign
+//***************************************************************************
+
+bool Ztring::Assign_FromFile (const Ztring &FileName)
+{
+ File F;
+ if (!F.Open(FileName))
+ return false;
+ int64u F_Size=F.Size_Get();
+ if (F_Size>((size_t)-1)-1)
+ return false;
+
+ //Creating buffer
+ int8u* Buffer=new int8u[(size_t)F_Size+1];
+ size_t Buffer_Offset=0;
+
+ //Reading the file
+ while(Buffer_Offset<F_Size)
+ {
+ size_t BytesRead=F.Read(Buffer+Buffer_Offset, (size_t)F_Size-Buffer_Offset);
+ if (BytesRead==0)
+ break; //Read is finished
+ Buffer_Offset+=BytesRead;
+ }
+ if (Buffer_Offset<F_Size)
+ return false;
+ Buffer[Buffer_Offset]='\0';
+
+ //Filling
+ assign((const Char*)Buffer);
+ delete[] Buffer;
+
+ return true;
+}
+
+//***************************************************************************
+// Conversions
+//***************************************************************************
+
+Ztring& Ztring::From_Unicode (const wchar_t* S)
+{
+ if (S==NULL)
+ return *this;
+
+ #ifdef _UNICODE
+ assign(S);
+ #else
+ #ifdef ZENLIB_USEWX
+ size_type OK=wxConvCurrent->WC2MB(NULL, S, 0);
+ if (OK!=0 && OK!=Error)
+ assign(wxConvCurrent->cWC2MB(S));
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ if (IsWin9X())
+ {
+ clear();
+ return *this; //Is not possible, UTF-8 is not supported by Win9X
+ }
+ int Size=WideCharToMultiByte(CP_UTF8, 0, S, -1, NULL, 0, NULL, NULL);
+ if (Size!=0)
+ {
+ char* AnsiString=new char[Size+1];
+ WideCharToMultiByte(CP_UTF8, 0, S, -1, AnsiString, Size, NULL, NULL);
+ AnsiString[Size]='\0';
+ assign (AnsiString);
+ delete[] AnsiString;
+ }
+ else
+ clear();
+ #else //WINDOWS
+ size_t Size=wcstombs(NULL, S, 0);
+ if (Size!=0 && Size!=(size_t)-1)
+ {
+ char* AnsiString=new char[Size+1];
+ Size=wcstombs(AnsiString, S, wcslen(S));
+ AnsiString[Size]='\0';
+ assign (AnsiString);
+ delete[] AnsiString;
+ }
+ else
+ clear();
+ #endif
+ #endif //ZENLIB_USEWX
+ #endif
+ return *this;
+}
+
+Ztring& Ztring::From_Unicode (const wchar_t *S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length==Error)
+ Length=wcslen(S+Start);
+ wchar_t* Temp=new wchar_t[Length+1];
+ wcsncpy (Temp, S+Start, Length);
+ Temp[Length]=_T('\0');
+
+ From_Unicode(Temp);
+ delete[] Temp; //Temp=NULL;
+ return *this;
+}
+
+Ztring& Ztring::From_UTF8 (const char* S)
+{
+ if (S==NULL)
+ return *this;
+
+ #ifdef ZENLIB_USEWX
+ size_type OK=wxConvUTF8.MB2WC(NULL, S, 0);
+ if (OK!=0 && OK!=Error)
+ #ifdef _UNICODE
+ assign(wxConvUTF8.cMB2WC(S).data());
+ #else
+ assign(wxConvCurrent->cWC2MB(wxConvUTF8.cMB2WC(S)));
+ #endif
+ #else //ZENLIB_USEWX
+ #ifdef _UNICODE
+ #ifdef WINDOWS
+ if (IsWin9X())
+ {
+ clear();
+ const int8u* Z=(const int8u*)S;
+ while (*Z) //0 is end
+ {
+ //1 byte
+ if (*Z<0x80)
+ {
+ operator += ((wchar_t)(*Z));
+ Z++;
+ }
+ //2 bytes
+ else if ((*Z&0xE0)==0xC0)
+ {
+ if ((*(Z+1)&0xC0)==0x80)
+ {
+ operator += ((((wchar_t)(*Z&0x1F))<<6)|(*(Z+1)&0x3F));
+ Z+=2;
+ }
+ else
+ break; //Bad character
+ }
+ else
+ break; //Bad character (or to be encoded in UTF-16LE, not yet supported)
+ }
+ }
+ else
+ {
+ int Size=MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, S, -1, NULL, 0);
+ if (Size!=0)
+ {
+ Char* WideString=new Char[Size+1];
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, S, -1, WideString, Size);
+ WideString[Size]=L'\0';
+ assign (WideString+(WideString[0]==0xFEFF?1:0));
+ delete[] WideString; //WideString=NULL;
+ }
+ else
+ clear();
+ }
+ #else //WINDOWS
+ clear();
+ const int8u* Z=(const int8u*)S;
+ while (*Z) //0 is end
+ {
+ //1 byte
+ if (*Z<0x80)
+ {
+ operator += ((wchar_t)(*Z));
+ Z++;
+ }
+ //2 bytes
+ else if ((*Z&0xE0)==0xC0)
+ {
+ if ((*(Z+1)&0xC0)==0x80)
+ {
+ operator += ((((wchar_t)(*Z&0x1F))<<6)|(*(Z+1)&0x3F));
+ Z+=2;
+ }
+ else
+ break; //Bad character
+ }
+ //3 bytes
+ else if ((*Z&0xF0)==0xE0)
+ {
+ if ((*(Z+1)&0xC0)==0x80 && (*(Z+2)&0xC0)==0x80)
+ {
+ operator += ((((wchar_t)(*Z&0x0F))<<12)|((*(Z+1)&0x3F)<<6)|(*(Z+2)&0x3F));
+ Z+=3;
+ }
+ else
+ break; //Bad character
+ }
+ //4 bytes
+ else if ((*Z&0xF8)==0xF0)
+ {
+ if ((*(Z+1)&0xC0)==0x80 && (*(Z+2)&0xC0)==0x80 && (*(Z+2)&0xC0)==0x80)
+ {
+ operator += ((((wchar_t)(*Z&0x0F))<<18)|((*(Z+1)&0x3F)<<12)||((*(Z+2)&0x3F)<<6)|(*(Z+3)&0x3F));
+ Z+=4;
+ }
+ else
+ break; //Bad character
+ }
+ else
+ break; //Bad character
+ }
+ #endif
+ #else
+ assign(S); //Not implemented
+ #endif
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+Ztring& Ztring::From_UTF8 (const char* S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length==Error)
+ Length=strlen(S+Start);
+ char* Temp=new char[Length+1];
+ strncpy (Temp, S+Start, Length);
+ Temp[Length]='\0';
+
+ From_UTF8(Temp);
+ delete[] Temp; //Temp=NULL;
+ return *this;
+}
+
+Ztring& Ztring::From_UTF16 (const char* S)
+{
+ if (S==NULL)
+ return *this;
+
+ if ((unsigned char)S[0]==(unsigned char)0xFF && (unsigned char)S[1]==(unsigned char)0xFE)
+ return From_UTF16LE(S+2);
+ else if ((unsigned char)S[0]==(unsigned char)0xFE && (unsigned char)S[1]==(unsigned char)0xFF)
+ return From_UTF16BE(S+2);
+ else if ((unsigned char)S[0]==(unsigned char)0x00 && (unsigned char)S[1]==(unsigned char)0x00)
+ {
+ clear(); //No begin!
+ return *this;
+ }
+ else
+ return From_UTF16LE(S); //Not sure, default
+}
+
+Ztring& Ztring::From_UTF16 (const char* S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length<2)
+ return *this;
+
+ if ((unsigned char)S[0]==(unsigned char)0xFF && (unsigned char)S[1]==(unsigned char)0xFE)
+ return From_UTF16LE(S+2, Start, Length-2);
+ else if ((unsigned char)S[0]==(unsigned char)0xFE && (unsigned char)S[1]==(unsigned char)0xFF)
+ return From_UTF16BE(S+2, Start, Length-2);
+ else if ((unsigned char)S[0]==(unsigned char)0x00 && (unsigned char)S[1]==(unsigned char)0x00)
+ {
+ clear(); //No begin!
+ return *this;
+ }
+ else
+ return From_UTF16LE(S, Start, Length); //Not sure, default
+}
+
+Ztring& Ztring::From_UTF16BE (const char* S)
+{
+ if (S==NULL)
+ return *this;
+
+ #ifdef ZENLIB_USEWX
+ //clear(); return *this;
+ wxMBConvUTF16BE wxConvUTF16BE;
+ size_type OK=wxConvUTF16BE.MB2WC(NULL, S, 0);
+ if (OK!=0 && OK!=Error)
+ #ifdef _UNICODE
+ assign(wxConvUTF16BE.cMB2WC(S).data());
+ #else
+ assign(wxConvCurrent->cWC2MB(wxConvUTF16BE.cMB2WC(S)));
+ #endif
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ clear();
+ const wchar_t* SW=(const wchar_t*)S;
+ size_t Pos=0;
+ while (SW[Pos]!=_T('\0'))
+ {
+ Char Temp=(Char)(((SW[Pos]&0xFF00)>>8)+((SW[Pos]&0x00FF)<<8));
+ append(1, Temp);
+ Pos++;
+ }
+ #else //WINDOWS
+ clear();
+ while (S[0]!=0 || S[1]!=0)
+ {
+ append(1, (Char)BigEndian2int16u(S));
+ S+=2;
+ }
+ #endif
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+Ztring& Ztring::From_UTF16BE (const char* S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length==Error)
+ {
+ Length=0;
+ while(S[Length]!=0x0000)
+ Length++;
+ }
+
+ char* Temp=new char[Length+2];
+ memcpy (Temp, S+Start, Length);
+ Temp[Length+0]=0x00;
+ Temp[Length+1]=0x00;
+ reserve(Length);
+ From_UTF16BE(Temp);
+ delete[] Temp; //Temp=NULL;
+ return *this;
+}
+
+Ztring& Ztring::From_UTF16LE (const char* S)
+{
+ if (S==NULL)
+ return *this;
+
+ #ifdef ZENLIB_USEWX
+ //clear(); return *this;
+ wxMBConvUTF16LE wxConvUTF16LE;
+ size_type OK=wxConvUTF16LE.MB2WC(NULL, S, 0);
+ if (OK!=0 && OK!=Error)
+ #ifdef _UNICODE
+ assign(wxConvUTF16LE.cMB2WC(S).data());
+ #else
+ assign(wxConvCurrent->cWC2MB(wxConvUTF16LE.cMB2WC(S)));
+ #endif
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ #ifdef UNICODE
+ const wchar_t* SW=(const wchar_t*)S;
+ assign(SW);
+ #else
+ clear(); //Not implemented
+ #endif
+ #else //WINDOWS
+ clear();
+ while (S[0]!=0 || S[1]!=0)
+ {
+ append(1, (Char)LittleEndian2int16u(S));
+ S+=2;
+ }
+ #endif
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+Ztring& Ztring::From_UTF16LE (const char* S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length==Error)
+ {
+ Length=0;
+ while(S[Length]!=0x0000)
+ Length+=2;
+ }
+
+ char* Temp=new char[Length+2];
+ memcpy (Temp, S+Start, Length);
+ Temp[Length+0]=0x00;
+ Temp[Length+1]=0x00;
+ From_UTF16LE(Temp);
+ delete[] Temp; //Temp=NULL;
+ return *this;
+}
+
+Ztring& Ztring::From_Local (const char* S)
+{
+ if (S==NULL)
+ return *this;
+
+ #ifdef _UNICODE
+ #ifdef ZENLIB_USEWX
+ size_type OK=wxConvCurrent->MB2WC(NULL, S, 0);
+ if (OK!=0 && OK!=Error)
+ assign(wxConvCurrent->cMB2WC(S).data());
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ int Size=MultiByteToWideChar(CP_ACP, 0, S, -1, NULL, 0);
+ if (Size!=0)
+ {
+ wchar_t* WideString=new wchar_t[Size+1];
+ MultiByteToWideChar(CP_ACP, 0, S, -1, WideString, Size);
+ WideString[Size]=L'\0';
+ assign (WideString);
+ delete[] WideString; //WideString=NULL;
+ }
+ else
+ clear();
+ #else //WINDOWS
+ size_t Size=mbstowcs(NULL, S, 0);
+ if (Size!=0 && Size!=(size_t)-1)
+ {
+ wchar_t* WideString=new wchar_t[Size+1];
+ Size=mbstowcs(WideString, S, Size);
+ WideString[Size]=L'\0';
+ assign (WideString);
+ delete[] WideString; //WideString=NULL;
+ }
+ else
+ clear();
+ #endif
+ #endif //ZENLIB_USEWX
+ #else
+ assign(S);
+ #endif
+ return *this;
+}
+
+Ztring& Ztring::From_Local (const char* S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length==Error)
+ Length=strlen(S+Start);
+ #ifdef _UNICODE
+ char* Temp=new char[Length+1];
+ strncpy (Temp, S+Start, Length);
+ Temp[Length]='\0';
+ From_Local(Temp);
+ delete[] Temp; //Temp=NULL;
+ #else
+ assign(S+Start, Length);
+ if (find(_T('\0'))!=std::string::npos)
+ resize(find(_T('\0')));
+ #endif
+ return *this;
+}
+
+Ztring& Ztring::From_ISO_8859_1(const char* S)
+{
+ size_t Length = strlen(S);
+ wchar_t* Temp = new wchar_t[Length +1];
+
+ for (size_t Pos=0; Pos<Length+1; Pos++)
+ Temp[Pos]=(wchar_t)((int8u)S[Pos]);
+
+ From_Unicode(Temp);
+ delete[] Temp;
+ return *this;
+}
+
+Ztring& Ztring::From_ISO_8859_1(const char* S, size_type Start, size_type Length)
+{
+ if (S==NULL)
+ return *this;
+
+ if (Length==Error)
+ Length=strlen(S+Start);
+ #ifdef _UNICODE
+ char* Temp = new char[Length+1];
+ strncpy(Temp, S +Start, Length);
+ Temp[Length] = '\0';
+ From_ISO_8859_1(Temp);
+ delete[] Temp;
+ #else
+ assign(S +Start, Length);
+ if (find(_T('\0')) != std::string::npos)
+ resize(find(_T('\0')));
+ #endif
+ return *this;
+}
+
+Ztring& Ztring::From_GUID (const int128u S)
+{
+ Ztring S1;
+ S1.From_CC1((int8u) ((S.hi&0x000000FF00000000LL)>>32)); append(S1);
+ S1.From_CC1((int8u) ((S.hi&0x0000FF0000000000LL)>>40)); append(S1);
+ S1.From_CC1((int8u) ((S.hi&0x00FF000000000000LL)>>48)); append(S1);
+ S1.From_CC1((int8u) ((S.hi&0xFF00000000000000LL)>>56)); append(S1); append(_T("-"));
+ S1.From_CC1((int8u) ((S.hi&0x0000000000FF0000LL)>>16)); append(S1);
+ S1.From_CC1((int8u) ((S.hi&0x00000000FF000000LL)>>24)); append(S1); append(_T("-"));
+ S1.From_CC1((int8u) ( S.hi&0x00000000000000FFLL )); append(S1);
+ S1.From_CC1((int8u) ((S.hi&0x000000000000FF00LL)>> 8)); append(S1); append(_T("-"));
+ S1.From_CC2((int16u)((S.lo&0xFFFF000000000000LL)>>48)); append(S1); append(_T("-"));
+ S1.From_CC2((int16u)((S.lo&0x0000FFFF00000000LL)>>32)); append(S1);
+ S1.From_CC2((int16u)((S.lo&0x00000000FFFF0000LL)>>16)); append(S1);
+ S1.From_CC2((int16u)( S.lo&0x000000000000FFFFLL )); append(S1);
+
+ return *this;
+}
+
+Ztring& Ztring::From_UUID (const int128u S)
+{
+ Ztring S1;
+ S1.From_CC2((int16u)((S.hi&0xFFFF000000000000LL)>>48)); assign(S1);
+ S1.From_CC2((int16u)((S.hi&0x0000FFFF00000000LL)>>32)); append(S1); append(_T("-"));
+ S1.From_CC2((int16u)((S.hi&0x00000000FFFF0000LL)>>16)); append(S1); append(_T("-"));
+ S1.From_CC2((int16u)( S.hi&0x000000000000FFFFLL )); append(S1); append(_T("-"));
+ S1.From_CC2((int16u)((S.lo&0xFFFF000000000000LL)>>48)); append(S1); append(_T("-"));
+ S1.From_CC2((int16u)((S.lo&0x0000FFFF00000000LL)>>32)); append(S1);
+ S1.From_CC2((int16u)((S.lo&0x00000000FFFF0000LL)>>16)); append(S1);
+ S1.From_CC2((int16u)( S.lo&0x000000000000FFFFLL )); append(S1);
+
+ return *this;
+}
+
+Ztring& Ztring::From_CC4 (const int32u S)
+{
+ std::string S1;
+ S1.append(1, (char)((S&0xFF000000)>>24));
+ S1.append(1, (char)((S&0x00FF0000)>>16));
+ S1.append(1, (char)((S&0x0000FF00)>> 8));
+ S1.append(1, (char)((S&0x000000FF)>> 0));
+ From_Local(S1.c_str());
+
+ //Test
+ if (empty())
+ assign(_T("(empty)"));
+
+ return *this;
+}
+
+Ztring& Ztring::From_CC3 (const int32u S)
+{
+ std::string S1;
+ S1.append(1, (char)((S&0x00FF0000)>>16));
+ S1.append(1, (char)((S&0x0000FF00)>> 8));
+ S1.append(1, (char)((S&0x000000FF)>> 0));
+ From_Local(S1.c_str());
+
+ //Test
+ if (empty())
+ assign(_T("(empty)"));
+
+ return *this;
+}
+
+Ztring& Ztring::From_CC2 (const int16u S)
+{
+ clear();
+ Ztring Pos1; Pos1.From_Number(S, 16);
+ resize(4-Pos1.size(), _T('0'));
+ append(Pos1);
+ MakeUpperCase();
+
+ return *this;
+}
+
+Ztring& Ztring::From_CC1 (const int8u S)
+{
+ clear();
+ Ztring Pos1; Pos1.From_Number(S, 16);
+ resize(2-Pos1.size(), _T('0'));
+ append(Pos1);
+ MakeUpperCase();
+
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int8s I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[33];
+ #ifdef __MINGW32__
+ _itot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 32, Radix==10?_T("%d"):(Radix==16?_T("%x"):(Radix==8?_T("%o"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ #ifdef UNICODE
+ SS << setbase(Radix) << I;
+ #else //UNICODE
+ SS << setbase(Radix) << (size_t)I; //On linux (at least), (un)signed char is detected as a char
+ #endif //UNICODE
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int8u I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[33];
+ #ifdef __MINGW32__
+ _ultot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 32, Radix==10?_T("%d"):(Radix==16?_T("%x"):(Radix==8?_T("%o"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ #ifdef UNICODE
+ SS << setbase(Radix) << I;
+ #else //UNICODE
+ SS << setbase(Radix) << (size_t)I; //On linux (at least), (un)signed char is detected as a char
+ #endif //UNICODE
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int16s I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[33];
+ #ifdef __MINGW32__
+ _itot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 32, Radix==10?_T("%d"):(Radix==16?_T("%x"):(Radix==8?_T("%o"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int16u I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[33];
+ #ifdef __MINGW32__
+ _ultot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 32, Radix==10?_T("%u"):(Radix==16?_T("%x"):(Radix==8?_T("%o"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int32s I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[33];
+ #ifdef __MINGW32__
+ _itot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 32, Radix==10?_T("%ld"):(Radix==16?_T("%lx"):(Radix==8?_T("%lo"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int32u I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[33];
+ #ifdef __MINGW32__
+ _ultot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 32, Radix==10?_T("%lu"):(Radix==16?_T("%lx"):(Radix==8?_T("%lo"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int64s I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[65];
+ #ifdef __MINGW32__
+ _i64tot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 64, Radix==10?_T("%lld"):(Radix==16?_T("%llx"):(Radix==8?_T("%llo"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int64u I, int8u Radix)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ if (Radix==0)
+ {
+ clear();
+ return *this;
+ }
+ Char* C1=new Char[65];
+ #ifdef __MINGW32__
+ _ui64tot (I, C1, Radix);
+ #else
+ _tnprintf(C1, 64, Radix==10?_T("%llu"):(Radix==16?_T("%llx"):(Radix==8?_T("%llo"):_T(""))), I);
+ #endif
+ assign (C1);
+ delete[] C1; //C1=NULL;
+ #else
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ #endif
+ MakeUpperCase();
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const int128u I, int8u Radix)
+{
+ From_Local(I.toString(Radix));
+
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const float32 F, int8u Precision, ztring_t Options)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) ) || defined(__mips__) || defined(__mipsel__)
+ Char C1[100];
+ _tnprintf (C1, 99, (Ztring(_T("%."))+Ztring::ToZtring(Precision)+_T("f")).c_str(), F);
+ assign(C1);
+ #else
+ toStringStream SS;
+ SS << setprecision(Precision) << fixed << F;
+ assign(SS.str());
+ #if defined(__BORLANDC__)
+ FindAndReplace(_T(","), _T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
+ #endif
+ #endif
+
+ if ((Options & Ztring_NoZero && size()>0) && find(_T('.'))>0)
+ {
+ while (size()>0 && ((*this)[size()-1]==_T('0')))
+ resize(size()-1);
+ if (size()>0 && (*this)[size()-1]==_T('.'))
+ resize(size()-1);
+ }
+
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const float64 F, int8u Precision, ztring_t Options)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) ) || defined(__mips__) || defined(__mipsel__)
+ Char C1[100];
+ _tnprintf (C1, 99, (Ztring(_T("%."))+Ztring::ToZtring(Precision)+_T("f")).c_str(), F);
+ assign(C1);
+ #else
+ toStringStream SS;
+ SS << setprecision(Precision) << fixed << F;
+ assign(SS.str());
+ #if defined(__BORLANDC__)
+ FindAndReplace(_T(","), _T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
+ #endif
+ #endif
+
+ if ((Options & Ztring_NoZero && size()>0) && find(_T('.'))>0)
+ {
+ while (size()>0 && ((*this)[size()-1]==_T('0')))
+ resize(size()-1);
+ if (size()>0 && (*this)[size()-1]==_T('.'))
+ resize(size()-1);
+ }
+
+ return *this;
+}
+
+Ztring& Ztring::From_Number (const float80 F, int8u Precision, ztring_t Options)
+{
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) ) || defined(__mips__) || defined(__mipsel__)
+ Char C1[100];
+ _tnprintf (C1, 99, (Ztring(_T("%."))+Ztring::ToZtring(Precision)+_T("f")).c_str(), F);
+ assign(C1);
+ #else
+ toStringStream SS;
+ SS << setprecision(Precision) << fixed << F;
+ assign(SS.str());
+ #if defined(__BORLANDC__)
+ FindAndReplace(_T(","), _T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
+ #endif
+ #endif
+
+ if ((Options & Ztring_NoZero && size()>0) && find(_T('.'))>0)
+ {
+ while (size()>0 && ((*this)[size()-1]==_T('0')))
+ resize(size()-1);
+ if (size()>0 && (*this)[size()-1]==_T('.'))
+ resize(size()-1);
+ }
+
+ return *this;
+}
+
+#ifdef NEED_SIZET
+Ztring& Ztring::From_Number (const size_t I, int8u Radix)
+{
+ toStringStream SS;
+ SS << setbase(Radix) << I;
+ assign(SS.str());
+ MakeUpperCase();
+ return *this;
+}
+#endif //NEED_SIZET
+
+Ztring& Ztring::From_BCD (const int8u I)
+{
+ #if ( defined(__sun__) && !defined(__sparc__) )
+ clear();
+ append(1, _T('0')+I/0x10);
+ append(1, _T('0')+I%0x10);
+ #else
+ toStringStream SS;
+ SS << I/0x10;
+ SS << I%0x10;
+ assign(SS.str());
+ #endif
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+Ztring& Ztring::Duration_From_Milliseconds (const int64s Value_)
+{
+ int64s Value=Value_;
+ bool Negative=false;
+ if (Value<0)
+ {
+ Value=-Value;
+ Negative=true;
+ }
+
+ int64u HH=(int8u)(Value/1000/60/60);
+ int64u MM=Value/1000/60 -((HH*60));
+ int64u SS=Value/1000 -((HH*60+MM)*60);
+ int64u MS=Value -((HH*60+MM)*60+SS)*1000;
+ Ztring DateT;
+ Ztring Date;
+ DateT.From_Number(HH); if (DateT.size()<2){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(MM); if (DateT.size()<2){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(SS); if (DateT.size()<2){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ Date+=_T(".");
+ DateT.From_Number(MS); if (DateT.size()<2){DateT=Ztring(_T("00"))+DateT;} else if (DateT.size()<3){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ if (Negative)
+ {
+ assign(_T("-"));
+ append(Date);
+ }
+ else
+ assign (Date.c_str());
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+Ztring& Ztring::Duration_From_Milliseconds (const int64u Value)
+{
+ int64u HH=(int8u)(Value/1000/60/60);
+ int64u MM=Value/1000/60 -((HH*60));
+ int64u SS=Value/1000 -((HH*60+MM)*60);
+ int64u MS=Value -((HH*60+MM)*60+SS)*1000;
+ Ztring DateT;
+ Ztring Date;
+ DateT.From_Number(HH); if (DateT.size()<2){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(MM); if (DateT.size()<2){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(SS); if (DateT.size()<2){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ Date+=_T(".");
+ DateT.From_Number(MS); if (DateT.size()<2){DateT=Ztring(_T("00"))+DateT;} else if (DateT.size()<3){DateT=Ztring(_T("0"))+DateT;}
+ Date+=DateT;
+ assign (Date.c_str());
+ return *this;
+}
+
+Ztring& Ztring::Date_From_Milliseconds_1601 (const int64u Value)
+{
+ if (Value>=11644473600000LL) //Values <1970 are not supported
+ {
+ Date_From_Seconds_1970((int32u)((Value-11644473600000LL)/1000));
+ append(_T("."));
+ Ztring Milliseconds; Milliseconds.From_Number(Value%1000);
+ while (Milliseconds.size()<3)
+ Milliseconds+=_T('0');
+ append(Milliseconds);
+ }
+ else
+ clear(); //Not supported
+
+ return *this;
+}
+
+Ztring& Ztring::Date_From_Seconds_1601 (const int64u Value)
+{
+ if (Value>=11644473600LL) //Values <1970 are not supported
+ Date_From_Seconds_1970((int32u)(Value-11644473600LL));
+ else
+ clear(); //Not supported
+
+ return *this;
+}
+
+Ztring& Ztring::Date_From_Seconds_1904 (const int64u Value)
+{
+ #ifdef ZENLIB_USEWX
+ /*
+ wxDateTime Date;
+ Date.SetYear(1904);
+ Date.SetMonth(wxDateTime::Jan);
+ Date.SetDay(1);
+ Date.SetHour(0);
+ Date.SetMinute(0);
+ Date.SetSecond(0);
+ if (Value>=0x80000000)
+ {
+ //wxTimeSpan doesn't support unsigned int
+ int64u Value2=Value;
+ while (Value2>0x7FFFFFFF)
+ {
+ Date+=wxTimeSpan::Seconds(0x7FFFFFFF);
+ Value2-=0x7FFFFFFF;
+ }
+ Date+=wxTimeSpan::Seconds(Value2);
+ }
+ else
+ Date+=wxTimeSpan::Seconds(Value);
+
+ Ztring ToReturn=_T("UTC ");
+ ToReturn+=Date.FormatISODate();
+ ToReturn+=_T(" ");
+ ToReturn+=Date.FormatISOTime();
+
+ assign (ToReturn.c_str());
+ */ //WxDateTime is buggy???
+ if (Value>2082844800 && Value<2082844800+0x100000000LL) //Values <1970 and >2038 are not supported, 1970-01-01 00:00:00 is considered as not possible too
+ Date_From_Seconds_1970((int32u)(Value-2082844800));
+ else
+ clear(); //Not supported
+
+ #else //ZENLIB_USEWX
+ if (Value>2082844800 && Value<2082844800+0x100000000LL) //Values <1970 and >2038 are not supported, 1970-01-01 00:00:00 is considered as not possible too
+ Date_From_Seconds_1970((int32u)(Value-2082844800));
+ else
+ clear(); //Not supported
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+Ztring& Ztring::Date_From_Seconds_1970 (const int32u Value)
+{
+ time_t Time=(time_t)Value;
+ struct tm *Gmt=gmtime(&Time);
+ Ztring DateT;
+ Ztring Date=_T("UTC ");
+ Date+=Ztring::ToZtring((Gmt->tm_year+1900));
+ Date+=_T("-");
+ DateT.From_Number(Gmt->tm_mon+1); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_mon+1);}
+ Date+=DateT;
+ Date+=_T("-");
+ DateT.From_Number(Gmt->tm_mday); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_mday);}
+ Date+=DateT;
+ Date+=_T(" ");
+ DateT.From_Number(Gmt->tm_hour); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_hour);}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT=Ztring::ToZtring(Gmt->tm_min); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_min);}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(Gmt->tm_sec); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_sec);}
+ Date+=DateT;
+ assign (Date.c_str());
+ return *this;
+}
+
+Ztring& Ztring::Date_From_Seconds_1970_Local (const int32u Value)
+{
+ time_t Time=(time_t)Value;
+ struct tm *Gmt=localtime(&Time);
+ Ztring DateT;
+ Ztring Date;
+ Date+=Ztring::ToZtring((Gmt->tm_year+1900));
+ Date+=_T("-");
+ DateT.From_Number(Gmt->tm_mon+1); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_mon+1);}
+ Date+=DateT;
+ Date+=_T("-");
+ DateT.From_Number(Gmt->tm_mday); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_mday);}
+ Date+=DateT;
+ Date+=_T(" ");
+ DateT.From_Number(Gmt->tm_hour); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_hour);}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT=Ztring::ToZtring(Gmt->tm_min); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_min);}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(Gmt->tm_sec); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Gmt->tm_sec);}
+ Date+=DateT;
+ assign (Date.c_str());
+ return *this;
+}
+
+Ztring& Ztring::Date_From_String (const char* Value, size_t Value_Size)
+{
+ //Only the year
+ if (Value_Size<10)
+ {
+ From_Local(Value, 0, Value_Size);
+ return *this;
+ }
+
+ #ifdef ZENLIB_USEWX
+ Ztring ToReturn=_T("UTC ");
+ wxDateTime Date;
+ Ztring DateS;
+ DateS.From_Local(Value, Value_Size).c_str();
+ if (!DateS.empty() && DateS[DateS.size()-1]==_T('\n'))
+ DateS.resize(DateS.size()-1);
+
+ //Some strange formating : exactly 24 bytes (or 25 with 0x0A at the end) and Year is at the end
+ if (DateS.size()==24 && DateS[23]>=_T('0') && DateS[23]<=_T('9') && DateS[21]>=_T('0') && DateS[21]<=_T('9') && DateS[19]==_T(' '))
+ Date.ParseFormat(DateS.c_str(), _T("%a %b %d %H:%M:%S %Y"));
+ //ISO date
+ else if (DateS.size()==10 && (DateS[4]<_T('0') || DateS[4]>_T('9')) && (DateS[7]<_T('0') || DateS[7]>_T('9')))
+ {
+ DateS[4]=_T('-');
+ DateS[7]=_T('-');
+ ToReturn+=DateS;
+ }
+ //Default
+ else
+ Date.ParseDateTime(DateS.c_str());
+
+ if (ToReturn.size()<5)
+ {
+ ToReturn+=Date.FormatISODate();
+ ToReturn+=_T(" ");
+ ToReturn+=Date.FormatISOTime();
+ }
+ else if (ToReturn.size()<5)
+ ToReturn+=DateS;
+
+ assign (ToReturn.c_str());
+ #else //ZENLIB_USEWX
+ Ztring DateS; DateS.From_Local(Value, 0, Value_Size);
+ if (DateS.size()==20 && DateS[4]==_T('-') && DateS[7]==_T('-') && DateS[10]==_T('T') && DateS[13]==_T(':') && DateS[16]==_T(':') && DateS[19]==_T('Z'))
+ {
+ DateS.resize(19);
+ DateS[10]=_T(' ');
+ assign(_T("UTC "));
+ append(DateS);
+ }
+ else if (DateS.size()==23 && DateS[4]==_T('-') && DateS[7]==_T('-') && DateS[10]==_T(' ') && DateS[14]==_T(' ') && DateS[17]==_T(':') && DateS[20]==_T(':'))
+ {
+ DateS.erase(10, 4);
+ //assign(_T("UTC ")); //Is not UTC
+ append(DateS);
+ }
+ else
+ From_Local(Value, 0, Value_Size); //Not implemented
+ #endif //ZENLIB_USEWX
+ return *this;
+}
+
+Ztring& Ztring::Date_From_Numbers (const int8u Year, const int8u Month, const int8u Day, const int8u Hour, const int8u Minute, const int8u Second)
+{
+ Ztring DateT;
+ Ztring Date=_T("UTC ");
+ DateT.From_Number(Year); if (DateT.size()<2){DateT=Ztring(_T("200"))+Ztring::ToZtring(Year);}; if (DateT.size()<3){DateT=Ztring(_T("20"))+Ztring::ToZtring(Year);}
+ Date+=DateT;
+ Date+=_T("-");
+ DateT.From_Number(Month); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Month);}
+ Date+=DateT;
+ Date+=_T("-");
+ DateT.From_Number(Day); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Day);}
+ Date+=DateT;
+ Date+=_T(" ");
+ DateT.From_Number(Hour); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Hour);}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT=Ztring::ToZtring(Minute); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Minute);}
+ Date+=DateT;
+ Date+=_T(":");
+ DateT.From_Number(Second); if (DateT.size()<2){DateT=Ztring(_T("0"))+Ztring::ToZtring(Second);}
+ Date+=DateT;
+ assign (Date.c_str());
+ return *this;
+}
+
+#ifndef WSTRING_MISSING
+//---------------------------------------------------------------------------
+std::wstring Ztring::To_Unicode () const
+{
+ #ifdef _UNICODE
+ return c_str();
+ #else //_UNICODE
+ #ifdef ZENLIB_USEWX
+ return wxConvCurrent->cMB2WC(c_str()).data();
+ #else //ZENLIB_USEWX
+ return std::wstring(); //Not implemented
+ #endif //ZENLIB_USEWX
+ #endif //_UNICODE
+}
+#endif //WSTRING_MISSING
+
+std::string Ztring::To_UTF8 () const
+{
+ #ifdef _UNICODE
+ #ifdef ZENLIB_USEWX
+ return wxConvUTF8.cWC2MB(c_str()).data();
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ if (IsWin9X())
+ {
+ std::string ToReturn;
+ const wchar_t* Z=c_str();
+ while (*Z) //0 is end
+ {
+ //1 byte
+ if (*Z<0x80)
+ ToReturn += (char) (*Z);
+ else if (*Z<0x1000)
+ {
+ ToReturn += (char)(((*Z)>> 6)&0x1F);
+ ToReturn += (char)( (*Z) &0x3F);
+ }
+ else
+ break; //Bad character (or UTF-16LE, not yet supported)
+ Z++;
+ }
+ return ToReturn;
+ }
+ else
+ {
+ int Size=WideCharToMultiByte(CP_UTF8, 0, c_str(), -1, NULL, 0, NULL, NULL);
+ if (Size!=0)
+ {
+ char* AnsiString=new char[Size+1];
+ WideCharToMultiByte(CP_UTF8, 0, c_str(), -1, AnsiString, Size, NULL, NULL);
+ AnsiString[Size]='\0';
+ std::string ToReturn(AnsiString);
+ delete[] AnsiString; //AnsiString=NULL;
+ return ToReturn;
+ }
+ else
+ return std::string();
+ }
+ #else //WINDOWS
+ std::string ToReturn;
+ const wchar_t* Z=c_str();
+ while (*Z) //0 is end
+ {
+ //1 byte
+ if (*Z<0x80)
+ ToReturn += (char) (*Z);
+ else if (*Z<0x1000)
+ {
+ ToReturn += (char)(((*Z)>> 6)&0x1F);
+ ToReturn += (char)( (*Z) &0x3F);
+ }
+ else if (*Z<0x40000)
+ {
+ ToReturn += (char)(((*Z)>>12)&0x0F);
+ ToReturn += (char)(((*Z)>> 6)&0x3F);
+ ToReturn += (char)( (*Z) &0x3F);
+ }
+ else if (*Z<0x1000000)
+ {
+ ToReturn += (char)(((*Z)>>18)&0x07);
+ ToReturn += (char)(((*Z)>>12)&0x3F);
+ ToReturn += (char)(((*Z)>> 6)&0x3F);
+ ToReturn += (char)( (*Z) &0x3F);
+ }
+ else
+ break; //Bad character
+ Z++;
+ }
+ return ToReturn;
+ #endif
+ #endif //ZENLIB_USEWX
+ #else
+ #ifdef ZENLIB_USEWX
+ return wxConvUTF8.cWC2MB(wxConvCurrent->cMB2WC(c_str())).data();
+ #else //ZENLIB_USEWX
+ return c_str(); //Not implemented
+ #endif //ZENLIB_USEWX
+ #endif
+}
+
+std::string Ztring::To_Local () const
+{
+ #ifdef _UNICODE
+ #ifdef ZENLIB_USEWX
+ wxCharBuffer C=wxConvCurrent->cWC2MB(c_str());
+ if (C.data())
+ return C.data();
+ else
+ return std::string();
+ #else //ZENLIB_USEWX
+ #ifdef WINDOWS
+ int Size=WideCharToMultiByte(CP_ACP, 0, c_str(), -1, NULL, 0, NULL, NULL);
+ if (Size!=0)
+ {
+ char* AnsiString=new char[Size+1];
+ WideCharToMultiByte(CP_ACP, 0, c_str(), -1, AnsiString, Size, NULL, NULL);
+ AnsiString[Size]='\0';
+ std::string ToReturn(AnsiString);
+ delete[] AnsiString; //AnsiString=NULL;
+ return ToReturn;
+ }
+ else
+ return std::string();
+ #else //WINDOWS
+ if (empty())
+ return std::string();
+
+ size_t Size=wcstombs(NULL, c_str(), 0);
+ if (Size!=0 && Size!=(size_t)-1)
+ {
+ char* AnsiString=new char[Size+1];
+ Size=wcstombs(AnsiString, c_str(), Size);
+ if (Size!=0 && Size!=(size_t)-1)
+ {
+ AnsiString[Size]='\0';
+ std::string ToReturn(AnsiString);
+ delete[] AnsiString; //AnsiString=NULL;
+ return ToReturn;
+ }
+
+ //Failed
+ delete[] AnsiString; //AnsiString=NULL;
+ }
+
+ //Trying with bad chars
+ char* Result=new char[MB_CUR_MAX];
+ std::string AnsiString;
+ for (size_t Pos=0; Pos<size(); Pos++)
+ {
+ int Result_Size=wctomb(Result, operator[](Pos));
+ if (Result_Size>=0)
+ AnsiString.append(Result, Result_Size);
+ else
+ AnsiString+='?';
+ }
+ delete[] Result; //Result=NULL;
+ return AnsiString;
+ #endif
+ #endif //ZENLIB_USEWX
+ #else
+ return c_str();
+ #endif
+}
+
+//---------------------------------------------------------------------------
+int128u Ztring::To_UUID () const
+{
+ if (size()!=36)
+ return 0;
+
+ Ztring Temp=*this;
+
+ for (size_t Pos=0; Pos<36; Pos++)
+ {
+ if ((Temp[Pos]< _T('0') || Temp[Pos]> _T('9'))
+ && (Temp[Pos]< _T('A') || Temp[Pos]> _T('F'))
+ && (Temp[Pos]< _T('a') || Temp[Pos]> _T('f')))
+ return 0;
+ if (Temp[Pos]>=_T('A') && Temp[Pos]<=_T('F'))
+ {
+ Temp[Pos]-=_T('A');
+ Temp[Pos]+=_T('9')+1;
+ }
+ if (Temp[Pos]>=_T('a') && Temp[Pos]<=_T('f'))
+ {
+ Temp[Pos]-=_T('a');
+ Temp[Pos]+=_T('9')+1;
+ }
+
+ switch(Pos)
+ {
+ case 7 :
+ case 12 :
+ case 17 :
+ case 22 :
+ if (at(Pos+1)!=_T('-'))
+ return 0;
+ Pos++; //Skipping dash in the test
+ }
+ }
+
+ int128u I;
+ I.hi=((int64u)((int8u)(Temp[ 0]-'0'))<<60)
+ | ((int64u)((int8u)(Temp[ 1]-'0'))<<56)
+ | ((int64u)((int8u)(Temp[ 2]-'0'))<<52)
+ | ((int64u)((int8u)(Temp[ 3]-'0'))<<48)
+ | ((int64u)((int8u)(Temp[ 4]-'0'))<<44)
+ | ((int64u)((int8u)(Temp[ 5]-'0'))<<40)
+ | ((int64u)((int8u)(Temp[ 6]-'0'))<<36)
+ | ((int64u)((int8u)(Temp[ 7]-'0'))<<32)
+ | ((int64u)((int8u)(Temp[ 9]-'0'))<<28)
+ | ((int64u)((int8u)(Temp[10]-'0'))<<24)
+ | ((int64u)((int8u)(Temp[11]-'0'))<<20)
+ | ((int64u)((int8u)(Temp[12]-'0'))<<16)
+ | ((int64u)((int8u)(Temp[14]-'0'))<<12)
+ | ((int64u)((int8u)(Temp[15]-'0'))<< 8)
+ | ((int64u)((int8u)(Temp[16]-'0'))<< 4)
+ | ((int64u)((int8u)(Temp[17]-'0')) );
+ I.lo=((int64u)((int8u)(Temp[19]-'0'))<<60)
+ | ((int64u)((int8u)(Temp[20]-'0'))<<56)
+ | ((int64u)((int8u)(Temp[21]-'0'))<<52)
+ | ((int64u)((int8u)(Temp[22]-'0'))<<48)
+ | ((int64u)((int8u)(Temp[24]-'0'))<<44)
+ | ((int64u)((int8u)(Temp[25]-'0'))<<40)
+ | ((int64u)((int8u)(Temp[26]-'0'))<<36)
+ | ((int64u)((int8u)(Temp[27]-'0'))<<32)
+ | ((int64u)((int8u)(Temp[28]-'0'))<<28)
+ | ((int64u)((int8u)(Temp[29]-'0'))<<24)
+ | ((int64u)((int8u)(Temp[30]-'0'))<<20)
+ | ((int64u)((int8u)(Temp[31]-'0'))<<16)
+ | ((int64u)((int8u)(Temp[32]-'0'))<<12)
+ | ((int64u)((int8u)(Temp[33]-'0'))<< 8)
+ | ((int64u)((int8u)(Temp[34]-'0'))<< 4)
+ | ((int64u)((int8u)(Temp[35]-'0')) );
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+int32u Ztring::To_CC4 () const
+{
+ int32u I;
+ I =((int32u)((int8u)at(0))<<24)
+ | ((int32u)((int8u)at(1))<<16)
+ | ((int32u)((int8u)at(2))<< 8)
+ | ((int32u)((int8u)at(3)) );
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int8s Ztring::To_int8s (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ int I;
+ #ifdef __MINGW32__
+ I=_ttoi(c_str());
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atoi(S.c_str());
+ #else //UNICODE
+ I=atoi(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=Error)
+ {
+ float80 F=To_float80();
+ F-=I;
+ if (F>=0.5)
+ return (int8s)I+1;
+ }
+
+ return (int8s)I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int8u Ztring::To_int8u (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ unsigned int I;
+ #ifdef __MINGW32__
+ I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFF - Replaced by i64 version to support, but not good
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atoi(S.c_str());
+ #else //UNICODE
+ I=atoi(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=std::string::npos)
+ {
+ float32 F=To_float32();
+ F-=I;
+ if (F>=0.5)
+ return (int8u)I+1;
+ }
+
+ return (int8u)I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int16s Ztring::To_int16s (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ int I;
+ #ifdef __MINGW32__
+ I=_ttoi(c_str());
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atoi(S.c_str());
+ #else //UNICODE
+ I=atoi(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=Error)
+ {
+ float80 F=To_float80();
+ F-=I;
+ if (F>=0.5)
+ return (int16s)I+1;
+ }
+
+ return (int16s)I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int16u Ztring::To_int16u (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ unsigned int I;
+ #ifdef __MINGW32__
+ I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFF - Replaced by i64 version to support, but not good
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atoi(S.c_str());
+ #else //UNICODE
+ I=atoi(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=std::string::npos)
+ {
+ float32 F=To_float32();
+ F-=I;
+ if (F>=0.5)
+ return (int16u)I+1;
+ }
+
+ return (int16u)I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int32s Ztring::To_int32s (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ int32s I;
+ #ifdef __MINGW32__
+ I=_ttoi(c_str());
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atol(S.c_str());
+ #else //UNICODE
+ I=atol(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=Error)
+ {
+ float80 F=To_float80();
+ F-=I;
+ if (F>=0.5)
+ return I+1;
+ }
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int32u Ztring::To_int32u (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ int32u I;
+ #ifdef __MINGW32__
+ I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFF - Replaced by i64 version to support, but not good
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atol(S.c_str());
+ #else //UNICODE
+ I=atol(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=std::string::npos)
+ {
+ float32 F=To_float32();
+ F-=I;
+ if (F>=0.5)
+ return I+1;
+ }
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int64s Ztring::To_int64s (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ int64s I;
+ #ifdef __MINGW32__
+ I=_ttoi64(c_str());
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atoll(S.c_str());
+ #else //UNICODE
+ I=atoll(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=std::string::npos)
+ {
+ float32 F=To_float32();
+ F-=I;
+ if (F>0.5)
+ return I+1;
+ }
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToInt
+int64u Ztring::To_int64u (int8u Radix, ztring_t Options) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ int64u I;
+ #ifdef __MINGW32__
+ I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFFFFFFFFFF
+ #elif ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ std::string S=To_UTF8();
+ I=atoll(S.c_str());
+ #else //UNICODE
+ I=atoll(c_str());
+ #endif //UNICODE
+ #else
+ tStringStream SS(*this);
+ SS >> setbase(Radix) >> I;
+ if (SS.fail())
+ return 0;
+ #endif
+
+ //Rounded
+ if (Options==Ztring_Rounded && find(_T("."))!=std::string::npos)
+ {
+ float32 F=To_float32();
+ F-=I;
+ if (F>=0.5)
+ return I+1;
+ }
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+int128u Ztring::To_int128u (int8u, ztring_t) const
+{
+ if (size()!=32)
+ return 0;
+
+ Ztring Temp=*this;
+
+ for (size_t Pos=0; Pos<32; Pos++)
+ {
+ if ((Temp[Pos]< _T('0') || Temp[Pos]> _T('9'))
+ && (Temp[Pos]< _T('A') || Temp[Pos]> _T('F'))
+ && (Temp[Pos]< _T('a') || Temp[Pos]> _T('f')))
+ return 0;
+ if (Temp[Pos]>=_T('A') && Temp[Pos]<=_T('F'))
+ {
+ Temp[Pos]-=_T('A');
+ Temp[Pos]+=_T('9')+1;
+ }
+ if (Temp[Pos]>=_T('a') && Temp[Pos]<=_T('f'))
+ {
+ Temp[Pos]-=_T('a');
+ Temp[Pos]+=_T('9')+1;
+ }
+ }
+
+ int128u I;
+ I.hi=((int64u)((int8u)(Temp[ 0]-'0'))<<60)
+ | ((int64u)((int8u)(Temp[ 1]-'0'))<<56)
+ | ((int64u)((int8u)(Temp[ 2]-'0'))<<52)
+ | ((int64u)((int8u)(Temp[ 3]-'0'))<<48)
+ | ((int64u)((int8u)(Temp[ 4]-'0'))<<44)
+ | ((int64u)((int8u)(Temp[ 5]-'0'))<<40)
+ | ((int64u)((int8u)(Temp[ 6]-'0'))<<36)
+ | ((int64u)((int8u)(Temp[ 7]-'0'))<<32)
+ | ((int64u)((int8u)(Temp[ 8]-'0'))<<28)
+ | ((int64u)((int8u)(Temp[ 9]-'0'))<<24)
+ | ((int64u)((int8u)(Temp[10]-'0'))<<20)
+ | ((int64u)((int8u)(Temp[11]-'0'))<<16)
+ | ((int64u)((int8u)(Temp[12]-'0'))<<12)
+ | ((int64u)((int8u)(Temp[13]-'0'))<< 8)
+ | ((int64u)((int8u)(Temp[14]-'0'))<< 4)
+ | ((int64u)((int8u)(Temp[15]-'0')) );
+ I.lo=((int64u)((int8u)(Temp[16]-'0'))<<60)
+ | ((int64u)((int8u)(Temp[17]-'0'))<<56)
+ | ((int64u)((int8u)(Temp[18]-'0'))<<52)
+ | ((int64u)((int8u)(Temp[19]-'0'))<<48)
+ | ((int64u)((int8u)(Temp[20]-'0'))<<44)
+ | ((int64u)((int8u)(Temp[21]-'0'))<<40)
+ | ((int64u)((int8u)(Temp[22]-'0'))<<36)
+ | ((int64u)((int8u)(Temp[23]-'0'))<<32)
+ | ((int64u)((int8u)(Temp[24]-'0'))<<28)
+ | ((int64u)((int8u)(Temp[25]-'0'))<<24)
+ | ((int64u)((int8u)(Temp[26]-'0'))<<20)
+ | ((int64u)((int8u)(Temp[27]-'0'))<<16)
+ | ((int64u)((int8u)(Temp[28]-'0'))<<12)
+ | ((int64u)((int8u)(Temp[29]-'0'))<< 8)
+ | ((int64u)((int8u)(Temp[30]-'0'))<< 4)
+ | ((int64u)((int8u)(Temp[31]-'0')) );
+
+ return I;
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToFloat
+float32 Ztring::To_float32(ztring_t) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ return (wcstod(c_str(),NULL));
+ #else
+ return (strtod(c_str(),NULL));
+ #endif
+ #else
+ float32 F;
+ tStringStream SS(*this);
+ SS >> F;
+ if (SS.fail())
+ return 0;
+
+ return F;
+ #endif
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToFloat
+float64 Ztring::To_float64(ztring_t) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ return (wcstod(c_str(),NULL)); //TODO verify no wcstold
+ #else
+ return (strtod(c_str(),NULL)); //TODO verify no strtold
+ #endif
+ #else
+ float64 F;
+ tStringStream SS(*this);
+ SS >> F;
+ if (SS.fail())
+ return 0;
+
+ return F;
+ #endif
+}
+
+//---------------------------------------------------------------------------
+//Operateur ToFloat
+float80 Ztring::To_float80(ztring_t) const
+{
+ //Integrity
+ if (empty())
+ return 0;
+
+ //Conversion
+ #if defined(__MINGW32__) || ( defined(__sun__) && !defined(__sparc__) )
+ #ifdef UNICODE
+ return (wcstod(c_str(),NULL)); //TODO verify no wcstold
+ #else
+ return (strtod(c_str(),NULL)); //TODO verify no strtold
+ #endif
+ #else
+ float80 F;
+ tStringStream SS(*this);
+ SS >> F;
+ if (SS.fail())
+ return 0;
+
+ return F;
+ #endif
+}
+
+//***************************************************************************
+// Edition
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Retourne une partie de la chaine
+Ztring Ztring::SubString (const tstring &Begin, const tstring &End, size_type Pos, ztring_t Options) const
+{
+ //Recherche Début
+ size_type I_Debut=find(Begin, Pos);
+ if (I_Debut==Error)
+ return Ztring();
+ I_Debut+=Begin.size();
+
+ //gestion fin NULL
+ if (End.empty())
+ return substr(I_Debut);
+
+ //Recherche Fin
+ size_type I_Fin=find(End, I_Debut);
+ if (I_Fin==Error)
+ {
+ if (Options & Ztring_AddLastItem)
+ return substr(I_Debut);
+ else
+ return Ztring();
+ }
+
+ return substr(I_Debut, I_Fin-I_Debut);
+}
+
+//---------------------------------------------------------------------------
+//FindAndReplace
+Ztring::size_type Ztring::FindAndReplace (const ZenLib::tstring &ToFind, const ZenLib::tstring &ReplaceBy, size_type Pos, ZenLib::ztring_t Options)
+{
+ if (ToFind.empty())
+ return 0;
+
+ size_type Count=0;
+ size_type Middle=Pos;
+ while (!(Count==1 && !(Options&Ztring_Recursive)) && (Middle=find(ToFind, Middle))!=npos)
+ {
+ replace(Middle, ToFind.length(), ReplaceBy);
+ Middle += ReplaceBy.length();
+ Count++;
+ }
+
+ return Count;
+}
+
+//---------------------------------------------------------------------------
+//test if it is a number
+bool Ztring::IsNumber() const
+{
+ if (empty())
+ return false;
+
+ bool OK=true;
+ size_t Size=size();
+ for (size_t Pos=0; Pos<Size; Pos++)
+ if (operator[](Pos)<_T('0') || operator[](Pos)>_T('9'))
+ {
+ OK=false;
+ break;
+ }
+ return OK;
+}
+
+//---------------------------------------------------------------------------
+//Mise en minuscules
+Ztring &Ztring::MakeLowerCase()
+{
+ transform(begin(), end(), begin(), (int(*)(int))tolower); //(int(*)(int)) is a patch for unix
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Mise en majuscules
+Ztring &Ztring::MakeUpperCase()
+{
+ transform(begin(), end(), begin(), (int(*)(int))toupper); //(int(*)(int)) is a patch for unix
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Remove leading whitespaces from a string
+Ztring &Ztring::TrimLeft(Char ToTrim)
+{
+ size_type First=0;
+ while (First<size() && operator[](First)==ToTrim)
+ First++;
+ assign (c_str()+First);
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Remove trailing whitespaces from a string
+Ztring &Ztring::TrimRight(Char ToTrim)
+{
+ if (size()==0)
+ return *this;
+
+ size_type Last=size()-1;
+ while (Last!=(size_type)-1 && operator[](Last)==ToTrim)
+ Last--;
+ assign (c_str(), Last+1);
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Remove leading and trailing whitespaces from a string
+Ztring &Ztring::Trim(Char ToTrim)
+{
+ TrimLeft(ToTrim);
+ TrimRight(ToTrim);
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Quotes a string
+Ztring &Ztring::Quote(Char ToTrim)
+{
+ assign(tstring(1, ToTrim)+c_str()+ToTrim);
+ return *this;
+}
+
+//***************************************************************************
+// Information
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Count
+Ztring::size_type Ztring::Count (const Ztring &ToCount, ztring_t) const
+{
+ size_type Count=0;
+ for (size_type Pos=0; Pos<=size(); Pos++)
+ if (find(ToCount, Pos)!=npos)
+ {
+ Count++;
+ Pos+=ToCount.size()-1; //-1 because the loop will add 1
+ }
+ return Count;
+}
+
+//---------------------------------------------------------------------------
+//Compare
+bool Ztring::Compare (const Ztring &ToCompare, const Ztring &Comparator, ztring_t Options) const
+{
+ //Integers management
+ if (IsNumber() && ToCompare.IsNumber())
+ {
+ int64s Left=To_int64s();
+ int64s Right=ToCompare.To_int64s();
+ if (Comparator==_T("==")) return (Left==Right);
+ if (Comparator==_T("<")) return (Left< Right);
+ if (Comparator==_T("<=")) return (Left<=Right);
+ if (Comparator==_T(">=")) return (Left>=Right);
+ if (Comparator==_T(">")) return (Left> Right);
+ if (Comparator==_T("!=")) return (Left!=Right);
+ if (Comparator==_T("<>")) return (Left!=Right);
+ return false;
+ }
+
+ //Case sensitive option
+ if (!(Options & Ztring_CaseSensitive))
+ {
+ //Need to copy strings and make it lowercase
+ Ztring Left (c_str());
+ Ztring Right (ToCompare.c_str());
+ Left.MakeLowerCase();
+ Right.MakeLowerCase();
+
+ //string comparasion
+ if (Comparator==_T("==")) return (Left==Right);
+ if (Comparator==_T("IN")) {if (Left.find(Right)!=string::npos) return true; else return false;}
+ if (Comparator==_T("<")) return (Left< Right);
+ if (Comparator==_T("<=")) return (Left<=Right);
+ if (Comparator==_T(">=")) return (Left>=Right);
+ if (Comparator==_T(">")) return (Left> Right);
+ if (Comparator==_T("!=")) return (Left!=Right);
+ if (Comparator==_T("<>")) return (Left!=Right);
+ return false;
+ }
+ else
+ {
+ //string comparasion
+ if (Comparator==_T("==")) return (*this==ToCompare);
+ if (Comparator==_T("IN")) {if (this->find(ToCompare)!=string::npos) return true; else return false;}
+ if (Comparator==_T("<")) return (*this< ToCompare);
+ if (Comparator==_T("<=")) return (*this<=ToCompare);
+ if (Comparator==_T(">=")) return (*this>=ToCompare);
+ if (Comparator==_T(">")) return (*this> ToCompare);
+ if (Comparator==_T("!=")) return (*this!=ToCompare);
+ if (Comparator==_T("<>")) return (*this!=ToCompare);
+ return false;
+ }
+}
+
+} //namespace
+
diff --git a/src/thirdparty/ZenLib/Ztring.h b/src/thirdparty/ZenLib/Ztring.h
new file mode 100644
index 000000000..9941f1777
--- /dev/null
+++ b/src/thirdparty/ZenLib/Ztring.h
@@ -0,0 +1,365 @@
+// ZenLib::Ztring - More methods for std::(w)string
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// More methods for std::(w)string
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_ZtringH
+#define ZenLib_ZtringH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf.h"
+#include "ZenLib/Utils.h"
+#include "ZenLib/int128u.h"
+#include <string>
+#include <sstream>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+typedef std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > tstring;
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+/// @brief Options for Ztring methods
+enum ztring_t
+{
+ Ztring_Nothing,
+ Ztring_Rounded = 1, ///< if >.5, upper, else lower
+ Ztring_CaseSensitive = 2, ///< Case sensitive ("A" and "a" are different)
+ Ztring_AddLastItem = 4, ///< if Begin is found and End is not found, return between Begin and end of string
+ Ztring_Recursive = 8, ///< Do all strings
+ Ztring_NoZero =16 ///> Doesn't keep Zero in the float number
+};
+
+//---------------------------------------------------------------------------
+
+//***************************************************************************
+/// @brief String manipulation (based on std::(w)string)
+//***************************************************************************
+
+class Ztring : public tstring //for details about undocumented methods see http://www.sgi.com/tech/stl/basic_string.html
+{
+public :
+ //Constructor/destructor
+ Ztring () : tstring(){};
+ Ztring (const tstring& str) : tstring(str){};
+ Ztring (const tstring& str, size_type pos, size_type n=npos) : tstring(str, pos, n){};
+ Ztring (const Char* s, size_type n) : tstring(s, n){};
+ Ztring (const Char* s) : tstring(s){};
+ Ztring (size_type n, Char c) : tstring(n, c){};
+ #ifdef UNICODE
+ Ztring (const char* S) : tstring(){From_UTF8(S);};
+ Ztring (const char* S, size_type n) : tstring(){From_UTF8(S, 0, n);};
+ #endif //UNICODE
+
+ //Operators
+ ///Same as [], but resize the string if Pos doesn't exist yet
+ Char &operator () (size_type Pos);
+
+ //Assign
+ bool Assign_FromFile (const Ztring &FileName);
+
+ //Conversions - From
+ #ifndef WSTRING_MISSING
+ /// @brief convert an Unicode encoded string into Ztring
+ Ztring& From_Unicode (const std::wstring &S) {return From_Unicode(S.c_str());};
+ #endif //WSTRING_MISSING
+ /// @brief convert an Unicode encoded string into Ztring
+ Ztring& From_Unicode (const wchar_t *S);
+ /// @brief convert an Unicode encoded string into Ztring
+ Ztring& From_Unicode (const wchar_t *S, size_type Start, size_type Length);
+ /// @brief convert an Unicode encoded string into Ztring
+ Ztring& From_Unicode (const wchar_t *S, size_type Length) {return From_Unicode(S, 0, Length);};
+ /// @brief convert an UTF-8 encoded string into Ztring
+ Ztring& From_UTF8 (const std::string &S) {return From_UTF8(S.c_str());};
+ /// @brief convert an UTF-8 encoded string into Ztring
+ Ztring& From_UTF8 (const char *S);
+ /// @brief convert an UTF-8 encoded string into Ztring
+ Ztring& From_UTF8 (const char *S, size_type Start, size_type Length);
+ /// @brief convert an UTF-8 encoded string into Ztring
+ Ztring& From_UTF8 (const char *S, size_type Length) {return From_UTF8(S, 0, Length);};
+ /// @brief convert an UTF-16 encoded string into Ztring
+ Ztring& From_UTF16 (const char *S);
+ /// @brief convert an UTF-16 encoded string into Ztring
+ Ztring& From_UTF16 (const char *S, size_type Start, size_type Length);
+ /// @brief convert an UTF-16 encoded string into Ztring
+ Ztring& From_UTF16 (const char *S, size_type Length) {return From_UTF16(S, 0, Length);};
+ /// @brief convert an UTF-16BE encoded string into Ztring
+ Ztring& From_UTF16BE (const char *S);
+ /// @brief convert an UTF-16BE encoded string into Ztring
+ Ztring& From_UTF16BE (const char *S, size_type Start, size_type Length);
+ /// @brief convert an UTF-16BE encoded string into Ztring
+ Ztring& From_UTF16BE (const char *S, size_type Length) {return From_UTF16BE(S, 0, Length);};
+ /// @brief convert an UTF-16LE encoded string into Ztring
+ Ztring& From_UTF16LE (const char *S);
+ /// @brief convert an UTF-16LE encoded string into Ztring
+ Ztring& From_UTF16LE (const char *S, size_type Start, size_type Length);
+ /// @brief convert an UTF-16LE encoded string into Ztring
+ Ztring& From_UTF16LE (const char *S, size_type Length) {return From_UTF16LE(S, 0, Length);};
+ /// @brief convert an Locael encoded string into Ztring
+ Ztring& From_Local (const std::string &S) {return From_Local(S.c_str());};
+ /// @brief convert an Local encoded string into Ztring
+ Ztring& From_Local (const char *S);
+ /// @brief convert an Local encoded string into Ztring
+ Ztring& From_Local (const char *S, size_type Start, size_type Length);
+ /// @brief convert an Local encoded string into Ztring
+ Ztring& From_Local (const char *S, size_type Length) {return From_Local(S, 0, Length);};
+
+ /// @brief convert an ISO-8859-1 encoded string into Ztring
+ Ztring& From_ISO_8859_1 (const char *S);
+ /// @brief convert an ISO-8859-1 encoded string into Ztring
+ Ztring& From_ISO_8859_1 (const char *S, size_type Start, size_type Length);
+ /// @brief convert an ISO-8859-1 encoded string into Ztring
+ Ztring& From_ISO_8859_1 (const char *S, size_type Length) {return From_ISO_8859_1(S, 0, Length);};
+
+ /// @brief convert an 16 byte GUID into Ztring
+ Ztring& From_GUID (const int128u S);
+ /// @brief convert an 16 byte UUID into Ztring
+ Ztring& From_UUID (const int128u S);
+ /// @brief convert an 4 Character Code into Ztring
+ Ztring& From_CC4 (const char *S) {return From_Local(S, 0, 4);};
+ /// @brief convert an 4 Character Code into Ztring
+ Ztring& From_CC4 (const int8u *S) {return From_Local((const char*)S, 0, 4);};
+ /// @brief convert an 4 Character Code into Ztring
+ Ztring& From_CC4 (const int32u S);
+ /// @brief convert an 2 Character Code into Ztring
+ Ztring& From_CC3 (const char *S) {return From_Local(S, 0, 3);};
+ /// @brief convert an 4 Character Code into Ztring
+ Ztring& From_CC3 (const int8u *S) {return From_Local((const char*)S, 0, 3);};
+ /// @brief convert an 4 Character Code into Ztring
+ Ztring& From_CC3 (const int32u S);
+ /// @brief convert an 2 Character Code into Ztring
+ Ztring& From_CC2 (const char *S) {return From_CC2(ZenLib::CC2(S));};
+ /// @brief convert an 2 Character Code into Ztring
+ Ztring& From_CC2 (const int8u *S) {return From_CC2(ZenLib::CC2(S));};
+ /// @brief convert an 2 Character Code into Ztring
+ Ztring& From_CC2 (const int16u S);
+ /// @brief convert an 1 Character Code into Ztring
+ Ztring& From_CC1 (const char *S) {return From_CC1(ZenLib::CC1(S));};
+ /// @brief convert an 1 Character Code into Ztring
+ Ztring& From_CC1 (const int8u *S) {return From_CC1(ZenLib::CC1(S));};
+ /// @brief convert an 1 Character Code into Ztring
+ Ztring& From_CC1 (const int8u S);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int8s, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int8u, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int16s, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int16u, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int32s, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int32u, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int64s, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int64u, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const int128u, int8u Radix=10);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const float32, int8u AfterComma=3, ztring_t Options=Ztring_Nothing);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const float64, int8u AfterComma=3, ztring_t Options=Ztring_Nothing);
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const float80, int8u AfterComma=3, ztring_t Options=Ztring_Nothing);
+ #ifdef NEED_SIZET
+ /// @brief convert number into Ztring
+ Ztring& From_Number (const size_t, int8u Radix=10);
+ #endif //NEED_SIZET
+ /// @brief convert number (BCD coded) into Ztring
+ Ztring& From_BCD (const int8u);
+ /// @brief convert count of milliseconds into a readable and sortable string
+ Ztring& Duration_From_Milliseconds (const int64s Milliseconds);
+ /// @deprecated replaced by the int64s version
+ Ztring& Duration_From_Milliseconds (const int64u Milliseconds);
+ /// @brief convert count of seconds since 1601 into a readable and sortable string
+ Ztring& Date_From_Milliseconds_1601 (const int64u Milliseconds);
+ /// @brief convert count of seconds since 1601 into a readable and sortable string
+ Ztring& Date_From_Seconds_1601 (const int64u Seconds);
+ /// @brief convert count of seconds since 1970 into a readable and sortable string
+ Ztring& Date_From_Seconds_1904 (const int64u Seconds);
+ /// @brief convert count of seconds since 1970 into a readable and sortable string
+ Ztring& Date_From_Seconds_1970 (const int32u Seconds);
+ /// @brief convert count of seconds since 1970 into a readable and sortable string (in local time)
+ Ztring& Date_From_Seconds_1970_Local (const int32u Seconds);
+ /// @brief convert a free formated string into a readable and sortable string
+ Ztring& Date_From_String (const char* Date, size_type Value_Size=Error);
+ /// @brief convert numbers into a readable and sortable string
+ Ztring& Date_From_Numbers (const int8u Year, const int8u Month, const int8u Day, const int8u Hour, const int8u Minute, const int8u Second);
+
+ //Conversions - To
+ #ifndef WSTRING_MISSING
+ /// @brief Convert into Unicode chars
+ /// @return the string corresponding \n
+ std::wstring To_Unicode () const;
+ #endif //WSTRING_MISSING
+ /// @brief Convert into char* (UTF-8 encoded)
+ /// @return the string corresponding \n
+ std::string To_UTF8 () const;
+ /// @brief Convert into char* (Local encoded)
+ /// @return the string corresponding \n
+ std::string To_Local () const;
+ /// @brief Convert into 16 byte UUID number
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int128u To_UUID () const;
+ /// @brief Convert into a 4 Character Code
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int32u To_CC4 () const;
+ /// @brief Convert into Int (8 bits)
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int8s To_int8s (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into unsigned Int (8 bits)
+ /// @return the value corresponding
+ /// 0 if there is a problem
+ int8u To_int8u (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into Int (16 bits)
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int16s To_int16s (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into unsigned Int (16 bits)
+ /// @return the value corresponding
+ /// 0 if there is a problem
+ int16u To_int16u (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into Int (32 bits)
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int32s To_int32s (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into unsigned Int (32 bits)
+ /// @return the value corresponding
+ /// 0 if there is a problem
+ int32u To_int32u (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into Int (64 bits)
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int64s To_int64s (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into unsigned Int (64 bits)
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int64u To_int64u (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into unsigned Int (64 bits)
+ /// @warning only hexadecimal and no rounding are currenlty supported \n
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ int128u To_int128u (int8u Radix=10, ztring_t Options=Ztring_Rounded) const;
+ /// @brief Convert into float
+ /// @return the value corresponding \n
+ /// 0 if there is a problem
+ float32 To_float32 (ztring_t Options=Ztring_Nothing) const;
+ float64 To_float64 (ztring_t Options=Ztring_Nothing) const;
+ float80 To_float80 (ztring_t Options=Ztring_Nothing) const;
+
+ //Static versions
+ static Ztring ToZtring_From_Local(const std::string &S) {return Ztring().From_Local(S);};
+ static Ztring ToZtring_From_Local(const char *S) {return Ztring().From_Local(S);};
+ static Ztring ToZtring_From_Local(const char *S, size_type Start, size_type Length) {return Ztring().From_Local(S, Start, Length);};
+ static Ztring ToZtring_From_Local(const char *S, size_type Length) {return Ztring().From_Local(S, Length);};
+ static Ztring ToZtring_From_CC4 (const char *S) {return Ztring().From_CC4(S);};
+ static Ztring ToZtring_From_CC4 (const int8u *S) {return Ztring().From_CC4(S);};
+ static Ztring ToZtring_From_CC4 (const int32u S) {return Ztring().From_CC4(S);};
+ static Ztring ToZtring_From_CC3 (const char *S) {return Ztring().From_CC3(S);};
+ static Ztring ToZtring_From_CC3 (const int8u *S) {return Ztring().From_CC3(S);};
+ static Ztring ToZtring_From_CC3 (const int32u S) {return Ztring().From_CC3(S);};
+ static Ztring ToZtring_From_CC2 (const char *S) {return Ztring().From_CC2(S);};
+ static Ztring ToZtring_From_CC2 (const int8u *S) {return Ztring().From_CC2(S);};
+ static Ztring ToZtring_From_CC2 (const int16u S) {return Ztring().From_CC2(S);};
+ static Ztring ToZtring_From_CC1 (const char *S) {return Ztring().From_CC1(S);};
+ static Ztring ToZtring_From_CC1 (const int8u *S) {return Ztring().From_CC1(S);};
+ static Ztring ToZtring_From_CC1 (const int8u S) {return Ztring().From_CC1(S);};
+ static Ztring ToZtring (const int8s I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int8u I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int16s I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int16u I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int32s I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int32u I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int64s I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int64u I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const int128u I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ static Ztring ToZtring (const float32 F, int8u AfterComma=3) {return Ztring().From_Number(F, AfterComma);};
+ static Ztring ToZtring (const float64 F, int8u AfterComma=3) {return Ztring().From_Number(F, AfterComma);};
+ static Ztring ToZtring (const float80 F, int8u AfterComma=3) {return Ztring().From_Number(F, AfterComma);};
+ #ifdef NEED_SIZET
+ static Ztring ToZtring (const size_t I, int8u Radix=10) {return Ztring().From_Number(I, Radix);};
+ #endif //NEED_SIZET
+
+ //Edition
+ /// @brief test if it is a number
+ bool IsNumber() const;
+ /// @brief convert into lowercase
+ Ztring &MakeLowerCase();
+ /// @brief convert into uppercase
+ Ztring &MakeUpperCase();
+ /// @brief Remove leading whitespaces from a string
+ Ztring &TrimLeft(Char ToTrim=_T(' '));
+ /// @brief Remove trailing whitespaces from a string
+ Ztring &TrimRight(Char ToTrim=_T(' '));
+ /// @brief Remove leading and trailing whitespaces from a string
+ Ztring &Trim(Char ToTrim=_T(' '));
+ /// @brief Quotes a string
+ Ztring &Quote(Char ToTrim=_T('\"'));
+ /// @brief return a string between two strings
+ /// @param Begin First string
+ /// @param End Second string
+ /// @param Pos Position to begin to scan string
+ /// @param Options Options for searching \n
+ /// Available : Ztring_CaseSensitive
+ /// @return The substring \n
+ /// "" if not found
+ Ztring SubString (const tstring &Begin, const tstring &End, size_type Pos=0, ztring_t Options=Ztring_Nothing) const;
+ /// @brief replace a string by another one
+ /// @param ToFind string to find
+ /// @param ToReplace string wich replace the string found
+ /// @param Pos Position to begin to scan string
+ /// @param Options Options for searching \n
+ /// Available : Ztring_CaseSensitive, Ztring_Recursive
+ /// @return The count of replacements
+ size_type FindAndReplace (const tstring &ToFind, const tstring &ReplaceBy, size_type Pos=0, ztring_t Options=Ztring_Nothing); //Remplace une chaine par une autre
+ /// @brief Count the number of occurencies of a string in the string
+ /// @param ToCount string to count
+ /// @param Options Options for count \n
+ /// Available : Ztring_CaseSensitive
+ /// @return the count
+
+ //Information
+ size_type Count (const Ztring &ToCount, ztring_t Options=Ztring_Nothing) const;
+ /// @brief compare with another string
+ /// @param ToCompare string to compare with
+ /// @param Options Options for comaparing \n
+ /// Available : Ztring_CaseSensitive
+ /// @return The result of comparasion
+ bool Compare (const Ztring &ToCompare, const Ztring &Comparator=_T("=="), ztring_t Options=Ztring_Nothing) const;
+};
+
+} //NameSpace
+
+#endif
+
diff --git a/src/thirdparty/ZenLib/ZtringList.cpp b/src/thirdparty/ZenLib/ZtringList.cpp
new file mode 100644
index 000000000..d42c48340
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZtringList.cpp
@@ -0,0 +1,373 @@
+// ZenLib::ZtringList - More methods for vector<std::(w)string>
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include <algorithm>
+#include <functional>
+#include "ZenLib/ZtringList.h"
+using namespace std;
+#if defined(_MSC_VER) && _MSC_VER <= 1200
+ using std::vector; //Visual C++ 6 patch
+#endif
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+extern Ztring EmptyZtring;
+//---------------------------------------------------------------------------
+
+
+//***************************************************************************
+// Constructors/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Constructors
+ZtringList::ZtringList ()
+: std::vector<ZenLib::Ztring, std::allocator<ZenLib::Ztring> > ()
+{
+ Separator[0]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+}
+
+ZtringList::ZtringList(const ZtringList &Source)
+: std::vector<ZenLib::Ztring, std::allocator<ZenLib::Ztring> > ()
+{
+ Separator[0]=Source.Separator[0];
+ Quote=Source.Quote;
+
+ reserve(Source.size());
+ for (intu Pos=0; Pos<Source.size(); Pos++)
+ push_back(Source[Pos]);
+}
+
+ZtringList::ZtringList (const Ztring &Source)
+{
+ Separator[0]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+ Write(Source.c_str());
+}
+
+ZtringList::ZtringList (const Char *Source)
+{
+ Separator[0]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+ Write(Source);
+}
+
+#ifdef _UNICODE
+ZtringList::ZtringList (const char* S)
+{
+ Write(Ztring(S));
+}
+#endif
+
+//***************************************************************************
+// Operator
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Operator ==
+bool ZtringList::operator== (const ZtringList &Source) const
+{
+ return (Read()==Source.Read());
+}
+
+//---------------------------------------------------------------------------
+// Operator !=
+bool ZtringList::operator!= (const ZtringList &Source) const
+{
+ return (!(Read()==Source.Read()));
+}
+
+//---------------------------------------------------------------------------
+// Operator +=
+ZtringList &ZtringList::operator+= (const ZtringList &Source)
+{
+ reserve(size()+Source.size());
+ for (size_type Pos=0; Pos<Source.size(); Pos++)
+ push_back(Source[Pos]);
+
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Operator =
+ZtringList &ZtringList::operator= (const ZtringList &Source)
+{
+ clear();
+ Ztring C=Separator[0];
+ Ztring Q=Quote;
+
+ Separator[0]=Source.Separator[0];
+ Quote=Source.Quote;
+ reserve(Source.size());
+ for (size_type Pos=0; Pos<Source.size(); Pos++)
+ push_back(Source[Pos]);
+
+ Separator[0]=C;
+ Quote=Q;
+
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Operator ()
+Ztring &ZtringList::operator() (size_type Pos)
+{
+ if (Pos>=size())
+ Write(Ztring(), Pos);
+
+ return operator[](Pos);
+}
+
+//***************************************************************************
+// In/Out
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Read
+Ztring ZtringList::Read () const
+{
+ //Integrity
+ if (size()==0)
+ return Ztring();
+
+ Ztring Retour;
+ Ztring ToFind=Separator[0]+Quote[0]+_T("\r\n");
+ for (size_type Pos=0; Pos<size(); Pos++)
+ {
+ if (operator[](Pos).find_first_of(ToFind)==std::string::npos)
+ Retour+=operator[](Pos)+Separator[0];
+ else if (operator[](Pos).find(Separator[0])==std::string::npos
+ && operator[](Pos).find(Quote)==std::string::npos
+ && operator[](Pos).find('\r')==std::string::npos
+ && operator[](Pos).find('\n')==std::string::npos)
+ Retour+=operator[](Pos)+Separator[0];
+ else
+ {
+ if (operator[](Pos).find(Quote)==std::string::npos)
+ Retour+=Quote+operator[](Pos)+Quote+Separator[0];
+ else
+ {
+ Ztring Value=operator[](Pos);
+ Value.FindAndReplace(Quote, Quote+Quote, 0, Ztring_Recursive);
+ Retour+=Quote+Value+Quote+Separator[0];
+ }
+ }
+ }
+
+ //delete all useless separators at the end
+ while (Retour.find(Separator[0].c_str(), Retour.size()-Separator[0].size())!=std::string::npos)
+ Retour.resize(Retour.size()-Separator[0].size());
+
+ return Retour;
+}
+
+const Ztring &ZtringList::Read (size_type Pos) const
+{
+ //Integrity
+ if (Pos>=size())
+ return EmptyZtring;
+
+ return operator[](Pos);
+}
+
+//---------------------------------------------------------------------------
+// Write
+void ZtringList::Write(const Ztring &ToWrite)
+{
+ clear();
+
+ if (!&ToWrite || !ToWrite.size())
+ return;
+
+ size_type PosC=0;
+ bool Fini=false;
+ Ztring C1;
+
+ Ztring DelimiterL;
+ Ztring DelimiterR;
+ do
+ {
+ //Searching quotes
+ if (ToWrite[PosC]==Quote[0])
+ {
+ size_t Pos_End=PosC+1;
+ while (Pos_End<ToWrite.size())
+ {
+ if (ToWrite[Pos_End]==Quote[0] && Pos_End+1<ToWrite.size() && ToWrite[Pos_End+1]==Quote[0])
+ Pos_End+=2; //Double quote, skipping
+ else
+ {
+ if (ToWrite[Pos_End]==Quote[0])
+ break;
+ Pos_End++;
+ }
+ }
+ C1=ToWrite.substr(PosC+Quote.size(), Pos_End-PosC);
+ PosC+=C1.size()+Quote.size();
+ if (C1.size()>0 && C1[C1.size()-1]==Quote[0])
+ {
+ C1.resize(C1.size()-1);
+ PosC+=Quote.size();
+ }
+ }
+ else //Normal
+ {
+ C1=ToWrite.SubString(tstring(), Separator[0], PosC, Ztring_AddLastItem);
+ PosC+=C1.size()+Separator[0].size();
+ }
+ C1.FindAndReplace(Quote+Quote, Quote, 0, Ztring_Recursive);
+ if (size()<Max[0])
+ push_back(C1);
+ if (PosC>=ToWrite.size())
+ Fini=true;
+ }
+ while (!Fini);
+
+ return;
+}
+
+void ZtringList::Write(const Ztring &ToWrite, size_type Pos)
+{
+ if (Pos==Error)
+ return;
+ if (Pos>=size())
+ {
+ //Resource reservation
+ size_t ToReserve=1;
+ while (ToReserve<Pos)
+ ToReserve*=2;
+ reserve(ToReserve);
+
+ while (Pos>size())
+ push_back(Ztring());
+ push_back(ToWrite);
+ }
+ else
+ operator[](Pos)=ToWrite;
+
+ return;
+}
+
+//***************************************************************************
+// Edition
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Swap
+void ZtringList::Swap (size_type Pos0_A, size_type Pos0_B)
+{
+ //Integrity
+ size_type Pos_Max;
+ if (Pos0_A<Pos0_B)
+ Pos_Max=Pos0_B;
+ else
+ Pos_Max=Pos0_A;
+ if (Pos_Max>=size())
+ Write(Ztring(), Pos_Max);
+
+ operator [] (Pos0_A).swap(operator [] (Pos0_B));
+}
+
+//---------------------------------------------------------------------------
+// Sort
+void ZtringList::Sort(ztring_t)
+{
+ std::stable_sort(begin(), end());
+ return;
+}
+
+//***************************************************************************
+// Information
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Find
+Ztring::size_type ZtringList::Find (const Ztring &ToFind, size_type Pos, const Ztring &Comparator, ztring_t Options) const
+{
+ while (Pos<size() && !(operator[](Pos).Compare(ToFind, Comparator, Options)))
+ Pos++;
+ if (Pos>=size())
+ return Error;
+ return Pos;
+}
+
+//---------------------------------------------------------------------------
+// Return the length of the longest string in the list.
+Ztring::size_type ZtringList::MaxStringLength_Get ()
+{
+ size_type Max = 0;
+ for (ZtringList::const_iterator it=begin(); it!=end(); ++it)
+ if (it->size()>Max)
+ Max=it->size();
+ return Max;
+}
+
+//***************************************************************************
+// Configuration
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Separator
+void ZtringList::Separator_Set (size_type Level, const Ztring &NewSeparator)
+{
+ if (Level>0)
+ return;
+ Separator[Level]=NewSeparator;
+}
+
+//---------------------------------------------------------------------------
+// Quote
+void ZtringList::Quote_Set (const Ztring &NewQuote)
+{
+ Quote=NewQuote;
+}
+
+//---------------------------------------------------------------------------
+// Separator
+void ZtringList::Max_Set (size_type Level, size_type Max_New)
+{
+ if (Level>0 || Max_New==0)
+ return;
+ Max[Level]=Max_New;
+}
+
+} //namespace
+
+
+
+
+
+
diff --git a/src/thirdparty/ZenLib/ZtringList.h b/src/thirdparty/ZenLib/ZtringList.h
new file mode 100644
index 000000000..1172a2576
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZtringList.h
@@ -0,0 +1,103 @@
+// ZenLib::ZtringList - More methods for vector<std::(w)string>
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// More methods for std::vector<std::(w)string>
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_ZtringListH
+#define ZenLib_ZtringListH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Ztring.h"
+#include <vector>
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Vector of strings manipulation (based on std::vector<std::(w)string>)
+//***************************************************************************
+
+class ZtringList : public std::vector<Ztring>
+{
+public :
+ //Constructors/destructor
+ ZtringList ();
+ ZtringList (const ZtringList &Source);
+ ZtringList (const Ztring &Source);
+ ZtringList (const Char *Source);
+ #ifdef _UNICODE
+ ZtringList (const char *Source); //convert a UTF-8 string into Unicode
+ #endif
+
+ //Operators
+ bool operator == (const ZtringList &Source) const;
+ bool operator != (const ZtringList &Source) const;
+ ZtringList &operator += (const ZtringList &Source);
+ ZtringList &operator = (const ZtringList &Source);
+
+ Ztring &operator () (size_type Pos); ///< Same as [], but write a empty string if Pos doesn't exist yet
+
+ //In/out
+ Ztring Read () const; /// Read all
+ const Ztring &Read (size_type Pos) const; /// Read a string
+ void Write (const Ztring &ToWrite); /// Write all
+ void Write (const Ztring &ToWrite, size_type Pos); /// Write a string
+ /// @brief Insert a string at position Pos0
+ void Insert (const Ztring &ToInsert, size_type Pos0) {insert(begin()+Pos0, ToInsert);};
+ /// @brief Delete a string at position Pos0
+ void Delete (size_type Pos0) {erase(begin()+Pos0);};
+
+ //Edition
+ /// @brief Swap 2 positions
+ void Swap (size_type Pos0_A, size_type Pos0_B);
+ /// @brief Sort
+ void Sort (ztring_t Options=Ztring_Nothing);
+
+ //Information
+ /// @brief Find the position of the string in the vector
+ size_type Find (const Ztring &ToFind, size_type PosBegin=0, const Ztring &Comparator=_T("=="), ztring_t Options=Ztring_Nothing) const;
+ /// @brief Return the length of the longest string in the list.
+ size_type MaxStringLength_Get ();
+
+ //Configuration
+ /// @brief Set the Separator character
+ void Separator_Set (size_type Level, const Ztring &NewSeparator);
+ /// @brief Set the Quote character
+ /// During Read() or Write() method, if Separator is in the sequence, we must quote it
+ void Quote_Set (const Ztring &NewQuote);
+ /// @brief Set the Maximum number of element to read
+ /// During Read() or Write() method, if there is more elements, merge them with the last element
+ void Max_Set (size_type Level, size_type Max_New);
+
+protected :
+ Ztring Separator[1];
+ Ztring Quote;
+ size_type Max[1];
+};
+
+} //namespace
+#endif
+
diff --git a/src/thirdparty/ZenLib/ZtringListList.cpp b/src/thirdparty/ZenLib/ZtringListList.cpp
new file mode 100644
index 000000000..6512b2d3d
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZtringListList.cpp
@@ -0,0 +1,577 @@
+// ZenLib::ZtringListList - More methods for std::vector<std::vector<std::(w)string>>
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include <algorithm>
+#include "ZenLib/ZtringListList.h"
+using namespace std;
+#if defined(_MSC_VER) && _MSC_VER <= 1200
+ using std::vector; //Visual C++ 6 patch
+#endif
+//---------------------------------------------------------------------------
+
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+extern Ztring EmptyZtring;
+//---------------------------------------------------------------------------
+
+//***************************************************************************
+// Constructors/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Constructors
+ZtringListList::ZtringListList()
+: std::vector<ZenLib::ZtringList, std::allocator<ZenLib::ZtringList> > ()
+{
+ Separator[0]=EOL;
+ Separator[1]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+ Max[1]=Error;
+}
+
+ZtringListList::ZtringListList(const ZtringListList &Source)
+: std::vector<ZenLib::ZtringList, std::allocator<ZenLib::ZtringList> > ()
+{
+ Separator[0]=Source.Separator[0];
+ Separator[1]=Source.Separator[1];
+ Quote=Source.Quote;
+ Max[0]=Source.Max[0];
+ Max[1]=Source.Max[1];
+ reserve(Source.size());
+ for (intu Pos=0; Pos<Source.size(); Pos++)
+ push_back(Source[Pos]);
+}
+
+ZtringListList::ZtringListList(const Ztring &Source)
+{
+ Separator[0]=_T("\r\n");
+ Separator[1]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+ Max[1]=Error;
+ Write(Source.c_str());
+}
+
+ZtringListList::ZtringListList(const Char *Source)
+{
+ Separator[0]=_T("\r\n");
+ Separator[1]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+ Max[1]=Error;
+ Write(Source);
+}
+
+#ifdef _UNICODE
+ZtringListList::ZtringListList (const char* S)
+{
+ Separator[0]=_T("\r\n");
+ Separator[1]=_T(";");
+ Quote=_T("\"");
+ Max[0]=Error;
+ Max[1]=Error;
+ Write(Ztring(S));
+}
+#endif
+
+//***************************************************************************
+// Operators
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+//Operator ==
+bool ZtringListList::operator== (const ZtringListList &Source) const
+{
+ return (Read()==Source.Read());
+}
+
+//---------------------------------------------------------------------------
+//Operator !=
+bool ZtringListList::operator!= (const ZtringListList &Source) const
+{
+ return (!(Read()==Source.Read()));
+}
+
+//---------------------------------------------------------------------------
+// Operator +=
+ZtringListList &ZtringListList::operator+= (const ZtringListList &Source)
+{
+ reserve(size()+Source.size());
+ for (size_type Pos=0; Pos<Source.size(); Pos++)
+ {
+ push_back(Source[Pos]);
+ operator[](size()-1).Separator_Set(0, Separator[1]);
+ operator[](size()-1).Quote_Set(Quote);
+ operator[](size()-1).Max_Set(0, Max[1]);
+ }
+
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Operator =
+ZtringListList &ZtringListList::operator= (const ZtringListList &Source)
+{
+ clear();
+
+ reserve(Source.size());
+ for (size_type Pos=0; Pos<Source.size(); Pos++)
+ {
+ push_back(Source[Pos]);
+ operator[](size()-1).Separator_Set(0, Separator[1]);
+ operator[](size()-1).Quote_Set(Quote);
+ operator[](size()-1).Max_Set(0, Max[1]);
+ }
+
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+// Operatorr ()
+ZtringList &ZtringListList::operator() (size_type Pos0)
+{
+ //Integrity
+ if (Pos0>=size())
+ Write(Ztring(), Pos0);
+
+ return operator[](Pos0);
+}
+
+Ztring &ZtringListList::operator() (size_type Pos0, size_type Pos1)
+{
+ //Integrity
+ if (Pos0>=size())
+ Write(Ztring(), Pos0);
+
+ return operator[](Pos0).operator()(Pos1);
+}
+
+Ztring &ZtringListList::operator() (const Ztring &Pos0, size_type Pos0_1, size_type Pos1)
+{
+ size_type Pos=0;
+ size_t Size=size();
+ for (; Pos<Size; Pos++)
+ if (operator[](Pos).size()>Pos0_1)
+ if (operator[](Pos)[Pos0_1]==Pos0)
+ break;
+
+ if (Pos>=Size)
+ {
+ Write(Pos0, Size, Pos0_1);
+ Pos=size()-1;
+ }
+
+ return operator[](Pos).operator()(Pos1);
+}
+
+//***************************************************************************
+// In/Out
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Read
+Ztring ZtringListList::Read () const
+{
+ //Integrity
+ if (size()==0)
+ return Ztring();
+
+ Ztring ToReturn;
+ size_type Size=size()-1;
+ for (size_type Pos0=0; Pos0<Size; Pos0++)
+ ToReturn+=Read(Pos0)+Separator[0];
+ ToReturn+=Read(Size);
+
+ //Delete all useless separators at the end
+ if(ToReturn.size()>0 && Separator[0].size() && ToReturn(ToReturn.size()-1)==Separator[0][Separator[0].size()-1]) //Optimize speed
+ while (ToReturn.find(Separator[0].c_str(), ToReturn.size()-Separator[0].size())!=std::string::npos)
+ ToReturn.resize(ToReturn.size()-Separator[0].size());
+
+ return ToReturn;
+}
+
+Ztring ZtringListList::Read (size_type Pos0) const
+{
+ //Integrity
+ if (Pos0>=size())
+ return Ztring();
+
+ return operator[](Pos0).Read();
+}
+
+const Ztring &ZtringListList::Read (size_type Pos0, size_type Pos1) const
+{
+ //Integrity
+ if (Pos0>=size())
+ return EmptyZtring;
+
+ return operator[](Pos0).Read(Pos1);
+}
+
+const Ztring &ZtringListList::Read (const Ztring &Pos0, size_type Pos1) const
+{
+ size_type Pos=Find(Pos0);
+ if (Pos==Error)
+ return EmptyZtring;
+
+ return operator[](Pos).Read(Pos1);
+}
+
+const Ztring &ZtringListList::Read (const Ztring &Pos0, size_type Pos0_1, size_type Pos1) const
+{
+ size_type Pos=Find(Pos0, Pos0_1);
+ if (Pos==Error)
+ return EmptyZtring;
+
+ return operator[](Pos).Read(Pos1);
+}
+
+const Ztring &ZtringListList::Read (const Ztring &Pos0, const Ztring &Default, size_type Pos1) const
+{
+ size_type Pos=Find(Pos0);
+ if (Pos==Error)
+ return Default;
+
+ return operator[](Pos).Read(Pos1);
+}
+
+const Ztring &ZtringListList::Read (const Ztring &Pos0, const Ztring &Default, size_type Pos0_1, size_type Pos1) const //Lecture d'un champs en position 0 avec une option par defaut
+{
+ size_type Pos=Find(Pos0, Pos0_1);
+ if (Pos==Error)
+ return Default;
+
+ return operator[](Pos).Read(Pos1);
+}
+
+Ztring ZtringListList::Read1 (size_type Pos1) const
+{
+ Ztring ToReturn;
+ size_type Size=size()-1;
+ for (size_type Pos=0; Pos<Size; Pos++)
+ ToReturn+=operator[](Pos).Read(Pos1)+Separator[0];
+ ToReturn+=operator[](Size).Read(Pos1);
+
+ //Delete all useless separators at the end
+ if(ToReturn(ToReturn.size()-1)==Separator[0][Separator[0].size()-1]) //Optimize speed
+ while (ToReturn.find(Separator[0].c_str(), ToReturn.size()-Separator[0].size())!=std::string::npos)
+ ToReturn.resize(ToReturn.size()-Separator[0].size());
+
+ return ToReturn;
+}
+
+//---------------------------------------------------------------------------
+// Write
+void ZtringListList::Write(const Ztring &ToWrite)
+{
+ clear();
+
+ if (!&ToWrite || !ToWrite.size())
+ return;
+
+ size_type PosC=0;
+ bool Fini=false;
+ Ztring C1;
+ ZtringList ZL1;
+ ZL1.Separator_Set(0, Separator[1]);
+ ZL1.Quote_Set(Quote);
+ ZL1.Max_Set(0, Max[1]);
+
+ do
+ {
+ //Searching end of line, but it must not be in quotes
+ bool InQuotes=false;
+ Ztring CharsToFind=Separator[0]+Quote;
+ size_t Pos_End=PosC;
+ while (Pos_End<ToWrite.size())
+ {
+ Pos_End=ToWrite.find_first_of(CharsToFind, Pos_End);
+ if (Pos_End!=string::npos)
+ {
+ if (Pos_End+Quote.size()<ToWrite.size() && ToWrite[Pos_End]==Quote[0] && ToWrite[Pos_End+1]!=Quote[0])
+ {
+ InQuotes=!InQuotes; //This is not double quotes, so this is a normal quote
+ /*if (!InQuotes)
+ {
+ C1=ToWrite.substr(PosC, Pos_End-PosC);
+ break;
+ }*/
+ }
+
+ if (!InQuotes && Pos_End+Separator[0].size()<=ToWrite.size() && ToWrite[Pos_End]==Separator[0][0])
+ {
+ C1=ToWrite.substr(PosC, Pos_End-PosC);
+ break;
+ }
+
+ if (InQuotes && Pos_End+Quote.size()*2<ToWrite.size() && ToWrite[Pos_End]==Quote[0] && ToWrite[Pos_End+1]==Quote[0])
+ Pos_End+=2;
+ else
+ Pos_End++;
+ }
+ }
+ if (Pos_End>=ToWrite.size())
+ C1=ToWrite.substr(PosC, string::npos);
+
+ ZL1.Write(C1);
+ push_back(ZL1);
+ PosC+=C1.size()+Separator[0].size();
+ if (PosC>=ToWrite.size())
+ Fini=true;
+ }
+ while (!Fini);
+}
+
+void ZtringListList::Write(const ZtringList &ToWrite, size_type Pos)
+{
+ //Integrity
+ if (Pos==Error)
+ return;
+
+ //Writing
+ if (Pos>=size())
+ {
+ //Reservation de ressources
+ if (!capacity())
+ reserve(1);
+ while (Pos>=capacity())
+ reserve(capacity()*2);
+
+ while (Pos>size())
+ push_back (Ztring());
+ push_back(ToWrite);
+ }
+ else
+ operator[](Pos)=ToWrite;
+}
+
+void ZtringListList::Write(const Ztring &ToWrite, size_type Pos0, size_type Pos1)
+{
+ if (Pos0>=size())
+ Write(Ztring(), Pos0);
+
+ operator[](Pos0).Write(ToWrite, Pos1);
+}
+
+void ZtringListList::push_back (const ZtringList &ToAdd)
+{
+ vector<ZtringList>::push_back(ToAdd); //Visual C++ 6 patch, should be std::vector
+ operator[](size()-1).Separator_Set(0, Separator[1]);
+ operator[](size()-1).Quote_Set(Quote);
+ operator[](size()-1).Max_Set(0, Max[1]);
+}
+
+void ZtringListList::push_back (const Ztring &ToAdd)
+{
+ ZtringList ZL1;
+ ZL1.Separator_Set(0, Separator[1]);
+ ZL1.Quote_Set(Quote);
+ ZL1.Max_Set(0, Max[1]);
+ ZL1.Write(ToAdd);
+ push_back(ZL1);
+}
+
+//---------------------------------------------------------------------------
+// Insert
+void ZtringListList::Insert1 (const Ztring &ToInsert, size_type Pos1)
+{
+ for (size_type Pos0=0; Pos0<size(); Pos0++)
+ operator[](Pos0).Insert(ToInsert, Pos1);
+}
+
+//---------------------------------------------------------------------------
+// Delete
+void ZtringListList::Delete (const Ztring &ToFind, size_type Pos1, const Ztring &Comparator, ztring_t Options)
+{
+ size_type Pos0=0;
+ while ((Pos0=Find(ToFind, Pos1, Pos0, Comparator, Options))!=Error)
+ operator [] (Pos0).Delete(Pos1);
+}
+
+void ZtringListList::Delete1 (size_type Pos1)
+{
+ for (size_type Pos0=0; Pos0<size(); Pos0++)
+ operator [] (Pos0).Delete(Pos1);
+}
+
+//***************************************************************************
+// Edition
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Swap
+void ZtringListList::Swap (size_type Pos0_A, size_type Pos0_B)
+{
+ //Integrity
+ size_type Pos_Max;
+ if (Pos0_A<Pos0_B)
+ Pos_Max=Pos0_B;
+ else
+ Pos_Max=Pos0_A;
+ if (Pos_Max>=size())
+ Write(Ztring(), Pos_Max);
+
+ operator [] (Pos0_A).swap(operator [] (Pos0_B));
+}
+
+void ZtringListList::Swap1 (size_type Pos1_A, size_type Pos1_B)
+{
+ for (size_type Pos0=0; Pos0<size(); Pos0++)
+ operator () (Pos0, Pos1_A).swap(operator () (Pos0, Pos1_B));
+}
+
+//---------------------------------------------------------------------------
+// Sort
+void ZtringListList::Sort(size_type, ztring_t)
+{
+ std::stable_sort(begin(), end());
+ return;
+}
+
+//---------------------------------------------------------------------------
+// Find
+Ztring::size_type ZtringListList::Find (const Ztring &ToFind, size_type Pos1, size_type Pos0) const
+{
+ size_t Size=size();
+ for (; Pos0<Size; Pos0++)
+ if (operator[](Pos0).size()>Pos1)
+ if (operator[](Pos0)[Pos1]==ToFind)
+ break;
+
+ if (Pos0>=Size)
+ return Error;
+ return Pos0;
+}
+
+Ztring::size_type ZtringListList::Find_Filled (size_type Pos1, size_type Pos0) const
+{
+ size_t Size=size();
+ for (; Pos0<Size; Pos0++)
+ if (operator[](Pos0).size()>Pos1)
+ if (!operator[](Pos0)[Pos1].empty())
+ break;
+
+ if (Pos0>=Size)
+ return Error;
+ return Pos0;
+}
+
+Ztring::size_type ZtringListList::Find (const Ztring &ToFind, size_type Pos1, size_type Pos0, const Ztring &Comparator, ztring_t Options) const
+{
+ while ( Pos0<size()
+ && ( Pos1>=at(Pos0).size()
+ || !at(Pos0).at(Pos1).Compare(ToFind, Comparator, Options)))
+ Pos0++;
+ if (Pos0>=size())
+ return Error;
+ return Pos0;
+}
+
+Ztring ZtringListList::FindValue (const Ztring &ToFind, size_type Pos1Value, size_type Pos1, size_type Pos0Begin, const Ztring &Comparator, ztring_t) const
+{
+ size_type Pos0=Find(ToFind, Pos1, Pos0Begin, Comparator);
+ if (Pos0==Error)
+ return Ztring();
+
+ return Read(Pos0, Pos1Value);
+}
+
+ZtringListList ZtringListList::SubSheet (const Ztring &ToFind, size_type Pos1, size_type Pos0, const Ztring &Comparator, ztring_t) const
+{
+ ZtringListList ToReturn;
+ ToReturn.Separator[0]=Separator[0];
+ ToReturn.Separator[1]=Separator[1];
+ ToReturn.Quote=Quote;
+
+ Pos0--;
+ do
+ {
+ Pos0=Find(ToFind, Pos1, Pos0+1, Comparator);
+ ToReturn.push_back(Read(Pos0));
+ }
+ while (Pos0!=Error);
+
+ return ToReturn;
+}
+
+//***************************************************************************
+// Configuration
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Separator
+void ZtringListList::Separator_Set (size_type Level, const Ztring &NewSeparator)
+{
+ if (Level>1)
+ return;
+
+ Separator[Level]=NewSeparator;
+ if (Level==1)
+ for (size_type Pos0=0; Pos0<size(); Pos0++)
+ operator () (Pos0).Separator_Set(0, Separator[1]);
+}
+
+//---------------------------------------------------------------------------
+// Quote
+void ZtringListList::Quote_Set (const Ztring &NewQuote)
+{
+ Quote=NewQuote;
+ for (size_type Pos0=0; Pos0<size(); Pos0++)
+ operator () (Pos0).Quote_Set(Quote);
+}
+
+//---------------------------------------------------------------------------
+// Max
+void ZtringListList::Max_Set (size_type Level, size_type NewMax)
+{
+ if (Level>1 || NewMax==0)
+ return;
+
+ Max[Level]=NewMax;
+ if (Level==1)
+ for (size_type Pos0=0; Pos0<size(); Pos0++)
+ operator () (Pos0).Max_Set(0, Max[1]);
+}
+
+//***************************************************************************
+//
+//***************************************************************************
+
+} //namespace
+
+
+
+
+
+
+
+
diff --git a/src/thirdparty/ZenLib/ZtringListList.h b/src/thirdparty/ZenLib/ZtringListList.h
new file mode 100644
index 000000000..e84acbc29
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZtringListList.h
@@ -0,0 +1,146 @@
+// ZenLib::ZtringListList - More methods for std::vector<std::vector<std::(w)string>>
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// More methods for std::vector<std::vector<std::(w)string>>
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZenLib_ZtringListListH
+#define ZenLib_ZtringListListH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/ZtringList.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief Vector of vectors of strings manipulation (based on std::vector<std::vector<std::(w)string>>)
+//***************************************************************************
+
+class ZtringListList : public std::vector<ZtringList>
+{
+public :
+ //Constructors/Destructor
+ ZtringListList ();
+ ZtringListList (const ZtringListList &Source);
+ ZtringListList (const Ztring &Source);
+ ZtringListList (const Char *Source);
+ #ifdef _UNICODE
+ ZtringListList (const char *Source); //convert a UTF-8 string into Unicode
+ #endif
+
+ //Operateurs
+ bool operator == (const ZtringListList &Source) const;
+ bool operator != (const ZtringListList &Source) const;
+ ZtringListList &operator += (const ZtringListList &Source);
+ ZtringListList &operator = (const ZtringListList &Source);
+
+ ZtringList &operator () (size_type Pos0); ///< Same as [], but write a empty string if Pos doesn't exist yet
+ Ztring &operator () (size_type Pos0, size_type Pos1);
+ /// @brief Return [Pos][Pos1], Pos=First occurency of Pos0 in [xxx][0]
+ Ztring &operator () (const Ztring &Pos0, size_type Pos1=1) {return operator() (Pos0, 0 , Pos1);};
+ /// @brief Return [Pos][Pos1], Pos=First occurency of Pos0 in [xxx][Pos0_1]
+ Ztring &operator () (const Ztring &Pos0, size_type Pos0_1, size_type Pos1);
+
+ //In/Out
+ /// @brief Read all
+ Ztring Read () const;
+ /// @brief Read a vector of string
+ Ztring Read (size_type Pos0) const;
+ /// @brief Read a string
+ const Ztring &Read (size_type Pos0, size_type Pos1) const;
+ /// @brief Return [Pos][Pos1], Pos=First occurency of Pos0 in [xxx][0]
+ const Ztring &Read (const Ztring &Pos0, size_type Pos1=1) const;
+ /// @brief Return [Pos][Pos1], Pos=First occurency of Pos0 in [xxx][Pos0_1]
+ const Ztring &Read (const Ztring &Pos0, size_type Pos0_1, size_type Pos1) const;
+ /// @brief Return [Pos][Pos1], Pos=First occurency of Pos0 in [xxx][0], with default value
+ const Ztring &Read (const Ztring &Pos0, const Ztring &Default, size_type Pos1=1) const;
+ /// @brief Return [Pos][Pos1], Pos=First occurency of Pos0 in [xxx][Pos0_1], with default value
+ const Ztring &Read (const Ztring &Pos0, const Ztring &Default, size_type Pos0_1, size_type Pos1) const;
+ /// @brief Read all strings at position Pos1
+ Ztring Read1 (size_type Pos1) const;
+
+ /// @brief Write all
+ void Write (const Ztring &ToWrite);
+ /// @brief Write a vector of string
+ void Write (const ZtringList &ToWrite, size_type Pos0);
+ /// @brief Write a vector of string
+ void Write (const Ztring &ToWrite, size_type Pos0, size_type Pos1);
+ /// @brief Add a vector of string
+ void push_back (const ZtringList &ToAdd);
+ /// @brief Add a vector of string (with separator is ZtringListList Separator)
+ void push_back (const Ztring &ToAdd);
+ /// @brief Add a vector of string (Char version)
+ void push_back (const Char* ToAdd) {push_back(Ztring(ToAdd));};
+ /// @brief Insert a vector of string at position Pos0
+ void Insert (const ZtringList &ToInsert, size_type Pos0) {insert(begin()+Pos0, ToInsert);};
+ /// @brief Insert a string at all positions Pos1
+ void Insert1 (const Ztring &ToInsert, size_type Pos1);
+ /// @brief Delete a vector of string at position Pos0
+ void Delete (size_type Pos0) {erase(begin()+Pos0);};
+ /// @brief Delete all vectors of string, with [xxx][Pos1] == ToFind
+ void Delete (const Ztring &ToFind, size_type Pos1=0, const Ztring &Comparator=_T("=="), ztring_t Options=Ztring_Nothing);
+ /// @brief Delete a string at all positions Pos1
+ void Delete1 (size_type Pos1);
+
+ //Edition
+ /// @brief Swap 2 positions
+ void Swap (size_type Pos0_A, size_type Pos0_B);
+ /// @brief Swap 2 columns for each line
+ void Swap1 (size_type Pos1_A, size_type Pos1_B);
+ /// @brief Sort
+ void Sort (size_type Pos1, ztring_t Options=Ztring_Nothing);
+
+ //Information
+ /// @brief Find the first position of the string in the vector of vector, in a specific column
+ size_type Find (const Ztring &ToFind, size_type Pos1=0, size_type Pos0Begin=0) const;
+ /// @brief Find the first position of the string in the vector of vector, in a specific column, which is not empty
+ size_type Find_Filled (size_type Pos1=0, size_type Pos0Begin=0) const;
+ /// @brief Find the first position of the string in the vector of vector, in a specific column
+ size_type Find (const Ztring &ToFind, size_type Pos1, size_type Pos0Begin, const Ztring &Comparator, ztring_t Options=Ztring_Nothing) const;
+ /// @brief Return [xxx][Pos1Value] when founded the first position of the string in the vector of vector, in a specific column
+ Ztring FindValue (const Ztring &ToFind, size_type Pos1Value=1, size_type Pos1=0, size_type Pos0Begin=0, const Ztring &Comparator=_T("=="), ztring_t Options=Ztring_Nothing) const;
+ /// @brief Return a subsheet, with all lines with position of the string in the vector of vector, in a specific column
+ ZtringListList SubSheet (const Ztring &ToFind, size_type Pos1=0, size_type Pos0Begin=0, const Ztring &Comparator=_T("=="), ztring_t Options=Ztring_Nothing) const;
+
+ //Configuration
+ /// @brief Set the Separator character
+ void Separator_Set (size_type Level, const Ztring &NewSeparator);
+ /// @brief Set the Quote character
+ /// During Read() or Write() method, if Separator is in the sequence, we must quote it
+ void Quote_Set (const Ztring &NewQuote);
+ /// @brief Set the Maximum number of element to read
+ /// During Read() or Write() method, if there is more elements, merge them with the last element
+ void Max_Set (size_type Level, size_type Max);
+
+protected :
+ Ztring Separator[2];
+ Ztring Quote;
+ size_type Max[2];
+};
+
+} //namespace
+#endif
+
diff --git a/src/thirdparty/ZenLib/ZtringListListF.cpp b/src/thirdparty/ZenLib/ZtringListListF.cpp
new file mode 100644
index 000000000..6557aa730
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZtringListListF.cpp
@@ -0,0 +1,376 @@
+// ZenLib::ZtringListListF - ZtringListList with file load/save
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// ZtringListList with file load/save
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#include "ZenLib/Conf_Internal.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+#include "ZenLib/ZtringListListF.h"
+#include "ZenLib/File.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//---------------------------------------------------------------------------
+#define READ_SIZE 512*1024
+//---------------------------------------------------------------------------
+
+//***************************************************************************
+// Constructors/Destructor
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Constructors
+void ZtringListListF::ZtringListListF_Common ()
+{
+ Backup_Nb_Max=0;
+ Backup_Nb=0;
+ Sauvegarde=true;
+ #ifdef _UNICODE
+ Local=false;
+ #else
+ Local=true;
+ #endif
+}
+
+ZtringListListF::ZtringListListF ()
+:ZtringListList ()
+{
+ ZtringListListF_Common();
+}
+
+ZtringListListF::ZtringListListF (const ZtringListList &Source)
+:ZtringListList (Source)
+{
+ ZtringListListF_Common();
+}
+
+ZtringListListF::ZtringListListF (const Ztring &Source)
+:ZtringListList (Source)
+{
+ ZtringListListF_Common();
+}
+
+ZtringListListF::ZtringListListF (const Char *Source)
+:ZtringListList (Source)
+{
+ ZtringListListF_Common();
+}
+
+#ifdef _UNICODE
+ZtringListListF::ZtringListListF (const char* Source)
+:ZtringListList (Source)
+{
+ ZtringListListF_Common();
+}
+#endif
+
+//***************************************************************************
+// File management
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Load
+bool ZtringListListF::Load (const Ztring &NewFileName)
+{
+ clear();
+ if (!NewFileName.empty())
+ Name=NewFileName;
+
+ size_t I1=Error;
+
+ if (Name.find(_T(".csv"))!=Error)
+ I1=CSV_Charger();
+ if (Name.find(_T(".cfg"))!=Error)
+ I1=CFG_Charger();
+ if (I1!=Error)
+ {
+ Backup_Nb=0; //mettre ici le code pour trouver le nb de backup
+ return true;
+ }
+ else
+ return false;
+}
+
+//---------------------------------------------------------------------------
+// Load CSV
+bool ZtringListListF::CSV_Charger ()
+{
+ //Read file
+ File F(Name);
+ int8u* Buffer=new int8u[(size_t)F.Size_Get()+1];
+ size_t BytesCount=F.Read(Buffer, (size_t)F.Size_Get());
+ F.Close();
+ if (BytesCount==Error)
+ {
+ delete[] Buffer; //Buffer=NULL;
+ return false;
+ }
+ Buffer[(int32u)BytesCount]=(int8u)'\0';
+
+ //Convert file in UTF-8 or Local
+ Ztring File;
+ if (!Local)
+ {
+ //UTF-8
+ File.From_UTF8((char*)Buffer, 0, BytesCount);
+ #ifdef _DEBUG
+ if (File.size()==0)
+ File.From_Local((char*)Buffer, 0, BytesCount);
+ #endif //_DEBUG
+ }
+ if (File.size()==0)
+ //Local of UTF-8 failed
+ File.From_Local((char*)Buffer, 0, BytesCount);
+
+ //Separators
+ if (Separator[0]==_T("(Default)"))
+ Separator[0]=EOL;
+ Ztring SeparatorT=Separator[1];
+ Separator[1]=_T(";");
+
+ //Writing
+ Write(File);
+
+ //Separators
+ Separator[1]=SeparatorT;
+
+ delete[] Buffer; //Buffer=NULL;
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// Chargement CFG
+bool ZtringListListF::CFG_Charger ()
+{
+ //Read file
+ File F(Name);
+ int8u* Buffer=new int8u[(size_t)F.Size_Get()+1];
+ size_t BytesCount=F.Read(Buffer, (size_t)F.Size_Get());
+ F.Close();
+ if (BytesCount==Error)
+ {
+ delete[] Buffer; //Buffer=NULL;
+ return false;
+ }
+ Buffer[(int32u)BytesCount]=(int8u)'\0';
+
+ //Convert File --> ZtringList
+ ZtringList List;
+ List.Separator_Set(0, EOL);
+ Ztring Z1;
+ Z1.From_UTF8((char*)Buffer, 0, BytesCount);
+ List.Write(Z1);
+
+ Ztring SeparatorT=Separator[1];
+ Separator[1]=_T(";");
+
+ Ztring Propriete, Valeur, Commentaire;
+
+ for (size_t Pos=0; Pos<List.size(); Pos++)
+ {
+ Ztring &Lu=List(Pos);
+ if (Lu.find(_T("="))>0)
+ {
+ //Obtention du Name
+ Propriete=Lu.SubString(Ztring(), _T("="));
+ NettoyerEspaces(Propriete);
+ //Obtention de la valeur
+ Valeur=Lu.SubString(_T("="), _T(";"), 0, Ztring_AddLastItem);
+ NettoyerEspaces(Valeur);
+ }
+ //Obtention du commentaire
+ Commentaire=Lu.SubString(_T(";"), Ztring(), 0, Ztring_AddLastItem);
+ NettoyerEspaces(Commentaire);
+ //Ecriture
+ push_back((Propriete+_T(";")+Valeur+_T(";")+Commentaire).c_str()); //Visual C++ 6 is old...
+ }
+ Separator[1]=SeparatorT;
+
+ delete[] Buffer; //Buffer=NULL;
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// Sauvegarde globale
+bool ZtringListListF::Save (const Ztring &FileName)
+{
+ //Gestion de l'annulation de la sauvegarde
+ if (!Sauvegarde)
+ return true;
+
+ if (FileName!=Ztring())
+ Name=FileName;
+
+ //Gestion des backups
+ Backup_Nb=0;
+ int8u I2;
+ Separator[0]=EOL;
+ if (Backup_Nb_Max>0)
+ {
+ //TODO : not tested
+ for (int8u I1=Backup_Nb_Max-1; I1>0; I1--)
+ {
+ Ztring Z1=Name+_T(".sav"); Z1+=Ztring::ToZtring(I1);
+ Ztring Z2=Name+_T(".sav"); Z2+=Ztring::ToZtring(I1+1);
+ File::Delete(Z2.c_str());
+ I2=File::Move(Z1.c_str(), Z2.c_str());
+ if (I2 && !Backup_Nb)
+ Backup_Nb=I2;
+ }
+ Ztring Z1=Name+_T(".sav0");
+ File::Delete(Z1.c_str());
+ File::Move(Name.c_str(), Z1.c_str());
+ Backup_Nb++;
+ }
+
+ I2=0;
+ if (Name.find(_T(".csv"))!=Error)
+ I2=CSV_Sauvegarder();
+ if (Name.find(_T(".cfg"))!=Error)
+ I2=CFG_Sauvegarder();
+
+ if (I2>0)
+ {
+ return true;
+ }
+ else
+ return false;
+}
+
+//---------------------------------------------------------------------------
+// Sauvegarde CSV
+bool ZtringListListF::CSV_Sauvegarder ()
+{
+ //Sauvegarde
+ File F;
+ if (!F.Create(Name, true))
+ return Error;
+
+ if (Separator[0]==_T("(Default)"))
+ Separator[0]=EOL;
+
+ F.Write(Read());
+
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// Sauvegarde CFG
+bool ZtringListListF::CFG_Sauvegarder ()
+{
+ File F;
+ if (!F.Create(Name, true))
+ return Error;
+
+ Ztring ToWrite;
+ Ztring Propriete, Valeur, Commentaire;
+
+ ;
+ for (size_t Pos=0; Pos<size(); Pos++)
+ {
+ Propriete=Read(Pos, 0);
+ Valeur=Read(Pos, 1);
+ Commentaire=Read(Pos, 2);
+ if (Propriete!=Ztring())
+ {
+ ToWrite+=Propriete+_T(" = ");
+ if (Valeur!=Ztring())
+ ToWrite+=Valeur+_T(" ");
+ }
+ if (Commentaire!=Ztring())
+ ToWrite+=_T("; ")+Commentaire;
+ ToWrite+=EOL;
+ }
+ F.Write(ToWrite);
+
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// Annulation
+bool ZtringListListF::Cancel ()
+{
+ Ztring Z1=Name+_T(".sav0"); //Visual C++ 6 patch
+ File::Delete(Name.c_str());
+ File::Move(Z1.c_str(), Name.c_str());
+ for (int8u I1=1; I1<=Backup_Nb; I1++)
+ {
+ Ztring Z2=Name+_T(".sav"); Z2+=Ztring::ToZtring(I1); //Visual C++ 6 patch
+ Ztring Z3=Name+_T(".sav"); Z3+=Ztring::ToZtring(I1-1); //Visual C++ 6 patch
+ File::Delete(Z3.c_str());
+ File::Move(Z2.c_str(), Z3.c_str());
+ }
+ Write(Ztring());
+ return CSV_Charger();
+}
+
+//***************************************************************************
+// Divers
+//***************************************************************************
+
+//---------------------------------------------------------------------------
+// Nettoyage
+bool ZtringListListF::NettoyerEspaces (Ztring &ANettoyer)
+{
+ size_t Debut=0;
+ while (Debut<ANettoyer.size() && ANettoyer[Debut]==_T(' '))
+ Debut++;
+ size_t Fin=ANettoyer.size()-1;
+ while (Fin!=(size_t)-2 && ANettoyer[Fin]==_T(' '))
+ Fin--;
+ if (Fin>=Debut)
+ ANettoyer=ANettoyer.substr(Debut, Fin-Debut+1);
+ else
+ ANettoyer=Ztring();
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// Backup
+void ZtringListListF::Backup_Set (bool NewSave)
+{
+ Sauvegarde=NewSave;
+ Save();
+}
+
+void ZtringListListF::Backup_Count_Set (int8u NewCount)
+{
+ Backup_Nb_Max=NewCount;
+}
+
+//---------------------------------------------------------------------------
+// Local
+void ZtringListListF::Local_Set (bool NewLocal)
+{
+ Local=NewLocal;
+}
+
+} //Namespace
+
diff --git a/src/thirdparty/ZenLib/ZtringListListF.h b/src/thirdparty/ZenLib/ZtringListListF.h
new file mode 100644
index 000000000..903e1a896
--- /dev/null
+++ b/src/thirdparty/ZenLib/ZtringListListF.h
@@ -0,0 +1,91 @@
+// ZenLib::ZtringListListF - ZtringListList with files
+// Copyright (C) 2002-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// ZtringListList with file load/save
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+#ifndef ZtringListListFH
+#define ZtringListListFH
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#include "ZenLib/ZtringListList.h"
+//---------------------------------------------------------------------------
+
+namespace ZenLib
+{
+
+//***************************************************************************
+/// @brief ZtringListList with file management
+//***************************************************************************
+
+class ZtringListListF : public ZtringListList
+{
+public :
+ //Constructors/Destructor
+ ZtringListListF ();
+ ZtringListListF (const ZtringListList &Source);
+ ZtringListListF (const Ztring &Source);
+ ZtringListListF (const Char *Source);
+ #ifdef _UNICODE
+ ZtringListListF (const char *Source); //convert a UTF-8 string into Unicode
+ #endif
+
+ //File management
+ bool Load (const Ztring &FileName=Ztring());
+ bool Save (const Ztring &FileName=Ztring());
+ bool Cancel ();
+
+ //Configuration
+ // @brief enable or disable backup creation
+ void Backup_Set (bool Save);
+ // @brief Set the count of versions to save
+ void Backup_Count_Set (int8u Count);
+ // @brief Set if the content of file is a localized (=not UTF8) file
+ void Local_Set (bool Local);
+
+protected :
+ Ztring Name; //Nom du fichier
+ bool Sauvegarde; //Indicateur si on a le droit de sauvegarder (par defaut)
+ int8u Backup_Nb_Max; //Nombre maxi de sauvegardes
+ int8u Backup_Nb; //Nombre actuel de backups pour cette session
+ bool Local; //if true, this is a local charset, else this is a UTF8 charset
+
+ //File management
+ bool CSV_Charger ();
+ bool CFG_Charger ();
+ bool CSV_Sauvegarder ();
+ bool CFG_Sauvegarder ();
+ bool File_Load ();
+
+ //Divers
+ bool NettoyerEspaces (Ztring &ANettoyer); //Enlever les espaces avant et apres
+
+private:
+ void ZtringListListF_Common();
+};
+
+} //Namespace
+
+#endif
+
diff --git a/src/thirdparty/ZenLib/int128s.cpp b/src/thirdparty/ZenLib/int128s.cpp
new file mode 100644
index 000000000..c4d0b30ea
--- /dev/null
+++ b/src/thirdparty/ZenLib/int128s.cpp
@@ -0,0 +1,410 @@
+// int128u - integer 8 bytes
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// based on http://Tringi.Mx-3.cz
+// Only adapted for ZenLib:
+// - uint128.hpp --> int128u.h
+// - Namespace
+// - int128u alias
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#include "int128s.h"
+
+/*
+ Name: int128.cpp
+ Copyright: Copyright (C) 2005, Jan Ringos
+ Author: Jan Ringos, http://Tringi.Mx-3.cz
+
+ Version: 1.1
+*/
+
+#include <memory>
+#include <cmath>
+#include <cstring>
+#if defined (__BORLANDC__) || defined (__SUNPRO_CC)
+ #define fmodf fmod
+#endif
+#if defined (__NO_LONG_DOUBLE_MATH) || \
+ defined (__MONTAVISTA__) || defined (__ARMEL__) || \
+ defined (__FreeBSD__) || defined (__OpenBSD__) || \
+ defined (__NetBSD__) || defined (__DragonFly__) || \
+ defined (__sparc__) || defined (__sparc64__) || \
+ defined (__SUNPRO_CC)
+ #define fmodl fmod
+#endif
+using namespace std;
+
+namespace ZenLib
+{
+
+// IMPLEMENTATION
+
+const char * int128::toString (unsigned int radix) const throw () {
+ if (!*this) return "0";
+ if (radix < 2 || radix > 37) return "(invalid radix)";
+
+ static char sz [256];
+ memset (sz, 0, 256);
+
+ int128 r;
+ int128 ii = (*this < 0) ? -*this : *this;
+ int i = 255;
+
+ while (!!ii && i) {
+ ii = ii.div (radix, r);
+ sz [--i] = (char) (r.toInt () + ((r.toInt () > 9) ? 'A' - 10 : '0'));
+ };
+
+ if (*this < 0)
+ sz [--i] = '-';
+
+ return &sz [i];
+};
+
+int128::int128 (const char * sz) throw ()
+ : lo (0u), hi (0) {
+
+ if (!sz) return;
+ if (!sz [0]) return;
+
+ unsigned int radix = 10;
+ unsigned int i = 0;
+ bool minus = false;
+
+ if (sz [i] == '-') {
+ ++i;
+ minus = true;
+ };
+
+ if (sz [i] == '0') {
+ radix = 8;
+ ++i;
+ if (sz [i] == 'x') {
+ radix = 16;
+ ++i;
+ };
+ };
+
+ for (; i < strlen (sz); ++i) {
+ unsigned int n = 0;
+ if (sz [i] >= '0' && sz [i] <= (('0' + (int) radix) < '9'?('0' + (int) radix):'9')) //if (sz [i] >= '0' && sz [i] <= (('0' + (int) radix) <? '9'))
+ n = sz [i] - '0';
+ else if (sz [i] >= 'a' && sz [i] <= 'a' + (int) radix - 10)
+ n = sz [i] - 'a' + 10;
+ else if (sz [i] >= 'A' && sz [i] <= 'A' + (int) radix - 10)
+ n = sz [i] - 'A' + 10;
+ else
+ break;
+
+ (*this) *= radix;
+ (*this) += n;
+ };
+
+ if (minus)
+ *this = 0 - *this;
+
+ return;
+};
+
+int128::int128 (const float a) throw ()
+ #if defined (__mips__) || defined (__mipsel__)
+ : lo ((int64u) fmodf ((const double)a, 18446744073709551616.0)),
+ #else
+ : lo ((int64u) fmodf (a, 18446744073709551616.0f)),
+ #endif
+ hi ((int64s) (a / 18446744073709551616.0f)) {};
+
+int128::int128 (const double & a) throw ()
+ : lo ((int64u) fmod (a, 18446744073709551616.0)),
+ hi ((int64s) (a / 18446744073709551616.0)) {};
+
+int128::int128 (const long double & a) throw ()
+ #if defined (__mips__) || defined (__mipsel__)
+ : lo ((int64u) fmod ((const double)a, 18446744073709551616.0)),
+ #else
+ : lo ((int64u) fmodl (a, 18446744073709551616.0l)),
+ #endif
+ hi ((int64s) (a / 18446744073709551616.0l)) {};
+
+float int128::toFloat () const throw () {
+ return (float) this->hi * 18446744073709551616.0f
+ + (float) this->lo;
+};
+
+double int128::toDouble () const throw () {
+ return (double) this->hi * 18446744073709551616.0
+ + (double) this->lo;
+};
+
+long double int128::toLongDouble () const throw () {
+ return (long double) this->hi * 18446744073709551616.0l
+ + (long double) this->lo;
+};
+
+int128 int128::operator - () const throw () {
+ if (!this->hi && !this->lo)
+ // number is 0, just return 0
+ return *this;
+ else
+ // non 0 number
+ return int128 (0-this->lo, ~this->hi);
+};
+
+int128 int128::operator ~ () const throw () {
+ return int128 (~this->lo, ~this->hi);
+};
+
+int128 & int128::operator ++ () {
+ ++this->lo;
+ if (!this->lo)
+ ++this->hi;
+
+ return *this;
+};
+
+int128 & int128::operator -- () {
+ if (!this->lo)
+ --this->hi;
+ --this->lo;
+
+ return *this;
+};
+
+int128 int128::operator ++ (int) {
+ int128 b = *this;
+ ++ *this;
+
+ return b;
+};
+
+int128 int128::operator -- (int) {
+ int128 b = *this;
+ -- *this;
+
+ return b;
+};
+
+int128 & int128::operator += (const int128 & b) throw () {
+ int64u old_lo = this->lo;
+
+ this->lo += b.lo;
+ this->hi += b.hi + (this->lo < old_lo);
+
+ return *this;
+};
+
+int128 & int128::operator *= (const int128 & b) throw () {
+ if (!b)
+ return *this = 0u;
+ if (b == 1u)
+ return *this;
+
+ int128 a = *this;
+ int128 t = b;
+
+ this->lo = 0ull;
+ this->hi = 0ll;
+
+ for (unsigned int i = 0; i < 128; ++i) {
+ if (t.lo & 1)
+ *this += a << i;
+
+ t >>= 1;
+ };
+
+ return *this;
+};
+
+
+int128 int128::div (const int128 & divisor, int128 & remainder) const throw () {
+ if (!divisor)
+ return 1u / (unsigned int) divisor.lo;
+ // or RaiseException (EXCEPTION_INT_DIVIDE_BY_ZERO,
+ // EXCEPTION_NONCONTINUABLE, 0, NULL);
+
+ int128 ds = (divisor < 0) ? -divisor : divisor;
+ int128 dd = (*this < 0) ? -*this : *this;
+
+ // only remainder
+ if (ds > dd) {
+ remainder = *this;
+ return 0ull;
+ };
+
+ int128 r = 0ull;
+ int128 q = 0ull;
+// while (dd >= ds) { dd -= ds; q += 1; }; // extreme slow version
+
+ unsigned int b = 127;
+ while (r < ds) {
+ r <<= 1;
+ if (dd.bit (b--))
+ r.lo |= 1;
+ };
+ ++b;
+
+ while (true)
+ if (r < ds) {
+ if (!(b--)) break;
+
+ r <<= 1;
+ if (dd.bit (b))
+ r.lo |= 1;
+
+ } else {
+ r -= ds;
+ q.bit (b, true);
+ };
+
+ // correct
+ if ((divisor < 0) ^ (*this < 0)) q =- q;
+ if (*this < 0) r =- r;
+
+ remainder = r;
+ return q;
+};
+
+bool int128::bit (unsigned int n) const throw () {
+ n &= 0x7F;
+
+ if (n < 64)
+ return (this->lo & (1ull << n))?true:false;
+ else
+ return (this->hi & (1ull << (n - 64)))?true:false;
+};
+
+void int128::bit (unsigned int n, bool val) throw () {
+ n &= 0x7F;
+
+ if (val) {
+ if (n < 64) this->lo |= (1ull << n);
+ else this->hi |= (1ull << (n - 64));
+ } else {
+ if (n < 64) this->lo &= ~(1ull << n);
+ else this->hi &= ~(1ull << (n - 64));
+ };
+};
+
+
+int128 & int128::operator >>= (unsigned int n) throw () {
+ n &= 0x7F;
+
+ if (n > 63) {
+ n -= 64;
+ this->lo = this->hi;
+
+ if (this->hi < 0) this->hi = -1ll;
+ else this->hi = 0ll;
+ };
+
+ if (n) {
+ // shift low qword
+ this->lo >>= n;
+
+ // get lower N bits of high qword
+ int64u mask = 0ull;
+ for (unsigned int i = 0; i < n; ++i) mask |= (1ull << i);
+
+ // and add them to low qword
+ this->lo |= (this->hi & mask) << (64 - n);
+
+ // and finally shift also high qword
+ this->hi >>= n;
+ };
+
+ return *this;
+};
+
+int128 & int128::operator <<= (unsigned int n) throw () {
+ n &= 0x7F;
+
+ if (n > 63) {
+ n -= 64;
+ this->hi = this->lo;
+ this->lo = 0ull;
+ };
+
+ if (n) {
+ // shift high qword
+ this->hi <<= n;
+
+ // get higher N bits of low qword
+ int64u mask = 0ull;
+ for (unsigned int i = 0; i < n; ++i) mask |= (1ull << (63 - i));
+
+ // and add them to high qword
+ this->hi |= (this->lo & mask) >> (64 - n);
+
+ // and finally shift also low qword
+ this->lo <<= n;
+ };
+
+ return *this;
+};
+
+bool int128::operator ! () const throw () {
+ return !(this->hi || this->lo);
+};
+
+int128 & int128::operator |= (const int128 & b) throw () {
+ this->hi |= b.hi;
+ this->lo |= b.lo;
+
+ return *this;
+};
+
+int128 & int128::operator &= (const int128 & b) throw () {
+ this->hi &= b.hi;
+ this->lo &= b.lo;
+
+ return *this;
+};
+
+int128 & int128::operator ^= (const int128 & b) throw () {
+ this->hi ^= b.hi;
+ this->lo ^= b.lo;
+
+ return *this;
+};
+
+bool operator < (const int128 & a, const int128 & b) throw () {
+ if (a.hi == b.hi) {
+ if (a.hi < 0)
+ return (int64s) a.lo < (int64s) b.lo;
+ else
+ return a.lo < b.lo;
+ } else
+ return a.hi < b.hi;
+};
+
+bool operator == (const int128 & a, const int128 & b) throw () {
+ return a.hi == b.hi && a.lo == b.lo;
+};
+bool operator && (const int128 & a, const int128 & b) throw () {
+ return (a.hi || a.lo) && (b.hi || b.lo);
+};
+bool operator || (const int128 & a, const int128 & b) throw () {
+ return (a.hi || a.lo) || (b.hi || b.lo);
+};
+
+} //NameSpace
diff --git a/src/thirdparty/ZenLib/int128s.h b/src/thirdparty/ZenLib/int128s.h
new file mode 100644
index 000000000..a63cab6d2
--- /dev/null
+++ b/src/thirdparty/ZenLib/int128s.h
@@ -0,0 +1,205 @@
+// int128s - integer 8 bytes
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// based on http://Tringi.Mx-3.cz
+// Only adapted for ZenLib:
+// - .hpp --> .h
+// - Namespace
+// - int128s alias
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef INT128_HPP
+#define INT128_HPP
+
+/*
+ Name: int128.hpp
+ Copyright: Copyright (C) 2005, Jan Ringos
+ Author: Jan Ringos, http://Tringi.Mx-3.cz
+
+ Version: 1.1
+*/
+
+#include <exception>
+#include <cstdlib>
+#include <cstdio>
+#include <new>
+#include "ZenLib/Conf.h"
+
+namespace ZenLib
+{
+
+// CLASS
+
+class int128 {
+ private:
+ // Binary correct representation of signed 128bit integer
+ int64u lo;
+ int64s hi;
+
+ protected:
+ // Some global operator functions must be friends
+ friend bool operator < (const int128 &, const int128 &) throw ();
+ friend bool operator == (const int128 &, const int128 &) throw ();
+ friend bool operator || (const int128 &, const int128 &) throw ();
+ friend bool operator && (const int128 &, const int128 &) throw ();
+
+ public:
+ // Constructors
+ inline int128 () throw () {};
+ inline int128 (const int128 & a) throw () : lo (a.lo), hi (a.hi) {};
+
+ inline int128 (const unsigned int & a) throw () : lo (a), hi (0ll) {};
+ inline int128 (const signed int & a) throw () : lo (a), hi (0ll) {
+ if (a < 0) this->hi = -1ll;
+ };
+
+ inline int128 (const int64u & a) throw () : lo (a), hi (0ll) {};
+ inline int128 (const int64s & a) throw () : lo (a), hi (0ll) {
+ if (a < 0) this->hi = -1ll;
+ };
+
+ int128 (const float a) throw ();
+ int128 (const double & a) throw ();
+ int128 (const long double & a) throw ();
+
+ int128 (const char * sz) throw ();
+
+ // TODO: Consider creation of operator= to eliminate
+ // the need of intermediate objects during assignments.
+
+ private:
+ // Special internal constructors
+ int128 (const int64u & a, const int64s & b) throw ()
+ : lo (a), hi (b) {};
+
+ public:
+ // Operators
+ bool operator ! () const throw ();
+
+ int128 operator - () const throw ();
+ int128 operator ~ () const throw ();
+
+ int128 & operator ++ ();
+ int128 & operator -- ();
+ int128 operator ++ (int);
+ int128 operator -- (int);
+
+ int128 & operator += (const int128 & b) throw ();
+ int128 & operator *= (const int128 & b) throw ();
+
+ int128 & operator >>= (unsigned int n) throw ();
+ int128 & operator <<= (unsigned int n) throw ();
+
+ int128 & operator |= (const int128 & b) throw ();
+ int128 & operator &= (const int128 & b) throw ();
+ int128 & operator ^= (const int128 & b) throw ();
+
+ // Inline simple operators
+ inline const int128 & operator + () const throw () { return *this; };
+
+ // Rest of inline operators
+ inline int128 & operator -= (const int128 & b) throw () {
+ return *this += (-b);
+ };
+ inline int128 & operator /= (const int128 & b) throw () {
+ int128 dummy;
+ *this = this->div (b, dummy);
+ return *this;
+ };
+ inline int128 & operator %= (const int128 & b) throw () {
+ this->div (b, *this);
+ return *this;
+ };
+
+ // Common methods
+ int toInt () const throw () { return (int) this->lo; };
+ int64s toInt64 () const throw () { return (int64s) this->lo; };
+
+ const char * toString (unsigned int radix = 10) const throw ();
+ float toFloat () const throw ();
+ double toDouble () const throw ();
+ long double toLongDouble () const throw ();
+
+ // Arithmetic methods
+ int128 div (const int128 &, int128 &) const throw ();
+
+ // Bit operations
+ bool bit (unsigned int n) const throw ();
+ void bit (unsigned int n, bool val) throw ();
+}
+#ifdef __GNUC__
+ __attribute__ ((__aligned__ (16), __packed__))
+#endif
+;
+
+
+// GLOBAL OPERATORS
+
+bool operator < (const int128 & a, const int128 & b) throw ();
+bool operator == (const int128 & a, const int128 & b) throw ();
+bool operator || (const int128 & a, const int128 & b) throw ();
+bool operator && (const int128 & a, const int128 & b) throw ();
+
+// GLOBAL OPERATOR INLINES
+
+inline int128 operator + (const int128 & a, const int128 & b) throw () {
+ return int128 (a) += b; };
+inline int128 operator - (const int128 & a, const int128 & b) throw () {
+ return int128 (a) -= b; };
+inline int128 operator * (const int128 & a, const int128 & b) throw () {
+ return int128 (a) *= b; };
+inline int128 operator / (const int128 & a, const int128 & b) throw () {
+ return int128 (a) /= b; };
+inline int128 operator % (const int128 & a, const int128 & b) throw () {
+ return int128 (a) %= b; };
+
+inline int128 operator >> (const int128 & a, unsigned int n) throw () {
+ return int128 (a) >>= n; };
+inline int128 operator << (const int128 & a, unsigned int n) throw () {
+ return int128 (a) <<= n; };
+
+inline int128 operator & (const int128 & a, const int128 & b) throw () {
+ return int128 (a) &= b; };
+inline int128 operator | (const int128 & a, const int128 & b) throw () {
+ return int128 (a) |= b; };
+inline int128 operator ^ (const int128 & a, const int128 & b) throw () {
+ return int128 (a) ^= b; };
+
+inline bool operator > (const int128 & a, const int128 & b) throw () {
+ return b < a; };
+inline bool operator <= (const int128 & a, const int128 & b) throw () {
+ return !(b < a); };
+inline bool operator >= (const int128 & a, const int128 & b) throw () {
+ return !(a < b); };
+inline bool operator != (const int128 & a, const int128 & b) throw () {
+ return !(a == b); };
+
+
+// MISC
+
+//typedef int128 __int128;
+
+typedef int128 int128s;
+} //NameSpace
+
+#endif
diff --git a/src/thirdparty/ZenLib/int128u.cpp b/src/thirdparty/ZenLib/int128u.cpp
new file mode 100644
index 000000000..bc096b833
--- /dev/null
+++ b/src/thirdparty/ZenLib/int128u.cpp
@@ -0,0 +1,392 @@
+// int128u - integer 8 bytes
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// based on http://Tringi.Mx-3.cz
+// Only adapted for ZenLib:
+// - uint128.hpp --> int128u.h
+// - Namespace
+// - int128u alias
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#include "int128u.h"
+
+/*
+ Name: uint128.cpp
+ Copyright: Copyright (C) 2005, Jan Ringos
+ Author: Jan Ringos, http://Tringi.Mx-3.cz
+
+ Version: 1.1
+*/
+
+#include <memory>
+#include <cmath>
+#include <cstring>
+#if defined (__BORLANDC__) || defined (__SUNPRO_CC)
+ #define fmodf fmod
+#endif
+#if defined (__NO_LONG_DOUBLE_MATH) || \
+ defined (__MONTAVISTA__) || defined (__ARMEL__) || \
+ defined (__FreeBSD__) || defined (__OpenBSD__) || \
+ defined (__NetBSD__) || defined (__DragonFly__) || \
+ defined (__sparc__) || defined (__sparc64__) || \
+ defined (__SUNPRO_CC)
+ #define fmodl fmod
+#endif
+using namespace std;
+
+namespace ZenLib
+{
+
+// IMPLEMENTATION
+
+const char * uint128::toString (unsigned int radix) const throw () {
+ if (!*this) return "0";
+ if (radix < 2 || radix > 37) return "(invalid radix)";
+
+ static char sz [256];
+ memset (sz, 0, 256);
+
+ uint128 r;
+ uint128 ii = *this;
+ int i = 255;
+
+ while (!!ii && i) {
+ ii = ii.div (radix, r);
+ sz [--i] = (char) (r.toUint () + ((r.toUint () > 9) ? 'A' - 10 : '0'));
+ };
+
+ return &sz [i];
+};
+
+uint128::uint128 (const char * sz) throw ()
+ : lo (0u), hi (0u) {
+
+ if (!sz) return;
+ if (!sz [0]) return;
+
+ unsigned int radix = 10;
+ unsigned int i = 0;
+ bool minus = false;
+
+ if (sz [i] == '-') {
+ ++i;
+ minus = true;
+ };
+
+ if (sz [i] == '0') {
+ radix = 8;
+ ++i;
+ if (sz [i] == 'x') {
+ radix = 16;
+ ++i;
+ };
+ };
+
+ for (; i < strlen (sz); ++i) {
+ unsigned int n = 0;
+ if (sz [i] >= '0' && sz [i] <= (('0' + (int) radix) < '9'?('0' + (int) radix):'9')) //if (sz [i] >= '0' && sz [i] <= (('0' + (int) radix) <? '9'))
+ n = sz [i] - '0';
+ else if (sz [i] >= 'a' && sz [i] <= 'a' + (int) radix - 10)
+ n = sz [i] - 'a' + 10;
+ else if (sz [i] >= 'A' && sz [i] <= 'A' + (int) radix - 10)
+ n = sz [i] - 'A' + 10;
+ else
+ break;
+
+ (*this) *= radix;
+ (*this) += n;
+ };
+
+ if (minus)
+ *this = 0u - *this;
+
+ return;
+};
+
+uint128::uint128 (const float a) throw ()
+ #if defined (__mips__) || defined (__mipsel__)
+ : lo ((int64u) fmod ((const double)a, 18446744073709551616.0)),
+ #else
+ : lo ((int64u) fmodf (a, 18446744073709551616.0f)),
+ #endif
+ hi ((int64u) (a / 18446744073709551616.0f)) {};
+
+uint128::uint128 (const double & a) throw ()
+ : lo ((int64u) fmod (a, 18446744073709551616.0)),
+ hi ((int64u) (a / 18446744073709551616.0)) {};
+
+uint128::uint128 (const long double & a) throw ()
+ #if defined (__mips__) || defined (__mipsel__)
+ : lo ((int64u) fmod ((const double)a, 18446744073709551616.0)),
+ #else
+ : lo ((int64u) fmodl (a, 18446744073709551616.0l)),
+ #endif
+ hi ((int64u) (a / 18446744073709551616.0l)) {};
+
+float uint128::toFloat () const throw () {
+ return (float) this->hi * 18446744073709551616.0f
+ + (float) this->lo;
+};
+
+double uint128::toDouble () const throw () {
+ return (double) this->hi * 18446744073709551616.0
+ + (double) this->lo;
+};
+
+long double uint128::toLongDouble () const throw () {
+ return (long double) this->hi * 18446744073709551616.0l
+ + (long double) this->lo;
+};
+
+uint128 uint128::operator - () const throw () {
+ if (!this->hi && !this->lo)
+ // number is 0, just return 0
+ return *this;
+ else
+ // non 0 number
+ return uint128 (0-this->lo, ~this->hi);
+};
+
+uint128 uint128::operator ~ () const throw () {
+ return uint128 (~this->lo, ~this->hi);
+};
+
+uint128 & uint128::operator ++ () {
+ ++this->lo;
+ if (!this->lo)
+ ++this->hi;
+
+ return *this;
+};
+
+uint128 & uint128::operator -- () {
+ if (!this->lo)
+ --this->hi;
+ --this->lo;
+
+ return *this;
+};
+
+uint128 uint128::operator ++ (int) {
+ uint128 b = *this;
+ ++ *this;
+
+ return b;
+};
+
+uint128 uint128::operator -- (int) {
+ uint128 b = *this;
+ -- *this;
+
+ return b;
+};
+
+uint128 & uint128::operator += (const uint128 & b) throw () {
+ int64u old_lo = this->lo;
+
+ this->lo += b.lo;
+ this->hi += b.hi + (this->lo < old_lo);
+
+ return *this;
+};
+
+uint128 & uint128::operator *= (const uint128 & b) throw () {
+ if (!b)
+ return *this = 0u;
+ if (b == 1u)
+ return *this;
+
+ uint128 a = *this;
+ uint128 t = b;
+
+ this->lo = 0ull;
+ this->hi = 0ull;
+
+ for (unsigned int i = 0; i < 128; ++i) {
+ if (t.lo & 1)
+ *this += a << i;
+
+ t >>= 1;
+ };
+
+ return *this;
+};
+
+
+uint128 uint128::div (const uint128 & ds, uint128 & remainder) const throw () {
+ if (!ds)
+ return 1u / (unsigned int) ds.lo;
+
+ uint128 dd = *this;
+
+ // only remainder
+ if (ds > dd) {
+ remainder = *this;
+ return 0ull;
+ };
+
+ uint128 r = 0ull;
+ uint128 q = 0ull;
+// while (dd >= ds) { dd -= ds; q += 1; }; // extreme slow version
+
+ unsigned int b = 127;
+ while (r < ds) {
+ r <<= 1;
+ if (dd.bit (b--))
+ r.lo |= 1;
+ };
+ ++b;
+
+ while (true)
+ if (r < ds) {
+ if (!(b--)) break;
+
+ r <<= 1;
+ if (dd.bit (b))
+ r.lo |= 1;
+
+ } else {
+ r -= ds;
+ q.bit (b, true);
+ };
+
+ remainder = r;
+ return q;
+};
+
+bool uint128::bit (unsigned int n) const throw () {
+ n &= 0x7F;
+
+ if (n < 64)
+ return (this->lo & (1ull << n))?true:false;
+ else
+ return (this->hi & (1ull << (n - 64)))?true:false;
+};
+
+void uint128::bit (unsigned int n, bool val) throw () {
+ n &= 0x7F;
+
+ if (val) {
+ if (n < 64) this->lo |= (1ull << n);
+ else this->hi |= (1ull << (n - 64));
+ } else {
+ if (n < 64) this->lo &= ~(1ull << n);
+ else this->hi &= ~(1ull << (n - 64));
+ };
+};
+
+
+uint128 & uint128::operator >>= (unsigned int n) throw () {
+ n &= 0x7F;
+
+ if (n > 63) {
+ n -= 64;
+ this->lo = this->hi;
+ this->hi = 0ull;
+ };
+
+ if (n) {
+ // shift low qword
+ this->lo >>= n;
+
+ // get lower N bits of high qword
+ int64u mask = 0ull;
+ for (unsigned int i = 0; i < n; ++i) mask |= (1ull << i);
+
+ // and add them to low qword
+ this->lo |= (this->hi & mask) << (64 - n);
+
+ // and finally shift also high qword
+ this->hi >>= n;
+ };
+
+ return *this;
+};
+
+uint128 & uint128::operator <<= (unsigned int n) throw () {
+ n &= 0x7F;
+
+ if (n > 63) {
+ n -= 64;
+ this->hi = this->lo;
+ this->lo = 0ull;
+ };
+
+ if (n) {
+ // shift high qword
+ this->hi <<= n;
+
+ // get higher N bits of low qword
+ int64u mask = 0ull;
+ for (unsigned int i = 0; i < n; ++i) mask |= (1ull << (63 - i));
+
+ // and add them to high qword
+ this->hi |= (this->lo & mask) >> (64 - n);
+
+ // and finally shift also low qword
+ this->lo <<= n;
+ };
+
+ return *this;
+};
+
+bool uint128::operator ! () const throw () {
+ return !(this->hi || this->lo);
+};
+
+uint128 & uint128::operator |= (const uint128 & b) throw () {
+ this->hi |= b.hi;
+ this->lo |= b.lo;
+
+ return *this;
+};
+
+uint128 & uint128::operator &= (const uint128 & b) throw () {
+ this->hi &= b.hi;
+ this->lo &= b.lo;
+
+ return *this;
+};
+
+uint128 & uint128::operator ^= (const uint128 & b) throw () {
+ this->hi ^= b.hi;
+ this->lo ^= b.lo;
+
+ return *this;
+};
+
+bool operator < (const uint128 & a, const uint128 & b) throw () {
+ return (a.hi == b.hi) ? (a.lo < b.lo) : (a.hi < b.hi);
+};
+
+bool operator == (const uint128 & a, const uint128 & b) throw () {
+ return a.hi == b.hi && a.lo == b.lo;
+};
+bool operator && (const uint128 & a, const uint128 & b) throw () {
+ return (a.hi || a.lo) && (b.hi || b.lo);
+};
+bool operator || (const uint128 & a, const uint128 & b) throw () {
+ return (a.hi || a.lo) || (b.hi || b.lo);
+};
+
+} //NameSpace
diff --git a/src/thirdparty/ZenLib/int128u.h b/src/thirdparty/ZenLib/int128u.h
new file mode 100644
index 000000000..e04d51337
--- /dev/null
+++ b/src/thirdparty/ZenLib/int128u.h
@@ -0,0 +1,201 @@
+// int128u - integer 8 bytes
+// Copyright (C) 2007-2010 MediaArea.net SARL, Info@MediaArea.net
+//
+// 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.
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// based on http://Tringi.Mx-3.cz
+// Only adapted for ZenLib:
+// - .hpp --> .h
+// - Namespace
+// - int128u alias
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef UINT128_HPP
+#define UINT128_HPP
+
+/*
+ Name: uint128.hpp
+ Copyright: Copyright (C) 2005, Jan Ringos
+ Author: Jan Ringos, http://Tringi.Mx-3.cz
+
+ Version: 1.1
+*/
+
+
+#include <exception>
+#include <cstdlib>
+#include <cstdio>
+#include <new>
+#include "ZenLib/Conf.h"
+
+// CLASS
+
+namespace ZenLib
+{
+
+class uint128 {
+ public://private:
+ // Binary correct representation of signed 128bit integer
+ int64u lo;
+ int64u hi;
+
+ protected:
+ // Some global operator functions must be friends
+ friend bool operator < (const uint128 &, const uint128 &) throw ();
+ friend bool operator == (const uint128 &, const uint128 &) throw ();
+ friend bool operator || (const uint128 &, const uint128 &) throw ();
+ friend bool operator && (const uint128 &, const uint128 &) throw ();
+
+ public:
+ // Constructors
+ inline uint128 () throw () {};
+ inline uint128 (const uint128 & a) throw () : lo (a.lo), hi (a.hi) {};
+
+ inline uint128 (const int & a) throw () : lo (a), hi (0ull) {};
+ inline uint128 (const unsigned int & a) throw () : lo (a), hi (0ull) {};
+ inline uint128 (const int64u & a) throw () : lo (a), hi (0ull) {};
+
+ uint128 (const float a) throw ();
+ uint128 (const double & a) throw ();
+ uint128 (const long double & a) throw ();
+
+ uint128 (const char * sz) throw ();
+
+ // TODO: Consider creation of operator= to eliminate
+ // the need of intermediate objects during assignments.
+
+ private:
+ // Special internal constructors
+ uint128 (const int64u & a, const int64u & b) throw ()
+ : lo (a), hi (b) {};
+
+ public:
+ // Operators
+ bool operator ! () const throw ();
+
+ uint128 operator - () const throw ();
+ uint128 operator ~ () const throw ();
+
+ uint128 & operator ++ ();
+ uint128 & operator -- ();
+ uint128 operator ++ (int);
+ uint128 operator -- (int);
+
+ uint128 & operator += (const uint128 & b) throw ();
+ uint128 & operator *= (const uint128 & b) throw ();
+
+ uint128 & operator >>= (unsigned int n) throw ();
+ uint128 & operator <<= (unsigned int n) throw ();
+
+ uint128 & operator |= (const uint128 & b) throw ();
+ uint128 & operator &= (const uint128 & b) throw ();
+ uint128 & operator ^= (const uint128 & b) throw ();
+
+ // Inline simple operators
+ inline const uint128 & operator + () const throw () { return *this; };
+
+ // Rest of inline operators
+ inline uint128 & operator -= (const uint128 & b) throw () {
+ return *this += (-b);
+ };
+ inline uint128 & operator /= (const uint128 & b) throw () {
+ uint128 dummy;
+ *this = this->div (b, dummy);
+ return *this;
+ };
+ inline uint128 & operator %= (const uint128 & b) throw () {
+ this->div (b, *this);
+ return *this;
+ };
+
+ // Common methods
+ unsigned int toUint () const throw () {
+ return (unsigned int) this->lo; };
+ int64u toUint64 () const throw () {
+ return (int64u) this->lo; };
+ const char * toString (unsigned int radix = 10) const throw ();
+ float toFloat () const throw ();
+ double toDouble () const throw ();
+ long double toLongDouble () const throw ();
+
+ // Arithmetic methods
+ uint128 div (const uint128 &, uint128 &) const throw ();
+
+ // Bit operations
+ bool bit (unsigned int n) const throw ();
+ void bit (unsigned int n, bool val) throw ();
+}
+#ifdef __GNUC__
+ __attribute__ ((__aligned__ (16), __packed__))
+#endif
+;
+
+
+// GLOBAL OPERATORS
+
+bool operator < (const uint128 & a, const uint128 & b) throw ();
+bool operator == (const uint128 & a, const uint128 & b) throw ();
+bool operator || (const uint128 & a, const uint128 & b) throw ();
+bool operator && (const uint128 & a, const uint128 & b) throw ();
+
+// GLOBAL OPERATOR INLINES
+
+inline uint128 operator + (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) += b; };
+inline uint128 operator - (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) -= b; };
+inline uint128 operator * (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) *= b; };
+inline uint128 operator / (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) /= b; };
+inline uint128 operator % (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) %= b; };
+
+inline uint128 operator >> (const uint128 & a, unsigned int n) throw () {
+ return uint128 (a) >>= n; };
+inline uint128 operator << (const uint128 & a, unsigned int n) throw () {
+ return uint128 (a) <<= n; };
+
+inline uint128 operator & (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) &= b; };
+inline uint128 operator | (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) |= b; };
+inline uint128 operator ^ (const uint128 & a, const uint128 & b) throw () {
+ return uint128 (a) ^= b; };
+
+inline bool operator > (const uint128 & a, const uint128 & b) throw () {
+ return b < a; };
+inline bool operator <= (const uint128 & a, const uint128 & b) throw () {
+ return !(b < a); };
+inline bool operator >= (const uint128 & a, const uint128 & b) throw () {
+ return !(a < b); };
+inline bool operator != (const uint128 & a, const uint128 & b) throw () {
+ return !(a == b); };
+
+
+// MISC
+
+typedef uint128 __uint128;
+
+typedef uint128 int128u;
+} //NameSpace
+
+#endif