Exemple #1
0
void RemoveUsers()
{
	if ( GetSettingBool("GlobalSettings", "RemoveAllUsers", TRUE) ) {
		// To be faster, remove first all metacontacts (because it syncs histories)
		MCONTACT hContact = db_find_first();
		while(hContact != NULL) {
			MCONTACT hContactOld = hContact;
			hContact = db_find_next(hContact);

			if (isMetaContact(hContactOld) )
				CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContactOld, 0);
		}

		// Now delete all left-overs
		hContact = db_find_first();
		while(hContact != NULL) {
			CallService(MS_DB_CONTACT_DELETE, hContact, 0);

			hContact = db_find_first();
		}

		// Delete events for contacts not in list
		MEVENT hDbEvent = db_event_first(0);

		while(hDbEvent != NULL) {
			db_event_delete(0, hDbEvent); 
			hDbEvent = db_event_first(0);
		}

		// Now delete groups
		DeleteSettingEx("CListGroups", NULL);
	}
}
Exemple #2
0
void CVkProto::GetServerHistoryLastNDay(MCONTACT hContact, int NDay)
{
	debugLogA("CVkProto::SvcGetServerHistoryLastNDay %d", NDay);

	time_t tTime = time(NULL) - 60 * 60 * 24 * NDay;

	MEVENT hDBEvent = db_event_first(hContact);
	while (hDBEvent) {
		MEVENT hDBEventNext = db_event_next(hContact, hDBEvent);
		DBEVENTINFO dbei = { sizeof(dbei) };
		db_event_get(hDBEvent, &dbei);
		if (dbei.timestamp > tTime)
			db_event_delete(hContact, hDBEvent);
		hDBEvent = hDBEventNext;
	}

	{
		mir_cslock lck(m_csLoadHistoryTask);
		m_iLoadHistoryTask++;
		if (NDay > 3)
			m_bNotifyForEndLoadingHistory = true;
	}

	db_unset(hContact, m_szModuleName, "lastmsgid");
	GetServerHistory(hContact, 0, MAXHISTORYMIDSPERONE, tTime, 0);
}
Exemple #3
0
INT_PTR __cdecl CVkProto::SvcGetAllServerHistoryForContact(WPARAM hContact, LPARAM)
{
	debugLogA("CVkProto::SvcGetAllServerHistoryForContact");
	if (!IsOnline())
		return 0;
	LPCTSTR str = TranslateT("Are you sure to reload all messages from vk.com?\nLocal contact history will be deleted and reloaded from the server.\nIt may take a long time.\nDo you want to continue?");
	if (IDNO == MessageBox(NULL, str, TranslateT("Attention!"), MB_ICONWARNING | MB_YESNO))
		return 0;

	LONG userID = getDword(hContact, "ID", -1);
	if (userID == -1 || userID == VK_FEED_USER)
		return 0;

	MEVENT hDBEvent = db_event_first(hContact);
	while (hDBEvent) {
		MEVENT hDBEventNext = db_event_next(hContact, hDBEvent);
		db_event_delete(hContact, hDBEvent);
		hDBEvent = hDBEventNext;
	}

	m_bNotifyForEndLoadingHistory = true;

	db_unset(hContact, m_szModuleName, "lastmsgid");
	GetServerHistory(hContact, 0, MAXHISTORYMIDSPERONE, 0, 0);
	return 1;
}
Exemple #4
0
int FillAvatarListFromDB(HWND list, MCONTACT hContact)
{
	int max_pos = 0;
	BYTE blob[2048];
	for (MEVENT hDbEvent = db_event_first(hContact); hDbEvent; hDbEvent = db_event_next(hContact, hDbEvent)) {
		DBEVENTINFO dbei = { sizeof(dbei) };
		dbei.cbBlob = sizeof(blob);
		dbei.pBlob = blob;
		if (db_event_get(hDbEvent, &dbei) != 0) continue;
		if (dbei.eventType != EVENTTYPE_AVATAR_CHANGE) continue;

		// Get time
		TCHAR date[64];
		TimeZone_ToStringT(dbei.timestamp, _T("d s"), date, _countof(date));

		// Get file in disk
		TCHAR path[MAX_PATH];
		ptrT tszStoredPath(mir_utf8decodeT((char*)dbei.pBlob));
		PathToAbsoluteT(tszStoredPath, path);

		// Add to list
		ListEntry *le = new ListEntry();
		le->hDbEvent = hDbEvent;
		le->filename = mir_tstrdup(path);
		max_pos = SendMessage(list,LB_ADDSTRING, 0, (LPARAM)date);
		SendMessage(list, LB_SETITEMDATA, max_pos, (LPARAM)le);
	}

	SendMessage(list, LB_SETCURSEL, max_pos, 0); // Set to first item
	return 0;
}
Exemple #5
0
void RemoveAllEvents(MCONTACT hContact)
{
    MEVENT hDBEvent = db_event_first(hContact);
    while(hDBEvent) {
        MEVENT hDBEventNext = db_event_next(hContact, hDBEvent);
        db_event_delete(hContact, hDBEvent);
        hDBEvent = hDBEventNext;
    }
}
Exemple #6
0
void ClearNotificationContactHistory(LPCSTR acc)
{
	MCONTACT hContact = db_get_dw(NULL, acc, PSEUDOCONTACT_LINK, 0);
	if (!hContact || !db_get_b(hContact, SHORT_PLUGIN_NAME, PSEUDOCONTACT_FLAG, 0))
		return;

	for (MEVENT hEvent = db_event_first(hContact); hEvent;) {
		MEVENT hEvent1 = db_event_next(hContact, hEvent);
		db_event_delete(hContact, hEvent);
		hEvent = hEvent1;
	}
}
Exemple #7
0
void CVkProto::NewsClearHistory()
{
	debugLogA("CVkProto::NewsClearHistory");
	MCONTACT hContact = FindUser(VK_FEED_USER);
	if (hContact == NULL || !m_bNewsAutoClearHistory)
		return;

	time_t tTime = time(NULL) - m_iNewsAutoClearHistoryInterval;
	MEVENT hDBEvent = db_event_first(hContact);
	while (hDBEvent) {
		MEVENT hDBEventNext = db_event_next(hContact, hDBEvent);
		DBEVENTINFO dbei = { sizeof(dbei) };
		db_event_get(hDBEvent, &dbei);
		if (dbei.timestamp < tTime)
			db_event_delete(hContact, hDBEvent);
		hDBEvent = hDBEventNext;
	}
}
Exemple #8
0
bool IsExistMyMessage(HANDLE hContact)
{
	HANDLE hDbEvent = db_event_first(hContact);
	while(hDbEvent){
		DBEVENTINFO dbei = { sizeof(dbei) };
		if (db_event_get(hDbEvent, &dbei))
			break;

		if (dbei.flags & DBEF_SENT){
			// mark contact as Answered
			db_set_b(hContact, pluginName, answeredSetting, 1);
			// ...let the event go its way
			return true;
		}
		hDbEvent = db_event_next(hDbEvent);
	}
	return false;
}
Exemple #9
0
static int lua_EventIterator(lua_State *L)
{
	MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1));
	MEVENT hEvent = luaL_checkinteger(L, lua_upvalueindex(2));

	hEvent = hEvent == NULL
		? db_event_first(hContact)
		: db_event_next(hContact, hEvent);

	if (hEvent)
	{
		lua_pushinteger(L, hEvent);
		lua_pushvalue(L, -1);
		lua_replace(L, lua_upvalueindex(2));
	}
	else
		lua_pushnil(L);

	return 1;
}
Exemple #10
0
void EventList::GetTempList(std::list<EventTempIndex>& tempList, bool noFilter, bool noExt, MCONTACT _hContact)
{
	bool isWndLocal = isWnd;
	EventTempIndex ti;
	EventData data;
	EventIndex ei;
	ti.isExternal = false;
	ei.isExternal = false;
	MEVENT hDbEvent = db_event_first(_hContact);
	while (hDbEvent != NULL) {
		if (isWndLocal && !IsWindow(hWnd))
			break;

		ei.hEvent = hDbEvent;
		if (GetEventData(ei, data)) {
			if (noFilter || CanShowHistory(&gdbei)) {
				ti.hEvent = hDbEvent;
				ti.timestamp = data.timestamp;
				tempList.push_back(ti);
			}
		}
		hDbEvent = db_event_next(_hContact, hDbEvent);
	}

	if (!noExt) {
		std::list<EventTempIndex>::iterator itL = tempList.begin();
		ti.isExternal = true;
		for (int i = 0; i < (int)importedMessages.size(); ++i) {
			if (noFilter || CanShowHistory(importedMessages[i])) {
				DWORD ts = importedMessages[i].timestamp;
				while(itL != tempList.end() && itL->timestamp < ts)++itL;
				if (itL == tempList.end() || itL->timestamp > ts) {
					ti.exIdx = i;
					ti.timestamp = ts;
					tempList.insert(itL, ti);
				}
			}
		}
	}
}
Exemple #11
0
INT_PTR __cdecl CVkProto::SvcGetAllServerHistory(WPARAM, LPARAM)
{
	debugLogA("CVkProto::SvcGetAllServerHistory start");
	if (!IsOnline())
		return 0;
	LPCTSTR str = TranslateT("Are you sure you want to reload all messages for all contacts from vk.com?\nLocal contact history will be deleted and reloaded from the server.\nIt may take a very long time and/or corrupt Miranda database.\nWe recommend check your database before reloading messages and after it (Miranda32.exe /svc:dbchecker or Miranda64.exe /svc:dbchecker).\nDo you want to continue?");
	if (IDNO == MessageBox(NULL, str, TranslateT("Attention!"), MB_ICONWARNING | MB_YESNO))
		return 0;

	for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
		LONG userID = getDword(hContact, "ID", -1);
		if (userID == -1 || userID == VK_FEED_USER)
			continue;

		
		MEVENT hDBEvent = db_event_first(hContact);
		while (hDBEvent) {
			MEVENT hDBEventNext = db_event_next(hContact, hDBEvent);
			db_event_delete(hContact, hDBEvent);
			hDBEvent = hDBEventNext;
		}

		{
			mir_cslock lck(m_csLoadHistoryTask);
			m_iLoadHistoryTask++;
			m_bNotifyForEndLoadingHistoryAllContact = m_bNotifyForEndLoadingHistory = true;
			debugLogA("CVkProto::SvcGetAllServerHistory for ID=%d m_iLoadHistoryTask=%d", userID, m_iLoadHistoryTask);
		}
		
		db_unset(hContact, m_szModuleName, "lastmsgid");
		GetServerHistory(hContact, 0, MAXHISTORYMIDSPERONE, 0, 0);
	
	}

	return 1;
}
Exemple #12
0
// 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;
}
//Sweep history from specified contact
void SweepHistoryFromContact(MCONTACT hContact, CriteriaStruct Criteria, BOOL keepUnread)
{
    int lPolicy;
    if (hContact == NULL)			// for system history
        lPolicy = db_get_b(NULL, ModuleName, "SweepSHistory", 0);
    else							// for contact history (or "SweepHistory" - default action)
        lPolicy = db_get_b(hContact, ModuleName, "SweepHistory", db_get_b(NULL, ModuleName, "SweepHistory", 0));

    if (lPolicy == 0) return;		// nothing to do

    int eventsCnt = db_event_count(hContact);
    if (eventsCnt == 0)
        return;

    BOOL doDelete, unsafe = db_get_b(NULL, ModuleName, "UnsafeMode", 0);
    BEventData *books, *item, ev = { 0 };
    size_t bookcnt, btshift;

    SetCursor(LoadCursor(0, IDC_WAIT));

    // switch off SAFETYMODE if necessary
    if (unsafe)
        CallService(MS_DB_SETSAFETYMODE, 0, 0);

    GetBookmarks(hContact, &books, &bookcnt);

    // Get first event
    for (MEVENT hDBEvent = db_event_first(hContact); hDBEvent != NULL; ) {
        DBEVENTINFO dbei = { sizeof(dbei) };
        db_event_get(hDBEvent, &dbei);

        // should we stop processing?
        // lPolicy == 1 - for time criterion, lPolicy == 2 - keep N last events, lPolicy == 3 - delete all events
        if ((lPolicy == 1 && (unsigned)Criteria.time < dbei.timestamp) || (lPolicy == 2 && Criteria.keep > --eventsCnt)) break;

        doDelete = TRUE;

        if (!(dbei.flags & (DBEF_SENT | DBEF_READ)) && keepUnread) doDelete = FALSE;	// keep unread events

        if (bookcnt != 0) { // keep bookmarks
            ev.hDBEvent = hDBEvent;
            item = (BEventData*)bsearch(&ev, books, bookcnt, sizeof(BEventData), CompareBookmarks);
            if (item != NULL && item->Timestamp == dbei.timestamp) {
                doDelete = FALSE;
                btshift = (--bookcnt - (item - books))*sizeof(BEventData);
                if (btshift)
                    memmove(item, item + 1, btshift);
            }
        }

        // find next event
        MEVENT hDBEventNext = db_event_next(hContact, hDBEvent);
        if (doDelete)
            db_event_delete(hContact, hDBEvent);

        hDBEvent = hDBEventNext;
    }

    mir_free(books);

    // switch ON safety mode as fast as we can to avoid  DB corruption
    if (unsafe)
        CallService(MS_DB_SETSAFETYMODE, 1, 0);

    SetCursor(LoadCursor(0, IDC_ARROW));
}
Exemple #14
0
static INT_PTR LinkList_Main(WPARAM wParam, LPARAM)
{
	HANDLE hContact = (HANDLE)wParam;
	HWND hWnd = WindowList_Find(hWindowList, hContact);
	if ( hWnd != NULL ) {
		int len;
		SetForegroundWindow(hWnd);
		SetFocus(hWnd);
		len = GetWindowTextLength(GetDlgItem(hWnd, IDC_MAIN));
		PostMessage(GetDlgItem(hWnd, IDC_MAIN), EM_SETSEL, (WPARAM)len, (LPARAM)len);
		return 0;
	}	
	
	HANDLE hEvent = db_event_first(hContact);
	if (hEvent == NULL) {
		MessageBox(NULL, TXT_EMPTYHISTORY, TXT_PLUGINNAME, MB_OK | MB_ICONINFORMATION );
		return 0;
	}

	int histCount = db_event_count(hContact), actCount = 0;

	DBEVENTINFO dbe = { sizeof(dbe) };
	dbe.cbBlob = db_event_getBlobSize(hEvent);
	dbe.pBlob  = (PBYTE)malloc(dbe.cbBlob+1);
	db_event_get(hEvent, &dbe);
	dbe.pBlob[dbe.cbBlob] = 0;

	RECT DesktopRect;
	GetWindowRect(GetDesktopWindow(), &DesktopRect);
	HWND hWndProgress = CreateWindow(_T("Progressbar"), TranslateT("Processing history..."), WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, 350, 45, NULL, NULL, hInst, NULL);
	if ( hWndProgress == 0 ) {
		free(dbe.pBlob);
		MessageBox(NULL, TranslateT("Could not create window!"), TranslateT("Error"), MB_OK | MB_ICONEXCLAMATION );
		return -1;
	}
	SetWindowPos(hWndProgress, HWND_TOP, (int)(DesktopRect.right*0.5)-175, (int)(DesktopRect.bottom*0.5)-22, 0, 0, SWP_NOSIZE);
	ShowWindow(hWndProgress, SW_SHOW);
	SetForegroundWindow(hWndProgress);

	LISTELEMENT *listStart = (LISTELEMENT*)malloc(sizeof(LISTELEMENT));
	ZeroMemory(listStart, sizeof(LISTELEMENT));

	while( 1 ) {
		if ( dbe.eventType == EVENTTYPE_URL || dbe.eventType == EVENTTYPE_MESSAGE ) {
			// Call function to find URIs
			if ( ExtractURI(&dbe, hEvent, listStart) < 0 ) {
				free(dbe.pBlob);
				RemoveList(listStart);
				MessageBox(NULL, TranslateT("Could not allocate memory!"), TranslateT("Error"), MB_OK | MB_ICONEXCLAMATION);
				return -1;
			}
		}
		actCount++;
		if ( ((int)(((float)actCount/histCount)*100.00)) % 10 == 0 )
			SendMessage(hWndProgress, WM_COMMAND, 100, ((int)(((float)actCount/histCount)*100.00)));
		
		hEvent = db_event_next(hEvent);
		if ( hEvent == NULL )
			break;

		free(dbe.pBlob);
		dbe.cbBlob = db_event_getBlobSize(hEvent);
		dbe.pBlob = (PBYTE)malloc(dbe.cbBlob+1);
		db_event_get(hEvent, &dbe);
		dbe.pBlob[dbe.cbBlob] = 0;
	}
	free(dbe.pBlob);
	SendMessage(hWndProgress, WM_CLOSE, 0, 0);
	if ( ListCount(listStart) <= 0 ) {	
		RemoveList(listStart);
		MessageBox(NULL, TXT_NOLINKINHISTORY, TXT_PLUGINNAME, MB_OK | MB_ICONINFORMATION);
		return 0;
	}

	DIALOGPARAM *DlgParam = (DIALOGPARAM*)malloc(sizeof(DIALOGPARAM));
	DlgParam->hContact    = hContact;
	DlgParam->listStart   = listStart;
	DlgParam->findMessage = 0;
	DlgParam->chrg.cpMax  = -1;
	DlgParam->chrg.cpMin  = -1;

	HWND hWndMain = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN_DLG), NULL, MainDlgProc, (LPARAM)DlgParam);
	if (hWndMain == 0) {
		RemoveList(listStart);
		MessageBox(NULL, TranslateT("Could not create window!"), TranslateT("Error"), MB_OK | MB_ICONEXCLAMATION );
		return -1;
	}

	ShowWindow(hWndMain, SW_SHOW);	
	return 0;
}
Exemple #15
0
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;
}