From 3d88a792fb2f3950989d95d91e7de57fa1b74923 Mon Sep 17 00:00:00 2001 From: ghazan Date: Sun, 7 Nov 2021 16:48:40 +0300 Subject: first version of mir_core that builds under Linux --- src/mir_core/main.cpp | 1 + src/mir_core/mir_core.cbp | 75 +++ src/mir_core/mir_core.depend | 231 +++++++ src/mir_core/mir_core.layout | 10 + src/mir_core/src/Linux/fileutil.cpp | 23 + src/mir_core/src/db.cpp | 1071 ++++++++++++++++----------------- src/mir_core/src/logger.cpp | 424 +++++++------ src/mir_core/src/md5.cpp | 716 +++++++++++----------- src/mir_core/src/memory.cpp | 580 +++++++++--------- src/mir_core/src/miranda.h | 186 +++--- src/mir_core/src/mstring.cpp | 282 +++++---- src/mir_core/src/sha256.cpp | 578 +++++++++--------- src/mir_core/src/stdafx.h | 152 ++--- src/mir_core/src/utf.cpp | 878 +++++++++++++-------------- src/mir_core/src/utils.cpp | 1126 ++++++++++++++++++----------------- 15 files changed, 3339 insertions(+), 2994 deletions(-) create mode 100644 src/mir_core/main.cpp create mode 100644 src/mir_core/mir_core.cbp create mode 100644 src/mir_core/mir_core.depend create mode 100644 src/mir_core/mir_core.layout create mode 100644 src/mir_core/src/Linux/fileutil.cpp (limited to 'src/mir_core') diff --git a/src/mir_core/main.cpp b/src/mir_core/main.cpp new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/mir_core/main.cpp @@ -0,0 +1 @@ + diff --git a/src/mir_core/mir_core.cbp b/src/mir_core/mir_core.cbp new file mode 100644 index 0000000000..b24f650bb3 --- /dev/null +++ b/src/mir_core/mir_core.cbp @@ -0,0 +1,75 @@ + + + + + + diff --git a/src/mir_core/mir_core.depend b/src/mir_core/mir_core.depend new file mode 100644 index 0000000000..bd3a5c7130 --- /dev/null +++ b/src/mir_core/mir_core.depend @@ -0,0 +1,231 @@ +# depslib dependency file v1.0 +1634479263 source:/var/www/miranda-ng/src/mir_core/src/binbuffer.cpp + "stdafx.h" + +1636290589 /var/www/miranda-ng/src/mir_core/src/stdafx.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "miranda.h" + + + +1636282921 /var/www/miranda-ng/include/m_system.h + + + +1636291943 /var/www/miranda-ng/include/m_core.h + + + + + +1636292217 /var/www/miranda-ng/include/m_types.h + + + +1636282895 /var/www/miranda-ng/include/m_string.h + + + + + + + +1636283401 /var/www/miranda-ng/include/m_database.h + "m_system.h" + "m_utils.h" + +1634479262 /var/www/miranda-ng/include/m_utils.h + + + + "m_system.h" + +1636283723 /var/www/miranda-ng/include/m_db_int.h + + +1636284034 /var/www/miranda-ng/include/newpluginapi.h + + + + +1634479262 /var/www/miranda-ng/include/m_protocols.h + "statusmodes.h" + + + + +1634479262 /var/www/miranda-ng/include/statusmodes.h + +1634479262 /var/www/miranda-ng/include/m_genmenu.h + + + +1634479262 /var/www/miranda-ng/include/m_langpack.h + + +1634479262 /var/www/miranda-ng/include/m_metacontacts.h + + +1634479262 /var/www/miranda-ng/include/m_skin.h + + +1634479262 /var/www/miranda-ng/include/m_icolib.h + + +1636284288 /var/www/miranda-ng/include/m_netlib.h + "m_utils.h" + +1636284672 /var/www/miranda-ng/include/m_timezones.h + + +1634479262 /var/www/miranda-ng/include/m_button.h + +1636286799 /var/www/miranda-ng/include/m_gui.h + + + + + +1636284756 /var/www/miranda-ng/include/m_protoint.h + + + + + + +1634479262 /var/www/miranda-ng/include/m_protosvc.h + "m_protocols.h" + +1636284822 /var/www/miranda-ng/include/m_clc.h + +1634479262 /var/www/miranda-ng/include/m_chat_int.h + + + + + + + +1634479262 /var/www/miranda-ng/include/m_chat.h + +1636286911 /var/www/miranda-ng/src/mir_core/src/miranda.h + +1636278170 /var/www/miranda-ng/include/m_xml.h + + "../src/mir_core/src/tinyxml2.h" + +1634479263 /var/www/miranda-ng/src/mir_core/src/tinyxml2.h + + + + + + + + + + + + + + + +1636290281 /var/www/miranda-ng/include/m_string.inl + +1634479263 source:/var/www/miranda-ng/src/mir_core/src/lists.cpp + "stdafx.h" + +1634479263 source:/var/www/miranda-ng/src/mir_core/src/sha1.cpp + "stdafx.h" + +1634479263 source:/var/www/miranda-ng/src/mir_core/src/stdafx.cxx + "stdafx.h" + +1634479263 source:/var/www/miranda-ng/src/mir_core/src/tinyxml2.cpp + "stdafx.h" + + + + + + +1636289969 source:/var/www/miranda-ng/src/mir_core/src/Linux/fileutil.cpp + "../stdafx.h" + +1634479263 source:/var/www/miranda-ng/src/mir_core/src/http.cpp + "stdafx.h" + +1636289767 source:/var/www/miranda-ng/src/mir_core/src/logger.cpp + "stdafx.h" + +1636290658 source:/var/www/miranda-ng/src/mir_core/src/md5.cpp + "stdafx.h" + +1636290256 source:/var/www/miranda-ng/src/mir_core/src/db.cpp + "stdafx.h" + +1636290951 source:/var/www/miranda-ng/src/mir_core/src/mstring.cpp + "stdafx.h" + +1636290966 source:/var/www/miranda-ng/src/mir_core/src/sha256.cpp + "stdafx.h" + +1636290782 source:/var/www/miranda-ng/src/mir_core/src/bitmaps.cpp + "stdafx.h" + + +1634479262 /var/www/miranda-ng/include/m_imgsrvc.h + "../libs/freeimage/src/FreeImage.h" + + +1634479262 /var/www/miranda-ng/libs/freeimage/src/FreeImage.h + + + +1636291741 source:/var/www/miranda-ng/src/mir_core/src/memory.cpp + "stdafx.h" + +1634479263 source:/var/www/miranda-ng/src/mir_core/src/tinyxml2_utils.cpp + "stdafx.h" + +1636291998 source:/var/www/miranda-ng/src/mir_core/src/utf.cpp + "stdafx.h" + +1636292418 source:/var/www/miranda-ng/src/mir_core/src/utils.cpp + "stdafx.h" + diff --git a/src/mir_core/mir_core.layout b/src/mir_core/mir_core.layout new file mode 100644 index 0000000000..5ca32c1036 --- /dev/null +++ b/src/mir_core/mir_core.layout @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/mir_core/src/Linux/fileutil.cpp b/src/mir_core/src/Linux/fileutil.cpp new file mode 100644 index 0000000000..e246219f46 --- /dev/null +++ b/src/mir_core/src/Linux/fileutil.cpp @@ -0,0 +1,23 @@ +/* +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org) + +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 version 2 +of the 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 the GNU General Public License +along with this program. If not, see . +*/ + +#include "../stdafx.h" + +MIR_CORE_DLL(FILE*) _wfopen(const wchar_t *pwszFileName, const wchar_t *pwszMode) +{ + return fopen(T2Utf(pwszFileName), T2Utf(pwszMode)); +} diff --git a/src/mir_core/src/db.cpp b/src/mir_core/src/db.cpp index 9f00db4387..11d28cf84a 100644 --- a/src/mir_core/src/db.cpp +++ b/src/mir_core/src/db.cpp @@ -1,533 +1,538 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -MIR_CORE_EXPORT MDatabaseCommon* g_pCurrDb = nullptr; - -///////////////////////////////////////////////////////////////////////////////////////// -// database functions - -MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode) -{ - if (g_pCurrDb) - g_pCurrDb->SetCacheSafetyMode(bNewMode != 0); -} - -MIR_CORE_DLL(int) db_get_contact_count(void) -{ - return (g_pCurrDb) ? g_pCurrDb->GetContactCount() : 0; -} - -MIR_CORE_DLL(MDatabaseCommon*) db_get_current() -{ - return g_pCurrDb; -} - -MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName) -{ - return (g_pCurrDb) ? g_pCurrDb->DeleteModule(hContact, szModuleName) : 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// contact functions - -MIR_CORE_DLL(MCONTACT) db_add_contact(void) -{ - MCONTACT hNew = (g_pCurrDb) ? g_pCurrDb->AddContact() : 0; - Netlib_Logf(nullptr, "New contact created: %d", hNew); - return hNew; -} - -MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact) -{ - ptrW wszPhoto(db_get_wsa(hContact, "ContactPhoto", "File")); - if (wszPhoto != NULL) - DeleteFile(wszPhoto); - - Netlib_Logf(nullptr, "Contact deleted: %d", hContact); - return (g_pCurrDb) ? g_pCurrDb->DeleteContact(hContact) : 0; -} - -MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact) -{ - return (g_pCurrDb) ? g_pCurrDb->IsDbContact(hContact) : 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// enumerators - -MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC pFunc, void *param) -{ - return (g_pCurrDb) ? g_pCurrDb->EnumModuleNames(pFunc, param) : 0; -} - -MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param) -{ - return (g_pCurrDb) ? g_pCurrDb->EnumResidentSettings(pFunc, param) : 0; -} - -EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pFunc, const char *szModule, void *param) -{ - return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, pFunc, szModule, param) : 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// getting data - -MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue) -{ - if (g_pCurrDb != nullptr) { - DBVARIANT dbv; - if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) - { - switch(dbv.type) { - case DBVT_BYTE: return dbv.bVal; - case DBVT_WORD: return BYTE(dbv.wVal); - case DBVT_DWORD: return BYTE(dbv.dVal); - } - g_pCurrDb->FreeVariant(&dbv); - } - } - return errorValue; -} - -MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue) -{ - if (g_pCurrDb != nullptr) { - DBVARIANT dbv; - if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) { - switch(dbv.type) { - case DBVT_BYTE: return dbv.bVal; - case DBVT_WORD: return dbv.wVal; - case DBVT_DWORD: return WORD(dbv.dVal); - } - g_pCurrDb->FreeVariant(&dbv); - } - } - return errorValue; -} - -MIR_CORE_DLL(DWORD) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue) -{ - if (g_pCurrDb != nullptr) { - DBVARIANT dbv; - if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) { - switch(dbv.type) { - case DBVT_BYTE: return dbv.bVal; - case DBVT_WORD: return dbv.wVal; - case DBVT_DWORD: return dbv.dVal; - } - g_pCurrDb->FreeVariant(&dbv); - } - } - - return errorValue; -} - -MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) -{ - if (g_pCurrDb == nullptr) - return 1; - - return g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, dbv); -} - -MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType) -{ - if (g_pCurrDb == nullptr) - return 1; - - dbv->type = (BYTE)nType; - return g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, dbv); -} - -MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue) -{ - if (g_pCurrDb) { - DBVARIANT dbv = { DBVT_ASCIIZ }; - if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) - return dbv.pszVal; - } - - return (szValue == nullptr) ? nullptr : mir_strdup(szValue); -} - -MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue) -{ - if (g_pCurrDb) { - DBVARIANT dbv = { DBVT_UTF8 }; - if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) - return dbv.pszVal; - } - - return (szValue == nullptr) ? nullptr : mir_strdup(szValue); -} - -MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue) -{ - if (g_pCurrDb) { - DBVARIANT dbv = { DBVT_WCHAR }; - if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) - return dbv.pwszVal; - } - - return (szValue == nullptr) ? nullptr : mir_wstrdup(szValue); -} - -MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const char *szValue) -{ - if (g_pCurrDb == nullptr) - return (szValue == nullptr) ? CMStringA() : CMStringA(szValue); - - DBVARIANT dbv = { DBVT_ASCIIZ }; - if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) - return (szValue == nullptr) ? CMStringA() : CMStringA(szValue); - - return CMStringA(ptrA(dbv.pszVal)); -} - -MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const wchar_t *szValue) -{ - if (g_pCurrDb == nullptr) - return (szValue == nullptr) ? CMStringW() : CMStringW(szValue); - - DBVARIANT dbv = { DBVT_WCHAR }; - if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) - return (szValue == nullptr) ? CMStringW() : CMStringW(szValue); - - return CMStringW(ptrW(dbv.pwszVal)); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// getting static data - -MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest) -{ - if (g_pCurrDb == nullptr) - return 1; - - DBVARIANT dbv; - dbv.type = DBVT_ASCIIZ; - dbv.pszVal = pDest; - dbv.cchVal = cbDest; - return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv); -} - -MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest) -{ - if (g_pCurrDb == nullptr) - return 1; - - DBVARIANT dbv; - dbv.type = DBVT_UTF8; - dbv.pszVal = pDest; - dbv.cchVal = cbDest; - return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv); -} - -MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest) -{ - if (g_pCurrDb == nullptr) - return 1; - - DBVARIANT dbv; - dbv.type = DBVT_WCHAR; - dbv.pwszVal = pDest; - dbv.cchVal = cbDest; - return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// setting data - -MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value = *dbv; - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE val) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_BYTE; - cws.value.bVal = val; - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, WORD val) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_WORD; - cws.value.wVal = val; - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD val) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_DWORD; - cws.value.dVal = val; - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_ASCIIZ; - cws.value.pszVal = (char*)(val == nullptr ? "" : val); - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_WCHAR; - cws.value.pwszVal = (wchar_t*)(val == nullptr ? L"" : val); - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_UTF8; - cws.value.pszVal = (char*)(val == nullptr ? "" : val); - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, void *val, unsigned len) -{ - if (g_pCurrDb == nullptr) return 1; - - DBCONTACTWRITESETTING cws; - cws.szModule = szModule; - cws.szSetting = szSetting; - cws.value.type = DBVT_BLOB; - cws.value.cpbVal = (WORD)len; - cws.value.pbVal = (unsigned char*)val; - return g_pCurrDb->WriteContactSetting(hContact, &cws); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// events - -MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->AddEvent(hContact, dbei); -} - -MIR_CORE_DLL(int) db_event_count(MCONTACT hContact) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventCount(hContact); -} - -MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->DeleteEvent(hDbEvent); -} - -MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EditEvent(hContact, hDbEvent, dbei); -} - -MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstEvent(hContact); -} - -MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstUnreadEvent(hContact); -} - -MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei) -{ - return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->GetEvent(hDbEvent, dbei); -} - -MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetBlobSize(hDbEvent); -} - -MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventContact(hDbEvent); -} - -MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindLastEvent(hContact); -} - -MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->MarkEventRead(hContact, hDbEvent); -} - -MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextEvent(hContact, hDbEvent); -} - -MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindPrevEvent(hContact, hDbEvent); -} - -MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventById(szModule, szId); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// event cursors - -DB::EventCursor::~EventCursor() -{ -} - -MIR_CORE_DLL(DB::EventCursor*) DB::Events(MCONTACT hContact, MEVENT iStartEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursor(hContact, iStartEvent); -} - -MIR_CORE_DLL(DB::EventCursor*) DB::EventsRev(MCONTACT hContact, MEVENT iStartEvent) -{ - return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursorRev(hContact, iStartEvent); -} - -DB::ECPTR::ECPTR(EventCursor *_pCursor) : - m_cursor(_pCursor), - m_prevFetched(-1), - m_currEvent(0) -{ -} - -DB::ECPTR::~ECPTR() -{ - delete m_cursor; -} - -void DB::ECPTR::DeleteEvent() -{ - m_prevFetched = m_cursor->FetchNext(); - db_event_delete(m_currEvent); -} - -MEVENT DB::ECPTR::FetchNext() -{ - if (m_prevFetched != -1) { - m_currEvent = m_prevFetched; - m_prevFetched = -1; - } - else m_currEvent = m_cursor->FetchNext(); - - return m_currEvent; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// misc functions - -MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv) -{ - return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->FreeVariant(dbv); -} - -MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting) -{ - if (g_pCurrDb == nullptr) - return 1; - - return g_pCurrDb->DeleteContactSetting(hContact, szModule, szSetting); -} - -MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT hContact) -{ - return (g_pCurrDb == nullptr) ? nullptr : g_pCurrDb->getCache()->GetCachedContact(hContact); -} - -MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto) -{ - return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindFirstContact(szProto); -} - -MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto) -{ - return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindNextContact(hContact, szProto); -} - -MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db) -{ - g_pCurrDb = _db; - if (g_pCurrDb == nullptr) - return; - - // try to get the langpack's name from a profile - ptrW langpack(db_get_wsa(0, "Langpack", "Current")); - if (langpack && langpack[0] != '\0') - LoadLangPack(langpack); - else - GetDefaultLang(); -} - -MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable) -{ - if (g_pCurrDb == nullptr || szModule == nullptr || szService == nullptr) - return FALSE; - - char str[MAXMODULELABELLENGTH * 2]; - mir_snprintf(str, "%s/%s", szModule, szService); - return g_pCurrDb->SetSettingResident(bEnable, str); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +MIR_CORE_EXPORT MDatabaseCommon* g_pCurrDb = nullptr; + +///////////////////////////////////////////////////////////////////////////////////////// +// database functions + +MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode) +{ + if (g_pCurrDb) + g_pCurrDb->SetCacheSafetyMode(bNewMode != 0); +} + +MIR_CORE_DLL(int) db_get_contact_count(void) +{ + return (g_pCurrDb) ? g_pCurrDb->GetContactCount() : 0; +} + +MIR_CORE_DLL(MDatabaseCommon*) db_get_current() +{ + return g_pCurrDb; +} + +MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName) +{ + return (g_pCurrDb) ? g_pCurrDb->DeleteModule(hContact, szModuleName) : 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// contact functions + +MIR_CORE_DLL(MCONTACT) db_add_contact(void) +{ + MCONTACT hNew = (g_pCurrDb) ? g_pCurrDb->AddContact() : 0; + Netlib_Logf(nullptr, "New contact created: %d", hNew); + return hNew; +} + +MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact) +{ + ptrW wszPhoto(db_get_wsa(hContact, "ContactPhoto", "File")); + if (wszPhoto != NULL) { + #ifdef _MSC_VER + DeleteFileW(wszPhoto); + #else + remove(T2Utf(wszPhoto)); + #endif + } + + Netlib_Logf(nullptr, "Contact deleted: %d", hContact); + return (g_pCurrDb) ? g_pCurrDb->DeleteContact(hContact) : 0; +} + +MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact) +{ + return (g_pCurrDb) ? g_pCurrDb->IsDbContact(hContact) : 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// enumerators + +MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC pFunc, void *param) +{ + return (g_pCurrDb) ? g_pCurrDb->EnumModuleNames(pFunc, param) : 0; +} + +MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param) +{ + return (g_pCurrDb) ? g_pCurrDb->EnumResidentSettings(pFunc, param) : 0; +} + +EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pFunc, const char *szModule, void *param) +{ + return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, pFunc, szModule, param) : 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// getting data + +MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue) +{ + if (g_pCurrDb != nullptr) { + DBVARIANT dbv; + if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) + { + switch(dbv.type) { + case DBVT_BYTE: return dbv.bVal; + case DBVT_WORD: return BYTE(dbv.wVal); + case DBVT_DWORD: return BYTE(dbv.dVal); + } + g_pCurrDb->FreeVariant(&dbv); + } + } + return errorValue; +} + +MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue) +{ + if (g_pCurrDb != nullptr) { + DBVARIANT dbv; + if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) { + switch(dbv.type) { + case DBVT_BYTE: return dbv.bVal; + case DBVT_WORD: return dbv.wVal; + case DBVT_DWORD: return WORD(dbv.dVal); + } + g_pCurrDb->FreeVariant(&dbv); + } + } + return errorValue; +} + +MIR_CORE_DLL(DWORD) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue) +{ + if (g_pCurrDb != nullptr) { + DBVARIANT dbv; + if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) { + switch(dbv.type) { + case DBVT_BYTE: return dbv.bVal; + case DBVT_WORD: return dbv.wVal; + case DBVT_DWORD: return dbv.dVal; + } + g_pCurrDb->FreeVariant(&dbv); + } + } + + return errorValue; +} + +MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) +{ + if (g_pCurrDb == nullptr) + return 1; + + return g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, dbv); +} + +MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType) +{ + if (g_pCurrDb == nullptr) + return 1; + + dbv->type = (BYTE)nType; + return g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, dbv); +} + +MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue) +{ + if (g_pCurrDb) { + DBVARIANT dbv = { DBVT_ASCIIZ }; + if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) + return dbv.pszVal; + } + + return (szValue == nullptr) ? nullptr : mir_strdup(szValue); +} + +MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue) +{ + if (g_pCurrDb) { + DBVARIANT dbv = { DBVT_UTF8 }; + if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) + return dbv.pszVal; + } + + return (szValue == nullptr) ? nullptr : mir_strdup(szValue); +} + +MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue) +{ + if (g_pCurrDb) { + DBVARIANT dbv = { DBVT_WCHAR }; + if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) + return dbv.pwszVal; + } + + return (szValue == nullptr) ? nullptr : mir_wstrdup(szValue); +} + +MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const char *szValue) +{ + if (g_pCurrDb == nullptr) + return (szValue == nullptr) ? CMStringA() : CMStringA(szValue); + + DBVARIANT dbv = { DBVT_ASCIIZ }; + if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) + return (szValue == nullptr) ? CMStringA() : CMStringA(szValue); + + return CMStringA(ptrA(dbv.pszVal).get()); +} + +MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const wchar_t *szValue) +{ + if (g_pCurrDb == nullptr) + return (szValue == nullptr) ? CMStringW() : CMStringW(szValue); + + DBVARIANT dbv = { DBVT_WCHAR }; + if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv)) + return (szValue == nullptr) ? CMStringW() : CMStringW(szValue); + + return CMStringW(ptrW(dbv.pwszVal).get()); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// getting static data + +MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest) +{ + if (g_pCurrDb == nullptr) + return 1; + + DBVARIANT dbv; + dbv.type = DBVT_ASCIIZ; + dbv.pszVal = pDest; + dbv.cchVal = cbDest; + return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv); +} + +MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest) +{ + if (g_pCurrDb == nullptr) + return 1; + + DBVARIANT dbv; + dbv.type = DBVT_UTF8; + dbv.pszVal = pDest; + dbv.cchVal = cbDest; + return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv); +} + +MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest) +{ + if (g_pCurrDb == nullptr) + return 1; + + DBVARIANT dbv; + dbv.type = DBVT_WCHAR; + dbv.pwszVal = pDest; + dbv.cchVal = cbDest; + return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// setting data + +MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value = *dbv; + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE val) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_BYTE; + cws.value.bVal = val; + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, WORD val) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_WORD; + cws.value.wVal = val; + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD val) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_DWORD; + cws.value.dVal = val; + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_ASCIIZ; + cws.value.pszVal = (char*)(val == nullptr ? "" : val); + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_WCHAR; + cws.value.pwszVal = (wchar_t*)(val == nullptr ? L"" : val); + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_UTF8; + cws.value.pszVal = (char*)(val == nullptr ? "" : val); + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, void *val, unsigned len) +{ + if (g_pCurrDb == nullptr) return 1; + + DBCONTACTWRITESETTING cws; + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_BLOB; + cws.value.cpbVal = (WORD)len; + cws.value.pbVal = (unsigned char*)val; + return g_pCurrDb->WriteContactSetting(hContact, &cws); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// events + +MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->AddEvent(hContact, dbei); +} + +MIR_CORE_DLL(int) db_event_count(MCONTACT hContact) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventCount(hContact); +} + +MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->DeleteEvent(hDbEvent); +} + +MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EditEvent(hContact, hDbEvent, dbei); +} + +MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstEvent(hContact); +} + +MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstUnreadEvent(hContact); +} + +MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei) +{ + return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->GetEvent(hDbEvent, dbei); +} + +MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetBlobSize(hDbEvent); +} + +MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventContact(hDbEvent); +} + +MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindLastEvent(hContact); +} + +MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->MarkEventRead(hContact, hDbEvent); +} + +MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextEvent(hContact, hDbEvent); +} + +MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindPrevEvent(hContact, hDbEvent); +} + +MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventById(szModule, szId); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// event cursors + +DB::EventCursor::~EventCursor() +{ +} + +MIR_CORE_DLL(DB::EventCursor*) DB::Events(MCONTACT hContact, MEVENT iStartEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursor(hContact, iStartEvent); +} + +MIR_CORE_DLL(DB::EventCursor*) DB::EventsRev(MCONTACT hContact, MEVENT iStartEvent) +{ + return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursorRev(hContact, iStartEvent); +} + +DB::ECPTR::ECPTR(EventCursor *_pCursor) : + m_cursor(_pCursor), + m_prevFetched(-1), + m_currEvent(0) +{ +} + +DB::ECPTR::~ECPTR() +{ + delete m_cursor; +} + +void DB::ECPTR::DeleteEvent() +{ + m_prevFetched = m_cursor->FetchNext(); + db_event_delete(m_currEvent); +} + +MEVENT DB::ECPTR::FetchNext() +{ + if (m_prevFetched != -1) { + m_currEvent = m_prevFetched; + m_prevFetched = -1; + } + else m_currEvent = m_cursor->FetchNext(); + + return m_currEvent; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// misc functions + +MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv) +{ + return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->FreeVariant(dbv); +} + +MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting) +{ + if (g_pCurrDb == nullptr) + return 1; + + return g_pCurrDb->DeleteContactSetting(hContact, szModule, szSetting); +} + +MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT hContact) +{ + return (g_pCurrDb == nullptr) ? nullptr : g_pCurrDb->getCache()->GetCachedContact(hContact); +} + +MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto) +{ + return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindFirstContact(szProto); +} + +MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto) +{ + return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindNextContact(hContact, szProto); +} + +MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db) +{ + g_pCurrDb = _db; + if (g_pCurrDb == nullptr) + return; + + // try to get the langpack's name from a profile + ptrW langpack(db_get_wsa(0, "Langpack", "Current")); + if (langpack && langpack[0] != '\0') + LoadLangPack(langpack); + else + GetDefaultLang(); +} + +MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable) +{ + if (g_pCurrDb == nullptr || szModule == nullptr || szService == nullptr) + return FALSE; + + char str[MAXMODULELABELLENGTH * 2]; + mir_snprintf(str, "%s/%s", szModule, szService); + return g_pCurrDb->SetSettingResident(bEnable, str); +} diff --git a/src/mir_core/src/logger.cpp b/src/mir_core/src/logger.cpp index c6a1681139..30244e45e4 100644 --- a/src/mir_core/src/logger.cpp +++ b/src/mir_core/src/logger.cpp @@ -1,222 +1,202 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#define SECRET_SIGNATURE 0x87654321 - -struct Logger -{ - Logger(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFilename, unsigned options) : - m_name(mir_strdup(pszName)), - m_descr(mir_wstrdup(ptszDescr)), - m_fileName(mir_wstrdup(ptszFilename)), - m_options(options), - m_signature(SECRET_SIGNATURE), - m_out(nullptr), - m_lastwrite(0) - { - } - - ~Logger() - { - if (m_out) - fclose(m_out); - } - - int m_signature; - ptrA m_name; - ptrW m_fileName, m_descr; - FILE *m_out; - __int64 m_lastwrite; - unsigned m_options; - mir_cs m_cs; -}; - -static int CompareLoggers(const Logger *p1, const Logger *p2) -{ return strcmp(p1->m_name, p2->m_name); -} - -static OBJLIST arLoggers(1, CompareLoggers); - -static __int64 llIdlePeriod; - -void InitLogs() -{ - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - llIdlePeriod = li.QuadPart; -} - -void UninitLogs() -{ - arLoggers.destroy(); -} - -void CheckLogs() -{ - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - - for (auto &p : arLoggers) { - mir_cslock lck(p->m_cs); - if (p->m_out && li.QuadPart - p->m_lastwrite > llIdlePeriod) { - fclose(p->m_out); - p->m_out = nullptr; - } - else fflush(p->m_out); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(HANDLE) mir_createLog(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options) -{ - if (ptszFile == nullptr) - return nullptr; - - Logger *result = new Logger(pszName, ptszDescr, ptszFile, options); - if (result == nullptr) - return nullptr; - - int idx = arLoggers.getIndex(result); - if (idx != -1) { - delete result; - return &arLoggers[idx]; - } - - FILE *fp = _wfopen(ptszFile, L"ab"); - if (fp == nullptr) - CreatePathToFileW(ptszFile); - else - fclose(fp); - - DeleteFile(ptszFile); - arLoggers.insert(result); - return result; -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -static Logger* prepareLogger(HANDLE hLogger) -{ - if (hLogger == nullptr) - return nullptr; - - Logger *p = (Logger*)hLogger; - return (p->m_signature == SECRET_SIGNATURE) ? p : nullptr; -} - -MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger) -{ - Logger *p = prepareLogger(hLogger); - if (p != nullptr) - arLoggers.remove(p); -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...) -{ - Logger *p = prepareLogger(hLogger); - if (p == nullptr) - return 1; - - mir_cslock lck(p->m_cs); - if (p->m_out == nullptr) - if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) - return 2; - - va_list args; - va_start(args, format); - vfprintf(p->m_out, format, args); - va_end(args); - - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - p->m_lastwrite = li.QuadPart; - return 0; -} - -MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...) -{ - Logger *p = prepareLogger(hLogger); - if (p == nullptr) - return 1; - - mir_cslock lck(p->m_cs); - if (p->m_out == nullptr) - if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) - return 2; - - va_list args; - va_start(args, format); - vfwprintf(p->m_out, format, args); - va_end(args); - - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - p->m_lastwrite = li.QuadPart; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args) -{ - Logger *p = prepareLogger(hLogger); - if (p == nullptr) - return 1; - - mir_cslock lck(p->m_cs); - if (p->m_out == nullptr) - if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) - return 2; - - vfprintf(p->m_out, format, args); - - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - p->m_lastwrite = li.QuadPart; - return 0; -} - -MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args) -{ - Logger *p = prepareLogger(hLogger); - if (p == nullptr) - return 1; - - mir_cslock lck(p->m_cs); - if (p->m_out == nullptr) - if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) - return 2; - - vfwprintf(p->m_out, format, args); - - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - p->m_lastwrite = li.QuadPart; - return 0; -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#define SECRET_SIGNATURE 0x87654321 + +struct Logger +{ + Logger(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFilename, unsigned options) : + m_name(mir_strdup(pszName)), + m_descr(mir_wstrdup(ptszDescr)), + m_fileName(mir_wstrdup(ptszFilename)), + m_options(options), + m_signature(SECRET_SIGNATURE), + m_out(nullptr), + m_lastwrite(0) + { + } + + ~Logger() + { + if (m_out) + fclose(m_out); + } + + int m_signature; + ptrA m_name; + ptrW m_fileName, m_descr; + FILE *m_out; + __int64_t m_lastwrite; + unsigned m_options; + mir_cs m_cs; +}; + +static int CompareLoggers(const Logger *p1, const Logger *p2) +{ return strcmp(p1->m_name, p2->m_name); +} + +static OBJLIST arLoggers(1, CompareLoggers); + +void InitLogs() +{ +} + +void UninitLogs() +{ + arLoggers.destroy(); +} + +void CheckLogs() +{ + time_t tm = time(0); + + for (auto &p : arLoggers) { + mir_cslock lck(p->m_cs); + if (p->m_out && tm - p->m_lastwrite > 5) { + fclose(p->m_out); + p->m_out = nullptr; + } + else fflush(p->m_out); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(HANDLE) mir_createLog(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options) +{ + if (ptszFile == nullptr) + return nullptr; + + Logger *result = new Logger(pszName, ptszDescr, ptszFile, options); + if (result == nullptr) + return nullptr; + + int idx = arLoggers.getIndex(result); + if (idx != -1) { + delete result; + return &arLoggers[idx]; + } + + CreatePathToFileW(ptszFile); + arLoggers.insert(result); + return result; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +static Logger* prepareLogger(HANDLE hLogger) +{ + if (hLogger == nullptr) + return nullptr; + + Logger *p = (Logger*)hLogger; + return (p->m_signature == SECRET_SIGNATURE) ? p : nullptr; +} + +MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger) +{ + Logger *p = prepareLogger(hLogger); + if (p != nullptr) + arLoggers.remove(p); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...) +{ + Logger *p = prepareLogger(hLogger); + if (p == nullptr) + return 1; + + mir_cslock lck(p->m_cs); + if (p->m_out == nullptr) + if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) + return 2; + + va_list args; + va_start(args, format); + vfprintf(p->m_out, format, args); + va_end(args); + + p->m_lastwrite = time(0); + return 0; +} + +MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...) +{ + Logger *p = prepareLogger(hLogger); + if (p == nullptr) + return 1; + + mir_cslock lck(p->m_cs); + if (p->m_out == nullptr) + if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) + return 2; + + va_list args; + va_start(args, format); + vfwprintf(p->m_out, format, args); + va_end(args); + + p->m_lastwrite = time(0); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args) +{ + Logger *p = prepareLogger(hLogger); + if (p == nullptr) + return 1; + + mir_cslock lck(p->m_cs); + if (p->m_out == nullptr) + if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) + return 2; + + vfprintf(p->m_out, format, args); + + p->m_lastwrite = time(0); + return 0; +} + +MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args) +{ + Logger *p = prepareLogger(hLogger); + if (p == nullptr) + return 1; + + mir_cslock lck(p->m_cs); + if (p->m_out == nullptr) + if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr) + return 2; + + vfwprintf(p->m_out, format, args); + + p->m_lastwrite = time(0); + return 0; +} diff --git a/src/mir_core/src/md5.cpp b/src/mir_core/src/md5.cpp index 6cb8419249..8b7b37020f 100644 --- a/src/mir_core/src/md5.cpp +++ b/src/mir_core/src/md5.cpp @@ -1,358 +1,358 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.c 2874 2006-05-16 21:38:00Z ghazan $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -// (C) 2005 Joe @ Whale - changed to compile with Miranda - -#include "stdafx.h" - -#define T_MASK ((UINT32)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - -//gfd* -static void md5_process(mir_md5_state_t *pms, const BYTE *data /*[64]*/) -{ - UINT32 - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - UINT32 t; - /* Define storage for little-endian or both types of CPUs. */ - UINT32 xbuf[16]; - const UINT32 *X; - - { - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const BYTE *)&w)) /* dynamic little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if ( !((data - (const BYTE *)nullptr) & 3)) { - /* data are properly aligned */ - X = (const UINT32 *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } - else /* dynamic big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const BYTE *xp = data; - int i; - - X = xbuf; /* (dynamic only) */ - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b, c, d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET1(a, b, c, d, k, s, Ti)\ - t = a + F(b, c, d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET1(a, b, c, d, 0, 7, T1); - SET1(d, a, b, c, 1, 12, T2); - SET1(c, d, a, b, 2, 17, T3); - SET1(b, c, d, a, 3, 22, T4); - SET1(a, b, c, d, 4, 7, T5); - SET1(d, a, b, c, 5, 12, T6); - SET1(c, d, a, b, 6, 17, T7); - SET1(b, c, d, a, 7, 22, T8); - SET1(a, b, c, d, 8, 7, T9); - SET1(d, a, b, c, 9, 12, T10); - SET1(c, d, a, b, 10, 17, T11); - SET1(b, c, d, a, 11, 22, T12); - SET1(a, b, c, d, 12, 7, T13); - SET1(d, a, b, c, 13, 12, T14); - SET1(c, d, a, b, 14, 17, T15); - SET1(b, c, d, a, 15, 22, T16); - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b, c, d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET2(a, b, c, d, k, s, Ti)\ - t = a + G(b, c, d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET2(a, b, c, d, 1, 5, T17); - SET2(d, a, b, c, 6, 9, T18); - SET2(c, d, a, b, 11, 14, T19); - SET2(b, c, d, a, 0, 20, T20); - SET2(a, b, c, d, 5, 5, T21); - SET2(d, a, b, c, 10, 9, T22); - SET2(c, d, a, b, 15, 14, T23); - SET2(b, c, d, a, 4, 20, T24); - SET2(a, b, c, d, 9, 5, T25); - SET2(d, a, b, c, 14, 9, T26); - SET2(c, d, a, b, 3, 14, T27); - SET2(b, c, d, a, 8, 20, T28); - SET2(a, b, c, d, 13, 5, T29); - SET2(d, a, b, c, 2, 9, T30); - SET2(c, d, a, b, 7, 14, T31); - SET2(b, c, d, a, 12, 20, T32); - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b, c, d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET3(a, b, c, d, k, s, Ti)\ - t = a + H(b, c, d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET3(a, b, c, d, 5, 4, T33); - SET3(d, a, b, c, 8, 11, T34); - SET3(c, d, a, b, 11, 16, T35); - SET3(b, c, d, a, 14, 23, T36); - SET3(a, b, c, d, 1, 4, T37); - SET3(d, a, b, c, 4, 11, T38); - SET3(c, d, a, b, 7, 16, T39); - SET3(b, c, d, a, 10, 23, T40); - SET3(a, b, c, d, 13, 4, T41); - SET3(d, a, b, c, 0, 11, T42); - SET3(c, d, a, b, 3, 16, T43); - SET3(b, c, d, a, 6, 23, T44); - SET3(a, b, c, d, 9, 4, T45); - SET3(d, a, b, c, 12, 11, T46); - SET3(c, d, a, b, 15, 16, T47); - SET3(b, c, d, a, 2, 23, T48); - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b, c, d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET4(a, b, c, d, k, s, Ti)\ - t = a + I(b, c, d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET4(a, b, c, d, 0, 6, T49); - SET4(d, a, b, c, 7, 10, T50); - SET4(c, d, a, b, 14, 15, T51); - SET4(b, c, d, a, 5, 21, T52); - SET4(a, b, c, d, 12, 6, T53); - SET4(d, a, b, c, 3, 10, T54); - SET4(c, d, a, b, 10, 15, T55); - SET4(b, c, d, a, 1, 21, T56); - SET4(a, b, c, d, 8, 6, T57); - SET4(d, a, b, c, 15, 10, T58); - SET4(c, d, a, b, 6, 15, T59); - SET4(b, c, d, a, 13, 21, T60); - SET4(a, b, c, d, 4, 6, T61); - SET4(d, a, b, c, 11, 10, T62); - SET4(c, d, a, b, 2, 15, T63); - SET4(b, c, d, a, 9, 21, T64); - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -MIR_CORE_DLL(void) mir_md5_init(mir_md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -MIR_CORE_DLL(void) mir_md5_append(mir_md5_state_t *pms, const BYTE *data, size_t nBytes) -{ - const BYTE *p = data; - size_t left = nBytes; - size_t offset = (pms->count[0] >> 3) & 63; - UINT32 nbits = (UINT32)(nBytes << 3); - - if (nBytes == 0) - return; - - /* Update the message length. */ - pms->count[1] += (UINT32)nBytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - size_t copy = (offset + nBytes > 64 ? 64 - offset : nBytes); - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -MIR_CORE_DLL(void) mir_md5_finish(mir_md5_state_t *pms, BYTE digest[16]) -{ - static const BYTE pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - BYTE data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (BYTE)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - mir_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - mir_md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (BYTE)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} - -MIR_CORE_DLL(void) mir_md5_hash(const BYTE *data, size_t len, BYTE digest[16]) -{ - mir_md5_state_t state; - mir_md5_init(&state); - mir_md5_append(&state, data, len); - mir_md5_finish(&state, digest); -} +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.c 2874 2006-05-16 21:38:00Z ghazan $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +// (C) 2005 Joe @ Whale - changed to compile with Miranda + +#include "stdafx.h" + +#define T_MASK ((uint32_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + +//gfd* +static void md5_process(mir_md5_state_t *pms, const BYTE *data /*[64]*/) +{ + uint32_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + uint32_t t; + /* Define storage for little-endian or both types of CPUs. */ + uint32_t xbuf[16]; + const uint32_t *X; + + { + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const BYTE *)&w)) /* dynamic little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if ( !((data - (const BYTE *)nullptr) & 3)) { + /* data are properly aligned */ + X = (const uint32_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } + else /* dynamic big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const BYTE *xp = data; + int i; + + X = xbuf; /* (dynamic only) */ + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b, c, d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET1(a, b, c, d, k, s, Ti)\ + t = a + F(b, c, d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET1(a, b, c, d, 0, 7, T1); + SET1(d, a, b, c, 1, 12, T2); + SET1(c, d, a, b, 2, 17, T3); + SET1(b, c, d, a, 3, 22, T4); + SET1(a, b, c, d, 4, 7, T5); + SET1(d, a, b, c, 5, 12, T6); + SET1(c, d, a, b, 6, 17, T7); + SET1(b, c, d, a, 7, 22, T8); + SET1(a, b, c, d, 8, 7, T9); + SET1(d, a, b, c, 9, 12, T10); + SET1(c, d, a, b, 10, 17, T11); + SET1(b, c, d, a, 11, 22, T12); + SET1(a, b, c, d, 12, 7, T13); + SET1(d, a, b, c, 13, 12, T14); + SET1(c, d, a, b, 14, 17, T15); + SET1(b, c, d, a, 15, 22, T16); + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b, c, d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET2(a, b, c, d, k, s, Ti)\ + t = a + G(b, c, d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET2(a, b, c, d, 1, 5, T17); + SET2(d, a, b, c, 6, 9, T18); + SET2(c, d, a, b, 11, 14, T19); + SET2(b, c, d, a, 0, 20, T20); + SET2(a, b, c, d, 5, 5, T21); + SET2(d, a, b, c, 10, 9, T22); + SET2(c, d, a, b, 15, 14, T23); + SET2(b, c, d, a, 4, 20, T24); + SET2(a, b, c, d, 9, 5, T25); + SET2(d, a, b, c, 14, 9, T26); + SET2(c, d, a, b, 3, 14, T27); + SET2(b, c, d, a, 8, 20, T28); + SET2(a, b, c, d, 13, 5, T29); + SET2(d, a, b, c, 2, 9, T30); + SET2(c, d, a, b, 7, 14, T31); + SET2(b, c, d, a, 12, 20, T32); + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b, c, d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET3(a, b, c, d, k, s, Ti)\ + t = a + H(b, c, d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET3(a, b, c, d, 5, 4, T33); + SET3(d, a, b, c, 8, 11, T34); + SET3(c, d, a, b, 11, 16, T35); + SET3(b, c, d, a, 14, 23, T36); + SET3(a, b, c, d, 1, 4, T37); + SET3(d, a, b, c, 4, 11, T38); + SET3(c, d, a, b, 7, 16, T39); + SET3(b, c, d, a, 10, 23, T40); + SET3(a, b, c, d, 13, 4, T41); + SET3(d, a, b, c, 0, 11, T42); + SET3(c, d, a, b, 3, 16, T43); + SET3(b, c, d, a, 6, 23, T44); + SET3(a, b, c, d, 9, 4, T45); + SET3(d, a, b, c, 12, 11, T46); + SET3(c, d, a, b, 15, 16, T47); + SET3(b, c, d, a, 2, 23, T48); + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b, c, d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET4(a, b, c, d, k, s, Ti)\ + t = a + I(b, c, d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET4(a, b, c, d, 0, 6, T49); + SET4(d, a, b, c, 7, 10, T50); + SET4(c, d, a, b, 14, 15, T51); + SET4(b, c, d, a, 5, 21, T52); + SET4(a, b, c, d, 12, 6, T53); + SET4(d, a, b, c, 3, 10, T54); + SET4(c, d, a, b, 10, 15, T55); + SET4(b, c, d, a, 1, 21, T56); + SET4(a, b, c, d, 8, 6, T57); + SET4(d, a, b, c, 15, 10, T58); + SET4(c, d, a, b, 6, 15, T59); + SET4(b, c, d, a, 13, 21, T60); + SET4(a, b, c, d, 4, 6, T61); + SET4(d, a, b, c, 11, 10, T62); + SET4(c, d, a, b, 2, 15, T63); + SET4(b, c, d, a, 9, 21, T64); + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +MIR_CORE_DLL(void) mir_md5_init(mir_md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +MIR_CORE_DLL(void) mir_md5_append(mir_md5_state_t *pms, const BYTE *data, size_t nBytes) +{ + const BYTE *p = data; + size_t left = nBytes; + size_t offset = (pms->count[0] >> 3) & 63; + uint32_t nbits = (uint32_t)(nBytes << 3); + + if (nBytes == 0) + return; + + /* Update the message length. */ + pms->count[1] += (uint32_t)nBytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + size_t copy = (offset + nBytes > 64 ? 64 - offset : nBytes); + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +MIR_CORE_DLL(void) mir_md5_finish(mir_md5_state_t *pms, BYTE digest[16]) +{ + static const BYTE pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + BYTE data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (BYTE)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + mir_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + mir_md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (BYTE)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} + +MIR_CORE_DLL(void) mir_md5_hash(const BYTE *data, size_t len, BYTE digest[16]) +{ + mir_md5_state_t state; + mir_md5_init(&state); + mir_md5_append(&state, data, len); + mir_md5_finish(&state, digest); +} diff --git a/src/mir_core/src/memory.cpp b/src/mir_core/src/memory.cpp index 849e42564a..3e3d7be69d 100644 --- a/src/mir_core/src/memory.cpp +++ b/src/mir_core/src/memory.cpp @@ -1,285 +1,295 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#define BLOCK_ALLOCED 0xABBABABA -#define BLOCK_FREED 0xDEADBEEF - -static int CheckBlock(void* blk) -{ - int result = FALSE; - char* p = (char*)blk - sizeof(DWORD)*2; - DWORD size, *b, *e; - - __try - { - size = *(DWORD*)p; - b = (DWORD*)&p[ sizeof(DWORD) ]; - e = (DWORD*)&p[ sizeof(DWORD)*2 + size ]; - - if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED) - { - if (*b == BLOCK_FREED && *e == BLOCK_FREED) - OutputDebugStringA("memory block is already deleted\n"); - else - OutputDebugStringA("memory block is corrupted\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - } - else result = TRUE; - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - OutputDebugStringA("access violation during checking memory block\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - } - - return result; -} - -/******************************************************************************/ - -MIR_C_CORE_DLL(void*) mir_alloc(size_t size) -{ - if (size == 0) - return nullptr; - - char *p = (char*)malloc(size + sizeof(DWORD)* 3); - if (p == nullptr) { - OutputDebugStringA("memory overflow\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - return nullptr; - } - - *(DWORD*)p = (DWORD)size; - *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED; - *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED; - return p + sizeof(DWORD)* 2; -} - -/******************************************************************************/ - -MIR_C_CORE_DLL(void*) mir_calloc(size_t size) -{ - void* p = mir_alloc(size); - if (p != nullptr) - memset(p, 0, size); - return p; -} - -/******************************************************************************/ - -MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t size) -{ - char *p; - - if (ptr != nullptr) { - if (!CheckBlock(ptr)) - return nullptr; - p = (char*)ptr - sizeof(DWORD)*2; - } - else p = nullptr; - - p = (char*)realloc(p, size + sizeof(DWORD)*3); - if (p == nullptr) { - OutputDebugStringA("memory overflow\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - return nullptr; - } - - *(DWORD*)p = (DWORD)size; - *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED; - *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED; - return p + sizeof(DWORD)*2; -} - -/******************************************************************************/ - -MIR_C_CORE_DLL(void) mir_free(void* ptr) -{ - char* p; - DWORD size; - - if (ptr == nullptr) - return; - if (!CheckBlock(ptr)) - return; - - p = (char*)ptr - sizeof(DWORD)*2; - size = *(DWORD*)p; - - *(DWORD*)&p[sizeof(DWORD)] = BLOCK_FREED; - *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_FREED; - free(p); -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_strdup(const char *str) -{ - if (str == nullptr) - return nullptr; - - char *p = (char*)mir_alloc(strlen(str)+1); - if (p) - strcpy(p, str); - return p; -} - -MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t *str) -{ - if (str == nullptr) - return nullptr; - - wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(wcslen(str)+1)); - if (p) - wcscpy(p, str); - return p; -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_strndup(const char *str, size_t len) -{ - if (str == nullptr || len == 0) - return nullptr; - - char *p = (char*)mir_alloc(len+1); - if (p) { - memcpy(p, str, len); - p[len] = 0; - } - return p; -} - -MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len) -{ - if (str == nullptr || len == 0) - return nullptr; - - wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(len+1)); - if (p) { - memcpy(p, str, sizeof(wchar_t)*len); - p[len] = 0; - } - return p; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...) -{ - va_list va; - va_start(va, fmt); - int len = _vsnprintf(buffer, count-1, fmt, va); - va_end(va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_snwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, ...) -{ - va_list va; - va_start(va, fmt); - int len = _vsnwprintf(buffer, count-1, fmt, va); - va_end(va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va) -{ - int len = _vsnprintf(buffer, count-1, fmt, va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_vsnwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, va_list va) -{ - int len = _vsnwprintf(buffer, count-1, fmt, va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage) -{ - if (src == nullptr) - return nullptr; - - int cbLen = MultiByteToWideChar(codepage, 0, src, -1, nullptr, 0); - wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1)); - if (result == nullptr) - return nullptr; - - MultiByteToWideChar(codepage, 0, src, -1, result, cbLen); - result[cbLen] = 0; - return result; -} - -/******************************************************************************/ - -MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src) -{ - return mir_a2u_cp(src, Langpack_GetDefaultCodePage()); -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage) -{ - if (src == nullptr) - return nullptr; - - int cbLen = WideCharToMultiByte(codepage, 0, src, -1, nullptr, 0, nullptr, nullptr); - char* result = (char*)mir_alloc(cbLen+1); - if (result == nullptr) - return nullptr; - - WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, nullptr, nullptr); - result[cbLen] = 0; - return result; -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src) -{ - return mir_u2a_cp(src, Langpack_GetDefaultCodePage()); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#define BLOCK_ALLOCED 0xABBABABA +#define BLOCK_FREED 0xDEADBEEF + +static int CheckBlock(void* blk) +{ + int result = FALSE; + char* p = (char*)blk - sizeof(DWORD)*2; + DWORD size, *b, *e; + + __try + { + size = *(DWORD*)p; + b = (DWORD*)&p[ sizeof(DWORD) ]; + e = (DWORD*)&p[ sizeof(DWORD)*2 + size ]; + + if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED) + { + #ifdef _MSC_VER + if (*b == BLOCK_FREED && *e == BLOCK_FREED) + OutputDebugStringA("memory block is already deleted\n"); + else + OutputDebugStringA("memory block is corrupted\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + #endif + } + else result = TRUE; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + #ifdef _MSC_VER + OutputDebugStringA("access violation during checking memory block\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + #endif + } + + return result; +} + +/******************************************************************************/ + +MIR_C_CORE_DLL(void*) mir_alloc(size_t size) +{ + if (size == 0) + return nullptr; + + char *p = (char*)malloc(size + sizeof(DWORD)* 3); + if (p == nullptr) { + #ifdef _MSC_VER + OutputDebugStringA("memory overflow\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + #endif + return nullptr; + } + + *(DWORD*)p = (DWORD)size; + *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED; + *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED; + return p + sizeof(DWORD)* 2; +} + +/******************************************************************************/ + +MIR_C_CORE_DLL(void*) mir_calloc(size_t size) +{ + void* p = mir_alloc(size); + if (p != nullptr) + memset(p, 0, size); + return p; +} + +/******************************************************************************/ + +MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t size) +{ + char *p; + + if (ptr != nullptr) { + if (!CheckBlock(ptr)) + return nullptr; + p = (char*)ptr - sizeof(DWORD)*2; + } + else p = nullptr; + + p = (char*)realloc(p, size + sizeof(DWORD)*3); + if (p == nullptr) { + #ifdef _MSC_VER + OutputDebugStringA("memory overflow\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + #endif + return nullptr; + } + + *(DWORD*)p = (DWORD)size; + *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED; + *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED; + return p + sizeof(DWORD)*2; +} + +/******************************************************************************/ + +MIR_C_CORE_DLL(void) mir_free(void* ptr) +{ + char* p; + DWORD size; + + if (ptr == nullptr) + return; + if (!CheckBlock(ptr)) + return; + + p = (char*)ptr - sizeof(DWORD)*2; + size = *(DWORD*)p; + + *(DWORD*)&p[sizeof(DWORD)] = BLOCK_FREED; + *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_FREED; + free(p); +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_strdup(const char *str) +{ + if (str == nullptr) + return nullptr; + + char *p = (char*)mir_alloc(strlen(str)+1); + if (p) + strcpy(p, str); + return p; +} + +MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t *str) +{ + if (str == nullptr) + return nullptr; + + wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(wcslen(str)+1)); + if (p) + wcscpy(p, str); + return p; +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_strndup(const char *str, size_t len) +{ + if (str == nullptr || len == 0) + return nullptr; + + char *p = (char*)mir_alloc(len+1); + if (p) { + memcpy(p, str, len); + p[len] = 0; + } + return p; +} + +MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len) +{ + if (str == nullptr || len == 0) + return nullptr; + + wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(len+1)); + if (p) { + memcpy(p, str, sizeof(wchar_t)*len); + p[len] = 0; + } + return p; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...) +{ + va_list va; + va_start(va, fmt); + int len = _vsnprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_snwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, ...) +{ + va_list va; + va_start(va, fmt); + int len = _vsnwprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va) +{ + int len = _vsnprintf(buffer, count-1, fmt, va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_vsnwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, va_list va) +{ + int len = _vsnwprintf(buffer, count-1, fmt, va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +#ifdef _MSC_VER +MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage) +{ + if (src == nullptr) + return nullptr; + + int cbLen = MultiByteToWideChar(codepage, 0, src, -1, nullptr, 0); + wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1)); + if (result == nullptr) + return nullptr; + + MultiByteToWideChar(codepage, 0, src, -1, result, cbLen); + result[cbLen] = 0; + return result; +} + +/******************************************************************************/ + +MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src) +{ + return mir_a2u_cp(src, Langpack_GetDefaultCodePage()); +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage) +{ + if (src == nullptr) + return nullptr; + + int cbLen = WideCharToMultiByte(codepage, 0, src, -1, nullptr, 0, nullptr, nullptr); + char* result = (char*)mir_alloc(cbLen+1); + if (result == nullptr) + return nullptr; + + WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, nullptr, nullptr); + result[cbLen] = 0; + return result; +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src) +{ + return mir_u2a_cp(src, Langpack_GetDefaultCodePage()); +} +#endif diff --git a/src/mir_core/src/miranda.h b/src/mir_core/src/miranda.h index 4805798fdd..32ea470e58 100644 --- a/src/mir_core/src/miranda.h +++ b/src/mir_core/src/miranda.h @@ -1,93 +1,93 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#pragma once - -void UnloadLangPackModule(void); - -int InitialiseModularEngine(void); -void DestroyModularEngine(void); - -int InitPathUtils(void); - -extern HINSTANCE g_hInst; -extern HWND hAPCWindow; -extern HANDLE hThreadQueueEmpty; -extern HCURSOR g_hCursorNS, g_hCursorWE; - -///////////////////////////////////////////////////////////////////////////////////////// -// modules.cpp - -struct THookSubscriber -{ - HINSTANCE hOwner; - int type; - union { - struct { - union { - MIRANDAHOOK pfnHook; - MIRANDAHOOKPARAM pfnHookParam; - MIRANDAHOOKOBJ pfnHookObj; - MIRANDAHOOKOBJPARAM pfnHookObjParam; - }; - void* object; - LPARAM lParam; - }; - struct { - HWND hwnd; - UINT message; - }; - }; -}; - -#define HOOK_SECRET_SIGNATURE 0xDEADBABA - -struct THook : public MZeroedObject -{ - char name[ MAXMODULELABELLENGTH ]; - int id; - int subscriberCount; - THookSubscriber* subscriber; - MIRANDAHOOK pfnHook; - DWORD secretSignature = HOOK_SECRET_SIGNATURE; - mir_cs csHook; -}; - -extern LIST pluginListAddr; - -///////////////////////////////////////////////////////////////////////////////////////// -// langpack.cpp - -char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W); - -///////////////////////////////////////////////////////////////////////////////////////// -// threads.cpp - -extern DWORD mir_tls; - -///////////////////////////////////////////////////////////////////////////////////////// -// utils.cpp - -typedef BOOL(APIENTRY *PGENRANDOM)(PVOID, ULONG); -extern PGENRANDOM pfnRtlGenRandom; +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +void UnloadLangPackModule(void); + +int InitialiseModularEngine(void); +void DestroyModularEngine(void); + +int InitPathUtils(void); + +extern HINSTANCE g_hInst; +extern HWND hAPCWindow; +extern HANDLE hThreadQueueEmpty; +extern HCURSOR g_hCursorNS, g_hCursorWE; + +///////////////////////////////////////////////////////////////////////////////////////// +// modules.cpp + +struct THookSubscriber +{ + HINSTANCE hOwner; + int type; + union { + struct { + union { + MIRANDAHOOK pfnHook; + MIRANDAHOOKPARAM pfnHookParam; + MIRANDAHOOKOBJ pfnHookObj; + MIRANDAHOOKOBJPARAM pfnHookObjParam; + }; + void* object; + LPARAM lParam; + }; + struct { + HWND hwnd; + UINT message; + }; + }; +}; + +#define HOOK_SECRET_SIGNATURE 0xDEADBABA + +struct THook : public MZeroedObject +{ + char name[ MAXMODULELABELLENGTH ]; + int id; + int subscriberCount; + THookSubscriber* subscriber; + MIRANDAHOOK pfnHook; + DWORD secretSignature = HOOK_SECRET_SIGNATURE; + mir_cs csHook; +}; + +extern LIST pluginListAddr; + +///////////////////////////////////////////////////////////////////////////////////////// +// langpack.cpp + +char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W); + +///////////////////////////////////////////////////////////////////////////////////////// +// threads.cpp + +extern DWORD mir_tls; + +///////////////////////////////////////////////////////////////////////////////////////// +// utils.cpp + +typedef BOOL(MIR_SYSCALL *PGENRANDOM)(void*, DWORD); +extern PGENRANDOM pfnRtlGenRandom; diff --git a/src/mir_core/src/mstring.cpp b/src/mir_core/src/mstring.cpp index 2779c93978..3982fc8d61 100644 --- a/src/mir_core/src/mstring.cpp +++ b/src/mir_core/src/mstring.cpp @@ -1,142 +1,140 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// -// CMBaseString - -class CNilMStringData : public CMStringData -{ -public: - CNilMStringData(); - -public: - wchar_t achNil[2]; -}; - -CNilMStringData::CNilMStringData() -{ - nRefs = 2; // Never gets freed - nDataLength = 0; - nAllocLength = 0; - achNil[0] = 0; - achNil[1] = 0; -} - -static CNilMStringData *m_nil = nullptr; - -///////////////////////////////////////////////////////////////////////////////////////// -// CMBaseString - -MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize) -{ - nChars++; // nil char - size_t nDataBytes = nCharSize * nChars; - size_t nTotalSize = nDataBytes + sizeof(CMStringData); - - CMStringData *pData = static_cast(malloc(nTotalSize)); - if (pData == nullptr) - return nullptr; - - pData->nRefs = 1; - pData->nAllocLength = nChars - 1; - pData->nDataLength = 0; - return pData; -} - -MIR_CORE_DLL(void) mirstr_free(CMStringData *pData) -{ - free(pData); -} - -MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize) -{ - nChars++; // nil char - ULONG nDataBytes = nCharSize * nChars; - ULONG nTotalSize = nDataBytes + sizeof(CMStringData); - - CMStringData *pNewData = static_cast(realloc(pData, nTotalSize)); - if (pNewData == nullptr) - return nullptr; - - pNewData->nAllocLength = nChars - 1; - return pNewData; -} - -MIR_CORE_DLL(CMStringData*) mirstr_getNil() -{ - if (m_nil == nullptr) - m_nil = new CNilMStringData(); - m_nil->AddRef(); - return m_nil; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// CMStringData - -MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis) -{ - pThis->nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary - if (pThis->nRefs == 0) - pThis->nRefs = -1; -} - -MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis) -{ - if (InterlockedDecrement(&pThis->nRefs) <= 0) - mirstr_free(pThis); -} - -MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis) -{ - if (pThis->IsLocked()) - { - pThis->nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary - if (pThis->nRefs == 0) - pThis->nRefs = 1; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// don't remove it -// this code just instantiates templates for CMStringW[A/W] - -template CMStringW; -template MIR_CORE_EXPORT CMStringW CALLBACK operator + (const CMStringW& str1, const CMStringW& str2); -template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2); -template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2); -template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2); -template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2); -template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2); -template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2); - -template CMStringA; -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2); -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2); -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2); -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2); -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2); -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2); -template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2); +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// +// CMBaseString + +class CNilMStringData : public CMStringData +{ +public: + CNilMStringData(); + +public: + wchar_t achNil[2]; +}; + +CNilMStringData::CNilMStringData() +{ + nRefs = 2; // Never gets freed + nDataLength = 0; + nAllocLength = 0; + achNil[0] = 0; + achNil[1] = 0; +} + +static CNilMStringData *m_nil = nullptr; + +///////////////////////////////////////////////////////////////////////////////////////// +// CMBaseString + +MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize) +{ + nChars++; // nil char + size_t nDataBytes = nCharSize * nChars; + size_t nTotalSize = nDataBytes + sizeof(CMStringData); + + CMStringData *pData = static_cast(malloc(nTotalSize)); + if (pData == nullptr) + return nullptr; + + pData->nRefs = 1; + pData->nAllocLength = nChars - 1; + pData->nDataLength = 0; + return pData; +} + +MIR_CORE_DLL(void) mirstr_free(CMStringData *pData) +{ + free(pData); +} + +MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize) +{ + nChars++; // nil char + uint32_t nDataBytes = nCharSize * nChars; + uint32_t nTotalSize = nDataBytes + sizeof(CMStringData); + + CMStringData *pNewData = static_cast(realloc(pData, nTotalSize)); + if (pNewData == nullptr) + return nullptr; + + pNewData->nAllocLength = nChars - 1; + return pNewData; +} + +MIR_CORE_DLL(CMStringData*) mirstr_getNil() +{ + if (m_nil == nullptr) + m_nil = new CNilMStringData(); + m_nil->AddRef(); + return m_nil; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// CMStringData + +MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis) +{ + pThis->nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary + if (pThis->nRefs == 0) + pThis->nRefs = -1; +} + +MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis) +{ + if (InterlockedDecrement(&pThis->nRefs) <= 0) + mirstr_free(pThis); +} + +MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis) +{ + if (pThis->IsLocked()) + { + pThis->nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary + if (pThis->nRefs == 0) + pThis->nRefs = 1; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// don't remove it +// this code just instantiates templates for CMStringW[A/W] + +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const CMStringW& str2); +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2); +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2); +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2); +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2); +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2); +template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2); + +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2); +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2); +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2); +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2); +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2); +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2); +template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2); diff --git a/src/mir_core/src/sha256.cpp b/src/mir_core/src/sha256.cpp index e3e5991f5f..63fd940a62 100644 --- a/src/mir_core/src/sha256.cpp +++ b/src/mir_core/src/sha256.cpp @@ -1,289 +1,289 @@ - -#include "stdafx.h" - -MIR_CORE_DLL(void) mir_sha256_init(SHA256_CONTEXT *hd) -{ - hd->h0 = 0x6a09e667; - hd->h1 = 0xbb67ae85; - hd->h2 = 0x3c6ef372; - hd->h3 = 0xa54ff53a; - hd->h4 = 0x510e527f; - hd->h5 = 0x9b05688c; - hd->h6 = 0x1f83d9ab; - hd->h7 = 0x5be0cd19; - - hd->nblocks = 0; - hd->count = 0; -} - -/* -Transform the message X which consists of 16 32-bit-words. See FIPS -180-2 for details. */ -#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) -#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ -#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ -#define R(a,b,c,d,e,f,g,h,k,w) do \ -{ \ - t1 = (h)+Sum1((e)) + Cho((e), (f), (g)) + (k)+(w); \ - t2 = Sum0((a)) + Maj((a), (b), (c)); \ - h = g; \ - g = f; \ - f = e; \ - e = d + t1; \ - d = c; \ - c = b; \ - b = a; \ - a = t1 + t2; \ -} while (0) - -/* (4.2) same as SHA-1's F1. */ -static inline UINT32 -Cho(UINT32 x, UINT32 y, UINT32 z) -{ - return (z ^ (x & (y ^ z))); -} - -/* (4.3) same as SHA-1's F3 */ -static inline UINT32 -Maj(UINT32 x, UINT32 y, UINT32 z) -{ - return ((x & y) | (z & (x | y))); -} - -/* (4.4) */ -static inline UINT32 Sum0(UINT32 x) -{ - return (ror(x, 2) ^ ror(x, 13) ^ ror(x, 22)); -} - -/* (4.5) */ -static inline UINT32 -Sum1(UINT32 x) -{ - return (ror(x, 6) ^ ror(x, 11) ^ ror(x, 25)); -} - - -static void transform(SHA256_CONTEXT *hd, const unsigned char *data) -{ - static const UINT32 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 - }; - - UINT32 a, b, c, d, e, f, g, h, t1, t2; - UINT32 x[16]; - UINT32 w[64]; - int i; - - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - f = hd->h5; - g = hd->h6; - h = hd->h7; - -#ifdef WORDS_BIGENDIAN - memcpy(x, data, 64); -#else - { - BYTE *p2; - - for (i = 0, p2 = (BYTE*)x; i < 16; i++, p2 += 4) { - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif - - for (i = 0; i < 16; i++) - w[i] = x[i]; - for (; i < 64; i++) - w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16]; - - for (i = 0; i < 64;) { -#if 0 - R(a, b, c, d, e, f, g, h, K[i], w[i]); - i++; -#else - t1 = h + Sum1(e) + Cho(e, f, g) + K[i] + w[i]; - t2 = Sum0(a) + Maj(a, b, c); - d += t1; - h = t1 + t2; - - t1 = g + Sum1(d) + Cho(d, e, f) + K[i + 1] + w[i + 1]; - t2 = Sum0(h) + Maj(h, a, b); - c += t1; - g = t1 + t2; - - t1 = f + Sum1(c) + Cho(c, d, e) + K[i + 2] + w[i + 2]; - t2 = Sum0(g) + Maj(g, h, a); - b += t1; - f = t1 + t2; - - t1 = e + Sum1(b) + Cho(b, c, d) + K[i + 3] + w[i + 3]; - t2 = Sum0(f) + Maj(f, g, h); - a += t1; - e = t1 + t2; - - t1 = d + Sum1(a) + Cho(a, b, c) + K[i + 4] + w[i + 4]; - t2 = Sum0(e) + Maj(e, f, g); - h += t1; - d = t1 + t2; - - t1 = c + Sum1(h) + Cho(h, a, b) + K[i + 5] + w[i + 5]; - t2 = Sum0(d) + Maj(d, e, f); - g += t1; - c = t1 + t2; - - t1 = b + Sum1(g) + Cho(g, h, a) + K[i + 6] + w[i + 6]; - t2 = Sum0(c) + Maj(c, d, e); - f += t1; - b = t1 + t2; - - t1 = a + Sum1(f) + Cho(f, g, h) + K[i + 7] + w[i + 7]; - t2 = Sum0(b) + Maj(b, c, d); - e += t1; - a = t1 + t2; - - i += 8; -#endif - } - - hd->h0 += a; - hd->h1 += b; - hd->h2 += c; - hd->h3 += d; - hd->h4 += e; - hd->h5 += f; - hd->h6 += g; - hd->h7 += h; -} -#undef S0 -#undef S1 -#undef R - - -/* Update the message digest with the contents of INBUF with length INLEN. */ -MIR_CORE_DLL(void) mir_sha256_write(SHA256_CONTEXT *hd, const void *inbuf_arg, size_t inlen) -{ - const unsigned char *inbuf = (const unsigned char *)inbuf_arg; - - if (hd->count == 64) { /* flush the buffer */ - transform(hd, hd->buf); - hd->count = 0; - hd->nblocks++; - } - if (!inbuf) - return; - if (hd->count) { - for (; inlen && hd->count < 64; inlen--) - hd->buf[hd->count++] = *inbuf++; - mir_sha256_write(hd, nullptr, 0); - if (!inlen) - return; - } - - while (inlen >= 64) { - transform(hd, inbuf); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - for (; inlen && hd->count < 64; inlen--) - hd->buf[hd->count++] = *inbuf++; -} - -/* -The routine finally terminates the computation and returns the -digest. The handle is prepared for a new cycle, but adding bytes -to the handle will the destroy the returned buffer. Returns: 32 -bytes with the message the digest. */ - -MIR_CORE_DLL(void) mir_sha256_final(SHA256_CONTEXT *hd, BYTE hashout[MIR_SHA256_HASH_SIZE]) -{ - UINT32 t, msb, lsb; - - mir_sha256_write(hd, nullptr, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a BYTE count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if ((lsb += hd->count) < t) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if (hd->count < 56) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while (hd->count < 56) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while (hd->count < 64) - hd->buf[hd->count++] = 0; - mir_sha256_write(hd, nullptr, 0); /* flush */; - memset(hd->buf, 0, 56); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = msb >> 24; - hd->buf[57] = msb >> 16; - hd->buf[58] = msb >> 8; - hd->buf[59] = msb; - hd->buf[60] = lsb >> 24; - hd->buf[61] = lsb >> 16; - hd->buf[62] = lsb >> 8; - hd->buf[63] = lsb; - transform(hd, hd->buf); - - BYTE *p = hashout; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(UINT32*)p = hd->h##a ; p += 4; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0) -#endif - X(0); - X(1); - X(2); - X(3); - X(4); - X(5); - X(6); - X(7); -#undef X -} - -MIR_CORE_DLL(void) mir_sha256_hash(const void *dataIn, size_t len, BYTE hashout[MIR_SHA256_HASH_SIZE]) -{ - SHA256_CONTEXT tmp; - mir_sha256_init(&tmp); - mir_sha256_write(&tmp, dataIn, len); - mir_sha256_final(&tmp, hashout); -} + +#include "stdafx.h" + +MIR_CORE_DLL(void) mir_sha256_init(SHA256_CONTEXT *hd) +{ + hd->h0 = 0x6a09e667; + hd->h1 = 0xbb67ae85; + hd->h2 = 0x3c6ef372; + hd->h3 = 0xa54ff53a; + hd->h4 = 0x510e527f; + hd->h5 = 0x9b05688c; + hd->h6 = 0x1f83d9ab; + hd->h7 = 0x5be0cd19; + + hd->nblocks = 0; + hd->count = 0; +} + +/* +Transform the message X which consists of 16 32-bit-words. See FIPS +180-2 for details. */ +#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) +#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ +#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ +#define R(a,b,c,d,e,f,g,h,k,w) do \ +{ \ + t1 = (h)+Sum1((e)) + Cho((e), (f), (g)) + (k)+(w); \ + t2 = Sum0((a)) + Maj((a), (b), (c)); \ + h = g; \ + g = f; \ + f = e; \ + e = d + t1; \ + d = c; \ + c = b; \ + b = a; \ + a = t1 + t2; \ +} while (0) + +/* (4.2) same as SHA-1's F1. */ +static inline uint32_t +Cho(uint32_t x, uint32_t y, uint32_t z) +{ + return (z ^ (x & (y ^ z))); +} + +/* (4.3) same as SHA-1's F3 */ +static inline uint32_t +Maj(uint32_t x, uint32_t y, uint32_t z) +{ + return ((x & y) | (z & (x | y))); +} + +/* (4.4) */ +static inline uint32_t Sum0(uint32_t x) +{ + return (ror(x, 2) ^ ror(x, 13) ^ ror(x, 22)); +} + +/* (4.5) */ +static inline uint32_t +Sum1(uint32_t x) +{ + return (ror(x, 6) ^ ror(x, 11) ^ ror(x, 25)); +} + + +static void transform(SHA256_CONTEXT *hd, const unsigned char *data) +{ + static const uint32_t 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 + }; + + uint32_t a, b, c, d, e, f, g, h, t1, t2; + uint32_t x[16]; + uint32_t w[64]; + int i; + + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + f = hd->h5; + g = hd->h6; + h = hd->h7; + +#ifdef WORDS_BIGENDIAN + memcpy(x, data, 64); +#else + { + BYTE *p2; + + for (i = 0, p2 = (BYTE*)x; i < 16; i++, p2 += 4) { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + + for (i = 0; i < 16; i++) + w[i] = x[i]; + for (; i < 64; i++) + w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16]; + + for (i = 0; i < 64;) { +#if 0 + R(a, b, c, d, e, f, g, h, K[i], w[i]); + i++; +#else + t1 = h + Sum1(e) + Cho(e, f, g) + K[i] + w[i]; + t2 = Sum0(a) + Maj(a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1(d) + Cho(d, e, f) + K[i + 1] + w[i + 1]; + t2 = Sum0(h) + Maj(h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1(c) + Cho(c, d, e) + K[i + 2] + w[i + 2]; + t2 = Sum0(g) + Maj(g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1(b) + Cho(b, c, d) + K[i + 3] + w[i + 3]; + t2 = Sum0(f) + Maj(f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1(a) + Cho(a, b, c) + K[i + 4] + w[i + 4]; + t2 = Sum0(e) + Maj(e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1(h) + Cho(h, a, b) + K[i + 5] + w[i + 5]; + t2 = Sum0(d) + Maj(d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1(g) + Cho(g, h, a) + K[i + 6] + w[i + 6]; + t2 = Sum0(c) + Maj(c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1(f) + Cho(f, g, h) + K[i + 7] + w[i + 7]; + t2 = Sum0(b) + Maj(b, c, d); + e += t1; + a = t1 + t2; + + i += 8; +#endif + } + + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + hd->h5 += f; + hd->h6 += g; + hd->h7 += h; +} +#undef S0 +#undef S1 +#undef R + + +/* Update the message digest with the contents of INBUF with length INLEN. */ +MIR_CORE_DLL(void) mir_sha256_write(SHA256_CONTEXT *hd, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = (const unsigned char *)inbuf_arg; + + if (hd->count == 64) { /* flush the buffer */ + transform(hd, hd->buf); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + mir_sha256_write(hd, nullptr, 0); + if (!inlen) + return; + } + + while (inlen >= 64) { + transform(hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + +/* +The routine finally terminates the computation and returns the +digest. The handle is prepared for a new cycle, but adding bytes +to the handle will the destroy the returned buffer. Returns: 32 +bytes with the message the digest. */ + +MIR_CORE_DLL(void) mir_sha256_final(SHA256_CONTEXT *hd, BYTE hashout[MIR_SHA256_HASH_SIZE]) +{ + uint32_t t, msb, lsb; + + mir_sha256_write(hd, nullptr, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a BYTE count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if (hd->count < 56) { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 56) + hd->buf[hd->count++] = 0; /* pad */ + } + else { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 64) + hd->buf[hd->count++] = 0; + mir_sha256_write(hd, nullptr, 0); /* flush */; + memset(hd->buf, 0, 56); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb; + transform(hd, hd->buf); + + BYTE *p = hashout; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(uint32_t*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); + X(5); + X(6); + X(7); +#undef X +} + +MIR_CORE_DLL(void) mir_sha256_hash(const void *dataIn, size_t len, BYTE hashout[MIR_SHA256_HASH_SIZE]) +{ + SHA256_CONTEXT tmp; + mir_sha256_init(&tmp); + mir_sha256_write(&tmp, dataIn, len); + mir_sha256_final(&tmp, hashout); +} diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h index 9b9d913bfc..cbc7f7af48 100644 --- a/src/mir_core/src/stdafx.h +++ b/src/mir_core/src/stdafx.h @@ -1,74 +1,78 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#pragma once - -#define INCL_WINSOCK_API_TYPEDEFS 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define __NO_CMPLUGIN_NEEDED -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "miranda.h" - -#include - -#include - -void GetDefaultLang(); \ No newline at end of file +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +#define INCL_WINSOCK_API_TYPEDEFS 1 + +#ifdef _MSC_VER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#endif // _WINDOWS + +#include +#include +#include +#include +#include +#include +#include +#include + +#define __NO_CMPLUGIN_NEEDED +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "miranda.h" + +#include + +#include + +void GetDefaultLang(); diff --git a/src/mir_core/src/utf.cpp b/src/mir_core/src/utf.cpp index 4af4d97fee..b5bd37717f 100644 --- a/src/mir_core/src/utf.cpp +++ b/src/mir_core/src/utf.cpp @@ -1,437 +1,441 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - - Copyright 2000 Alexandre Julliard of Wine project - (UTF-8 conversion routines) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */ -static const char utf8_length[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */ - 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */ -}; - -/* first byte mask depending on UTF-8 sequence length */ -static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 }; - -/* minimum Unicode value depending on UTF-8 sequence length */ -static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 }; - -/* get the next char value taking surrogates into account */ -static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen) -{ - if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */ - if (src[0] > 0xdbff || /* invalid high surrogate */ - srclen <= 1 || /* missing low surrogate */ - src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */ - return 0; - return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff); - } - return src[0]; -} - -/* query necessary dst length for src string */ -static int mir_utf8len(const wchar_t *src, unsigned int srclen) -{ - int len; - unsigned int val; - - for (len = 0; srclen; srclen--, src++) { - if (*src < 0x80) { /* 0x00-0x7f: 1 byte */ - len++; - continue; - } - if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */ - len += 2; - continue; - } - if (!(val = getSurrogateValue(src, srclen))) - return -2; - - if (val < 0x10000) /* 0x800-0xffff: 3 bytes */ - len += 3; - else { /* 0x10000-0x10ffff: 4 bytes */ - len += 4; - src++; - srclen--; - } - } - return len; -} - -MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src) -{ - if (src == nullptr) - return 0; - - return mir_utf8len(src, (int)wcslen(src)); -} - -/* wide char to UTF-8 string conversion */ -/* return -1 on dst buffer overflow, -2 on invalid input char */ -int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen) -{ - int len; - - for (len = dstlen; srclen; srclen--, src++) { - wchar_t ch = *src; - unsigned int val; - - if (ch < 0x80) { /* 0x00-0x7f: 1 byte */ - if (!len--) return -1; /* overflow */ - *dst++ = ch; - continue; - } - - if (ch < 0x800) { /* 0x80-0x7ff: 2 bytes */ - if ((len -= 2) < 0) return -1; /* overflow */ - dst[1] = 0x80 | (ch & 0x3f); - ch >>= 6; - dst[0] = 0xc0 | ch; - dst += 2; - continue; - } - - if (!(val = getSurrogateValue(src, srclen))) - return -2; - - if (val < 0x10000) { /* 0x800-0xffff: 3 bytes */ - if ((len -= 3) < 0) return -1; /* overflow */ - dst[2] = 0x80 | (val & 0x3f); - val >>= 6; - dst[1] = 0x80 | (val & 0x3f); - val >>= 6; - dst[0] = 0xe0 | val; - dst += 3; - } - else { /* 0x10000-0x10ffff: 4 bytes */ - if ((len -= 4) < 0) return -1; /* overflow */ - dst[3] = 0x80 | (val & 0x3f); - val >>= 6; - dst[2] = 0x80 | (val & 0x3f); - val >>= 6; - dst[1] = 0x80 | (val & 0x3f); - val >>= 6; - dst[0] = 0xf0 | val; - dst += 4; - src++; - srclen--; - } - } - return dstlen - len; -} - -/* helper for the various utf8 mbstowcs functions */ -static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend) -{ - unsigned int len = utf8_length[ch - 0x80]; - unsigned int res = ch & utf8_mask[len]; - const char *end = *str + len; - - if (end > strend) return ~0; - switch (len) { - case 3: - if ((ch = end[-3] ^ 0x80) >= 0x40) break; - res = (res << 6) | ch; - (*str)++; - - case 2: - if ((ch = end[-2] ^ 0x80) >= 0x40) break; - res = (res << 6) | ch; - (*str)++; - - case 1: - if ((ch = end[-1] ^ 0x80) >= 0x40) break; - res = (res << 6) | ch; - (*str)++; - if (res < utf8_minval[len]) break; - return res; - } - return ~0; -} - -/* query necessary dst length for src string */ -static int Utf8toUcs2Len(const char *src, size_t srclen) -{ - int ret = 0; - unsigned int res; - const char *srcend = src + srclen; - - while (src < srcend) { - unsigned char ch = *src++; - if (ch < 0x80) { /* special fast case for 7-bit ASCII */ - ret++; - continue; - } - if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) { - if (res > 0xffff) ret++; - ret++; - } - else return -2; /* bad char */ - /* otherwise ignore it */ - } - return ret; -} - -/* UTF-8 to wide char string conversion */ -/* return -1 on dst buffer overflow, -2 on invalid input char */ -MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen) -{ - unsigned int res; - const char *srcend = src + srclen; // including trailing zero - wchar_t *dstend = dst + dstlen; - - while ((dst < dstend) && (src < srcend)) { - unsigned char ch = *src++; - if (ch < 0x80) { /* special fast case for 7-bit ASCII */ - *dst++ = ch; - continue; - } - - if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff) - *dst++ = res; - else if (res <= 0x10ffff) { /* we need surrogates */ - if (dst == dstend - 1) - return -1; /* overflow */ - res -= 0x10000; - *dst++ = 0xd800 | (res >> 10); - *dst++ = 0xdc00 | (res & 0x3ff); - } - else return -2; /* bad char */ - } - - if (src < srcend) - return -1; /* overflow */ - - return (int)(dstlen - (dstend - dst)); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// mir_utf8decode - converts UTF8-encoded string to the UCS2/MBCS format - -MIR_CORE_DLL(char*) mir_utf8decodecp(char *str, int codepage, wchar_t **ucs2) -{ - bool needs_free = false; - wchar_t* tempBuf = nullptr; - if (ucs2) - *ucs2 = nullptr; - - if (str == nullptr) - return nullptr; - - size_t len = strlen(str); - if (len < 2) { - if (ucs2 != nullptr) { - *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); - MultiByteToWideChar(codepage, 0, str, (int)len, tempBuf, (int)len); - tempBuf[len] = 0; - } - return str; - } - - int destlen = Utf8toUcs2Len(str, len); - if (destlen < 0) - return nullptr; - - if (ucs2 == nullptr) { - __try { - tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - tempBuf = nullptr; - needs_free = true; - } - } - - if (tempBuf == nullptr) { - tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); - if (tempBuf == nullptr) - return nullptr; - } - - Utf8toUcs2(str, len, tempBuf, destlen); - tempBuf[destlen] = 0; - WideCharToMultiByte(codepage, 0, tempBuf, -1, str, (int)len + 1, "?", nullptr); - - if (ucs2) - *ucs2 = tempBuf; - else if (needs_free) - mir_free(tempBuf); - - return str; -} - -MIR_CORE_DLL(char*) mir_utf8decode(char *str, wchar_t **ucs2) -{ - return mir_utf8decodecp(str, Langpack_GetDefaultCodePage(), ucs2); -} - -MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char *str) -{ - if (str == nullptr) - return nullptr; - - size_t len = strlen(str); - - int destlen = Utf8toUcs2Len(str, len); - if (destlen < 0) - return nullptr; - - wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); - if (ucs2 == nullptr) - return nullptr; - - if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) { - ucs2[destlen] = 0; - return ucs2; - } - - mir_free(ucs2); - - return nullptr; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// mir_utf8encode - converts MBCS string to the UTF8-encoded format - -MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage) -{ - int len; - bool needs_free = false; - char* result = nullptr; - wchar_t* tempBuf; - - if (src == nullptr) - return nullptr; - - len = (int)strlen(src); - - __try { - tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); - if (tempBuf == nullptr) return nullptr; - needs_free = true; - } - - len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1); - - int destlen = mir_utf8len(tempBuf, len); - if (destlen >= 0) { - result = (char*)mir_alloc(destlen + 1); - if (result) { - Ucs2toUtf8(tempBuf, len, result, destlen); - result[destlen] = 0; - } - } - - if (needs_free) - mir_free(tempBuf); - - return result; -} - -MIR_CORE_DLL(char*) mir_utf8encode(const char* src) -{ - return mir_utf8encodecp(src, Langpack_GetDefaultCodePage()); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// mir_utf8encode - converts UCS2 string to the UTF8-encoded format - -MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* src) -{ - if (src == nullptr) - return nullptr; - - int len = (int)wcslen(src); - - int destlen = mir_utf8len(src, len); - if (destlen < 0) return nullptr; - - char* result = (char*)mir_alloc(destlen + 1); - if (result == nullptr) - return nullptr; - - Ucs2toUtf8(src, len, result, destlen); - result[destlen] = 0; - - return result; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Utf8CheckString - checks if a string is a valid utf8-encoded string - -MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str) -{ - int expect_bytes = 0, utf_found = 0; - - if (!str) return 0; - - while (*str) { - if ((*str & 0x80) == 0) { - /* Looks like an ASCII character */ - if (expect_bytes) - /* byte of UTF-8 character expected */ - return 0; - } - else { - /* Looks like byte of an UTF-8 character */ - if (expect_bytes) { - /* expect_bytes already set: first byte of UTF-8 char already seen */ - if ((*str & 0xC0) != 0x80) { - /* again first byte ?!?! */ - return 0; - } - } - else { - /* First byte of the UTF-8 character */ - /* count initial one bits and set expect_bytes to 1 less */ - char ch = *str; - while (ch & 0x80) { - expect_bytes++; - ch = (ch & 0x7f) << 1; - } - } - /* OK, next byte of UTF-8 character */ - /* Decrement number of expected bytes */ - if (--expect_bytes == 0) - utf_found = 1; - } - str++; - } - - return (utf_found && expect_bytes == 0); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + + Copyright 2000 Alexandre Julliard of Wine project + (UTF-8 conversion routines) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */ +static const char utf8_length[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */ + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */ +}; + +/* first byte mask depending on UTF-8 sequence length */ +static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 }; + +/* minimum Unicode value depending on UTF-8 sequence length */ +static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 }; + +/* get the next char value taking surrogates into account */ +static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen) +{ + if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */ + if (src[0] > 0xdbff || /* invalid high surrogate */ + srclen <= 1 || /* missing low surrogate */ + src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */ + return 0; + return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff); + } + return src[0]; +} + +/* query necessary dst length for src string */ +static int mir_utf8len(const wchar_t *src, unsigned int srclen) +{ + int len; + unsigned int val; + + for (len = 0; srclen; srclen--, src++) { + if (*src < 0x80) { /* 0x00-0x7f: 1 byte */ + len++; + continue; + } + if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */ + len += 2; + continue; + } + if (!(val = getSurrogateValue(src, srclen))) + return -2; + + if (val < 0x10000) /* 0x800-0xffff: 3 bytes */ + len += 3; + else { /* 0x10000-0x10ffff: 4 bytes */ + len += 4; + src++; + srclen--; + } + } + return len; +} + +MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src) +{ + if (src == nullptr) + return 0; + + return mir_utf8len(src, (int)wcslen(src)); +} + +/* wide char to UTF-8 string conversion */ +/* return -1 on dst buffer overflow, -2 on invalid input char */ +int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen) +{ + int len; + + for (len = dstlen; srclen; srclen--, src++) { + wchar_t ch = *src; + unsigned int val; + + if (ch < 0x80) { /* 0x00-0x7f: 1 byte */ + if (!len--) return -1; /* overflow */ + *dst++ = ch; + continue; + } + + if (ch < 0x800) { /* 0x80-0x7ff: 2 bytes */ + if ((len -= 2) < 0) return -1; /* overflow */ + dst[1] = 0x80 | (ch & 0x3f); + ch >>= 6; + dst[0] = 0xc0 | ch; + dst += 2; + continue; + } + + if (!(val = getSurrogateValue(src, srclen))) + return -2; + + if (val < 0x10000) { /* 0x800-0xffff: 3 bytes */ + if ((len -= 3) < 0) return -1; /* overflow */ + dst[2] = 0x80 | (val & 0x3f); + val >>= 6; + dst[1] = 0x80 | (val & 0x3f); + val >>= 6; + dst[0] = 0xe0 | val; + dst += 3; + } + else { /* 0x10000-0x10ffff: 4 bytes */ + if ((len -= 4) < 0) return -1; /* overflow */ + dst[3] = 0x80 | (val & 0x3f); + val >>= 6; + dst[2] = 0x80 | (val & 0x3f); + val >>= 6; + dst[1] = 0x80 | (val & 0x3f); + val >>= 6; + dst[0] = 0xf0 | val; + dst += 4; + src++; + srclen--; + } + } + return dstlen - len; +} + +/* helper for the various utf8 mbstowcs functions */ +static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend) +{ + unsigned int len = utf8_length[ch - 0x80]; + unsigned int res = ch & utf8_mask[len]; + const char *end = *str + len; + + if (end > strend) return ~0; + switch (len) { + case 3: + if ((ch = end[-3] ^ 0x80) >= 0x40) break; + res = (res << 6) | ch; + (*str)++; + + case 2: + if ((ch = end[-2] ^ 0x80) >= 0x40) break; + res = (res << 6) | ch; + (*str)++; + + case 1: + if ((ch = end[-1] ^ 0x80) >= 0x40) break; + res = (res << 6) | ch; + (*str)++; + if (res < utf8_minval[len]) break; + return res; + } + return ~0; +} + +/* query necessary dst length for src string */ +static int Utf8toUcs2Len(const char *src, size_t srclen) +{ + int ret = 0; + unsigned int res; + const char *srcend = src + srclen; + + while (src < srcend) { + unsigned char ch = *src++; + if (ch < 0x80) { /* special fast case for 7-bit ASCII */ + ret++; + continue; + } + if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) { + if (res > 0xffff) ret++; + ret++; + } + else return -2; /* bad char */ + /* otherwise ignore it */ + } + return ret; +} + +/* UTF-8 to wide char string conversion */ +/* return -1 on dst buffer overflow, -2 on invalid input char */ +MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen) +{ + unsigned int res; + const char *srcend = src + srclen; // including trailing zero + wchar_t *dstend = dst + dstlen; + + while ((dst < dstend) && (src < srcend)) { + unsigned char ch = *src++; + if (ch < 0x80) { /* special fast case for 7-bit ASCII */ + *dst++ = ch; + continue; + } + + if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff) + *dst++ = res; + else if (res <= 0x10ffff) { /* we need surrogates */ + if (dst == dstend - 1) + return -1; /* overflow */ + res -= 0x10000; + *dst++ = 0xd800 | (res >> 10); + *dst++ = 0xdc00 | (res & 0x3ff); + } + else return -2; /* bad char */ + } + + if (src < srcend) + return -1; /* overflow */ + + return (int)(dstlen - (dstend - dst)); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// mir_utf8decode - converts UTF8-encoded string to the UCS2/MBCS format + +#ifdef _MSC_VER +MIR_CORE_DLL(char*) mir_utf8decodecp(char *str, int codepage, wchar_t **ucs2) +{ + bool needs_free = false; + wchar_t* tempBuf = nullptr; + if (ucs2) + *ucs2 = nullptr; + + if (str == nullptr) + return nullptr; + + size_t len = strlen(str); + if (len < 2) { + if (ucs2 != nullptr) { + *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); + MultiByteToWideChar(codepage, 0, str, (int)len, tempBuf, (int)len); + tempBuf[len] = 0; + } + return str; + } + + int destlen = Utf8toUcs2Len(str, len); + if (destlen < 0) + return nullptr; + + if (ucs2 == nullptr) { + __try { + tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t)); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + tempBuf = nullptr; + needs_free = true; + } + } + + if (tempBuf == nullptr) { + tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); + if (tempBuf == nullptr) + return nullptr; + } + + Utf8toUcs2(str, len, tempBuf, destlen); + tempBuf[destlen] = 0; + WideCharToMultiByte(codepage, 0, tempBuf, -1, str, (int)len + 1, "?", nullptr); + + if (ucs2) + *ucs2 = tempBuf; + else if (needs_free) + mir_free(tempBuf); + + return str; +} + +MIR_CORE_DLL(char*) mir_utf8decode(char *str, wchar_t **ucs2) +{ + return mir_utf8decodecp(str, Langpack_GetDefaultCodePage(), ucs2); +} +#endif + +MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char *str) +{ + if (str == nullptr) + return nullptr; + + size_t len = strlen(str); + + int destlen = Utf8toUcs2Len(str, len); + if (destlen < 0) + return nullptr; + + wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); + if (ucs2 == nullptr) + return nullptr; + + if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) { + ucs2[destlen] = 0; + return ucs2; + } + + mir_free(ucs2); + + return nullptr; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// mir_utf8encode - converts MBCS string to the UTF8-encoded format + +#ifdef _MSC_VER +MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage) +{ + int len; + bool needs_free = false; + char* result = nullptr; + wchar_t* tempBuf; + + if (src == nullptr) + return nullptr; + + len = (int)strlen(src); + + __try { + tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t)); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); + if (tempBuf == nullptr) return nullptr; + needs_free = true; + } + + len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1); + + int destlen = mir_utf8len(tempBuf, len); + if (destlen >= 0) { + result = (char*)mir_alloc(destlen + 1); + if (result) { + Ucs2toUtf8(tempBuf, len, result, destlen); + result[destlen] = 0; + } + } + + if (needs_free) + mir_free(tempBuf); + + return result; +} + +MIR_CORE_DLL(char*) mir_utf8encode(const char* src) +{ + return mir_utf8encodecp(src, Langpack_GetDefaultCodePage()); +} +#endif + +///////////////////////////////////////////////////////////////////////////////////////// +// mir_utf8encode - converts UCS2 string to the UTF8-encoded format + +MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* src) +{ + if (src == nullptr) + return nullptr; + + int len = (int)wcslen(src); + + int destlen = mir_utf8len(src, len); + if (destlen < 0) return nullptr; + + char* result = (char*)mir_alloc(destlen + 1); + if (result == nullptr) + return nullptr; + + Ucs2toUtf8(src, len, result, destlen); + result[destlen] = 0; + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8CheckString - checks if a string is a valid utf8-encoded string + +MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str) +{ + int expect_bytes = 0, utf_found = 0; + + if (!str) return 0; + + while (*str) { + if ((*str & 0x80) == 0) { + /* Looks like an ASCII character */ + if (expect_bytes) + /* byte of UTF-8 character expected */ + return 0; + } + else { + /* Looks like byte of an UTF-8 character */ + if (expect_bytes) { + /* expect_bytes already set: first byte of UTF-8 char already seen */ + if ((*str & 0xC0) != 0x80) { + /* again first byte ?!?! */ + return 0; + } + } + else { + /* First byte of the UTF-8 character */ + /* count initial one bits and set expect_bytes to 1 less */ + char ch = *str; + while (ch & 0x80) { + expect_bytes++; + ch = (ch & 0x7f) << 1; + } + } + /* OK, next byte of UTF-8 character */ + /* Decrement number of expected bytes */ + if (--expect_bytes == 0) + utf_found = 1; + } + str++; + } + + return (utf_found && expect_bytes == 0); +} diff --git a/src/mir_core/src/utils.cpp b/src/mir_core/src/utils.cpp index ccd89aabcc..26f6c2970b 100644 --- a/src/mir_core/src/utils.cpp +++ b/src/mir_core/src/utils.cpp @@ -1,561 +1,565 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src) -{ - if (dest != nullptr) - mir_free(dest); - - return dest = (src != nullptr) ? mir_strdup(src) : nullptr; -} - -MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src) -{ - if (dest != nullptr) - mir_free(dest); - - return dest = (src != nullptr) ? mir_wstrdup(src) : nullptr; -} - -MIR_CORE_DLL(char*) rtrim(char *str) -{ - if (str == nullptr) - return nullptr; - - char* p = strchr(str, 0); - while (--p >= str) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - *p = 0; break; - default: - return str; - } - } - return str; -} - -MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str) -{ - if (str == nullptr) - return nullptr; - - wchar_t *p = wcschr(str, 0); - while (--p >= str) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - *p = 0; break; - default: - return str; - } - } - return str; -} - -MIR_CORE_DLL(char*) ltrim(char *str) -{ - if (str == nullptr) - return nullptr; - - char* p = str; - for (;;) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - ++p; break; - default: - memmove(str, p, strlen(p) + 1); - return str; - } - } -} - -MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str) -{ - if (str == nullptr) - return nullptr; - - wchar_t *p = str; - for (;;) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - ++p; break; - default: - memmove(str, p, sizeof(wchar_t)*(wcslen(p) + 1)); - return str; - } - } -} - -MIR_CORE_DLL(char*) ltrimp(char *str) -{ - if (str == nullptr) - return nullptr; - - char *p = str; - for (;;) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - ++p; break; - default: - return p; - } - } -} - -MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str) -{ - if (str == nullptr) - return nullptr; - - wchar_t *p = str; - for (;;) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - ++p; break; - default: - return p; - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(char*) strdel(char *str, size_t len) -{ - char* p; - for (p = str + len; *p != 0; p++) - *(p - len) = *p; - - *(p - len) = '\0'; - return str; -} - -MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len) -{ - wchar_t* p; - for (p = str + len; *p != 0; p++) - *(p - len) = *p; - - *(p - len) = '\0'; - return str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask) -{ - if (name == nullptr || mask == nullptr) - return false; - - const char *last = nullptr; - for (;; mask++, name++) { - if (*mask != '?' && *mask != *name) break; - if (*name == '\0') return ((BOOL)!*mask); - } - if (*mask != '*') return FALSE; - for (;; mask++, name++) { - while (*mask == '*') { - last = mask++; - if (*mask == '\0') return ((BOOL)!*mask); /* true */ - } - if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ - if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last; - } -} - -MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask) -{ - if (name == nullptr || mask == nullptr) - return false; - - const wchar_t* last = nullptr; - for (;; mask++, name++) { - if (*mask != '?' && *mask != *name) break; - if (*name == '\0') return ((BOOL)!*mask); - } - if (*mask != '*') return FALSE; - for (;; mask++, name++) { - while (*mask == '*') { - last = mask++; - if (*mask == '\0') return ((BOOL)!*mask); /* true */ - } - if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ - if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last; - } -} - -#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-'a'+'A'):(_c)) - -MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask) -{ - if (name == nullptr || mask == nullptr) - return false; - - const char *last = nullptr; - for (;; mask++, name++) { - if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break; - if (*name == '\0') return ((BOOL)!*mask); - } - if (*mask != '*') return FALSE; - for (;; mask++, name++) { - while (*mask == '*') { - last = mask++; - if (*mask == '\0') return ((BOOL)!*mask); /* true */ - } - if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ - if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last; - } -} - -MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask) -{ - if (name == nullptr || mask == nullptr) - return false; - - const wchar_t* last = nullptr; - for (;; mask++, name++) { - if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break; - if (*name == '\0') return ((BOOL)!*mask); - } - if (*mask != '*') return FALSE; - for (;; mask++, name++) { - while (*mask == '*') { - last = mask++; - if (*mask == '\0') return ((BOOL)!*mask); /* true */ - } - if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ - if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static char szHexTable[] = "0123456789abcdef"; - -MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest) -{ - const BYTE *p = (const BYTE*)pData; - char *d = dest; - - for (size_t i = 0; i < len; i++, p++) { - *d++ = szHexTable[*p >> 4]; - *d++ = szHexTable[*p & 0x0F]; - } - *d = 0; - - return dest; -} - -MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest) -{ - const BYTE *p = (const BYTE*)pData; - wchar_t *d = dest; - - for (size_t i = 0; i < len; i++, p++) { - *d++ = szHexTable[*p >> 4]; - *d++ = szHexTable[*p & 0x0F]; - } - *d = 0; - - return dest; -} - -static int hex2dec(int iHex) -{ - if (iHex >= '0' && iHex <= '9') - return iHex - '0'; - if (iHex >= 'a' && iHex <= 'f') - return iHex - 'a' + 10; - if (iHex >= 'A' && iHex <= 'F') - return iHex - 'A' + 10; - return 0; -} - -MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len) -{ - if (pSrc == nullptr || pData == nullptr || len == 0) - return false; - - size_t bufLen = strlen(pSrc)/2; - if (pSrc[bufLen*2] != 0 || bufLen > len) - return false; - - BYTE *pDest = (BYTE*)pData; - const char *p = (const char *)pSrc; - for (size_t i = 0; i < bufLen; i++, p += 2) - pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]); - - if (bufLen < len) - memset(pDest + bufLen, 0, len - bufLen); - return true; -} - -MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len) -{ - if (pSrc == nullptr || pData == nullptr || len == 0) - return false; - - size_t bufLen = wcslen(pSrc)/2; - if (pSrc[bufLen * 2] != 0 || bufLen > len) - return false; - - BYTE *pDest = (BYTE*)pData; - const wchar_t *p = (const wchar_t *)pSrc; - for (size_t i = 0; i < bufLen; i++, p += 2) - pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]); - - if (bufLen < len) - memset(pDest+bufLen, 0, len - bufLen); - return true; -} - - -///////////////////////////////////////////////////////////////////////////////////////// - -#pragma intrinsic(strlen, strcpy, strcat, strcmp, wcslen, wcscpy, wcscat, wcscmp) - -MIR_CORE_DLL(size_t) mir_strlen(const char *p) -{ - return (p) ? strlen(p) : 0; -} - -MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p) -{ - return (p) ? wcslen(p) : 0; -} - -MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) { - *dest = 0; - return dest; - } - - return strcpy(dest, src); -} - -MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) { - *dest = 0; - return dest; - } - - return wcscpy(dest, src); -} - -MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) - *dest = 0; - else - strncpy_s(dest, len, src, _TRUNCATE); - return dest; -} - -MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) - *dest = 0; - else - wcsncpy_s(dest, len, src, _TRUNCATE); - return dest; -} - -MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) { - *dest = 0; - return dest; - } - - return strcat(dest, src); -} - -MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) { - *dest = 0; - return dest; - } - - return wcscat(dest, src); -} - -MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) - *dest = 0; - else - strncat_s(dest, len, src, _TRUNCATE); - return dest; -} - -MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len) -{ - if (dest == nullptr) - return nullptr; - - if (src == nullptr) - *dest = 0; - else - wcsncat_s(dest, len, src, _TRUNCATE); - return dest; -} - -MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return strcmp(p1, p2); -} - -MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return wcscmp(p1, p2); -} - -MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return stricmp(p1, p2); -} - -MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return wcsicmp(p1, p2); -} - -MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return strncmp(p1, p2, n); -} - -MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return wcsncmp(p1, p2, n); -} - -MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return strnicmp(p1, p2, n); -} - -MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n) -{ - if (p1 == nullptr) - return (p2 == nullptr) ? 0 : -1; - if (p2 == nullptr) - return 1; - return wcsnicmp(p1, p2, n); -} - -MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2) -{ - for (int i = 0; s1[i]; i++) - for (int j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++) - if (!s2[k + 1]) - return s1 + i; - - return nullptr; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -PGENRANDOM pfnRtlGenRandom; - -MIR_CORE_DLL(void) Utils_GetRandom(void *pszDest, size_t cbLen) -{ - if (pszDest == nullptr || cbLen == 0) - return; - - if (pfnRtlGenRandom != nullptr) - pfnRtlGenRandom(pszDest, (ULONG)cbLen); - else { - srand(time(0)); - BYTE *p = (BYTE*)pszDest; - for (size_t i = 0; i < cbLen; i++) - p[i] = rand() & 0xFF; - } -} - -MIR_CORE_DLL(bool) Utils_IsRtl(const wchar_t *pszwText) -{ - size_t iLen = mir_wstrlen(pszwText); - mir_ptr infoTypeC2((WORD*)mir_calloc(sizeof(WORD) * (iLen + 2))); - GetStringTypeW(CT_CTYPE2, pszwText, (int)iLen, infoTypeC2); - - for (size_t i = 0; i < iLen; i++) - if (infoTypeC2[i] == C2_RIGHTTOLEFT) - return true; - - return false; -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src) +{ + if (dest != nullptr) + mir_free(dest); + + return dest = (src != nullptr) ? mir_strdup(src) : nullptr; +} + +MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src) +{ + if (dest != nullptr) + mir_free(dest); + + return dest = (src != nullptr) ? mir_wstrdup(src) : nullptr; +} + +MIR_CORE_DLL(char*) rtrim(char *str) +{ + if (str == nullptr) + return nullptr; + + char* p = strchr(str, 0); + while (--p >= str) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + *p = 0; break; + default: + return str; + } + } + return str; +} + +MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str) +{ + if (str == nullptr) + return nullptr; + + wchar_t *p = wcschr(str, 0); + while (--p >= str) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + *p = 0; break; + default: + return str; + } + } + return str; +} + +MIR_CORE_DLL(char*) ltrim(char *str) +{ + if (str == nullptr) + return nullptr; + + char* p = str; + for (;;) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + ++p; break; + default: + memmove(str, p, strlen(p) + 1); + return str; + } + } +} + +MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str) +{ + if (str == nullptr) + return nullptr; + + wchar_t *p = str; + for (;;) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + ++p; break; + default: + memmove(str, p, sizeof(wchar_t)*(wcslen(p) + 1)); + return str; + } + } +} + +MIR_CORE_DLL(char*) ltrimp(char *str) +{ + if (str == nullptr) + return nullptr; + + char *p = str; + for (;;) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + ++p; break; + default: + return p; + } + } +} + +MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str) +{ + if (str == nullptr) + return nullptr; + + wchar_t *p = str; + for (;;) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + ++p; break; + default: + return p; + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(char*) strdel(char *str, size_t len) +{ + char* p; + for (p = str + len; *p != 0; p++) + *(p - len) = *p; + + *(p - len) = '\0'; + return str; +} + +MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len) +{ + wchar_t* p; + for (p = str + len; *p != 0; p++) + *(p - len) = *p; + + *(p - len) = '\0'; + return str; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask) +{ + if (name == nullptr || mask == nullptr) + return false; + + const char *last = nullptr; + for (;; mask++, name++) { + if (*mask != '?' && *mask != *name) break; + if (*name == '\0') return ((BOOL)!*mask); + } + if (*mask != '*') return FALSE; + for (;; mask++, name++) { + while (*mask == '*') { + last = mask++; + if (*mask == '\0') return ((BOOL)!*mask); /* true */ + } + if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ + if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last; + } +} + +MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask) +{ + if (name == nullptr || mask == nullptr) + return false; + + const wchar_t* last = nullptr; + for (;; mask++, name++) { + if (*mask != '?' && *mask != *name) break; + if (*name == '\0') return ((BOOL)!*mask); + } + if (*mask != '*') return FALSE; + for (;; mask++, name++) { + while (*mask == '*') { + last = mask++; + if (*mask == '\0') return ((BOOL)!*mask); /* true */ + } + if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ + if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last; + } +} + +#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-'a'+'A'):(_c)) + +MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask) +{ + if (name == nullptr || mask == nullptr) + return false; + + const char *last = nullptr; + for (;; mask++, name++) { + if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break; + if (*name == '\0') return ((BOOL)!*mask); + } + if (*mask != '*') return FALSE; + for (;; mask++, name++) { + while (*mask == '*') { + last = mask++; + if (*mask == '\0') return ((BOOL)!*mask); /* true */ + } + if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ + if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last; + } +} + +MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask) +{ + if (name == nullptr || mask == nullptr) + return false; + + const wchar_t* last = nullptr; + for (;; mask++, name++) { + if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break; + if (*name == '\0') return ((BOOL)!*mask); + } + if (*mask != '*') return FALSE; + for (;; mask++, name++) { + while (*mask == '*') { + last = mask++; + if (*mask == '\0') return ((BOOL)!*mask); /* true */ + } + if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ + if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static char szHexTable[] = "0123456789abcdef"; + +MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest) +{ + const BYTE *p = (const BYTE*)pData; + char *d = dest; + + for (size_t i = 0; i < len; i++, p++) { + *d++ = szHexTable[*p >> 4]; + *d++ = szHexTable[*p & 0x0F]; + } + *d = 0; + + return dest; +} + +MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest) +{ + const BYTE *p = (const BYTE*)pData; + wchar_t *d = dest; + + for (size_t i = 0; i < len; i++, p++) { + *d++ = szHexTable[*p >> 4]; + *d++ = szHexTable[*p & 0x0F]; + } + *d = 0; + + return dest; +} + +static int hex2dec(int iHex) +{ + if (iHex >= '0' && iHex <= '9') + return iHex - '0'; + if (iHex >= 'a' && iHex <= 'f') + return iHex - 'a' + 10; + if (iHex >= 'A' && iHex <= 'F') + return iHex - 'A' + 10; + return 0; +} + +MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len) +{ + if (pSrc == nullptr || pData == nullptr || len == 0) + return false; + + size_t bufLen = strlen(pSrc)/2; + if (pSrc[bufLen*2] != 0 || bufLen > len) + return false; + + BYTE *pDest = (BYTE*)pData; + const char *p = (const char *)pSrc; + for (size_t i = 0; i < bufLen; i++, p += 2) + pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]); + + if (bufLen < len) + memset(pDest + bufLen, 0, len - bufLen); + return true; +} + +MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len) +{ + if (pSrc == nullptr || pData == nullptr || len == 0) + return false; + + size_t bufLen = wcslen(pSrc)/2; + if (pSrc[bufLen * 2] != 0 || bufLen > len) + return false; + + BYTE *pDest = (BYTE*)pData; + const wchar_t *p = (const wchar_t *)pSrc; + for (size_t i = 0; i < bufLen; i++, p += 2) + pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]); + + if (bufLen < len) + memset(pDest+bufLen, 0, len - bufLen); + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////////// + +#pragma intrinsic(strlen, strcpy, strcat, strcmp, wcslen, wcscpy, wcscat, wcscmp) + +MIR_CORE_DLL(size_t) mir_strlen(const char *p) +{ + return (p) ? strlen(p) : 0; +} + +MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p) +{ + return (p) ? wcslen(p) : 0; +} + +MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) { + *dest = 0; + return dest; + } + + return strcpy(dest, src); +} + +MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) { + *dest = 0; + return dest; + } + + return wcscpy(dest, src); +} + +MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) + *dest = 0; + else + strncpy_s(dest, len, src, _TRUNCATE); + return dest; +} + +MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) + *dest = 0; + else + wcsncpy_s(dest, len, src, _TRUNCATE); + return dest; +} + +MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) { + *dest = 0; + return dest; + } + + return strcat(dest, src); +} + +MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) { + *dest = 0; + return dest; + } + + return wcscat(dest, src); +} + +MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) + *dest = 0; + else + strncat_s(dest, len, src, _TRUNCATE); + return dest; +} + +MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len) +{ + if (dest == nullptr) + return nullptr; + + if (src == nullptr) + *dest = 0; + else + wcsncat_s(dest, len, src, _TRUNCATE); + return dest; +} + +MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return strcmp(p1, p2); +} + +MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return wcscmp(p1, p2); +} + +MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return stricmp(p1, p2); +} + +MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return wcsicmp(p1, p2); +} + +MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return strncmp(p1, p2, n); +} + +MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return wcsncmp(p1, p2, n); +} + +MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return strnicmp(p1, p2, n); +} + +MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n) +{ + if (p1 == nullptr) + return (p2 == nullptr) ? 0 : -1; + if (p2 == nullptr) + return 1; + return wcsnicmp(p1, p2, n); +} + +#ifdef _MSC_VER +MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2) +{ + for (int i = 0; s1[i]; i++) + for (int j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++) + if (!s2[k + 1]) + return s1 + i; + + return nullptr; +} +#endif + +///////////////////////////////////////////////////////////////////////////////////////// + +PGENRANDOM pfnRtlGenRandom; + +MIR_CORE_DLL(void) Utils_GetRandom(void *pszDest, size_t cbLen) +{ + if (pszDest == nullptr || cbLen == 0) + return; + + if (pfnRtlGenRandom != nullptr) + pfnRtlGenRandom(pszDest, (uint32_t)cbLen); + else { + srand(time(0)); + BYTE *p = (BYTE*)pszDest; + for (size_t i = 0; i < cbLen; i++) + p[i] = rand() & 0xFF; + } +} + +MIR_CORE_DLL(bool) Utils_IsRtl(const wchar_t *pszwText) +{ + #ifdef _MSC_VER + size_t iLen = mir_wstrlen(pszwText); + mir_ptr infoTypeC2((WORD*)mir_calloc(sizeof(WORD) * (iLen + 2))); + GetStringTypeW(CT_CTYPE2, pszwText, (int)iLen, infoTypeC2); + + for (size_t i = 0; i < iLen; i++) + if (infoTypeC2[i] == C2_RIGHTTOLEFT) + return true; + #endif + + return false; +} -- cgit v1.2.3