static TCHAR *parseGetDefault(ARGUMENTSINFO *ai) { if (ai->argc != 2) return NULL; MCONTACT hContact = NULL; CONTACTSINFO ci = { 0 }; ci.cbSize = sizeof(ci); ci.tszContact = ai->targv[1]; ci.flags = 0xFFFFFFFF ^ (CI_TCHAR == 0 ? CI_UNICODE : 0); int count = getContactFromString(&ci); if (count == 1 && ci.hContacts != NULL) { hContact = ci.hContacts[0]; mir_free(ci.hContacts); } else { mir_free(ci.hContacts); return NULL; } hContact = db_mc_getDefault(hContact); if (hContact == NULL) return NULL; TCHAR* szUniqueID = NULL; char* szProto = GetContactProto(hContact); if (szProto != NULL) szUniqueID = getContactInfoT(CNF_UNIQUEID, hContact); if (szUniqueID == NULL) { szProto = PROTOID_HANDLE; szUniqueID = (TCHAR *)mir_alloc(32); mir_sntprintf(szUniqueID, 32, _T("%p"), hContact); if (szProto == NULL || szUniqueID == NULL) return NULL; } size_t size = strlen(szProto) + _tcslen(szUniqueID) + 4; TCHAR *res = (TCHAR *)mir_alloc(size * sizeof(TCHAR)); if (res == NULL) { mir_free(szUniqueID); return NULL; } TCHAR *tszProto = mir_a2t(szProto); if (tszProto != NULL && szUniqueID != NULL) { mir_sntprintf(res, size, _T("<%s:%s>"), tszProto, szUniqueID); mir_free(szUniqueID); mir_free(tszProto); } return res; }
static TCHAR *parseGetDefault(ARGUMENTSINFO *ai) { if (ai->argc != 2) return NULL; MCONTACT hContact = NULL; CONTACTSINFO ci = { 0 }; ci.cbSize = sizeof(ci); ci.tszContact = ai->targv[1]; ci.flags = 0xFFFFFFFF ^ (CI_TCHAR == 0 ? CI_UNICODE : 0); int count = getContactFromString(&ci); if (count == 1 && ci.hContacts != NULL) { hContact = ci.hContacts[0]; mir_free(ci.hContacts); } else { mir_free(ci.hContacts); return NULL; } hContact = db_mc_getDefault(hContact); if (hContact == NULL) return NULL; ptrT szUniqueID; char* szProto = GetContactProto(hContact); if (szProto != NULL) szUniqueID = getContactInfoT(CNF_UNIQUEID, hContact); if (szUniqueID == NULL) { szProto = PROTOID_HANDLE; TCHAR tszID[40]; mir_sntprintf(tszID, _countof(tszID), _T("%p"), hContact); szUniqueID = mir_tstrdup(tszID); } return CMString(FORMAT, _T("<%S:%s>"), szProto, szUniqueID).Detach(); }
int Meta_SettingChanged(WPARAM hContact, LPARAM lParam) { DBCONTACTWRITESETTING *dcws = (DBCONTACTWRITESETTING *)lParam; char buffer[512]; // the only global options we're interested in if (hContact == 0) return 0; DBCachedContact *cc = currDb->m_cache->GetCachedContact(hContact); if (cc == NULL || !cc->IsSub()) return 0; DBCachedContact *ccMeta = currDb->m_cache->GetCachedContact(cc->parentID); if (ccMeta == NULL || !ccMeta->IsMeta()) return 0; // This contact is attached to a MetaContact. int contact_number = Meta_GetContactNumber(ccMeta, hContact); if (contact_number == -1) return 0; // exit - db corruption if (!strcmp(dcws->szSetting, "IP")) { if (dcws->value.type == DBVT_DWORD) db_set_dw(ccMeta->contactID, META_PROTO, "IP", dcws->value.dVal); else db_unset(ccMeta->contactID, META_PROTO, "IP"); } else if (!strcmp(dcws->szSetting, "RealIP")) { if (dcws->value.type == DBVT_DWORD) db_set_dw(ccMeta->contactID, META_PROTO, "RealIP", dcws->value.dVal); else db_unset(ccMeta->contactID, META_PROTO, "RealIP"); } else if (!strcmp(dcws->szSetting, "ListeningTo")) { switch (dcws->value.type) { case DBVT_ASCIIZ: db_set_s(ccMeta->contactID, META_PROTO, "ListeningTo", dcws->value.pszVal); break; case DBVT_UTF8: db_set_utf(ccMeta->contactID, META_PROTO, "ListeningTo", dcws->value.pszVal); break; case DBVT_WCHAR: db_set_ws(ccMeta->contactID, META_PROTO, "ListeningTo", dcws->value.pwszVal); break; case DBVT_DELETED: db_unset(ccMeta->contactID, META_PROTO, "ListeningTo"); break; } } else if (!strcmp(dcws->szSetting, "Nick") && dcws->value.type != DBVT_DELETED) { // subcontact nick has changed - update metacontact mir_snprintf(buffer, SIZEOF(buffer), "Nick%d", contact_number); db_set(ccMeta->contactID, META_PROTO, buffer, &dcws->value); ptrT tszMyhandle(db_get_tsa(hContact, "CList", "MyHandle")); if (tszMyhandle == NULL) { mir_snprintf(buffer, SIZEOF(buffer), "CListName%d", contact_number); db_set(ccMeta->contactID, META_PROTO, buffer, &dcws->value); } // copy nick to metacontact, if it's the most online MCONTACT hMostOnline = Meta_GetMostOnline(ccMeta); Meta_CopyContactNick(ccMeta, hMostOnline); } else if (!strcmp(dcws->szSetting, "IdleTS")) { if (dcws->value.type == DBVT_DWORD) db_set_dw(ccMeta->contactID, META_PROTO, "IdleTS", dcws->value.dVal); else if (dcws->value.type == DBVT_DELETED) db_set_dw(ccMeta->contactID, META_PROTO, "IdleTS", 0); } else if (!strcmp(dcws->szSetting, "LogonTS")) { if (dcws->value.type == DBVT_DWORD) db_set_dw(ccMeta->contactID, META_PROTO, "LogonTS", dcws->value.dVal); else if (dcws->value.type == DBVT_DELETED) db_set_dw(ccMeta->contactID, META_PROTO, "LogonTS", 0); } else if (!strcmp(dcws->szModule, "CList") && !strcmp(dcws->szSetting, "MyHandle")) { if (dcws->value.type == DBVT_DELETED) { char *proto = GetContactProto(hContact); mir_snprintf(buffer, SIZEOF(buffer), "CListName%d", contact_number); DBVARIANT dbv; if (proto && !db_get_ts(hContact, proto, "Nick", &dbv)) { db_set_ts(ccMeta->contactID, META_PROTO, buffer, dbv.ptszVal); db_free(&dbv); } else db_unset(ccMeta->contactID, META_PROTO, buffer); } else { // subcontact clist displayname has changed - update metacontact mir_snprintf(buffer, SIZEOF(buffer), "CListName%d", contact_number); db_set(ccMeta->contactID, META_PROTO, buffer, &dcws->value); } // copy nick to metacontact, if it's the most online Meta_CopyContactNick(ccMeta, Meta_GetMostOnline(ccMeta)); } // subcontact changing status else if (!strcmp(dcws->szSetting, "Status") && dcws->value.type != DBVT_DELETED) { // update subcontact status setting mir_snprintf(buffer, SIZEOF(buffer), "Status%d", contact_number); db_set_w(ccMeta->contactID, META_PROTO, buffer, dcws->value.wVal); mir_snprintf(buffer, SIZEOF(buffer), "StatusString%d", contact_number); db_set_ts(ccMeta->contactID, META_PROTO, buffer, cli.pfnGetStatusModeDescription(dcws->value.wVal, 0)); // set status to that of most online contact MCONTACT hMostOnline = Meta_GetMostOnline(ccMeta); if (hMostOnline != db_mc_getDefault(ccMeta->contactID)) db_mc_notifyDefChange(ccMeta->contactID, hMostOnline); Meta_CopyContactNick(ccMeta, hMostOnline); Meta_FixStatus(ccMeta); // most online contact with avatar support might have changed - update avatar hMostOnline = Meta_GetMostOnlineSupporting(ccMeta, PFLAGNUM_4, PF4_AVATARS); if (hMostOnline) { PROTO_AVATAR_INFORMATIONT AI = { sizeof(AI) }; AI.hContact = ccMeta->contactID; AI.format = PA_FORMAT_UNKNOWN; _tcscpy(AI.filename, _T("X")); if (CallProtoService(META_PROTO, PS_GETAVATARINFOT, 0, (LPARAM)&AI) == GAIR_SUCCESS) db_set_ts(ccMeta->contactID, "ContactPhoto", "File", AI.filename); } } return 0; }
int CDb3Mmap::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) { if (szSetting == NULL || szModule == NULL) return 1; // the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name int settingNameLen = (int)mir_strlen(szSetting); int moduleNameLen = (int)mir_strlen(szModule); if (settingNameLen > 0xFE) { #ifdef _DEBUG OutputDebugStringA("GetContactSettingWorker() got a > 255 setting name length. \n"); #endif return 1; } if (moduleNameLen > 0xFE) { #ifdef _DEBUG OutputDebugStringA("GetContactSettingWorker() got a > 255 module name length. \n"); #endif return 1; } mir_cslock lck(m_csDbAccess); LBL_Seek: char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); log3("get [%08p] %s (%p)", hContact, szCachedSettingName, szCachedSettingName); DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0); if (pCachedValue != NULL) { if (pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8) { int cbOrigLen = dbv->cchVal; char *cbOrigPtr = dbv->pszVal; memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); if (isStatic) { int cbLen = 0; if (pCachedValue->pszVal != NULL) cbLen = (int)mir_strlen(pCachedValue->pszVal); cbOrigLen--; dbv->pszVal = cbOrigPtr; if (cbLen < cbOrigLen) cbOrigLen = cbLen; memcpy(dbv->pszVal, pCachedValue->pszVal, cbOrigLen); dbv->pszVal[cbOrigLen] = 0; dbv->cchVal = cbLen; } else { dbv->pszVal = (char*)mir_alloc(mir_strlen(pCachedValue->pszVal) + 1); mir_strcpy(dbv->pszVal, pCachedValue->pszVal); } } else memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); log2("get cached %s (%p)", printVariant(dbv), pCachedValue); return (pCachedValue->type == DBVT_DELETED) ? 1 : 0; } // never look db for the resident variable if (szCachedSettingName[-1] != 0) return 1; DBCachedContact *cc; DWORD ofsContact = GetContactOffset(contactID, &cc); DWORD ofsModuleName = GetModuleNameOfs(szModule); DBContact dbc = *(DBContact*)DBRead(ofsContact, NULL); if (dbc.signature != DBCONTACT_SIGNATURE) return 1; DWORD ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc, ofsModuleName); if (ofsSettingsGroup) { int bytesRemaining; unsigned varLen; DWORD ofsBlobPtr = ofsSettingsGroup + offsetof(DBContactSettings, blob); PBYTE pBlob = DBRead(ofsBlobPtr, &bytesRemaining); while (pBlob[0]) { NeedBytes(1 + settingNameLen); if (pBlob[0] == settingNameLen && !memcmp(pBlob + 1, szSetting, settingNameLen)) { MoveAlong(1 + settingNameLen); NeedBytes(5); if (isStatic && (pBlob[0] & DBVTF_VARIABLELENGTH) && VLT(dbv->type) != VLT(pBlob[0])) return 1; BYTE iType = dbv->type = pBlob[0]; switch (iType) { case DBVT_DELETED: /* this setting is deleted */ dbv->type = DBVT_DELETED; return 2; case DBVT_BYTE: dbv->bVal = pBlob[1]; break; case DBVT_WORD: memmove(&(dbv->wVal), (PWORD)(pBlob + 1), 2); break; case DBVT_DWORD: memmove(&(dbv->dVal), (PDWORD)(pBlob + 1), 4); break; case DBVT_UTF8: case DBVT_ASCIIZ: varLen = *(PWORD)(pBlob + 1); NeedBytes(int(3 + varLen)); if (isStatic) { dbv->cchVal--; if (varLen < dbv->cchVal) dbv->cchVal = varLen; memmove(dbv->pszVal, pBlob + 3, dbv->cchVal); // decode dbv->pszVal[dbv->cchVal] = 0; dbv->cchVal = varLen; } else { dbv->pszVal = (char*)mir_alloc(1 + varLen); memmove(dbv->pszVal, pBlob + 3, varLen); dbv->pszVal[varLen] = 0; } break; case DBVT_BLOB: varLen = *(PWORD)(pBlob + 1); NeedBytes(int(3 + varLen)); if (isStatic) { if (varLen < dbv->cpbVal) dbv->cpbVal = varLen; memmove(dbv->pbVal, pBlob + 3, dbv->cpbVal); } else { dbv->pbVal = (BYTE *)mir_alloc(varLen); memmove(dbv->pbVal, pBlob + 3, varLen); } dbv->cpbVal = varLen; break; case DBVT_ENCRYPTED: if (m_crypto == NULL) return 1; else { varLen = *(PWORD)(pBlob + 1); NeedBytes(int(3 + varLen)); size_t realLen; ptrA decoded(m_crypto->decodeString(pBlob + 3, varLen, &realLen)); if (decoded == NULL) return 1; varLen = (WORD)realLen; dbv->type = DBVT_UTF8; if (isStatic) { dbv->cchVal--; if (varLen < dbv->cchVal) dbv->cchVal = varLen; memmove(dbv->pszVal, decoded, dbv->cchVal); dbv->pszVal[dbv->cchVal] = 0; dbv->cchVal = varLen; } else { dbv->pszVal = (char*)mir_alloc(1 + varLen); memmove(dbv->pszVal, decoded, varLen); dbv->pszVal[varLen] = 0; } } break; } /**** add to cache **********************/ if (iType != DBVT_BLOB && iType != DBVT_ENCRYPTED) { DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1); if (pCachedValue != NULL) { m_cache->SetCachedVariant(dbv, pCachedValue); log3("set cached [%08p] %s (%p)", hContact, szCachedSettingName, pCachedValue); } } return 0; } NeedBytes(1); MoveAlong(pBlob[0] + 1); NeedBytes(3); MoveAlong(1 + GetSettingValueLength(pBlob)); NeedBytes(1); } } // try to get the missing mc setting from the active sub if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) { if (contactID = db_mc_getDefault(contactID)) { if (szModule = GetContactProto(contactID)) { moduleNameLen = (int)mir_strlen(szModule); goto LBL_Seek; } } } logg(); return 1; }
int CDbxKV::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) { if (szSetting == NULL || szModule == NULL) return 1; // the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name int settingNameLen = (int)strlen(szSetting); int moduleNameLen = (int)strlen(szModule); if (settingNameLen > 0xFE) { #ifdef _DEBUG OutputDebugStringA("GetContactSettingWorker() got a > 255 setting name length. \n"); #endif return 1; } if (moduleNameLen > 0xFE) { #ifdef _DEBUG OutputDebugStringA("GetContactSettingWorker() got a > 255 module name length. \n"); #endif return 1; } mir_cslock lck(m_csDbAccess); LBL_Seek: char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0); if (pCachedValue != NULL) { if (pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8) { int cbOrigLen = dbv->cchVal; char *cbOrigPtr = dbv->pszVal; memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); if (isStatic) { int cbLen = 0; if (pCachedValue->pszVal != NULL) cbLen = (int)strlen(pCachedValue->pszVal); cbOrigLen--; dbv->pszVal = cbOrigPtr; if (cbLen < cbOrigLen) cbOrigLen = cbLen; memcpy(dbv->pszVal, pCachedValue->pszVal, cbOrigLen); dbv->pszVal[cbOrigLen] = 0; dbv->cchVal = cbLen; } else { dbv->pszVal = (char*)mir_alloc(strlen(pCachedValue->pszVal) + 1); strcpy(dbv->pszVal, pCachedValue->pszVal); } } else memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); return (pCachedValue->type == DBVT_DELETED) ? 1 : 0; } // never look db for the resident variable if (szCachedSettingName[-1] != 0) return 1; DBCachedContact *cc = (contactID) ? m_cache->GetCachedContact(contactID) : NULL; DBSettingSortingKey keySearch; keySearch.dwContactID = contactID; keySearch.dwOfsModule = GetModuleNameOfs(szModule); strncpy_s(keySearch.szSettingName, szSetting, _TRUNCATE); ham_key_t key = { 2 * sizeof(DWORD) + settingNameLen, &keySearch }; ham_record_t rec = { 0 }; if (ham_db_find(m_dbSettings, NULL, &key, &rec, 0)) { // try to get the missing mc setting from the active sub if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) { if (contactID = db_mc_getDefault(contactID)) { if (szModule = GetContactProto(contactID)) { moduleNameLen = (int)strlen(szModule); goto LBL_Seek; } } } return 1; } BYTE *pBlob = (BYTE*)rec.data; if (isStatic && (pBlob[0] & DBVTF_VARIABLELENGTH) && VLT(dbv->type) != VLT(pBlob[0])) return 1; int varLen; BYTE iType = dbv->type = pBlob[0]; pBlob++; switch (iType) { case DBVT_DELETED: /* this setting is deleted */ dbv->type = DBVT_DELETED; return 2; case DBVT_BYTE: dbv->bVal = *pBlob; break; case DBVT_WORD: dbv->wVal = *(WORD*)pBlob; break; case DBVT_DWORD: dbv->dVal = *(DWORD*)pBlob; break; case DBVT_UTF8: case DBVT_ASCIIZ: varLen = *(WORD*)pBlob; pBlob += 2; if (isStatic) { dbv->cchVal--; if (varLen < dbv->cchVal) dbv->cchVal = varLen; memmove(dbv->pszVal, pBlob, dbv->cchVal); // decode dbv->pszVal[dbv->cchVal] = 0; dbv->cchVal = varLen; } else { dbv->pszVal = (char*)mir_alloc(1 + varLen); memmove(dbv->pszVal, pBlob, varLen); dbv->pszVal[varLen] = 0; } break; case DBVT_BLOB: varLen = *(WORD*)pBlob; pBlob += 2; if (isStatic) { if (varLen < dbv->cpbVal) dbv->cpbVal = varLen; memmove(dbv->pbVal, pBlob, dbv->cpbVal); } else { dbv->pbVal = (BYTE *)mir_alloc(varLen); memmove(dbv->pbVal, pBlob, varLen); } dbv->cpbVal = varLen; break; case DBVT_ENCRYPTED: if (m_crypto == NULL) return 1; varLen = *(WORD*)pBlob; pBlob += 2; size_t realLen; ptrA decoded(m_crypto->decodeString(pBlob, varLen, &realLen)); if (decoded == NULL) return 1; varLen = (WORD)realLen; dbv->type = DBVT_UTF8; if (isStatic) { dbv->cchVal--; if (varLen < dbv->cchVal) dbv->cchVal = varLen; memmove(dbv->pszVal, decoded, dbv->cchVal); dbv->pszVal[dbv->cchVal] = 0; dbv->cchVal = varLen; } else { dbv->pszVal = (char*)mir_alloc(1 + varLen); memmove(dbv->pszVal, decoded, varLen); dbv->pszVal[varLen] = 0; } break; } /**** add to cache **********************/ if (iType != DBVT_BLOB && iType != DBVT_ENCRYPTED) { DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1); if (pCachedValue != NULL) m_cache->SetCachedVariant(dbv, pCachedValue); } return 0; }
bool metaIsDefaultSubContact(MCONTACT hContact) { return db_mc_getDefault(db_mc_getMeta(hContact)) == hContact; }