/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2003 Miranda ICQ/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. */ // Miranda Memory-Mapped Secured DataBase // (C) Artem Shpynov aka FYR, Igonin Vitaliy aka chaos.persei, Victor Pavlychko aka nullbie, 2007 - 2008 #include "commonheaders.h" /* Public API */ int DBPreset_QuerySetting (const char *szModule, const char *szSetting, DBVARIANT *dbv, BOOL isStatic); int DBPreset_CompareSetting (const char *szModule, const char *szSetting, DBVARIANT *dbv); /* Preset cache item */ typedef struct { DWORD dwHash; char *szModule; char *szSetting; DBVARIANT dbv; } DBPresetItem; static DBPresetItem * DBPresetItem_Create (char *szModule, char *szSetting, BYTE bType); static void DBPresetItem_Destroy (DBPresetItem *item); static void DBPresetItem_Hash (DBPresetItem *item); static int DBPresetItem_Cmp (DBPresetItem *item1, DBPresetItem *item2); SortedList *lstPresets = NULL; int InitPreset() { char szIniPath[MAX_PATH]; char szLine[2048]; int lineLength; char szSection[128]; FILE *fp; GetModuleFileNameA(GetModuleHandle(NULL), szIniPath, SIZEOF(szIniPath)); strcpy(strrchr(szIniPath, '\\')+1, "dbpreset.ini"); fp = fopen(szIniPath,"rt"); // no preset if (!fp) return 0; lstPresets = List_Create(0, 50); lstPresets->sortFunc = (FSortFunc)DBPresetItem_Cmp; while(!feof(fp)) { if (fgets(szLine,sizeof(szLine),fp) == NULL) break; lineLength = lstrlenA(szLine); while(lineLength && (BYTE)(szLine[lineLength-1]) <= ' ') szLine[--lineLength] = '\0'; if (szLine[0] == ';' || szLine[0] <= ' ') continue; if (szLine[0] == '[') { char *szEnd = strchr(szLine+1,']'); if (szEnd == NULL) continue; if (szLine[1] == '!') szSection[0] = '\0'; else lstrcpynA(szSection, szLine+1, (int)min(sizeof(szSection), szEnd-szLine)); } else { char *szValue; char szName[128]; DBPresetItem *item; if (szSection[0] == '\0') continue; szValue = strchr(szLine,' = '); if (szValue == NULL) continue; lstrcpynA(szName, szLine, (int)min(sizeof(szName), szValue-szLine+1)); szValue++; switch(szValue[0]) { case 'b': case 'B': item = DBPresetItem_Create(szSection, szName, DBVT_BYTE); item->dbv.bVal = (BYTE)strtol(szValue+1,NULL,0); List_InsertPtr(lstPresets, item); break; case 'w': case 'W': item = DBPresetItem_Create(szSection, szName, DBVT_WORD); item->dbv.wVal = (WORD)strtol(szValue+1,NULL,0); List_InsertPtr(lstPresets, item); break; case 'd': case 'D': item = DBPresetItem_Create(szSection, szName, DBVT_DWORD); item->dbv.dVal = (DWORD)strtoul(szValue+1,NULL,0); List_InsertPtr(lstPresets, item); break; case 's': case 'S': item = DBPresetItem_Create(szSection, szName, DBVT_ASCIIZ); item->dbv.pszVal = mir_strdup(szValue+1); List_InsertPtr(lstPresets, item); break; case 'u': case 'U': item = DBPresetItem_Create(szSection, szName, DBVT_UTF8); item->dbv.pszVal = mir_strdup(szValue+1); List_InsertPtr(lstPresets, item); break; case 'n': case 'N': { PBYTE buf; int len; char *pszValue,*pszEnd; buf = (PBYTE)mir_alloc(lstrlenA(szValue+1)); for (len = 0,pszValue = szValue+1;;len++) { buf[len] = (BYTE)strtol(pszValue,&pszEnd,0x10); if (pszValue == pszEnd) break; pszValue = pszEnd; } item = DBPresetItem_Create(szSection, szName, DBVT_BLOB); item->dbv.pbVal = buf; item->dbv.cpbVal = len; List_InsertPtr(lstPresets, item); break; } } } } fclose(fp); return 0; } void UninitPreset() { int i; if (!lstPresets) return; for (i = 0; i < lstPresets->realCount; ++i) DBPresetItem_Destroy((DBPresetItem *)lstPresets->items[i]); List_Destroy(lstPresets); } int DBPreset_QuerySetting(const char *szModule, const char *szSetting, DBVARIANT *dbv, BOOL isStatic) { DBPresetItem *item; DBPresetItem search = {0}; if (!lstPresets) return FALSE; search.szModule = (char *)szModule; search.szSetting = (char *)szSetting; DBPresetItem_Hash(&search); item = (DBPresetItem *)List_Find(lstPresets, &search); if (!item) return FALSE; dbv->type = item->dbv.type; switch (item->dbv.type) { case DBVT_BYTE: dbv->bVal = item->dbv.bVal; return TRUE; case DBVT_WORD: dbv->wVal = item->dbv.wVal; return TRUE; case DBVT_DWORD: dbv->dVal = item->dbv.dVal; return TRUE; case DBVT_UTF8: case DBVT_ASCIIZ: if (isStatic && dbv->pszVal) lstrcpynA(dbv->pszVal, item->dbv.pszVal, dbv->cchVal); else if (!isStatic) dbv->pszVal = mir_strdup(item->dbv.pszVal); return TRUE; default: return FALSE; } return FALSE; } int DBPreset_CompareSetting(const char *szModule, const char *szSetting, DBVARIANT *dbv) { DBPresetItem *item; DBPresetItem search = {0}; if (!lstPresets) return FALSE; search.szModule = (char *)szModule; search.szSetting = (char *)szSetting; DBPresetItem_Hash(&search); item = (DBPresetItem *)List_Find(lstPresets, &search); if (!item) return FALSE; if (item->dbv.type != item->dbv.type) return FALSE; switch (item->dbv.type) { case DBVT_BYTE: return dbv->bVal == item->dbv.bVal ? TRUE : FALSE; case DBVT_WORD: return dbv->wVal == item->dbv.wVal ? TRUE : FALSE; case DBVT_DWORD: return dbv->dVal == item->dbv.dVal ? TRUE : FALSE; case DBVT_UTF8: case DBVT_ASCIIZ: return strcmp(dbv->pszVal, item->dbv.pszVal) ? FALSE : TRUE; } return FALSE; } static DBPresetItem *DBPresetItem_Create(char *szModule, char *szSetting, BYTE bType) { DBPresetItem *item = (DBPresetItem *)mir_alloc(sizeof(DBPresetItem)); item->szModule = mir_strdup(szModule); item->szSetting = mir_strdup(szSetting); DBPresetItem_Hash(item); item->dbv.type = bType; return item; } static void DBPresetItem_Destroy(DBPresetItem *item) { if (!item) return; if (item->szModule) { mir_free(item->szModule); item->szModule = NULL; } if (item->szSetting) { mir_free(item->szSetting); item->szSetting = NULL; } switch (item->dbv.type) { case DBVT_ASCIIZ: case DBVT_UTF8: case DBVT_WCHAR: { if (item->dbv.pszVal) mir_free(item->dbv.pszVal); item->dbv.pszVal = 0; break; } case DBVT_BLOB: { if (item->dbv.pbVal) mir_free(item->dbv.pbVal); item->dbv.pbVal = 0; break; } } item->dbv.type = 0; } static void DBPresetItem_Hash(DBPresetItem *item) { int i; int shift = 0; item->dwHash = 0; for (i = 0;item->szModule[i];i++) { item->dwHash ^= item->szModule[i]<24) item->dwHash ^= (item->szModule[i]>>(32-shift))&0x7F; shift = (shift+5)&0x1F; } for (i = 0;item->szSetting[i];i++) { item->dwHash ^= item->szSetting[i]<24) item->dwHash ^= (item->szSetting[i]>>(32-shift))&0x7F; shift = (shift+5)&0x1F; } } static int DBPresetItem_Cmp(DBPresetItem *item1, DBPresetItem *item2) { int cmp; if (item1->dwHash < item2->dwHash) return -1; if (item1->dwHash > item2->dwHash) return 1; if (cmp = strcmp(item1->szModule, item2->szModule)) return cmp; return strcmp(item1->szSetting, item2->szSetting); }