MEVENT CSkypeProto::GetMessageFromDb(MCONTACT hContact, const char *messageId, LONGLONG timestamp) { if (messageId == NULL) return NULL; timestamp -= 600; // we check events written 10 minutes ago size_t messageIdLength = mir_strlen(messageId); mir_cslock lock(messageSyncLock); for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) { DBEVENTINFO dbei = { sizeof(dbei) }; dbei.cbBlob = db_event_getBlobSize(hDbEvent); if (dbei.cbBlob < messageIdLength) continue; mir_ptr<BYTE> blob((PBYTE)mir_alloc(dbei.cbBlob)); dbei.pBlob = blob; db_event_get(hDbEvent, &dbei); size_t cbLen = mir_strlen((char*)dbei.pBlob); if (memcmp(&dbei.pBlob[cbLen + 1], messageId, messageIdLength) == 0) return hDbEvent; if (dbei.timestamp < timestamp) break; } return NULL; }
BOOL checkMsgTimestamp(MCONTACT hContact, HANDLE hEventCurrent, DWORD timestampCurrent) { if (!bFlashIfMsgOlder) return TRUE; for (HANDLE hEvent = db_event_prev(hContact, hEventCurrent); hEvent; hEvent = db_event_prev(hContact, hEvent)) { DBEVENTINFO einfo = { sizeof(einfo) }; if(!db_event_get(hEvent, &einfo)) { if ((einfo.timestamp + wSecondsOlder) <= timestampCurrent) return TRUE; if (einfo.eventType == EVENTTYPE_MESSAGE) return FALSE; } } return TRUE; }
DWORD INTSORT_GetLastMsgTime(MCONTACT hContact) { for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) { DBEVENTINFO dbei = { sizeof(dbei) }; db_event_get(hDbEvent, &dbei); if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) return dbei.timestamp; } return 0; }
//************************************************************************ // updates the message count for the specified contact //************************************************************************ void CContactList::UpdateMessageCounter(CListEntry<CContactListEntry*,CContactListGroup*> *pContactEntry) { CContactListEntry *pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } int iOldMessages = pEntry->iMessages; bool bSort = false; HANDLE hEvent= NULL; hEvent = db_event_firstUnread(pEntry->hHandle); if(CAppletManager::IsMessageWindowOpen(pEntry->hHandle) || (hEvent == NULL && pEntry->iMessages > 0)) { pEntry->iMessages = 0; bSort = true; } else { pEntry->iMessages = 0; HANDLE hLastEvent = db_event_last(pEntry->hHandle); while(hLastEvent != NULL && hEvent != NULL) { pEntry->iMessages++; if(hLastEvent == hEvent) break; hLastEvent = db_event_prev(hLastEvent); } } if(pEntry->iMessages >= 100) pEntry->strMessages = _T(">99"); else { char buffer[8]; buffer[0] = 0; itoa(pEntry->iMessages,buffer,10); pEntry->strMessages = toTstring(buffer); } CListContainer<CContactListEntry*,CContactListGroup*>* pContainer = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent()); // Update the contacts group if it has one if(pContainer->GetType() != ROOT) { // Update the groups event count if(iOldMessages != 0 && pEntry->iMessages == 0) ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,-1); else if(iOldMessages == 0 && pEntry->iMessages != 0) ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,1); else return; // sort the groups parent ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContainer->GetParent())->sort(CContactList::CompareEntries); } }
LONGLONG GetLastSentMessageTime(MCONTACT hContact) { for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) { DBEVENTINFO dbei = { sizeof(dbei) }; db_event_get(hDbEvent, &dbei); if (FLAG_CONTAINS(dbei.flags, DBEF_SENT)) return dbei.timestamp; } return -1; }
DWORD CompareContacts2_getLMTime(MCONTACT hContact) { MEVENT hDbEvent = db_event_last(hContact); while (hDbEvent) { DBEVENTINFO dbei = { sizeof(dbei) }; db_event_get(hDbEvent, &dbei); if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) return dbei.timestamp; hDbEvent = db_event_prev(hContact, hDbEvent); } return 0; }
time_t getLastInputMsg(MCONTACT hContact) { MEVENT hDbEvent = db_event_last(hContact); while (hDbEvent) { DBEVENTINFO dbei = {}; db_event_get(hDbEvent, &dbei); if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) return dbei.timestamp; hDbEvent = db_event_prev(hContact, hDbEvent); } return -1; }
/** * calculate message frequency for a single contact */ static void MF_CalcFrequency(MCONTACT hContact, DWORD dwCutoffDays, int doSleep) { DWORD curTime = time(NULL); DWORD frequency, eventCount; DBEVENTINFO dbei = {0}; MEVENT hEvent = db_event_last(hContact); eventCount = 0; dbei.cbSize = sizeof(dbei); dbei.timestamp = 0; while(hEvent) { dbei.cbBlob = 0; dbei.pBlob = NULL; db_event_get(hEvent, &dbei); if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { // record time of last event eventCount++; } /* * consider the most recent 100 messages and ignore messages that are older than the cutoff days. * this will prevent contacts with a high message rate in the past to keep occupying the * top positions forever. */ if(eventCount >= 100 || dbei.timestamp < curTime - (dwCutoffDays * 86400)) break; hEvent = db_event_prev(hContact, hEvent); // check for main update thread still running (if not, application is shutting down, so terminate our work) if(doSleep && mf_updatethread_running == FALSE) return; if(doSleep) Sleep(100); } if(eventCount == 0) { frequency = 0x7fffffff; cfg::writeDword(hContact, "CList", "mf_firstEvent", curTime - (dwCutoffDays * 86400)); } else { frequency = (curTime - dbei.timestamp) / eventCount; cfg::writeDword(hContact, "CList", "mf_firstEvent", dbei.timestamp); } cfg::writeDword(hContact, "CList", "mf_freq", frequency); cfg::writeDword(hContact, "CList", "mf_count", eventCount); }
static void FillHistoryThread(void* param) { Thread_SetName("HistoryWindow::FillHistoryThread"); THistoryThread *hInfo = (THistoryThread*)param; HWND hwndList = GetDlgItem(hInfo->hwnd, IDC_LIST); SendDlgItemMessage(hInfo->hwnd, IDC_LIST, LB_RESETCONTENT, 0, 0); int i = db_event_count(hInfo->hContact); SendDlgItemMessage(hInfo->hwnd, IDC_LIST, LB_INITSTORAGE, i, i * 40); DBEVENTINFO dbei = { sizeof(dbei) }; int oldBlobSize = 0; MEVENT hDbEvent = db_event_last(hInfo->hContact); while (hDbEvent != NULL) { if (!IsWindow(hInfo->hwnd)) break; int newBlobSize = db_event_getBlobSize(hDbEvent); if (newBlobSize > oldBlobSize) { dbei.pBlob = (PBYTE)mir_realloc(dbei.pBlob, newBlobSize); oldBlobSize = newBlobSize; } dbei.cbBlob = oldBlobSize; db_event_get(hDbEvent, &dbei); TCHAR str[200], eventText[256], strdatetime[64]; GetObjectSummary(&dbei, str, _countof(str)); if (str[0]) { TimeZone_PrintTimeStamp(NULL, dbei.timestamp, _T("d t"), strdatetime, _countof(strdatetime), 0); mir_sntprintf(eventText, _T("%s: %s"), strdatetime, str); i = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)eventText); SendMessage(hwndList, LB_SETITEMDATA, i, (LPARAM)hDbEvent); } hDbEvent = db_event_prev(hInfo->hContact, hDbEvent); } mir_free(dbei.pBlob); SendDlgItemMessage(hInfo->hwnd, IDC_LIST, LB_SETCURSEL, 0, 0); SendMessage(hInfo->hwnd, WM_COMMAND, MAKEWPARAM(IDC_LIST, LBN_SELCHANGE), 0); EnableWindow(GetDlgItem(hInfo->hwnd, IDC_LIST), TRUE); mir_free(hInfo); }
static int lua_EventReverseIterator(lua_State *L) { MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); MEVENT hEvent = luaL_checkinteger(L, lua_upvalueindex(2)); hEvent = hEvent == NULL ? db_event_last(hContact) : db_event_prev(hContact, hEvent); if (hEvent) { lua_pushinteger(L, hContact); lua_pushvalue(L, -1); lua_replace(L, lua_upvalueindex(2)); } else lua_pushnil(L); return 1; }
static void MF_CalcFrequency(MCONTACT hContact, DWORD dwCutoffDays, int doSleep) { DWORD curTime = time(NULL); DWORD frequency, eventCount; MEVENT hEvent = db_event_last(hContact); eventCount = 0; DBEVENTINFO dbei = { sizeof(dbei) }; while (hEvent) { db_event_get(hEvent, &dbei); if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { // record time of last event eventCount++; } if (eventCount >= 100 || dbei.timestamp < curTime - (dwCutoffDays * 86400)) break; hEvent = db_event_prev(hContact, hEvent); if (doSleep && mf_updatethread_running == FALSE) return; if (doSleep) Sleep(100); } if (eventCount == 0) { frequency = 0x7fffffff; cfg::writeDword(hContact, "CList", "mf_firstEvent", curTime - (dwCutoffDays * 86400)); } else { frequency = (curTime - dbei.timestamp) / eventCount; cfg::writeDword(hContact, "CList", "mf_firstEvent", dbei.timestamp); } cfg::writeDword(hContact, "CList", "mf_freq", frequency); cfg::writeDword(hContact, "CList", "mf_count", eventCount); }
// Returns TRUE if the event already exist in the database BOOL IsDuplicateEvent(MCONTACT hContact, DBEVENTINFO& dbei) { HANDLE hExistingDbEvent; DWORD dwEventTimeStamp; // get last event if (!(hExistingDbEvent = db_event_last(hContact))) return FALSE; DBEVENTINFO dbeiExisting = { sizeof(dbeiExisting) }; db_event_get(hExistingDbEvent, &dbeiExisting); dwEventTimeStamp = dbeiExisting.timestamp; // compare with last timestamp if (dbei.timestamp > dwEventTimeStamp) { // remember event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dwEventTimeStamp; return FALSE; } if (hContact != hPreviousContact) { hPreviousContact = hContact; // remember event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dwEventTimeStamp; // get first event if (!(hExistingDbEvent = db_event_first(hContact))) return FALSE; memset(&dbeiExisting, 0, sizeof(dbeiExisting)); dbeiExisting.cbSize = sizeof(dbeiExisting); db_event_get(hExistingDbEvent, &dbeiExisting); dwEventTimeStamp = dbeiExisting.timestamp; // compare with first timestamp if (dbei.timestamp <= dwEventTimeStamp) { // remember event dwPreviousTimeStamp = dwEventTimeStamp; hPreviousDbEvent = hExistingDbEvent; if ( dbei.timestamp != dwEventTimeStamp ) return FALSE; } } // check for equal timestamps if (dbei.timestamp == dwPreviousTimeStamp) { memset(&dbeiExisting, 0, sizeof(dbeiExisting)); dbeiExisting.cbSize = sizeof(dbeiExisting); db_event_get(hPreviousDbEvent, &dbeiExisting); if ((dbei.timestamp == dbeiExisting.timestamp) && (dbei.eventType == dbeiExisting.eventType) && (dbei.cbBlob == dbeiExisting.cbBlob) && ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) return TRUE; // find event with another timestamp hExistingDbEvent = db_event_next(hContact, hPreviousDbEvent); while (hExistingDbEvent != NULL) { memset(&dbeiExisting, 0, sizeof(dbeiExisting)); dbeiExisting.cbSize = sizeof(dbeiExisting); db_event_get(hExistingDbEvent, &dbeiExisting); if (dbeiExisting.timestamp != dwPreviousTimeStamp) { // use found event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dbeiExisting.timestamp; break; } hPreviousDbEvent = hExistingDbEvent; hExistingDbEvent = db_event_next(hContact, hExistingDbEvent); } } hExistingDbEvent = hPreviousDbEvent; if (dbei.timestamp <= dwPreviousTimeStamp) { // look back while (hExistingDbEvent != NULL) { memset(&dbeiExisting, 0, sizeof(dbeiExisting)); dbeiExisting.cbSize = sizeof(dbeiExisting); db_event_get(hExistingDbEvent, &dbeiExisting); if (dbei.timestamp > dbeiExisting.timestamp) { // remember event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dbeiExisting.timestamp; return FALSE; } // Compare event with import candidate if ((dbei.timestamp == dbeiExisting.timestamp) && (dbei.eventType == dbeiExisting.eventType) && (dbei.cbBlob == dbeiExisting.cbBlob) && ((dbei.flags & DBEF_SENT) == (dbeiExisting.flags & DBEF_SENT))) { // remember event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dbeiExisting.timestamp; return TRUE; } // Get previous event in chain hExistingDbEvent = db_event_prev(hContact, hExistingDbEvent); } } else { // look forward while (hExistingDbEvent != NULL) { memset(&dbeiExisting, 0, sizeof(dbeiExisting)); dbeiExisting.cbSize = sizeof(dbeiExisting); db_event_get(hExistingDbEvent, &dbeiExisting); if (dbei.timestamp < dbeiExisting.timestamp) { // remember event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dbeiExisting.timestamp; return FALSE; } // Compare event with import candidate if ((dbei.timestamp == dbeiExisting.timestamp) && (dbei.eventType == dbeiExisting.eventType) && (dbei.cbBlob == dbeiExisting.cbBlob) && ((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT))) { // remember event hPreviousDbEvent = hExistingDbEvent; dwPreviousTimeStamp = dbeiExisting.timestamp; return TRUE; } // Get next event in chain hExistingDbEvent = db_event_next(hContact, hExistingDbEvent); } } // reset last event hPreviousContact = INVALID_CONTACT_ID; return FALSE; }
//************************************************************************ // loads the contacts history //************************************************************************ void CChatScreen::LoadHistory() { if(!m_hContact) return; char *szProto = GetContactProto(m_hContact); if(m_bIRCProtocol && db_get_b(m_hContact, szProto, "ChatRoom", 0) != 0) { if(!CAppletManager::GetInstance()->IsIRCHookEnabled()) { time_t now; tm tm_now; time(&now); localtime_s(&tm_now,&now); AddIncomingMessage(CAppletManager::TranslateString(_T("IRC-Chatroom support is disabled!\nYou need to install the patched IRC.dll (see the readme) to use IRC-Chatrooms on the LCD")),&tm_now,true); } else { CIRCHistory *pHistory = CAppletManager::GetInstance()->GetIRCHistory(m_hContact); if(pHistory) { list<SIRCMessage>::iterator iter = pHistory->LMessages.begin(); while(iter != pHistory->LMessages.end()) { if((*iter).bIsMe) AddOutgoingMessage((*iter).strMessage,&((*iter).Time),true); else AddIncomingMessage((*iter).strMessage,&((*iter).Time),true); iter++; } } } } else { // Get last events from database CEvent Event; list<MEVENT> LHandles; MEVENT hEvent = db_event_last(m_hContact); MEVENT hUnread = db_event_firstUnread(m_hContact); if(CConfig::GetBoolSetting(SESSION_LOADDB)) { while(hEvent != NULL && hUnread != NULL) { LHandles.push_front(hEvent); if(CConfig::GetBoolSetting(SESSION_LOADDB) && *(LHandles.begin()) == hUnread) break; hEvent = db_event_prev(m_hContact, hEvent); } } else { for (int i = CConfig::GetIntSetting(SESSION_LOGSIZE); i > 0 && hEvent!=NULL; i--) { LHandles.push_front(hEvent); hEvent = db_event_prev(m_hContact, hEvent); } } bool bRead = true; while(!(LHandles.empty())) { if(CAppletManager::TranslateDBEvent(&Event,(LPARAM)m_hContact,(WPARAM)*(LHandles.begin()))) { if(Event.hValue == hUnread) bRead = false; if(Event.eType == EVENT_MSG_RECEIVED) { AddIncomingMessage(Event.strValue,&Event.Time); if(!bRead && CConfig::GetBoolSetting(SESSION_MARKREAD) && !CAppletManager::IsMessageWindowOpen(m_hContact)) CAppletManager::MarkMessageAsRead(m_hContact,Event.hValue); } else AddOutgoingMessage(Event.strValue,&Event.Time); } LHandles.pop_front(); } } }
static MEVENT findDbEvent(MCONTACT hContact, MEVENT hDbEvent, int flags) { DBEVENTINFO dbe; BOOL bEventOk; do { memset(&dbe, 0, sizeof(DBEVENTINFO)); dbe.cbSize = sizeof(DBEVENTINFO); dbe.cbBlob = 0; dbe.pBlob = NULL; if (hContact != NULL) { if ((flags & DBE_FIRST) && (flags & DBE_UNREAD)) { hDbEvent = db_event_firstUnread(hContact); if (hDbEvent == NULL && (flags & DBE_READ)) hDbEvent = db_event_first(hContact); } else if (flags & DBE_FIRST) hDbEvent = db_event_first(hContact); else if (flags & DBE_LAST) hDbEvent = db_event_last(hContact); else if (flags & DBE_NEXT) hDbEvent = db_event_next(hContact, hDbEvent); else if (flags & DBE_PREV) hDbEvent = db_event_prev(hContact, hDbEvent); } else { MEVENT hMatchEvent = NULL, hSearchEvent = NULL; DWORD matchTimestamp = 0, priorTimestamp = 0; if (flags & DBE_FIRST) { for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) { hSearchEvent = findDbEvent(hSearchContact, NULL, flags); dbe.cbBlob = 0; if (!db_event_get(hSearchEvent, &dbe)) { if ((dbe.timestamp < matchTimestamp) || (matchTimestamp == 0)) { hMatchEvent = hSearchEvent; matchTimestamp = dbe.timestamp; } } } hDbEvent = hMatchEvent; } else if (flags & DBE_LAST) { for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) { hSearchEvent = findDbEvent(hSearchContact, NULL, flags); dbe.cbBlob = 0; if (!db_event_get(hSearchEvent, &dbe)) { if ((dbe.timestamp > matchTimestamp) || (matchTimestamp == 0)) { hMatchEvent = hSearchEvent; matchTimestamp = dbe.timestamp; } } } hDbEvent = hMatchEvent; } else if (flags & DBE_NEXT) { dbe.cbBlob = 0; if (!db_event_get(hDbEvent, &dbe)) { priorTimestamp = dbe.timestamp; for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) { hSearchEvent = findDbEvent(hSearchContact, hDbEvent, flags); dbe.cbBlob = 0; if (!db_event_get(hSearchEvent, &dbe)) { if (((dbe.timestamp < matchTimestamp) || (matchTimestamp == 0)) && (dbe.timestamp > priorTimestamp)) { hMatchEvent = hSearchEvent; matchTimestamp = dbe.timestamp; } } } hDbEvent = hMatchEvent; } } else if (flags & DBE_PREV) { if (!db_event_get(hDbEvent, &dbe)) { priorTimestamp = dbe.timestamp; for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) { hSearchEvent = findDbEvent(hSearchContact, hDbEvent, flags); dbe.cbBlob = 0; if (!db_event_get(hSearchEvent, &dbe)) { if (((dbe.timestamp > matchTimestamp) || (matchTimestamp == 0)) && (dbe.timestamp < priorTimestamp)) { hMatchEvent = hSearchEvent; matchTimestamp = dbe.timestamp; } } } hDbEvent = hMatchEvent; } } } dbe.cbBlob = 0; if (db_event_get(hDbEvent, &dbe)) bEventOk = FALSE; else bEventOk = isValidDbEvent(&dbe, flags); if (!bEventOk) { if (flags&DBE_FIRST) { flags |= DBE_NEXT; flags &= ~DBE_FIRST; } else if (flags&DBE_LAST) { flags |= DBE_PREV; flags &= ~DBE_LAST; } } } while ((!bEventOk) && (hDbEvent != NULL)); return hDbEvent; }