diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-01-02 01:48:38 +0200 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-01-02 02:41:24 +0200 |
commit | 3eeae12c498d1a4dbe969462d2ba841f77ee3ccb (patch) | |
tree | ff8eab35e732bc0749fc11677c8873a7b3a58704 /src/utils | |
download | plus-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.cpp | 170 | ||||
-rw-r--r-- | src/utils/base64.h | 36 | ||||
-rw-r--r-- | src/utils/copynpaste.cpp | 324 | ||||
-rw-r--r-- | src/utils/copynpaste.h | 33 | ||||
-rw-r--r-- | src/utils/dtor.h | 54 | ||||
-rw-r--r-- | src/utils/gettext.h | 44 | ||||
-rw-r--r-- | src/utils/mathutils.h | 114 | ||||
-rw-r--r-- | src/utils/mkdir.cpp | 118 | ||||
-rw-r--r-- | src/utils/mkdir.h | 26 | ||||
-rw-r--r-- | src/utils/mutex.h | 97 | ||||
-rw-r--r-- | src/utils/sha256.cpp | 294 | ||||
-rw-r--r-- | src/utils/sha256.h | 35 | ||||
-rw-r--r-- | src/utils/specialfolder.cpp | 78 | ||||
-rw-r--r-- | src/utils/specialfolder.h | 30 | ||||
-rw-r--r-- | src/utils/stringutils.cpp | 360 | ||||
-rw-r--r-- | src/utils/stringutils.h | 159 | ||||
-rw-r--r-- | src/utils/xml.cpp | 164 | ||||
-rw-r--r-- | src/utils/xml.h | 101 |
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 |