summaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2011-01-02 01:48:38 +0200
committerAndrei Karas <akaras@inbox.ru>2011-01-02 02:41:24 +0200
commit3eeae12c498d1a4dbe969462d2ba841f77ee3ccb (patch)
treeff8eab35e732bc0749fc11677c8873a7b3a58704 /src/utils
downloadplus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.gz
plus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.bz2
plus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.xz
plus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.zip
Initial commit.
This code based on mana client http://www.gitorious.org/mana/mana and my private repository.
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/base64.cpp170
-rw-r--r--src/utils/base64.h36
-rw-r--r--src/utils/copynpaste.cpp324
-rw-r--r--src/utils/copynpaste.h33
-rw-r--r--src/utils/dtor.h54
-rw-r--r--src/utils/gettext.h44
-rw-r--r--src/utils/mathutils.h114
-rw-r--r--src/utils/mkdir.cpp118
-rw-r--r--src/utils/mkdir.h26
-rw-r--r--src/utils/mutex.h97
-rw-r--r--src/utils/sha256.cpp294
-rw-r--r--src/utils/sha256.h35
-rw-r--r--src/utils/specialfolder.cpp78
-rw-r--r--src/utils/specialfolder.h30
-rw-r--r--src/utils/stringutils.cpp360
-rw-r--r--src/utils/stringutils.h159
-rw-r--r--src/utils/xml.cpp164
-rw-r--r--src/utils/xml.h101
18 files changed, 2237 insertions, 0 deletions
diff --git a/src/utils/base64.cpp b/src/utils/base64.cpp
new file mode 100644
index 000000000..1221a7c7f
--- /dev/null
+++ b/src/utils/base64.cpp
@@ -0,0 +1,170 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2000 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Author: Jim Winstead (jimw@php.net) |
+ +----------------------------------------------------------------------+
+ */
+
+#include "utils/base64.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static char base64_table[] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
+};
+static char base64_pad = '=';
+
+unsigned char *php3_base64_encode(const unsigned char *string,
+ int length, int *ret_length)
+{
+ const unsigned char *current = string;
+ int i = 0;
+ unsigned char *result = (unsigned char *)malloc(
+ ((length + 3 - length % 3) * 4 / 3 + 1) * sizeof(char));
+
+ while (length > 2)
+ { /* keep going until we have less than 24 bits */
+ result[i++] = base64_table[current[0] >> 2];
+ result[i++] = base64_table[((current[0] & 0x03)
+ << 4) + (current[1] >> 4)];
+ result[i++] = base64_table[((current[1] & 0x0f)
+ << 2) + (current[2] >> 6)];
+ result[i++] = base64_table[current[2] & 0x3f];
+
+ current += 3;
+ length -= 3; /* we just handle 3 octets of data */
+ }
+
+ /* now deal with the tail end of things */
+ if (length != 0)
+ {
+ result[i++] = base64_table[current[0] >> 2];
+ if (length > 1)
+ {
+ result[i++] = base64_table[((current[0] & 0x03) << 4)
+ + (current[1] >> 4)];
+ result[i++] = base64_table[(current[1] & 0x0f) << 2];
+ result[i++] = base64_pad;
+ }
+ else
+ {
+ result[i++] = base64_table[(current[0] & 0x03) << 4];
+ result[i++] = base64_pad;
+ result[i++] = base64_pad;
+ }
+ }
+ if (ret_length)
+ {
+ *ret_length = i;
+ }
+ result[i] = '\0';
+ return result;
+}
+
+/* as above, but backwards. :) */
+unsigned char *php3_base64_decode(const unsigned char *string,
+ int length, int *ret_length)
+{
+ const unsigned char *current = string;
+ int ch, i = 0, j = 0, k;
+ char *chp;
+
+ unsigned char *result = (unsigned char *)malloc(length + 1);
+
+ if (result == NULL)
+ return NULL;
+
+ /* run through the whole string, converting as we go */
+ while ((ch = *current++) != '\0')
+ {
+ if (ch == base64_pad) break;
+
+ /* When Base64 gets POSTed, all pluses are interpreted as spaces.
+ This line changes them back. It's not exactly the Base64 spec,
+ but it is completely compatible with it (the spec says that
+ spaces are invalid). This will also save many people considerable
+ headache. - Turadg Aleahmad <turadg@wise.berkeley.edu>
+ */
+
+ if (ch == ' ') ch = '+';
+
+ chp = strchr(base64_table, ch);
+ if (!chp)
+ continue;
+ ch = chp - base64_table;
+
+ switch(i % 4)
+ {
+ case 0:
+ result[j] = ch << 2;
+ break;
+ case 1:
+ result[j++] |= ch >> 4;
+ result[j] = (ch & 0x0f) << 4;
+ break;
+ case 2:
+ result[j++] |= ch >>2;
+ result[j] = (ch & 0x03) << 6;
+ break;
+ case 3:
+ result[j++] |= ch;
+ break;
+ default:
+ break;
+ }
+ i++;
+ }
+
+ k = j;
+ /* mop things up if we ended on a boundary */
+ if (ch == base64_pad)
+ {
+ switch(i % 4)
+ {
+ case 0:
+ case 1:
+ free(result);
+ return 0;
+ case 2:
+ k++;
+ case 3:
+ result[k++] = 0;
+ default:
+ break;
+ }
+ }
+ if (ret_length)
+ {
+ *ret_length = j;
+ }
+ result[k] = '\0';
+ return result;
+}
diff --git a/src/utils/base64.h b/src/utils/base64.h
new file mode 100644
index 000000000..92c230169
--- /dev/null
+++ b/src/utils/base64.h
@@ -0,0 +1,36 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Author: Jim Winstead (jimw@php.net) |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+extern unsigned char *php3_base64_encode(const unsigned char *, int, int *);
+extern unsigned char *php3_base64_decode(const unsigned char *, int, int *);
+
+#endif /* BASE64_H */
diff --git a/src/utils/copynpaste.cpp b/src/utils/copynpaste.cpp
new file mode 100644
index 000000000..498c012b5
--- /dev/null
+++ b/src/utils/copynpaste.cpp
@@ -0,0 +1,324 @@
+/*
+ * Retrieve string pasted depending on OS mechanisms.
+ * Copyright (C) 2001-2010 Wormux Team
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * IMPORTANT!
+ *
+ * This code was taken from Wormux svn trunk at Feb 25 2010. Please don't
+ * make any unnecessary modifications, and try to sync up modifications
+ * when possible.
+ */
+
+#ifdef _MSC_VER
+# include "msvc/config.h"
+#elif defined(HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include <SDL_syswm.h>
+#include "copynpaste.h"
+
+#ifdef WIN32
+bool RetrieveBuffer(std::string& text, std::string::size_type& pos)
+{
+ bool ret = false;
+
+ if (!OpenClipboard(NULL))
+ return false;
+
+ HANDLE h = GetClipboardData(CF_UNICODETEXT);
+ if (h)
+ {
+ LPCWSTR data = (LPCWSTR)GlobalLock(h);
+
+ if (data)
+ {
+ int len = WideCharToMultiByte(CP_UTF8, 0, data, -1, NULL, 0, NULL, NULL);
+ if (len > 0)
+ {
+ // Convert from UTF-16 to UTF-8
+ void *temp = malloc(len);
+ if (WideCharToMultiByte(CP_UTF8, 0, data, -1, (LPSTR)temp, len, NULL, NULL))
+ {
+ text.insert(pos, (char*)temp);
+ pos += len-1;
+ }
+ free(temp);
+ ret = true;
+ }
+ }
+ GlobalUnlock(h);
+ }
+ else
+ {
+ h = GetClipboardData(CF_TEXT);
+
+ if (h)
+ {
+ const char *data = (char*)GlobalLock(h);
+ if (data)
+ {
+ text.insert(pos, data);
+ pos += strlen(data);
+ ret = true;
+ }
+ GlobalUnlock(h);
+ }
+ }
+
+ CloseClipboard();
+ return ret;
+}
+#elif defined(__APPLE__)
+
+#ifdef Status
+#undef Status
+#endif
+
+#include <Carbon/Carbon.h>
+
+// Sorry for the very long code, all nicer OS X APIs are coded in Objective C and not C!
+// Also it does very thorough error handling
+bool GetDataFromPasteboard( PasteboardRef inPasteboard, char* flavorText /* out */, const int bufSize )
+{
+ OSStatus err = noErr;
+ PasteboardSyncFlags syncFlags;
+ ItemCount itemCount;
+
+ syncFlags = PasteboardSynchronize( inPasteboard );
+
+ //require_action( syncFlags & kPasteboardModified, PasteboardOutOfSync,
+ // err = badPasteboardSyncErr );
+
+ err = PasteboardGetItemCount( inPasteboard, &itemCount );
+ require_noerr( err, CantGetPasteboardItemCount );
+
+ for (UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++)
+ {
+ PasteboardItemID itemID;
+ CFArrayRef flavorTypeArray;
+ CFIndex flavorCount;
+
+ err = PasteboardGetItemIdentifier( inPasteboard, itemIndex, &itemID );
+ require_noerr( err, CantGetPasteboardItemIdentifier );
+
+ err = PasteboardCopyItemFlavors( inPasteboard, itemID, &flavorTypeArray );
+ require_noerr( err, CantCopyPasteboardItemFlavors );
+
+ flavorCount = CFArrayGetCount( flavorTypeArray );
+
+ for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
+ {
+ CFStringRef flavorType;
+ CFDataRef flavorData;
+ CFIndex flavorDataSize;
+ flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
+
+ // we're only interested by text...
+ if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text")))
+ {
+ err = PasteboardCopyItemFlavorData( inPasteboard, itemID,
+ flavorType, &flavorData );
+ require_noerr( err, CantCopyFlavorData );
+ flavorDataSize = CFDataGetLength( flavorData );
+ flavorDataSize = (flavorDataSize<254) ? flavorDataSize : 254;
+
+ if (flavorDataSize+2 > bufSize)
+ {
+ fprintf(stderr, "Cannot copy clipboard, contents is too big!\n");
+ return false;
+ }
+
+ for (short dataIndex = 0; dataIndex <= flavorDataSize; dataIndex++)
+ {
+ char byte = *(CFDataGetBytePtr( flavorData ) + dataIndex);
+ flavorText[dataIndex] = byte;
+ }
+
+ flavorText[flavorDataSize] = '\0';
+ flavorText[flavorDataSize+1] = '\n';
+
+ CFRelease (flavorData);
+ return true;
+ }
+
+ continue;
+ CantCopyFlavorData: fprintf(stderr, "Cannot copy clipboard, CantCopyFlavorData!\n");
+ }
+
+ CFRelease (flavorTypeArray);
+ continue;
+
+ CantCopyPasteboardItemFlavors: fprintf(stderr, "Cannot copy clipboard, CantCopyPasteboardItemFlavors!\n"); continue;
+ CantGetPasteboardItemIdentifier: fprintf(stderr, "Cannot copy clipboard, CantGetPasteboardItemIdentifier!\n"); continue;
+ }
+ fprintf(stderr, "Cannot copy clipboard, found no acceptable flavour!\n");
+ return false;
+
+ CantGetPasteboardItemCount: fprintf(stderr, "Cannot copy clipboard, CantGetPasteboardItemCount!\n"); return false;
+ //PasteboardOutOfSync: fprintf(stderr, "Cannot copy clipboard, PasteboardOutOfSync!\n"); return false;
+}
+
+bool getClipBoard(char* text /* out */, const int bufSize )
+{
+ OSStatus err = noErr;
+
+ PasteboardRef theClipboard;
+ err = PasteboardCreate( kPasteboardClipboard, &theClipboard );
+ require_noerr( err, PasteboardCreateFailed );
+
+ if (!GetDataFromPasteboard(theClipboard, text, bufSize))
+ {
+ fprintf(stderr, "Cannot copy clipboard, GetDataFromPasteboardFailed!\n");
+ return false;
+ }
+
+ CFRelease(theClipboard);
+
+ return true;
+
+ // ---- error handling
+ PasteboardCreateFailed: fprintf(stderr, "Cannot copy clipboard, PasteboardCreateFailed!\n");
+ CFRelease(theClipboard);
+ return false;
+}
+
+bool RetrieveBuffer(std::string& text, std::string::size_type& pos)
+{
+ const int bufSize = 512;
+ char buffer[bufSize+1];
+
+ if (getClipBoard(buffer, bufSize))
+ {
+ text = buffer;
+ pos += strlen(buffer);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+#elif USE_X11
+static char* getSelection(Display *dpy, Window us, Atom selection)
+{
+ int max_events = 50;
+ Window owner = XGetSelectionOwner (dpy, selection);
+ int ret;
+
+ //printf("XConvertSelection on %s\n", XGetAtomName(dpy, selection));
+ if (owner == None)
+ {
+ //printf("No owner\n");
+ return NULL;
+ }
+ XConvertSelection(dpy, selection, XA_STRING, XA_PRIMARY, us, CurrentTime);
+ XFlush(dpy);
+
+ while (max_events--)
+ {
+ XEvent e;
+
+ XNextEvent(dpy, &e);
+ if(e.type == SelectionNotify)
+ {
+ //printf("Received %s\n", XGetAtomName(dpy, e.xselection.selection));
+ if(e.xselection.property == None)
+ {
+ //printf("Couldn't convert\n");
+ return NULL;
+ }
+
+ long unsigned len, left, dummy;
+ int format;
+ Atom type;
+ unsigned char *data = NULL;
+
+ ret = XGetWindowProperty(dpy, us, e.xselection.property, 0, 0, False,
+ AnyPropertyType, &type, &format, &len, &left,
+ &data);
+ if (left < 1)
+ {
+ if (ret == Success)
+ XFree(data);
+ return NULL;
+ }
+
+ ret = XGetWindowProperty(dpy, us, e.xselection.property, 0, left, False,
+ AnyPropertyType, &type, &format, &len, &dummy,
+ &data);
+ if (ret != Success)
+ {
+ //printf("Failed to get property: %p on %lu\n", data, len);
+ return NULL;
+ }
+
+ //printf(">>> Got %s: len=%lu left=%lu (event %i)\n", data, len, left, 50-max_events);
+ return (char*)data;
+ }
+ }
+ return NULL;
+}
+
+bool RetrieveBuffer(std::string& text, std::string::size_type& pos)
+{
+ SDL_SysWMinfo info;
+
+ //printf("Retrieving buffer...\n");
+ SDL_VERSION(&info.version);
+ if ( SDL_GetWMInfo(&info) )
+ {
+ Display *dpy = info.info.x11.display;
+ Window us = info.info.x11.window;
+ char *data = NULL;
+
+ if (!data)
+ {
+ data = getSelection(dpy, us, XA_PRIMARY);
+ }
+ if (!data)
+ {
+ data = getSelection(dpy, us, XA_SECONDARY);
+ }
+ if (!data)
+ {
+ Atom XA_CLIPBOARD = XInternAtom(dpy, "CLIPBOARD", 0);
+ data = getSelection(dpy, us, XA_CLIPBOARD);
+ }
+ if (data)
+ {
+ // check cursor position
+ if (pos > text.size()) {
+ pos = text.size();
+ }
+
+ text.insert(pos, data);
+ pos += strlen(data);
+ XFree(data);
+
+ return true;
+ }
+ }
+ return false;
+}
+#else
+bool RetrieveBuffer(std::string&, std::string::size_type&) { return false; }
+#endif
diff --git a/src/utils/copynpaste.h b/src/utils/copynpaste.h
new file mode 100644
index 000000000..1a7c81d05
--- /dev/null
+++ b/src/utils/copynpaste.h
@@ -0,0 +1,33 @@
+/*
+ * Retrieve string pasted depending on OS mechanisms.
+ * Copyright (C) 2001-2010 Wormux Team
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string>
+
+/**
+ * Attempts to retrieve text from the clipboard buffer and inserts it in
+ * \a text at position \pos. The characters are encoded in utf-8.
+ *
+ * Implemented for Windows, X11 and Mac OS X.
+ *
+ * @return <code>true</code> when successful or <code>false</code> when there
+ * was a problem retrieving the clipboard buffer.
+ */
+bool RetrieveBuffer(std::string& text, std::string::size_type& pos);
+
diff --git a/src/utils/dtor.h b/src/utils/dtor.h
new file mode 100644
index 000000000..a50189c4e
--- /dev/null
+++ b/src/utils/dtor.h
@@ -0,0 +1,54 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_DTOR_H
+#define UTILS_DTOR_H
+
+#include <algorithm>
+#include <functional>
+#include <utility>
+
+template<typename T>
+struct dtor : public std::unary_function <T, void>
+{
+ void operator()(T &ptr) { delete ptr; }
+};
+
+template<typename T1, typename T2>
+struct dtor<std::pair<T1, T2> > :
+public std::unary_function <std::pair<T1, T2>, void>
+{
+ void operator()(std::pair<T1, T2> &pair) { delete pair.second; }
+};
+
+template<class Cont>
+inline dtor<typename Cont::value_type> make_dtor(Cont const&)
+{
+ return dtor<typename Cont::value_type>();
+}
+
+template<typename Container>
+inline void delete_all(Container &c)
+{
+ std::for_each(c.begin(), c.end(), make_dtor(c));
+}
+
+#endif
diff --git a/src/utils/gettext.h b/src/utils/gettext.h
new file mode 100644
index 000000000..feeb6595b
--- /dev/null
+++ b/src/utils/gettext.h
@@ -0,0 +1,44 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_GETTEXT_H
+#define UTILS_GETTEXT_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libintl.h>
+
+#if ENABLE_NLS
+
+#define _(s) (const_cast <char*>(gettext(s)))
+#define N_(s) (const_cast <char*>(s))
+
+#else
+
+#define gettext(s) (const_cast <char*>(s))
+#define _(s) (const_cast <char*>(s))
+#define N_(s) (const_cast <char*>(s))
+
+#endif
+
+#endif // UTILS_GETTEXT_H
diff --git a/src/utils/mathutils.h b/src/utils/mathutils.h
new file mode 100644
index 000000000..4917b5566
--- /dev/null
+++ b/src/utils/mathutils.h
@@ -0,0 +1,114 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_MATHUTILS_H
+#define UTILS_MATHUTILS_H
+
+#include <stdint.h>
+
+static uint16_t crc_table[256] =
+{
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+inline uint16_t getCrc16(const std::string &str)
+{
+ size_t f = str.size();
+ uint16_t crc16 = 0xffff;
+
+ while (f != 0)
+ {
+ f --;
+ crc16 = static_cast<uint16_t>(
+ crc_table[(crc16 ^ (str[f])) & 0xff] ^ (crc16 >> 8));
+ }
+
+ return crc16;
+}
+
+/* A very fast function to calculate the approximate inverse square root of a
+ * floating point value and a helper function that uses it for getting the
+ * normal squareroot. For an explanation of the inverse squareroot function
+ * read:
+ * http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf
+ *
+ * Unfortunately the original creator of this function seems to be unknown.
+ */
+
+inline float fastInvSqrt(float x)
+{
+ union { int i; float x; } tmp;
+ float xhalf = 0.5f * x;
+ tmp.x = x;
+ tmp.i = 0x5f375a86 - (tmp.i >> 1);
+ x = tmp.x;
+ x = x * (1.5f - xhalf * x * x);
+ return x;
+}
+
+inline float fastSqrt(float x)
+{
+ return 1.0f / fastInvSqrt(x);
+}
+
+inline float weightedAverage(float n1, float n2, float w)
+{
+ if (w < 0.0f)
+ return n1;
+
+ if (w > 1.0f)
+ return n2;
+
+ return w * n2 + (1.0f - w) * n1;
+}
+
+#endif // UTILS_MATHUTILS_H
diff --git a/src/utils/mkdir.cpp b/src/utils/mkdir.cpp
new file mode 100644
index 000000000..e7b126ae7
--- /dev/null
+++ b/src/utils/mkdir.cpp
@@ -0,0 +1,118 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <climits>
+#include <cstring>
+#include <cerrno>
+
+#if defined WIN32
+#include <windows.h>
+#endif
+
+#include <sys/stat.h>
+
+#ifdef _MKDIR_TEST_
+// compile with -D_MKDIR_TEST_ to get a standalone binary
+#include <cstdio>
+#include <cstdlib>
+#endif
+
+#include "mkdir.h"
+
+int mkdir_r(const char *pathname)
+{
+ char tmp[PATH_MAX];
+ char *p;
+
+ if (strlen(pathname) >= PATH_MAX - 2)
+ return -1;
+
+ strncpy(tmp, pathname, sizeof(tmp) - 1);
+ tmp[PATH_MAX - 1] = '\0';
+
+ int len = strlen(tmp);
+
+ // terminate the pathname with '/'
+ if (tmp[len - 1] != '/')
+ {
+ tmp[len] = '/';
+ tmp[len + 1] = '\0';
+ }
+
+ for (p = tmp; *p; p++)
+ {
+#if defined WIN32
+ if (*p == '/' || *p == '\\')
+#else
+ if (*p == '/')
+#endif
+ {
+ *p = '\0';
+ // ignore a slash at the beginning of a path
+ if (strlen(tmp) == 0)
+ {
+ *p = '/';
+ continue;
+ }
+
+ // check if the name already exists, but not as directory
+ struct stat statbuf;
+ if (!stat(tmp, &statbuf))
+ {
+ if (S_ISDIR(statbuf.st_mode))
+ {
+ *p = '/';
+ continue;
+ }
+ else
+ return -1;
+ }
+
+#if defined WIN32
+ if (!CreateDirectory(tmp, 0))
+#else
+ if (mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
+#endif
+ {
+#if defined WIN32
+ // hack, hack. just assume that x: might be a drive
+ // letter, and try again
+ if (!(strlen(tmp) == 2 &&
+ !strcmp(tmp + 1, ":")))
+#endif
+ return -1;
+ }
+
+#ifdef _MKDIR_TEST_
+ printf("%s\n", tmp);
+#endif
+ *p = '/';
+ }
+ }
+ return 0;
+}
+
+#ifdef _MKDIR_TEST_
+int main(int argc, char** argv)
+{
+ if (argc < 2) exit(1);
+ mkdir_r(argv[1]);
+}
+#endif
diff --git a/src/utils/mkdir.h b/src/utils/mkdir.h
new file mode 100644
index 000000000..9369b4e7b
--- /dev/null
+++ b/src/utils/mkdir.h
@@ -0,0 +1,26 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MKDIR_H
+#define _MKDIR_H
+
+int mkdir_r(const char *pathname);
+
+#endif
diff --git a/src/utils/mutex.h b/src/utils/mutex.h
new file mode 100644
index 000000000..f98bcdfec
--- /dev/null
+++ b/src/utils/mutex.h
@@ -0,0 +1,97 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUTEX_H
+#define MUTEX_H
+
+#include "log.h"
+
+#include <SDL_thread.h>
+
+/**
+ * A mutex provides mutual exclusion of access to certain data that is
+ * accessed by multiple threads.
+ */
+class Mutex
+{
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+
+private:
+ Mutex(const Mutex&); // prevent copying
+ Mutex& operator=(const Mutex&);
+
+ SDL_mutex *mMutex;
+};
+
+/**
+ * A convenience class for locking a mutex.
+ */
+class MutexLocker
+{
+public:
+ MutexLocker(Mutex *mutex);
+ ~MutexLocker();
+
+private:
+ Mutex *mMutex;
+};
+
+
+inline Mutex::Mutex()
+{
+ mMutex = SDL_CreateMutex();
+}
+
+inline Mutex::~Mutex()
+{
+ SDL_DestroyMutex(mMutex);
+}
+
+inline void Mutex::lock()
+{
+ if (SDL_mutexP(mMutex) == -1)
+ logger->log("Mutex locking failed: %s", SDL_GetError());
+}
+
+inline void Mutex::unlock()
+{
+ if (SDL_mutexV(mMutex) == -1)
+ logger->log("Mutex unlocking failed: %s", SDL_GetError());
+}
+
+
+inline MutexLocker::MutexLocker(Mutex *mutex):
+ mMutex(mutex)
+{
+ mMutex->lock();
+}
+
+inline MutexLocker::~MutexLocker()
+{
+ mMutex->unlock();
+}
+
+#endif // MUTEX_H
diff --git a/src/utils/sha256.cpp b/src/utils/sha256.cpp
new file mode 100644
index 000000000..29bbed29f
--- /dev/null
+++ b/src/utils/sha256.cpp
@@ -0,0 +1,294 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file has been slighly modified as part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2008 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+/* m_sha256 - Based on m_opersha256 written by Special <john@yarbbles.com>
+ * Modified and improved by Craig Edwards, December 2006.
+ *
+ *
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 05/23/2005
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "utils/sha256.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <memory.h>
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#else
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+#endif
+
+#define SHA256_BLOCK_SIZE (512 / 8)
+
+/** An sha 256 context, used by original m_opersha256 */
+class SHA256Context
+{
+ public:
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA256_BLOCK_SIZE];
+ uint32_t h[8];
+};
+
+#define SHA256_DIGEST_SIZE (256 / 8)
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str) \
+{ \
+ *((str) + 3) = (uint8_t) ((x) ); \
+ *((str) + 2) = (uint8_t) ((x) >> 8); \
+ *((str) + 1) = (uint8_t) ((x) >> 16); \
+ *((str) + 0) = (uint8_t) ((x) >> 24); \
+}
+
+#define PACK32(str, x) \
+{ \
+ *(x) = ((uint32_t) *((str) + 3) ) \
+ | ((uint32_t) *((str) + 2) << 8) \
+ | ((uint32_t) *((str) + 1) << 16) \
+ | ((uint32_t) *((str) + 0) << 24); \
+}
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+{ \
+ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ + SHA256_F3(w[i - 15]) + w[i - 16]; \
+}
+
+const unsigned int sha256_h0[8] =
+{
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+};
+
+uint32_t sha256_k[64] =
+{
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+void SHA256Init(SHA256Context *ctx);
+
+void SHA256Transform(SHA256Context *ctx,
+ unsigned char *message,
+ unsigned int block_nb);
+
+void SHA256Update(SHA256Context *ctx,
+ unsigned char *message,
+ unsigned int len);
+
+void SHA256Final(SHA256Context *ctx, unsigned char *digest);
+
+std::string SHA256Hash(const char *src, int len);
+
+void SHA256Init(SHA256Context *ctx)
+{
+ for (int i = 0; i < 8; i++)
+ ctx->h[i] = sha256_h0[i];
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void SHA256Transform(SHA256Context *ctx,
+ unsigned char *message,
+ unsigned int block_nb)
+{
+ uint32_t w[64];
+ uint32_t wv[8];
+ unsigned char *sub_block;
+ for (unsigned int i = 1; i <= block_nb; i++)
+ {
+ int j;
+ sub_block = message + ((i - 1) << 6);
+
+ for (j = 0; j < 16; j++)
+ PACK32(&sub_block[j << 2], &w[j]);
+ for (j = 16; j < 64; j++)
+ SHA256_SCR(j);
+ for (j = 0; j < 8; j++)
+ wv[j] = ctx->h[j];
+ for (j = 0; j < 64; j++)
+ {
+ uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
+ uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+ for (j = 0; j < 8; j++)
+ ctx->h[j] += wv[j];
+ }
+}
+
+void SHA256Update(SHA256Context *ctx,
+ unsigned char *message,
+ unsigned int len)
+{
+ /*
+ * XXX here be dragons!
+ * After many hours of pouring over this, I think I've found the problem.
+ * When Special created our module from the reference one, he used:
+ *
+ * unsigned int rem_len = SHA256_BLOCK_SIZE - ctx->len;
+ *
+ * instead of the reference's version of:
+ *
+ * unsigned int tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+ * unsigned int rem_len = len < tmp_len ? len : tmp_len;
+ *
+ * I've changed back to the reference version of this code, and it seems to work with no errors.
+ * So I'm inclined to believe this was the problem..
+ * -- w00t (January 06, 2008)
+ */
+ unsigned int tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+ unsigned int rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+ if (ctx->len + len < SHA256_BLOCK_SIZE)
+ {
+ ctx->len += len;
+ return;
+ }
+ unsigned int new_len = len - rem_len;
+ unsigned int block_nb = new_len / SHA256_BLOCK_SIZE;
+ unsigned char *shifted_message = message + rem_len;
+ SHA256Transform(ctx, ctx->block, 1);
+ SHA256Transform(ctx, shifted_message, block_nb);
+ rem_len = new_len % SHA256_BLOCK_SIZE;
+ memcpy(ctx->block, &shifted_message[block_nb << 6],rem_len);
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void SHA256Final(SHA256Context *ctx, unsigned char *digest)
+{
+ unsigned int block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE)));
+ unsigned int len_b = (ctx->tot_len + ctx->len) << 3;
+ unsigned int pm_len = block_nb << 6;
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+ SHA256Transform(ctx, ctx->block, block_nb);
+ for (int i = 0 ; i < 8; i++)
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+}
+
+std::string SHA256Hash(const char *src, int len)
+{
+ // Generate the hash
+ unsigned char bytehash[SHA256_DIGEST_SIZE];
+ SHA256Context ctx;
+ SHA256Init(&ctx);
+ SHA256Update(&ctx, (unsigned char *)src, (unsigned int)len);
+ SHA256Final(&ctx, bytehash);
+ // Convert it to hex
+ const char* hxc = "0123456789abcdef";
+ std::string hash = "";
+ for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
+ {
+ hash += hxc[bytehash[i] / 16];
+ hash += hxc[bytehash[i] % 16];
+ }
+ return hash;
+}
+
+std::string sha256(const std::string &string)
+{
+ return SHA256Hash(string.c_str(), string.length());
+}
diff --git a/src/utils/sha256.h b/src/utils/sha256.h
new file mode 100644
index 000000000..1248e8ddd
--- /dev/null
+++ b/src/utils/sha256.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_SHA256_H
+#define UTILS_SHA256_H
+
+#include <string>
+
+/**
+ * Returns the SHA-256 hash for the given string.
+ *
+ * @param string the string to create the SHA-256 hash for
+ * @return the SHA-256 hash for the given string.
+ */
+std::string sha256(const std::string &string);
+
+#endif // UTILS_SHA256_H
diff --git a/src/utils/specialfolder.cpp b/src/utils/specialfolder.cpp
new file mode 100644
index 000000000..646077161
--- /dev/null
+++ b/src/utils/specialfolder.cpp
@@ -0,0 +1,78 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef WIN32
+#include "specialfolder.h"
+#include <windows.h>
+
+#ifdef _SPECIALFOLDERLOCATION_TEST_
+// compile with -D_SPECIALFOLDERLOCATION_TEST_ to get a standalone
+// binary for testing
+#include <iostream>
+#endif
+
+/*
+ * Retrieve the pathname of special folders on win32, or an empty string
+ * on error / if the folder does not exist.
+ * See http://msdn.microsoft.com/en-us/library/bb762494(VS.85).aspx for
+ * a list of folder ids
+ */
+std::string getSpecialFolderLocation(int folderId)
+{
+ std::string ret;
+ LPITEMIDLIST pItemIdList;
+ LPMALLOC pMalloc;
+ char szPath[_MAX_PATH];
+
+ // get the item ID list for folderId
+ HRESULT hr = SHGetSpecialFolderLocation(NULL, folderId, &pItemIdList);
+ if (hr != S_OK)
+ return ret;
+
+ // convert the ID list into a file system path
+ if (SHGetPathFromIDList(pItemIdList, szPath) == FALSE)
+ return ret;
+
+ // get the IMalloc pointer and free all resources we used
+ hr = SHGetMalloc(&pMalloc);
+ pMalloc->Free(pItemIdList);
+ pMalloc->Release();
+
+ ret = szPath;
+ return ret;
+}
+
+#ifdef _SPECIALFOLDERLOCATION_TEST_
+int main()
+{
+ std::cout << "APPDATA " << getSpecialFolderLocation(CSIDL_APPDATA)
+ << std::endl;
+ std::cout << "DESKTOP " << getSpecialFolderLocation(CSIDL_DESKTOP)
+ << std::endl;
+ std::cout << "LOCAL_APPDATA "
+ << getSpecialFolderLocation(CSIDL_LOCAL_APPDATA)
+ << std::endl;
+ std::cout << "MYPICTURES " << getSpecialFolderLocation(CSIDL_MYPICTURES)
+ << std::endl;
+ std::cout << "PERSONAL " << getSpecialFolderLocation(CSIDL_PERSONAL)
+ << std::endl;
+}
+#endif
+#endif
diff --git a/src/utils/specialfolder.h b/src/utils/specialfolder.h
new file mode 100644
index 000000000..c2c2e0bea
--- /dev/null
+++ b/src/utils/specialfolder.h
@@ -0,0 +1,30 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SPECIALFOLDER_H
+#define _SPECIALFOLDER_H
+
+#ifdef WIN32
+#include <shlobj.h>
+#include <string>
+std::string getSpecialFolderLocation(int folderId);
+#endif
+
+#endif
diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp
new file mode 100644
index 000000000..e69b03937
--- /dev/null
+++ b/src/utils/stringutils.cpp
@@ -0,0 +1,360 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/stringutils.h"
+
+#include <string.h>
+#include <algorithm>
+#include <cstdarg>
+#include <cstdio>
+#include <list>
+
+static int UTF8_MAX_SIZE = 10;
+
+std::string &trim(std::string &str)
+{
+ std::string::size_type pos = str.find_last_not_of(' ');
+ if (pos != std::string::npos)
+ {
+ str.erase(pos + 1);
+ pos = str.find_first_not_of(' ');
+
+ if (pos != std::string::npos)
+ str.erase(0, pos);
+ }
+ else
+ {
+ // There is nothing else but whitespace in the string
+ str.clear();
+ }
+ return str;
+}
+
+std::string &toLower(std::string &str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), tolower);
+ return str;
+}
+
+std::string &toUpper(std::string &str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), toupper);
+ return str;
+}
+
+unsigned int atox(const std::string &str)
+{
+ unsigned int value;
+ sscanf(str.c_str(), "0x%06x", &value);
+
+ return value;
+}
+
+const char *ipToString(int address)
+{
+ static char asciiIP[18];
+
+ sprintf(asciiIP, "%i.%i.%i.%i",
+ (unsigned char)(address),
+ (unsigned char)(address >> 8),
+ (unsigned char)(address >> 16),
+ (unsigned char)(address >> 24));
+
+ return asciiIP;
+}
+
+std::string strprintf(char const *format, ...)
+{
+ char buf[257];
+ va_list(args);
+ va_start(args, format);
+ int nb = vsnprintf(buf, 256, format, args);
+ va_end(args);
+ if (nb < 256)
+ return buf;
+
+ // The static size was not big enough, try again with a dynamic allocation.
+ ++nb;
+ char *buf2 = new char[nb];
+ va_start(args, format);
+ vsnprintf(buf2, nb, format, args);
+ va_end(args);
+ std::string res(buf2);
+ delete [] buf2;
+ return res;
+}
+
+std::string &removeBadChars(std::string &str)
+{
+ std::string::size_type pos;
+ do
+ {
+ pos = str.find_first_of("@#[]");
+ if (pos != std::string::npos)
+ str.erase(pos, 1);
+ }
+ while (pos != std::string::npos);
+
+ return str;
+}
+
+std::string removeColors(std::string msg)
+{
+ for (unsigned int f = 0; f < msg.length() - 2 && msg.length() > 2; f++)
+ {
+ while (msg.length() > f + 2 && msg.at(f) == '#'
+ && msg.at(f + 1) == '#')
+ {
+ msg = msg.erase(f, 3);
+ }
+ }
+ return msg;
+}
+
+int compareStrI(const std::string &a, const std::string &b)
+{
+ std::string::const_iterator itA = a.begin();
+ std::string::const_iterator endA = a.end();
+ std::string::const_iterator itB = b.begin();
+ std::string::const_iterator endB = b.end();
+
+ for (; itA < endA, itB < endB; ++itA, ++itB)
+ {
+ int comp = tolower(*itA) - tolower(*itB);
+ if (comp)
+ return comp;
+ }
+
+ // Check string lengths
+ if (itA == endA && itB == endB)
+ return 0;
+ else if (itA == endA)
+ return -1;
+ else
+ return 1;
+}
+
+
+bool isWordSeparator(char chr)
+{
+ return (chr == ' ' || chr == ',' || chr == '.' || chr == '"');
+}
+
+const std::string findSameSubstring(const std::string &str1,
+ const std::string &str2)
+{
+ int minLength = str1.length() > str2.length()
+ ? static_cast<int>(str2.length()) : static_cast<int>(str1.length());
+ for (int f = 0; f < minLength; f ++)
+ {
+ if (str1.at(f) != str2.at(f))
+ return str1.substr(0, f);
+ }
+ return str1.substr(0, minLength);
+}
+
+unsigned long findI(std::string str, std::string subStr)
+{
+ str = toLower(str);
+ subStr = toLower(subStr);
+ return str.find(subStr);
+}
+
+unsigned long findI(std::string str, std::list<std::string> &list)
+{
+ str = toLower(str);
+ unsigned long idx;
+ for (std::list<std::string>::iterator i = list.begin();
+ i != list.end(); i++)
+ {
+ std::string subStr = toLower(*i);
+ idx = str.find(subStr);
+ if (idx != std::string::npos)
+ return idx;
+ }
+ return std::string::npos;
+}
+
+int base = 94;
+int start = 33;
+
+const std::string encodeStr(unsigned int value, unsigned int size)
+{
+ std::string buf;
+
+ do
+ {
+ buf += static_cast<char>(value % base + start);
+ value /= base;
+ }
+ while (value);
+
+ while (buf.length() < size)
+ buf += (char)start;
+ return buf;
+}
+
+
+unsigned int decodeStr(const std::string &str)
+{
+ if (str.empty())
+ return 0;
+
+ int res = str[0] - start;
+ int mult = 1;
+ for (unsigned int f = 1; f < str.length(); f ++)
+ {
+ mult *= base;
+ res = res + (str[f] - start) * mult;
+ }
+ return res;
+}
+
+std::string extractNameFromSprite(std::string str)
+{
+ size_t pos1 = str.rfind(".");
+ if (pos1 != std::string::npos)
+ {
+ size_t pos2 = str.rfind("/");
+ size_t pos3 = str.rfind("\\");
+ if (pos3 != std::string::npos)
+ {
+ if (pos2 == std::string::npos || pos3 > pos2)
+ pos2 = pos3;
+ }
+ if (pos2 == std::string::npos)
+ pos2 = -1;
+
+ int size = static_cast<int>(pos1) - static_cast<int>(pos2) - 1;
+ if (size > 0)
+ str = str.substr(pos2 + 1, size);
+ }
+ return str;
+}
+
+std::string removeSpriteIndex(std::string str)
+{
+ size_t pos1 = str.rfind("[");
+
+ if (pos1 != std::string::npos)
+ {
+ size_t pos2 = str.rfind("/");
+ size_t pos3 = str.rfind("\\");
+ if (pos3 != std::string::npos)
+ {
+ if (pos2 == std::string::npos || pos3 > pos2)
+ pos2 = pos3;
+ }
+ if (pos2 == std::string::npos)
+ pos2 = -1;
+
+ int size = static_cast<int>(pos1) - static_cast<int>(pos2) - 1;
+ if (size > 0)
+ str = str.substr(pos2 + 1, size);
+ }
+ return str;
+}
+
+const char* getSafeUtf8String(std::string text)
+{
+ int size = static_cast<int>(text.size()) + UTF8_MAX_SIZE;
+ char* buf = new char[size];
+ memcpy(buf, text.c_str(), text.size());
+ memset(buf + text.size(), 0, UTF8_MAX_SIZE);
+ return buf;
+}
+
+void getSafeUtf8String(std::string text, char *buf)
+{
+ int size = static_cast<int>(text.size()) + UTF8_MAX_SIZE;
+ if (size > 65500)
+ text = text.substr(0, 65500);
+ memcpy(buf, text.c_str(), text.size());
+ memset(buf + text.size(), 0, UTF8_MAX_SIZE);
+ return;
+}
+
+std::string getFileName(std::string path)
+{
+ size_t pos = path.rfind("/");
+ if (pos == std::string::npos)
+ pos = path.rfind("\\");
+ if (pos == std::string::npos)
+ return path;
+ return path.substr(pos + 1);
+}
+
+std::string& replaceAll(std::string& context, const std::string& from,
+ const std::string& to)
+{
+ size_t lookHere = 0;
+ size_t foundHere;
+ while ((foundHere = context.find(from, lookHere)) != std::string::npos)
+ {
+ context.replace(foundHere, from.size(), to);
+ lookHere = foundHere + to.size();
+ }
+ return context;
+}
+
+bool getBoolFromString(const std::string &text)
+{
+ std::string txt = text;
+ toLower(trim(txt));
+ if (txt == "true" || txt == "yes" || txt == "on" || txt == "1")
+ return true;
+ else if (txt == "false" || txt == "no" || txt == "off" || txt == "0")
+ return false;
+ else
+ return (bool) atoi(txt.c_str());
+}
+
+void replaceSpecialChars(std::string &text)
+{
+ size_t idx = 0;
+ size_t pos1 = text.find("&");
+ while (pos1 != std::string::npos)
+ {
+ idx = pos1 + 1;
+ if (idx >= text.size())
+ break;
+
+ unsigned f;
+ for (f = idx; f < text.size(); f ++)
+ {
+ if (text[f] < '0' || text[f] > '9')
+ break;
+ }
+ if (idx + 1 < f && text[f] == ';')
+ {
+ std::string str = " ";
+ str[0] = (char)atoi(text.substr(idx, f - idx).c_str());
+ text = text.substr(0, pos1) + str + text.substr(f + 1);
+ pos1 += 1;
+ }
+ else
+ {
+ pos1 = f + 1;
+ }
+
+ pos1 = text.find("&", pos1);
+ }
+} \ No newline at end of file
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
new file mode 100644
index 000000000..4532a5b00
--- /dev/null
+++ b/src/utils/stringutils.h
@@ -0,0 +1,159 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_STRINGUTILS_H
+#define UTILS_STRINGUTILS_H
+
+#include <string>
+#include <sstream>
+#include <list>
+
+/**
+ * Trims spaces off the end and the beginning of the given string.
+ *
+ * @param str the string to trim spaces off
+ * @return a reference to the trimmed string
+ */
+std::string &trim(std::string &str);
+
+/**
+ * Converts the given string to lower case.
+ *
+ * @param str the string to convert to lower case
+ * @return a reference to the given string converted to lower case
+ */
+std::string &toLower(std::string &str);
+
+/**
+ * Converts the given string to upper case.
+ *
+ * @param str the string to convert to upper case
+ * @return a reference to the given string converted to upper case
+ */
+std::string &toUpper(std::string &str);
+
+
+/**
+ * Converts an ascii hexidecimal string to an integer
+ *
+ * @param str the hex string to convert to an int
+ * @return the integer representation of the hex string
+ */
+unsigned int atox(const std::string &str);
+
+/**
+ * Converts the given value to a string using std::stringstream.
+ *
+ * @param arg the value to convert to a string
+ * @return the string representation of arg
+ */
+template<typename T> std::string toString(const T &arg)
+{
+ std::stringstream ss;
+ ss << arg;
+ return ss.str();
+}
+
+/**
+ * Converts the given IP address to a string.
+ *
+ * The returned string is statically allocated, and shouldn't be freed. It is
+ * changed upon the next use of this method.
+ *
+ * @param address the address to convert to a string
+ * @return the string representation of the address
+ */
+const char *ipToString(int address);
+
+/**
+ * A safe version of sprintf that returns a std::string of the result.
+ */
+std::string strprintf(char const *, ...)
+#ifdef __GNUC__
+ /* This attribute is nice: it even works through gettext invokation. For
+ example, gcc will complain that strprintf(_("%s"), 42) is ill-formed. */
+ __attribute__((__format__(__printf__, 1, 2)))
+#endif
+;
+
+/**
+ * Removes bad characters from a string
+ *
+ * @param str the string to remove the bad chars from
+ * @return a reference to the string without bad chars
+ */
+std::string &removeBadChars(std::string &str);
+
+/**
+ * Removes colors from a string
+ *
+ * @param msg the string to remove the colors from
+ * @return string without colors
+ */
+std::string removeColors(std::string msg);
+
+bool isWordSeparator(char chr);
+
+const std::string findSameSubstring(const std::string &str1,
+ const std::string &str2);
+
+/**
+ * Compares the two strings case-insensitively.
+ *
+ * @param a the first string in the comparison
+ * @param b the second string in the comparison
+ * @return 0 if the strings are equal, positive if the first is greater,
+ * negative if the second is greater
+ */
+int compareStrI(const std::string &a, const std::string &b);
+
+unsigned long findI(std::string str, std::string subStr);
+
+unsigned long findI(std::string str, std::list<std::string> &list);
+
+const std::string encodeStr(unsigned int value, unsigned int size = 0);
+
+unsigned int decodeStr(const std::string &str);
+
+std::string extractNameFromSprite(std::string str);
+
+std::string removeSpriteIndex(std::string str);
+
+const char* getSafeUtf8String(std::string text);
+
+void getSafeUtf8String(std::string text, char *buf);
+
+std::string getFileName(std::string path);
+
+std::string& replaceAll(std::string& context, const std::string& from,
+ const std::string& to);
+
+/**
+ * Returns a bool value depending on the given string value.
+ *
+ * @param text the string used to get the bool value
+ * @return a boolean value..
+ */
+bool getBoolFromString(const std::string &text);
+
+void replaceSpecialChars(std::string &text);
+
+#endif // UTILS_STRINGUTILS_H
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
new file mode 100644
index 000000000..9521f377d
--- /dev/null
+++ b/src/utils/xml.cpp
@@ -0,0 +1,164 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/xml.h"
+
+#include "log.h"
+
+#include "resources/resourcemanager.h"
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+
+namespace XML
+{
+ Document::Document(const std::string &filename, bool useResman):
+ mDoc(0)
+ {
+ int size;
+ char *data = NULL;
+ if (useResman)
+ {
+ ResourceManager *resman = ResourceManager::getInstance();
+ data = (char*) resman->loadFile(filename.c_str(), size);
+ }
+ else
+ {
+ std::ifstream file;
+ file.open(filename.c_str(), std::ios::in);
+
+ if (file.is_open())
+ {
+ // Get length of file
+ file.seekg (0, std::ios::end);
+ size = static_cast<int>(file.tellg());
+ file.seekg(0, std::ios::beg);
+
+ data = (char*) malloc(size);
+
+ file.read(data, size);
+ file.close();
+ }
+ else
+ {
+ logger->log("Error loading XML file %s", filename.c_str());
+ }
+ }
+
+ if (data)
+ {
+ mDoc = xmlParseMemory(data, size);
+ free(data);
+
+ if (!mDoc)
+ logger->log("Error parsing XML file %s", filename.c_str());
+ }
+ else
+ {
+ logger->log("Error loading %s", filename.c_str());
+ }
+ }
+
+ Document::Document(const char *data, int size)
+ {
+ if (data)
+ mDoc = xmlParseMemory(data, size);
+ else
+ mDoc = 0;
+ }
+
+ Document::~Document()
+ {
+ if (mDoc)
+ xmlFreeDoc(mDoc);
+ }
+
+ xmlNodePtr Document::rootNode()
+ {
+ return mDoc ? xmlDocGetRootElement(mDoc) : 0;
+ }
+
+ int getProperty(xmlNodePtr node, const char* name, int def)
+ {
+ int &ret = def;
+
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop)
+ {
+ ret = atoi((char*)prop);
+ xmlFree(prop);
+ }
+
+ return ret;
+ }
+
+ double getFloatProperty(xmlNodePtr node, const char* name, double def)
+ {
+ double &ret = def;
+
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop)
+ {
+ ret = atof((char*)prop);
+ xmlFree(prop);
+ }
+
+ return ret;
+ }
+
+ std::string getProperty(xmlNodePtr node, const char *name,
+ const std::string &def)
+ {
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop)
+ {
+ std::string val = (char*)prop;
+ xmlFree(prop);
+ return val;
+ }
+
+ return def;
+ }
+
+ bool getBoolProperty(xmlNodePtr node, const char* name, bool def)
+ {
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+
+ if (xmlStrEqual(prop, BAD_CAST "true" ))
+ return true;
+ if (xmlStrEqual(prop, BAD_CAST "false"))
+ return false;
+ return def;
+ }
+
+ xmlNodePtr findFirstChildByName(xmlNodePtr parent, const char *name)
+ {
+ for_each_xml_child_node(child, parent)
+ {
+ if (xmlStrEqual(child->name, BAD_CAST name))
+ return child;
+ }
+
+ return NULL;
+ }
+
+} // namespace XML
diff --git a/src/utils/xml.h b/src/utils/xml.h
new file mode 100644
index 000000000..253c4e094
--- /dev/null
+++ b/src/utils/xml.h
@@ -0,0 +1,101 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XML_H
+#define XML_H
+
+#include <libxml/tree.h>
+
+#include <string>
+
+/**
+ * XML helper functions.
+ */
+namespace XML
+{
+ /**
+ * A helper class for parsing an XML document, which also cleans it up
+ * again (RAII).
+ */
+ class Document
+ {
+ public:
+ /**
+ * Constructor that attempts to load the given file through the
+ * resource manager. Logs errors.
+ */
+ Document(const std::string &filename, bool useResman = true);
+
+ /**
+ * Constructor that attempts to load an XML document from memory.
+ * Does not log errors.
+ *
+ * @param data the string to parse as XML
+ * @param size the length of the string in bytes
+ */
+ Document(const char *data, int size);
+
+ /**
+ * Destructor. Frees the loaded XML file.
+ */
+ ~Document();
+
+ /**
+ * Returns the root node of the document (or NULL if there was a
+ * load error).
+ */
+ xmlNodePtr rootNode();
+
+ private:
+ xmlDocPtr mDoc;
+ };
+
+ /**
+ * Gets an floating point property from an xmlNodePtr.
+ */
+ double getFloatProperty(xmlNodePtr node, const char *name, double def);
+
+ /**
+ * Gets an integer property from an xmlNodePtr.
+ */
+ int getProperty(xmlNodePtr node, const char *name, int def);
+
+ /**
+ * Gets a string property from an xmlNodePtr.
+ */
+ std::string getProperty(xmlNodePtr node, const char *name,
+ const std::string &def);
+
+ /**
+ * Gets a boolean property from an xmlNodePtr.
+ */
+ bool getBoolProperty(xmlNodePtr node, const char *name, bool def);
+
+ /**
+ * Finds the first child node with the given name
+ */
+ xmlNodePtr findFirstChildByName(xmlNodePtr parent, const char *name);
+}
+
+#define for_each_xml_child_node(var, parent) \
+ for (xmlNodePtr var = parent->xmlChildrenNode; var; var = var->next)
+
+#endif // XML_H