// ---------------------------------------------------------------------------80 // ICQ plugin for Miranda Instant Messenger // ________________________________________ // // Copyright © 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede // Copyright © 2001-2002 Jon Keating, Richard Hughes // Copyright © 2002-2004 Martin Öberg, Sam Kothari, Robert Rainwater // Copyright © 2004-2010 Joe Kucera // // 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // ----------------------------------------------------------------------------- // DESCRIPTION: // // Internal Database API // // ----------------------------------------------------------------------------- #include "icqoscar.h" void CIcqProto::CreateResidentSetting(const char *szSetting) { char pszSetting[2*MAX_PATH]; strcpy(pszSetting, m_szModuleName); strcat(pszSetting, "/"); strcat(pszSetting, szSetting); CallService(MS_DB_SETSETTINGRESIDENT, 1, (WPARAM)pszSetting); } int CIcqProto::getSetting(HANDLE hContact, const char *szSetting, DBVARIANT *dbv) { return DBGetContactSettingW(hContact, m_szModuleName, szSetting, dbv); } BYTE CIcqProto::getSettingByte(HANDLE hContact, const char *szSetting, BYTE byDef) { return DBGetContactSettingByte(hContact, m_szModuleName, szSetting, byDef); } WORD CIcqProto::getSettingWord(HANDLE hContact, const char *szSetting, WORD wDef) { return DBGetContactSettingWord(hContact, m_szModuleName, szSetting, wDef); } DWORD CIcqProto::getSettingDword(HANDLE hContact, const char *szSetting, DWORD dwDef) { DBVARIANT dbv = {DBVT_DELETED}; DWORD dwRes; if (getSetting(hContact, szSetting, &dbv)) return dwDef; // not found, give default if (dbv.type != DBVT_DWORD) dwRes = dwDef; // invalid type, give default else // found and valid, give result dwRes = dbv.dVal; ICQFreeVariant(&dbv); return dwRes; } double CIcqProto::getSettingDouble(HANDLE hContact, const char *szSetting, double dDef) { DBVARIANT dbv = {DBVT_DELETED}; double dRes; if (getSetting(hContact, szSetting, &dbv)) return dDef; // not found, give default if (dbv.type != DBVT_BLOB || dbv.cpbVal != sizeof(double)) dRes = dDef; else dRes = *(double*)dbv.pbVal; ICQFreeVariant(&dbv); return dRes; } DWORD CIcqProto::getContactUin(HANDLE hContact) { return getSettingDword(hContact, UNIQUEIDSETTING, 0); } int CIcqProto::getContactUid(HANDLE hContact, DWORD *pdwUin, uid_str *ppszUid) { DBVARIANT dbv = {DBVT_DELETED}; int iRes = 1; *pdwUin = 0; if (ppszUid) *ppszUid[0] = '\0'; if (!getSetting(hContact, UNIQUEIDSETTING, &dbv)) { if (dbv.type == DBVT_DWORD) { *pdwUin = dbv.dVal; iRes = 0; } else if (dbv.type == DBVT_ASCIIZ) { if (ppszUid && m_bAimEnabled) { strcpy(*ppszUid, dbv.pszVal); iRes = 0; } else NetLog_Server("AOL screennames not accepted"); } ICQFreeVariant(&dbv); } return iRes; } int CIcqProto::getSettingString(HANDLE hContact, const char *szSetting, DBVARIANT *dbv) { int res = DBGetContactSettingString(hContact, m_szModuleName, szSetting, dbv); if (res) ICQFreeVariant(dbv); return res; } int CIcqProto::getSettingStringW(HANDLE hContact, const char *szSetting, DBVARIANT *dbv) { int res = DBGetContactSettingWString(hContact, m_szModuleName, szSetting, dbv); if (res) ICQFreeVariant(dbv); return res; } char* CIcqProto::getSettingStringUtf(HANDLE hContact, const char *szModule, const char *szSetting, char *szDef) { DBVARIANT dbv = {DBVT_DELETED}; if (DBGetContactSettingUTF8String(hContact, szModule, szSetting, &dbv)) { ICQFreeVariant(&dbv); // for a setting with invalid contents/type return null_strdup(szDef); } char *szRes = null_strdup(dbv.pszVal); ICQFreeVariant(&dbv); return szRes; } char* CIcqProto::getSettingStringUtf(HANDLE hContact, const char *szSetting, char *szDef) { return getSettingStringUtf(hContact, m_szModuleName, szSetting, szDef); } WORD CIcqProto::getContactStatus(HANDLE hContact) { return getSettingWord(hContact, "Status", ID_STATUS_OFFLINE); } int CIcqProto::getSettingStringStatic(HANDLE hContact, const char *szSetting, char *dest, int dest_len) { DBVARIANT dbv = {DBVT_DELETED}; DBCONTACTGETSETTING sVal = {0}; dbv.pszVal = dest; dbv.cchVal = dest_len; dbv.type = DBVT_ASCIIZ; sVal.pValue = &dbv; sVal.szModule = m_szModuleName; sVal.szSetting = szSetting; if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0) { // due to MS_DB_CONTACT_GETSETTINGSTATIC setting type check, we need to request UTF8 as well dbv.pszVal = dest; dbv.cchVal = dest_len; dbv.type = DBVT_UTF8; if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0) return 1; // nothing found } return (dbv.type != DBVT_ASCIIZ); } int CIcqProto::deleteSetting(HANDLE hContact, const char *szSetting) { return DBDeleteContactSetting(hContact, m_szModuleName, szSetting); } int CIcqProto::setSettingByte(HANDLE hContact, const char *szSetting, BYTE byValue) { return DBWriteContactSettingByte(hContact, m_szModuleName, szSetting, byValue); } int CIcqProto::setSettingWord(HANDLE hContact, const char *szSetting, WORD wValue) { return DBWriteContactSettingWord(hContact, m_szModuleName, szSetting, wValue); } int CIcqProto::setSettingDword(HANDLE hContact, const char *szSetting, DWORD dwValue) { return DBWriteContactSettingDword(hContact, m_szModuleName, szSetting, dwValue); } int CIcqProto::setSettingDouble(HANDLE hContact, const char *szSetting, double dValue) { return setSettingBlob(hContact, szSetting, (BYTE*)&dValue, sizeof(double)); } int CIcqProto::setSettingString(HANDLE hContact, const char *szSetting, const char *szValue) { return DBWriteContactSettingString(hContact, m_szModuleName, szSetting, szValue); } int CIcqProto::setSettingStringW(HANDLE hContact, const char *szSetting, const WCHAR *wszValue) { return DBWriteContactSettingWString(hContact, m_szModuleName, szSetting, wszValue); } int CIcqProto::setSettingStringUtf(HANDLE hContact, const char *szModule, const char *szSetting, const char *szValue) { return DBWriteContactSettingUTF8String(hContact, szModule, szSetting, (char*)szValue); } int CIcqProto::setSettingStringUtf(HANDLE hContact, const char *szSetting, const char *szValue) { return setSettingStringUtf(hContact, m_szModuleName, szSetting, szValue); } int CIcqProto::setSettingBlob(HANDLE hContact, const char *szSetting, const BYTE *pValue, const int cbValue) { return DBWriteContactSettingBlob(hContact, m_szModuleName, szSetting, (void*)pValue, cbValue); } int CIcqProto::setContactHidden(HANDLE hContact, BYTE bHidden) { int nResult = DBWriteContactSettingByte(hContact, "CList", "Hidden", bHidden); if (!bHidden) // clear zero setting DBDeleteContactSetting(hContact, "CList", "Hidden"); return nResult; } void CIcqProto::setStatusMsgVar(HANDLE hContact, char* szStatusMsg, bool isAnsi) { if (szStatusMsg && szStatusMsg[0]) { if (isAnsi) { char* szStatusNote = getSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, ""); wchar_t* szStatusNoteW = make_unicode_string(szStatusNote); int len = (int)wcslen(szStatusNoteW) * 3 + 1; char* szStatusNoteAnsi = (char*)alloca(len); WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, szStatusNoteW, -1, szStatusNoteAnsi, len, NULL, NULL); bool notmatch = false; for (int i=0; ;++i) { if (szStatusNoteAnsi[i] != szStatusMsg[i] && szStatusNoteAnsi[i] != '?' && szStatusMsg[i] != '?') { notmatch = true; break; } if (!szStatusNoteAnsi[i] || !szStatusMsg[i]) break; } szStatusMsg = notmatch ? ansi_to_utf8(szStatusMsg) : szStatusNote; SAFE_FREE(&szStatusNoteW); if (notmatch) SAFE_FREE(&szStatusNote); } char* oldStatusMsg = NULL; DBVARIANT dbv; if (!DBGetContactSetting(hContact, "CList", "StatusMsg", &dbv)) { switch (dbv.type) { case DBVT_UTF8: oldStatusMsg = null_strdup(dbv.pszVal); break; case DBVT_WCHAR: oldStatusMsg = make_utf8_string(dbv.pwszVal); break; } ICQFreeVariant(&dbv); } if (!oldStatusMsg || strcmp(oldStatusMsg, szStatusMsg)) setSettingStringUtf(hContact, "CList", "StatusMsg", szStatusMsg); SAFE_FREE(&oldStatusMsg); if (isAnsi) SAFE_FREE(&szStatusMsg); } else DBDeleteContactSetting(hContact, "CList", "StatusMsg"); } int __fastcall ICQFreeVariant(DBVARIANT *dbv) { return DBFreeVariant(dbv); } int CIcqProto::IsICQContact(HANDLE hContact) { char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); return !strcmpnull(szProto, m_szModuleName); } HANDLE CIcqProto::AddEvent(HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob) { DBEVENTINFO dbei = {0}; dbei.cbSize = sizeof(dbei); dbei.szModule = m_szModuleName; dbei.timestamp = dwTime; dbei.flags = flags; dbei.eventType = wType; dbei.cbBlob = cbBlob; dbei.pBlob = pBlob; return (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); } HANDLE CIcqProto::FindFirstContact() { HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, (LPARAM)m_szModuleName); if (IsICQContact(hContact)) return hContact; return FindNextContact(hContact); } HANDLE CIcqProto::FindNextContact(HANDLE hContact) { hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,(LPARAM)m_szModuleName); while (hContact != NULL) { if (IsICQContact(hContact)) { return hContact; } hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,(LPARAM)m_szModuleName); } return hContact; } char* CIcqProto::getContactCListGroup(HANDLE hContact) { return getSettingStringUtf(hContact, "CList", "Group", NULL); } int __stdcall ICQSetContactCListGroup(HANDLE hContact, const char *szGroup) { /// TODO return 0; }