Exemple #1
0
CContact *CRoutingBin::GetContact(uint32_t ip, uint16_t port, bool tcpPort) const throw()
{
	for (ContactList::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it) {
		CContact *contact = *it;
		if ((contact->GetIPAddress() == ip)
		    && ((!tcpPort && port == contact->GetUDPPort()) || (tcpPort && port == contact->GetTCPPort()) || port == 0)) {
			return contact;
		}
	}
	return NULL;
}
Exemple #2
0
    TInt Compare(TInt aLeft, TInt aRight) const
        {
        CContact* left = arr[aLeft];
        CContact* right = arr[aRight];

        left->Name(name1, last_name_first);
        right->Name(name2, last_name_first);

        //TCollationMethod m = *Mem::CollationMethodByIndex(0); // get the standard method
        //m.iFlags |= TCollationMethod::EIgnoreNone; // dont ignore punctuation and spaces

        return name1->CompareC(*name2, 3 /* string level */, NULL);
        }
Exemple #3
0
void CRoutingBin::SetAlive(CContact *contact)
{
	wxASSERT(contact != NULL);
	// Check if we already have a contact with this ID in the list.
	CContact *test = GetContact(contact->GetClientID());
	wxASSERT(contact == test);
	if (test) {
		// Mark contact as being alive.
		test->UpdateType();
		// Move to the end of the list
		PushToBottom(test);
	}
}
Exemple #4
0
bool CKademlia::FindNodeIDByIP(CKadClientSearcher& requester, uint32_t ip, uint16_t tcpPort, uint16_t udpPort)
{
	wxCHECK(IsRunning() && instance && GetUDPListener() && GetRoutingZone(), false);

	// first search our known contacts if we can deliver a result without asking, otherwise forward the request
	CContact* contact;
	if ((contact = GetRoutingZone()->GetContact(wxUINT32_SWAP_ALWAYS(ip), tcpPort, true)) != NULL) {
		uint8_t nodeID[16];
		contact->GetClientID().ToByteArray(nodeID);
		requester.KadSearchNodeIDByIPResult(KCSR_SUCCEEDED, nodeID);
		return true;
	} else {
		return GetUDPListener()->FindNodeIDByIP(&requester, wxUINT32_SWAP_ALWAYS(ip), tcpPort, udpPort);
	}
}
Exemple #5
0
void CRoutingBin::SetTCPPort(uint32_t ip, uint16_t port, uint16_t tcpPort)
{
	// Find contact with IP/Port
	for (ContactList::iterator it = m_entries.begin(); it != m_entries.end(); ++it) {
		CContact *c = *it;
		if ((ip == c->GetIPAddress()) && (port == c->GetUDPPort())) {
			// Set TCPPort and mark as alive.
			c->SetTCPPort(tcpPort);
			c->UpdateType();
			// Move to the end of the list
			PushToBottom(c);
			break;
		}
	}
}
Exemple #6
0
bool CKademlia::FindIPByNodeID(CKadClientSearcher& requester, const uint8_t* nodeID)
{
	wxCHECK(IsRunning() && instance && GetUDPListener(), false);

	// first search our known contacts if we can deliver a result without asking, otherwise forward the request
	CContact* contact;
	if ((contact = GetRoutingZone()->GetContact(CUInt128(nodeID))) != NULL) {
		// make sure that this entry is not too old, otherwise just do a search to be sure
		if (contact->GetLastSeen() != 0 && time(NULL) - contact->GetLastSeen() < 1800) {
			requester.KadSearchIPByNodeIDResult(KCSR_SUCCEEDED, wxUINT32_SWAP_ALWAYS(contact->GetIPAddress()), contact->GetTCPPort());
			return true;
		}
	}
	return CSearchManager::FindNodeSpecial(CUInt128(nodeID), &requester);
}
Exemple #7
0
bool CRoutingZone::Add(CContact* pContact, bool bUpdate)
{
	// If we are not a leaf, call add on the correct branch.
	if (!IsLeaf())
		return m_pSubZones[pContact->GetDistance().GetBitNumber(m_uLevel)]->Add(pContact, bUpdate);
	else
	{
		// Do we already have a contact with this KadID?
		CContact* pContactUpdate = m_pBin->GetContact(pContact->GetClientID());
		if (pContactUpdate)
		{
			if(bUpdate)
			{
				pContactUpdate->SetIPAddress(pContact->GetIPAddress());
				pContactUpdate->SetUDPPort(pContact->GetUDPPort());
				pContactUpdate->SetTCPPort(pContact->GetTCPPort());
				pContactUpdate->SetVersion(pContact->GetVersion());
				m_pBin->SetAlive(pContactUpdate);
//------> xt	theApp.emuledlg->kademliawnd->ContactRef(pContactUpdate);
				CKademlia::GetListCtrl()->ContactRef(pContactUpdate);
			}
			return false;
		}
		else if (m_pBin->GetRemaining())
		{
			// This bin is not full, so add the new contact.
			if(m_pBin->AddContact(pContact))
			{
				// Add was successful, add to the GUI and let contact know it's listed in the gui.
//------> xt	if (theApp.emuledlg->kademliawnd->ContactAdd(pContact))
				if (CKademlia::GetListCtrl()->ContactAdd(pContact) && CKademlia::GetHistogramCtrl()->ContactAdd(pContact))
				{
					pContact->SetGuiRefs(true);
				}
				return true;
			}
			return false;
		}
		else if (CanSplit())
		{
			// This bin was full and split, call add on the correct branch.
			Split();
			return m_pSubZones[pContact->GetDistance().GetBitNumber(m_uLevel)]->Add(pContact, bUpdate);
		}
		else
			return false;
	}
}
Exemple #8
0
bool CKademlia::FindIPByNodeID(CKadClientSearcher& rRequester, const uchar* pachNodeID){
	if (!IsRunning() || m_pInstance == NULL || GetUDPListener() == NULL){
		ASSERT( false );
		return false;
	}
	// first search our known contacts if we can deliver a result without asking, otherwise forward the request
	CContact* pContact;
	if ((pContact = GetRoutingZone()->GetContact(CUInt128(pachNodeID))) != NULL){
		// make sure that this entry is not too old, otherwise just do a search to be sure
		if (pContact->GetLastSeen() != 0 && time(NULL) - pContact->GetLastSeen() < 1800){
			rRequester.KadSearchIPByNodeIDResult(KCSR_SUCCEEDED, ntohl(pContact->GetIPAddress()), pContact->GetTCPPort());
			return true;
		}
	}
	return CSearchManager::FindNodeSpecial(CUInt128(pachNodeID), &rRequester);
}
Exemple #9
0
bool CKademlia::FindNodeIDByIP(CKadClientSearcher& rRequester, uint32_t dwIP, uint16_t nTCPPort, uint16_t nUDPPort) {
	if (!IsRunning() || m_pInstance == NULL || GetUDPListener() == NULL || GetRoutingZone() == NULL){
		ASSERT( false );
		return false;
	}
	// first search our known contacts if we can deliver a result without asking, otherwise forward the request
	CContact* pContact;
	if ((pContact = GetRoutingZone()->GetContact(ntohl(dwIP), nTCPPort, true)) != NULL){
		uchar uchID[16];
		pContact->GetClientID().ToByteArray(uchID);
		rRequester.KadSearchNodeIDByIPResult(KCSR_SUCCEEDED, uchID);
		return true;
	}
	else
		return GetUDPListener()->FindNodeIDByIP(&rRequester, ntohl(dwIP), nTCPPort, nUDPPort);
}
bool CRoutingZone::VerifyContact(const CUInt128& id, uint32_t ip)
{
    CContact* contact = GetContact(id);
    if (contact == NULL) {
        return false;
    } else if (ip != contact->GetIPAddress()) {
        return false;
    } else {
        if (contact->IsIPVerified()) {
            LogKadLine(LOG_DEBUG /*logKadRouting*/, L"Sender already verified (sender: %s)", IPToStr(ip).c_str());
        } else {
            contact->SetIPVerified(true);
        }
        return true;
    }
}
Exemple #11
0
TInt CPhoneBkEngine::compareName(const CContact& aFirst,
        const CContact& aSecond)
    {
    HBufC* name1 = HBufC::NewL(128);
    CleanupStack::PushL(name1);
    HBufC* name2 = HBufC::NewL(128);
    CleanupStack::PushL(name2);

    aFirst.Name(name1, false);
    aSecond.Name(name2, false);

    TInt comparison = name1->CompareC(*name2, 3 /* string level */, NULL);
    CleanupStack::PopAndDestroy(2);

    return comparison;
    }
void CRoutingZone::DbgWriteBootstrapFile()
{
	DebugLogWarning(_T("Writing special bootstrap nodes.dat - not intended for normal use"));
	try
	{
		// Write a saved contact list.
		CUInt128 uID;
		CSafeBufferedFile file;
		CFileException fexp;
		if (file.Open(m_sFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary|CFile::shareDenyWrite, &fexp))
		{
			setvbuf(file.m_pStream, NULL, _IOFBF, 32768);

			// The bootstrap method gets a very nice sample of contacts to save.
			ContactMap mapContacts;
			CUInt128 uRandom(CUInt128((ULONG)0), 0);
			CUInt128 uDistance = uRandom;
			uDistance.Xor(uMe);
			GetClosestTo(2, uRandom, uDistance, 1200, &mapContacts, false, false);
			// filter out Kad1 nodes
			for (ContactMap::iterator itContactMap = mapContacts.begin(); itContactMap != mapContacts.end(); )
			{
				ContactMap::iterator itCurContactMap = itContactMap;
				++itContactMap;
				CContact* pContact = itCurContactMap->second;
				if (pContact->GetVersion() <= 1)
					mapContacts.erase(itCurContactMap);
			}
			// Start file with 0 to prevent older clients from reading it.
			file.WriteUInt32(0);
			// Now tag it with a version which happens to be 2 (1 till 0.48a).
			file.WriteUInt32(3);
			file.WriteUInt32(1); // if we would use version >=3, this would mean that this is not a normal nodes.dat
			file.WriteUInt32((uint32_t)mapContacts.size());
			for (ContactMap::const_iterator itContactMap = mapContacts.begin(); itContactMap != mapContacts.end(); ++itContactMap)
			{
				CContact* pContact = itContactMap->second;
				pContact->GetClientID(&uID);
				file.WriteUInt128(&uID);
				file.WriteUInt32(pContact->GetIPAddress());
				file.WriteUInt16(pContact->GetUDPPort());
				file.WriteUInt16(pContact->GetTCPPort());
				file.WriteUInt8(pContact->GetVersion());
			}
			file.Close();
			AddDebugLogLine( false, _T("Wrote %ld contact to bootstrap file."), mapContacts.size());
		}
		else
			DebugLogError(_T("Unable to store Kad file: %s"), m_sFilename);
	}
	catch (CFileException* e)
	{
		e->Delete();
		AddDebugLogLine(false, _T("CFileException in CRoutingZone::writeFile"));
	}

}
// Returns true if a contact was added or updated, false if the routing table was not touched.
bool CRoutingZone::AddUnfiltered(const CUInt128& id, uint32_t ip, uint16_t port, uint16_t tport, uint8_t version, const CKadUDPKey& key, bool& ipVerified, bool update, bool fromHello)
{
    if (id != me) {
        CContact *contact = new CContact(id, ip, port, tport, version, key, ipVerified);
        if (fromHello) {
            contact->SetReceivedHelloPacket();
        }
        if (Add(contact, update, ipVerified)) {
            ASSERT(!update);
            return true;
        } else {
            delete contact;
            return update;
        }
    }
    return false;
}
bool CRoutingZone::VerifyContact(const CUInt128 &uID, uint32_t uIP){
	CContact* pContact = GetContact(uID);
	if (pContact == NULL){
		return false;
	}
	else if (uIP != pContact->GetIPAddress())
		return false;
	else {
		if (pContact->IsIpVerified())
			DebugLogWarning(_T("Kad: VerifyContact: Sender already verified (sender: %s)"), ipstr(ntohl(uIP)));
		else{
			pContact->SetIpVerified(true);
			theApp.emuledlg->kademliawnd->ContactRef(pContact);
		}
		return true;
	}
}
void CRoutingBin::setAlive(uint32 ip, uint16 port)
{
	if (m_entries.empty())
		return;

	CContact *c;
	ContactList::iterator it;
	for (it = m_entries.begin(); it != m_entries.end(); it++)
	{
		c = *it;
		if ((ip == c->getIPAddress()) && (port == c->getUDPPort()))
		{
			c->updateType();
			break;
		}
	}
}
bool CRoutingZone::IsAcceptableContact(const CContact *toCheck) const
{
    // Check if we know a contact with the same ID or IP but notmatching IP/ID and other limitations, similar checks like when adding a node to the table except allowing duplicates
    // we use this to check KADEMLIA_RES routing answers on searches
    if (toCheck->GetVersion() <= 1) {
        // No Kad1 contacts allowed
        return false;
    }
    CContact *duplicate = GetContact(toCheck->GetClientID());
    if (duplicate != NULL) {
        if ((duplicate->IsIPVerified() && duplicate->GetIPAddress() != toCheck->GetIPAddress()) || duplicate->GetUDPPort() != toCheck->GetUDPPort()) {
            // already existing verified node with different IP
            return false;
        } else {
            // node exists already in our routing table, that's fine
            return true;
        }
    }
    // if the node is not yet known, check if our IP limitations would hit
    return CRoutingBin::CheckGlobalIPLimits(toCheck->GetIPAddress(), toCheck->GetUDPPort());
}
void CRoutingBin::setTCPPort(uint32 ip, uint16 port, uint16 tcpPort)
{
	if (m_entries.empty())
		return;

	CContact *c;
	ContactList::iterator it;
	for (it = m_entries.begin(); it != m_entries.end(); it++)
	{
		c = *it;
		if ((ip == c->getIPAddress()) && (port == c->getUDPPort()))
		{
			c->setTCPPort(tcpPort);
			c->updateType();
			// Move to the end of the list
			remove(c);
			m_entries.push_back(c);
			break;
		}
	}
}
void CRoutingZone::WriteFile()
{
	// don't overwrite a bootstrap nodes.dat with an empty one, if we didn't finished probing
	if (!CKademlia::s_liBootstapList.IsEmpty() && GetNumContacts() == 0){
		DebugLogWarning(_T("Skipped storing nodes.dat, because we have an unfinished bootstrap of the nodes.dat version and no contacts in our routing table"));
		return;
	}
	try
	{
		// Write a saved contact list.
		CUInt128 uID;
		CSafeBufferedFile file;
		CFileException fexp;
		if (file.Open(m_sFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary|CFile::shareDenyWrite, &fexp))
		{
			setvbuf(file.m_pStream, NULL, _IOFBF, 32768);

			// The bootstrap method gets a very nice sample of contacts to save.
			ContactList listContacts;
			GetBootstrapContacts(&listContacts, 200);
			// Start file with 0 to prevent older clients from reading it.
			file.WriteUInt32(0);
			// Now tag it with a version which happens to be 2 (1 till 0.48a).
			file.WriteUInt32(2);
			// file.WriteUInt32(0) // if we would use version >=3, this would mean that this is a normal nodes.dat
			file.WriteUInt32((uint32_t)listContacts.size());
			for (ContactList::const_iterator itContactList = listContacts.begin(); itContactList != listContacts.end(); ++itContactList)
			{
				CContact* pContact = *itContactList;
				pContact->GetClientID(&uID);
				file.WriteUInt128(&uID);
				file.WriteUInt32(pContact->GetIPAddress());
				file.WriteUInt16(pContact->GetUDPPort());
				file.WriteUInt16(pContact->GetTCPPort());
				file.WriteUInt8(pContact->GetVersion());
				pContact->GetUDPKey().StoreToFile(file);
				file.WriteUInt8(pContact->IsIpVerified() ? 1 : 0);
			}
			file.Close();
			AddDebugLogLine( false, _T("Wrote %ld contact%s to file."), listContacts.size(), ((listContacts.size() == 1) ? _T("") : _T("s")));
		}
		else
			DebugLogError(_T("Unable to store Kad file: %s"), m_sFilename);
	}
	catch (CFileException* e)
	{
		e->Delete();
		AddDebugLogLine(false, _T("CFileException in CRoutingZone::writeFile"));
	}
}
Exemple #19
0
void CMainApp::OnResolverResponse(wxThreadEvent& event)
{
  unsigned key = event.GetInt();
  unsigned data = event.GetExtraLong();
  CContact c = event.GetPayload<CContact>();
  CJournalEntry *pE = findActiveEntry(key);
  if (pE != NULL) {
    if (data == RESOLVE_CALLER) {
      pE->setCallerName(c.getSN());
      if (pE->getType() == CJournalEntry::J_INCOMING) {
        pE->setImage(c.getImage());
      }
    } else if (data == RESOLVE_CALLED) {
      pE->setCalledName(c.getSN());
      if (pE->getType() == CJournalEntry::J_OUTGOING) {
        pE->setImage(c.getImage());
      }
    }
    m_pJournalModel->insertUpdateEntry(*pE);
  }
  else {
    CJournalEntry e;
    if (findJournalEntry(key, e)) {
      if (data == RESOLVE_CALLER) e.setCallerName(c.getSN());
      if (data == RESOLVE_CALLED) e.setCalledName(c.getSN());
      m_pJournalModel->insertUpdateEntry(e);
    }
  }
}
// Returns true if a contact was added or updated, false if the routing table was not touched
bool CRoutingZone::AddUnfiltered(const CUInt128 &uID, uint32_t uIP, uint16_t uUDPPort, uint16_t uTCPPort, uint8_t uVersion, CKadUDPKey cUDPKey, bool& bIPVerified, bool bUpdate, bool bFromNodesDat, bool bFromHello)
{
	if (uID != uMe)
	{
		// JOHNTODO -- How do these end up leaking at times?
		CContact* pContact = new CContact(uID, uIP, uUDPPort, uTCPPort, uVersion, cUDPKey, bIPVerified);
		if (bFromNodesDat)
			pContact->CheckIfKad2(); // do not test nodes which we loaded from our nodes.dat for Kad2 again
		else if (bFromHello)
			pContact->SetReceivedHelloPacket();

		if (Add(pContact, bUpdate, bIPVerified)){
			ASSERT( !bUpdate );
			return true;
		}
		else{
			delete pContact;
			return bUpdate;
		}
	}
	return false;
}
bool CRoutingZone::IsAcceptableContact(const CContact* pToCheck) const
{
	// Check if we know a conact with the same ID or IP but notmatching IP/ID and other limitations, similar checks like when adding a node to the table except allowing duplicates
	// we use this to check KADEMLIA_RES routing answers on searches
	CContact* pDuplicate = GetContact(pToCheck->GetClientID());
	if (pDuplicate != NULL)
	{
		if (pDuplicate->IsIpVerified() 
			&& (pDuplicate->GetIPAddress() != pToCheck->GetIPAddress() || pDuplicate->GetUDPPort() != pToCheck->GetUDPPort()))
		{
			// already existing verfied node with different IP
			return false;
		}
		else
			return true; // node exists already in our routing table, thats fine
	}
	// if the node is not yet know, check if we out IP limitations would hit
#ifdef _DEBUG
	return CRoutingBin::CheckGlobalIPLimits(pToCheck->GetIPAddress(), pToCheck->GetUDPPort(), true);
#else
	return CRoutingBin::CheckGlobalIPLimits(pToCheck->GetIPAddress(), pToCheck->GetUDPPort(), false);
#endif
}
Exemple #22
0
void CSQLiteAddressbook::deleteEntry(const CContact& c)
{
  if (isOk())
  {
    soci::session session(m_conn_pool);
    int contactkey    = (int) c.getDbKey();
    try
    {
      if (contactkey != 0) {
        session.begin();
        session << "delete from contacts "
                   "where id = :id", use(contactkey);
        session.commit();
      }
    }
    catch (const std::exception& e) {
      m_strLastError = e.what();
      session.rollback();
      wxMessageBox(wxString::FromUTF8(
          m_strLastError.data(), m_strLastError.length()),
          wxT("SQLite Plugin"), wxOK|wxICON_ERROR);
    }
  }
}
Exemple #23
0
void CRoutingZone::WriteFile()
{
	try
	{
		// Write a saved contact list.
		CUInt128 uID;
		//CSafeBufferedFile file;
		CBufferedFileIO file;
		CFileException fexp;
		if (file.Open(m_sFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary|CFile::shareDenyWrite, &fexp))
		{
			setvbuf(file.m_pStream, NULL, _IOFBF, 32768);

			// The bootstrap method gets a very nice sample of contacts to save.
			ContactList listContacts;
			GetBootstrapContacts(&listContacts, 200);
			// Start file with 0 to prevent older clients from reading it.
			file.WriteUInt32(0);
			// Now tag it with a version which happens to be 1.
			file.WriteUInt32(1);
			file.WriteUInt32((uint32)listContacts.size());
			for (ContactList::const_iterator itContactList = listContacts.begin(); itContactList != listContacts.end(); ++itContactList)
			{
				CContact* pContact = *itContactList;
				pContact->GetClientID(&uID);
				file.WriteUInt128(&uID);
				file.WriteUInt32(pContact->GetIPAddress());
				file.WriteUInt16(pContact->GetUDPPort());
				file.WriteUInt16(pContact->GetTCPPort());
				file.WriteUInt8(pContact->GetVersion());
			}
			file.Close();
			//AddDebugLogLine( false, _T("Wrote %ld contact%s to file."), listContacts.size(), ((listContacts.size() == 1) ? _T("") : _T("s")));
			TRACE(_T("Wrote %ld contact%s to file.\n"), listContacts.size(), ((listContacts.size() == 1) ? _T("") : _T("s")));
		}
	}
	catch (CFileException* e)
	{
		e->Delete();
		AddDebugLogLine(false, _T("CFileException in CRoutingZone::writeFile"));
	}
}
Exemple #24
0
void CUDPFirewallTester::QueryNextClient(){ // try the next available client for the firewallcheck
	
	if (!IsFWCheckUDPRunning() || !GetUDPCheckClientsNeeded() || CKademlia::GetPrefs()->GetExternalKadPort() == 0)
		return; // check if more tests are needed and wait till we know our extern port

	if (!CKademlia::IsRunning() || CKademlia::GetRoutingZone() == NULL){
		ASSERT( false );
		return;
	}

	while (!m_liPossibleTestClients.IsEmpty()){
		CContact curContact = m_liPossibleTestClients.RemoveHead();
		// udp firewallchecks are not supported by clients with kadversion < 6
		if (curContact.GetVersion() <= KADEMLIA_VERSION5_48a)
			continue;

		// sanitize - do not test ourself
		if (ntohl(curContact.GetIPAddress()) == theApp.GetPublicIP() || curContact.GetClientID().CompareTo(CKademlia::GetPrefs()->GetKadID()) == 0)
			continue;

		// check if we actually requested a firewallcheck from this client at some point
		bool bAlreadyRequested = false;
		for (POSITION pos = m_liUsedTestClients.GetHeadPosition(); pos != NULL;){
			if (m_liUsedTestClients.GetNext(pos).contact.GetIPAddress() == curContact.GetIPAddress()){
				bAlreadyRequested = true;
				break;
			}
		}
		// check if we know itsIP already from kademlia - we need an IP which was never used for UDP yet
		if (!bAlreadyRequested && CKademlia::GetRoutingZone()->GetContact(curContact.GetIPAddress(), 0, false) == NULL){
			// ok, tell the clientlist to do the same search and start the check if ok
			if (theApp.clientlist->DoRequestFirewallCheckUDP(curContact)){
				UsedClient_Struct sAdd = { curContact, false };
				m_liUsedTestClients.AddHead(sAdd);
				m_byFWChecksRunningUDP++;
				break;
			}
		}
	}
}
LPMAPIFOLDER CExMapi::GetContacts(LPMAPIFOLDER pFolder,LONG& folderCount,LONG& contactCount,LONG& skipCount,LONG& contactIndex,CObArray& contactArray,BOOL doLog)
{
	__recursionCount++;
	wchar_t buffer[5];
	_itow(__recursionCount,buffer,10);
	if(doLog)
	{
		if(__recursionCount > 1)
			m_logHelper.LogPAB(L"-------------------------------------");
		m_logHelper.LogPAB(L"Recursive Call No: "+CString(buffer));
		m_logHelper.LogPAB(L"-------------------------------------");
	}
	CString strFilterBy = m_pCtrl->GetPABSerachBy();
	CString strStartWith = m_pCtrl->GetPABSerachStartWith();
	strStartWith = strStartWith.MakeLower();
	ULONG pageSize;
	m_pCtrl->get_PABPageSize(&pageSize);
	LONG pageNumber = m_pCtrl->GetPABPageNumber();
	LONG startIndex = -1;
	if(pageSize>0)
	{
		startIndex = (pageSize * pageNumber) - pageSize;
	}

	LPMAPIFOLDER pSubFolder=NULL;
	LPMAPITABLE pHierarchy;
	CString strFolder;

	try
	{
		if(doLog)
			m_logHelper.LogPAB(L"RELEASE(m_pHierarchy); START");

		RELEASE(m_pHierarchy);
		
		if(doLog)
			m_logHelper.LogPAB(L"RELEASE(m_pHierarchy); END");

		if(doLog)
			m_logHelper.LogPAB(L"pHierarchy = GetHierarchy(pFolder); START");

		pHierarchy = GetHierarchy(pFolder);

		if(doLog)
			m_logHelper.LogPAB(L"pHierarchy = GetHierarchy(pFolder); END");

		if(pHierarchy) 
		{
			LPMAPIFOLDER pRecurse = NULL;
			do 
			{
				RELEASE(pSubFolder);
				m_pHierarchy = pHierarchy;			

				if(doLog)
					m_logHelper.LogPAB(L"pSubFolder = GetNextSubFolder(strFolder,pFolder); START");

				pSubFolder = GetNextSubFolder(strFolder,pFolder);

				if(doLog)
					m_logHelper.LogPAB(L"pSubFolder = GetNextSubFolder(strFolder,pFolder); END");
			
				if(pSubFolder) 
				{
					//if(strFolder == L"Deleted Items")
					//	continue;

					if(IsContactFolder(pSubFolder))
					{
						folderCount++;
	 					if(doLog)
							m_logHelper.LogPAB(L"if(GetContents(pSubFolder)) START");

						if(GetContents(pSubFolder))
						{
							if(doLog)
								m_logHelper.LogPAB(L"if(GetContents(pSubFolder)) END");

							SortContents(TABLE_SORT_ASCEND,PR_DISPLAY_NAME);
							//SortContents(TABLE_SORT_ASCEND,PR_SUBJECT);

							CString strText;
							CExMapiContact mapiContact;
							CString name;
							CString email;
							BOOL mustFilter = FALSE;
							mustFilter = strStartWith != "";
							
							if(doLog)
								m_logHelper.LogPAB(L"Start Reading Contact properties");

							while(GetNextContact(mapiContact) && !m_pCtrl->IsPABSearchAbort()) 
							{
								if(pageSize > 0)
								{
									if(contactCount == pageSize)
									{
										break;								
									}
								}

								contactIndex++;
								if(mustFilter)
								{
									if(strFilterBy == "Name")
									{
										mapiContact.GetName(name,PR_GIVEN_NAME);
										name = name.MakeLower();
										if(name.Find(strStartWith) != 0)				
										{
											continue;									
										}
									}

									if(strFilterBy == "Email")
									{
										mapiContact.GetEmail(email);
										email = email.MakeLower();
										if(email.Find(strStartWith) != 0)
										{
											continue;
										}
									}																
								}
								if(startIndex > 0 && skipCount < startIndex)
								{
									skipCount++;
									continue;								
								}

								CContact* pContact = new CContact();

								pContact->SetId(contactIndex);

								pContact->SetFolderName(strFolder);

								mapiContact.GetName(strText);
								pContact->SetFullName(strText);

								mapiContact.GetCompany(strText);
								pContact->SetCompany(strText);

								mapiContact.GetIMAddress(strText);
								pContact->SetIMAddress(strText);

								mapiContact.GetName(strText,PR_GIVEN_NAME);
								pContact->SetFirstName(strText);

								mapiContact.GetName(strText,PR_MIDDLE_NAME);
								pContact->SetMiddleName(strText);

								mapiContact.GetName(strText,PR_SURNAME);
								pContact->SetLastName(strText);

								mapiContact.GetEmail(strText);
								pContact->SetEmail(strText);	

								mapiContact.GetEmail(strText,2);//Email 2
								pContact->SetEmail2(strText);

								mapiContact.GetEmail(strText,3);//Email 3
								pContact->SetEmail3(strText);

								mapiContact.GetPhoneNumber(strText,PR_BUSINESS_TELEPHONE_NUMBER);
								pContact->SetBusinessPhone(strText);

								mapiContact.GetPhoneNumber(strText,PR_COMPANY_MAIN_PHONE_NUMBER);
								pContact->SetCompanyPhone(strText);

								mapiContact.GetPhoneNumber(strText,PR_BUSINESS_FAX_NUMBER);
								pContact->SetFax(strText);

								mapiContact.GetPhoneNumber(strText,PR_MOBILE_TELEPHONE_NUMBER);
								pContact->SetMobilePhone(strText);

								mapiContact.GetPhoneNumber(strText,PR_HOME_TELEPHONE_NUMBER);
								pContact->SetHomePhone(strText);

								if(m_pCtrl->FetchUnique())
								{
									BOOL isContactExist = FALSE;
									for(int i=0;i<contactArray.GetCount();i++)
									{
										CContact* pTemp = (CContact*)contactArray.GetAt(i);

										if(pContact->GetEmail() != "" && pTemp->GetEmail() == pContact->GetEmail())
										{
											isContactExist = TRUE;
											break;																	
										}
										else if(pContact->GetFullName() != "" && pTemp->GetFullName() == pContact->GetFullName())
										{
											isContactExist = TRUE;
											break;
										}
										else if(pContact->GetMobilePhone() != "" && pTemp->GetMobilePhone() == pContact->GetMobilePhone())
										{
											isContactExist = TRUE;
											break;
										}
										else if(pContact->GetHomePhone() != "" && pTemp->GetHomePhone() == pContact->GetHomePhone())
										{
											isContactExist = TRUE;
											break;
										}
										else if(pContact->GetBusinessPhone() != "" && pTemp->GetBusinessPhone() == pContact->GetBusinessPhone())
										{
											isContactExist = TRUE;
											break;
										}
									}

									if(isContactExist)
									{
										continue;
									}
								}														
								contactArray.Add(pContact);							
								contactCount++;							
							}
						}
					}

					m_pHierarchy = NULL; // so we don't release it in subsequent drilldown
					if(pageSize > 0)
					{
						if(contactCount == pageSize)
							break;								
					}
					
					if(__recursionCount < m_pCtrl->GetSubFOlderLevel())
					{
						pRecurse = GetContacts(pSubFolder,folderCount,contactCount,skipCount,contactIndex,contactArray,doLog);
					}
					if(pRecurse) 
					{
						RELEASE(pSubFolder);
						pSubFolder = pRecurse;
						break;
					}
				}
				else
				{
					__recursionCount = 1;
				}
				if(pageSize > 0)
				{
					if(contactCount == pageSize)
						break;								
				}

			} while(pSubFolder && !m_pCtrl->IsPABSearchAbort());
			RELEASE(pHierarchy);
			m_pHierarchy=NULL;
		}
		// this may occur many times depending on how deep the recursion is; make sure we haven't already assigned m_pFolder
		if(pSubFolder && m_pFolder!=pSubFolder) {
			RELEASE(m_pFolder);
			m_pFolder=pSubFolder;
		}
	}
	catch(_com_error &e)
	{
		if(doLog)
		{
			m_logHelper.LogPAB(L"GetContactFolderCount Exception Catch START:");
			m_logHelper.LogPAB(L"FolderName: " + strFolder );
			m_logHelper.LogPAB(e.ErrorMessage());
			m_logHelper.LogPAB(L"GetContactFolderCount Exception Catch END:");
		}
	}
	return pSubFolder;
} 
BOOL CExMapi::GetContacts(CObArray& contactArray,CTRError& error)
{
	BOOL doLog = m_pCtrl->IsEnableLog();
	if(doLog)
	{
		m_logHelper.LogPAB(L"------------------------------------");
		m_logHelper.LogPAB(L"Function GetPABCotacts START:");
		m_logHelper.LogPAB(L"------------------------------------");
	}

	CString strFilterBy = m_pCtrl->GetPABSerachBy();
	CString strStartWith = m_pCtrl->GetPABSerachStartWith();
	strStartWith = strStartWith.MakeLower();
	ULONG pageSize;
	m_pCtrl->get_PABPageSize(&pageSize);
	ULONG pageNumber = m_pCtrl->GetPABPageNumber();
	LONG contactCount = 0;
	LONG skipCount = 0;
	LONG startIndex = -1;
	LONG contactIndex = 0;
	LONG folderCount = 0;
	if(pageSize>0)
	{
		startIndex = (pageSize * pageNumber) - pageSize;
	}

	CString strFolder;
	int msgStoreCount = 0;
	wchar_t buffer[5];

	LPMAPIFOLDER pSubFolder=NULL;	
	LPMAPITABLE lpMsgStoreTable = NULL;
	lpMsgStoreTable = GetMessageStoresTable();	
	if(lpMsgStoreTable)
	{
		while(OpenNextMessageStore(lpMsgStoreTable))
		{	
			//GetContacts(OpenRootFolder(),folderCount,contactCount,skipCount,contactIndex,contactArray);

			msgStoreCount++;
			_itow(msgStoreCount,buffer,10);
			if(doLog)
			{
				if(msgStoreCount > 1)
					m_logHelper.LogPAB(L"-------------------------------------");
				m_logHelper.LogPAB(L"Message Store No : "+CString(buffer));
				m_logHelper.LogPAB(L"-------------------------------------");
			}

			pSubFolder = OpenContacts();
			if(pSubFolder && IsContactFolder(pSubFolder))
			{
				if(doLog)
					m_logHelper.LogPAB(L"Open Main Contacts Folder");

				strFolder = GetFolderName(pSubFolder);
				folderCount++;
				if(GetContents(pSubFolder))
				{
					SortContents(TABLE_SORT_ASCEND,PR_DISPLAY_NAME);
					//SortContents(TABLE_SORT_ASCEND,PR_SUBJECT);

					CString strText;
					CExMapiContact mapiContact;
					CString name;
					CString email;
					BOOL mustFilter = FALSE;
					mustFilter = strStartWith != "";
					
					if(doLog)
						m_logHelper.LogPAB(L"Start reading contacts from main contact fodler");

					while(GetNextContact(mapiContact) && !m_pCtrl->IsPABSearchAbort()) 
					{
						if(pageSize > 0)
						{
							if(contactCount == pageSize)
							{
								break;								
							}
						}

						contactIndex++;
						if(mustFilter)
						{
							if(strFilterBy == "Name")
							{
								mapiContact.GetName(name,PR_GIVEN_NAME);
								name = name.MakeLower();
								if(name.Find(strStartWith) != 0)				
								{
									continue;									
								}
							}

							if(strFilterBy == "Email")
							{
								mapiContact.GetEmail(email);
								email = email.MakeLower();
								if(email.Find(strStartWith) != 0)
								{
									continue;
								}
							}																
						}
						if(startIndex > 0 && skipCount < startIndex)
						{
							skipCount++;
							continue;								
						}

						CContact* pContact = new CContact();

						pContact->SetId(contactIndex);

						pContact->SetFolderName(strFolder);

						mapiContact.GetName(strText);
						pContact->SetFullName(strText);

						mapiContact.GetCompany(strText);
						pContact->SetCompany(strText);

						mapiContact.GetIMAddress(strText);
						pContact->SetIMAddress(strText);

						mapiContact.GetName(strText,PR_GIVEN_NAME);
						pContact->SetFirstName(strText);

						mapiContact.GetName(strText,PR_MIDDLE_NAME);
						pContact->SetMiddleName(strText);

						mapiContact.GetName(strText,PR_SURNAME);
						pContact->SetLastName(strText);

						mapiContact.GetEmail(strText);
						pContact->SetEmail(strText);	

						mapiContact.GetEmail(strText,2);//Email 2
						pContact->SetEmail2(strText);

						mapiContact.GetEmail(strText,3);//Email 3
						pContact->SetEmail3(strText);

						mapiContact.GetPhoneNumber(strText,PR_BUSINESS_TELEPHONE_NUMBER);
						pContact->SetBusinessPhone(strText);

						mapiContact.GetPhoneNumber(strText,PR_COMPANY_MAIN_PHONE_NUMBER);
						pContact->SetCompanyPhone(strText);

						mapiContact.GetPhoneNumber(strText,PR_BUSINESS_FAX_NUMBER);
						pContact->SetFax(strText);

						mapiContact.GetPhoneNumber(strText,PR_MOBILE_TELEPHONE_NUMBER);
						pContact->SetMobilePhone(strText);

						mapiContact.GetPhoneNumber(strText,PR_HOME_TELEPHONE_NUMBER);
						pContact->SetHomePhone(strText);

						if(m_pCtrl->FetchUnique())
						{
							BOOL isContactExist = FALSE;
							for(int i=0;i<contactArray.GetCount();i++)
							{
								CContact* pTemp = (CContact*)contactArray.GetAt(i);

								if(pContact->GetEmail() != "" && pTemp->GetEmail() == pContact->GetEmail())
								{
									isContactExist = TRUE;
									break;																	
								}
								else if(pContact->GetFullName() != "" && pTemp->GetFullName() == pContact->GetFullName())
								{
									isContactExist = TRUE;
									break;
								}
								else if(pContact->GetMobilePhone() != "" && pTemp->GetMobilePhone() == pContact->GetMobilePhone())
								{
									isContactExist = TRUE;
									break;
								}
								else if(pContact->GetHomePhone() != "" && pTemp->GetHomePhone() == pContact->GetHomePhone())
								{
									isContactExist = TRUE;
									break;
								}
								else if(pContact->GetBusinessPhone() != "" && pTemp->GetBusinessPhone() == pContact->GetBusinessPhone())
								{
									isContactExist = TRUE;
									break;
								}
							}

							if(isContactExist)
							{
								continue;
							}
						}														
						contactArray.Add(pContact);							
						contactCount++;							
					}
				}
				if(doLog)
					m_logHelper.LogPAB(L"Open Sub Contacts Folder");
				GetContacts(pSubFolder,folderCount,contactCount,skipCount,contactIndex,contactArray,doLog);
			}
			if(pageSize > 0)
			{
				if(contactCount == pageSize)
					break;								
			}
			if(m_pCtrl->IsPABSearchAbort())
				break;
			__recursionCount = 0;
		}
	}	
	if(doLog)
	{
		m_logHelper.LogPAB(L"------------------------------------");
		m_logHelper.LogPAB(L"Function GetPABCotacts END:");
		m_logHelper.LogPAB(L"------------------------------------");	
		m_logHelper.ClosePABLog();
	}
	__recursionCount = 0;
	RELEASE(lpMsgStoreTable);		

	if(folderCount == 0 && !m_pCtrl->IsPABSearchAbort())
	{
		error.code = 107;
		error.err = "TRContactFinder Cannot find private folders.";
		return FALSE;
	}

	return TRUE;
}
Exemple #27
0
TBool CVoIPForm::SaveFormDataL()
    {
    CVoIPAppUi* iAppUi = static_cast<CVoIPAppUi*> (iEikonEnv->EikAppUi());
    CVoIPDocument* iDocument =
            static_cast<CVoIPDocument*> (iAppUi->Document());

    TInt iModifyIndex = iDocument->ModifyIndex();
    RPointerArray<CContact> contacts = iAppUi->GetPhoneBook()->GetContactsL();

    if (iModifyIndex >= 0)
        {
        CContact* contact = contacts[iModifyIndex];

        if (contact)
            {
            iAppUi->GetPhoneBook()->DeleteContactItem(contact->GetEntryId());

            TContactItemId contactItemId =
                    iAppUi->GetPhoneBook()->CreateDefaultContactItem();

            contact->SetEntryId(contactItemId);

            CPbkContactItem* contactItem =
                    iAppUi->GetPhoneBook()->OpenContactItemLCX(contactItemId);

            TInt pageId = ActivePageId();

            RArray<CEikCaptionedControl*> aControls;

            ControlsOnPage(aControls, pageId);

            for (TInt i = 0; i < aControls.Count(); i++)
                {
                CEikCaptionedControl* control =
                        ((CEikCaptionedControl*) aControls[i]);

                TPbkContactItemField* field = contactItem->FindField(
                        control->iId);

                if (field == NULL)
                    {
                    CPbkFieldInfo* fieldInfo =
                            iAppUi->GetPhoneBook()->GetFieldsInfo().Find(
                                    control->iId);
                    contactItem->AddFieldL(*fieldInfo);
                    field = contactItem->FindField(control->iId);
                    }

                field->SetLabelL(control->GetFullCaptionText());

                CPbkFieldInfo& fieldInfo = field->FieldInfo();
                if (fieldInfo.CtrlType() == EPbkFieldCtrlTypeDateEditor)
                    {
                    CEikDateEditor* nEditor =
                            static_cast<CEikDateEditor*> (ControlOrNull(
                                    control->iId));
                    TTime time = nEditor->Date();
                    field->DateTimeStorage()->SetTime(time);
                    }
                else
                    {
                    CEikEdwin* nEditor =
                            static_cast<CEikEdwin*> (ControlOrNull(
                                    control->iId));
                    HBufC* text = nEditor->GetTextInHBufL();
                    field->TextStorage()->SetText(text);
                    }
                }

            aControls.Reset();

            iAppUi->GetPhoneBook()->CommitContactItem(contactItem);
            CleanupStack::PopAndDestroy(2); //OpenContactItemLCX
            }
        }
    return ETrue;
    }
Exemple #28
0
void CVoIPForm::LoadFormValuesFromDataL()
    {
    TInt pageId = ActivePageId();

    // Delete all controls not saved.

    RArray<CEikCaptionedControl*> aControls;

    ControlsOnPage(aControls, pageId);

    for (TInt i = 0; i < aControls.Count(); i++)
        {
        CEikCaptionedControl* control =
                ((CEikCaptionedControl*) aControls[i]);
        DeleteLine(control->iId, EFalse);
        }

    aControls.Reset();

    // Create controls based on PhoneBook contact item.

    CVoIPAppUi* iAppUi = static_cast<CVoIPAppUi*> (iEikonEnv->EikAppUi());
    CVoIPDocument* iDocument =
            static_cast<CVoIPDocument*> (iAppUi->Document());

    TInt iModifyIndex = iDocument->ModifyIndex();
    RPointerArray<CContact> contacts = iAppUi->GetPhoneBook()->GetContactsL();

    if (iModifyIndex >= 0)
        {
        CContact* contact = contacts[iModifyIndex];

        if (contact)
            {
            CPbkContactItem* contactItem =
                    iAppUi->GetPhoneBook()->ReadContactItemLC(
                            contact->GetEntryId());

            CPbkFieldArray& fieldArray = contactItem->CardFields();

            for (TInt i = 0; i < fieldArray.Count(); i++)
                {
                TPbkContactItemField field = fieldArray[i];
                if (field.IsEmpty() == EFalse)
                    {
                    CPbkFieldInfo& fieldInfo = field.FieldInfo();
                    TInt id = fieldInfo.FieldId();
                    TAny* unused = 0;

                    if (fieldInfo.CtrlType() == EPbkFieldCtrlTypeTextEditor)
                        {
                        TInt type = EEikCtEdwin;

                        CEikEdwin * nEditor =
                                static_cast<CEikEdwin*> (ControlOrNull(id));
                        if (!nEditor)
                            {
                            CEikEdwin* edwin =
                                    (CEikEdwin*) CreateLineByTypeL(
                                            field.Label(), pageId, id, type,
                                            unused);

                            edwin->ConstructL(EEikEdwinNoHorizScrolling
                                    | EEikEdwinResizable, 10, 100, 1);

                            edwin->SetTextL(&(field.Text()));
                            }
                        }
                    else if (fieldInfo.CtrlType()
                            == EPbkFieldCtrlTypeNumberEditor)
                        {
                        TInt type = EAknCtIntegerEdwin;

                        CAknNumericEdwin
                                * nEditor =
                                        static_cast<CAknNumericEdwin*> (ControlOrNull(
                                                id));
                        if (!nEditor)
                            {
                            CAknNumericEdwin* edwin =
                                    (CAknNumericEdwin*) CreateLineByTypeL(
                                            field.Label(), pageId, id, type,
                                            unused);

                            edwin->ConstructL(EEikEdwinNoHorizScrolling
                                    | EEikEdwinResizable, 10, 100, 1);

                            edwin->SetTextL(&(field.Text()));
                            }
                        }
                    else if (fieldInfo.CtrlType()
                            == EPbkFieldCtrlTypeDateEditor)
                        {
                        TInt type = EEikCtDateEditor;

                        CEikDateEditor * nEditor =
                                static_cast<CEikDateEditor*> (ControlOrNull(
                                        id));
                        if (!nEditor)
                            {
                            CEikDateEditor* editor =
                                    (CEikDateEditor*) CreateLineByTypeL(
                                            field.Label(), pageId, id, type,
                                            unused);

                            editor->ConstructL(TTime(mindateTime), TTime(
                                    maxdateTime),
                                    field.DateTimeStorage()->Time(), ETrue);
                            }
                        Line(id)->ActivateL();
                        }
                    }
                }
            SetChangesPending(ETrue);
            UpdatePageL(ETrue);
            CleanupStack::PopAndDestroy(); //contactItem
            }
        }
    }
Exemple #29
0
bool CSQLiteAddressbook::resolve(const wxString& strNumber,
                               CContact& resolvedContact)
{
  bool rc = false;
  if (isOk())
  {
    CPhone phoneNr(CPhone::NT_GENERAL);
    phoneNr.setNumber(strNumber);
    stringstream  ss;
    if (!phoneNr.isInternal()) {
      std::string toSearch = strNumber.Right(6).ToUTF8().data();
      ss << "select cref, canonical from numbers where "
            "replace(replace(replace(replace(replace(canonical,"
            "'+', ''),"
            "'(', ''),"
            "')', ''),"
            "'-', ''),"
            "' ', '')"
            " like '%" << toSearch << "%'";
    } else {
      std::string toSearch = strNumber.ToUTF8().data();
      ss << "select cref, canonical from numbers where "
            "cast(canonical as integer) = " << toSearch;
    }
    soci::session session(m_conn_pool);
    try
    {
      int contactref; std::string canonical;
      indicator i_ref, i_canonical;
      statement phones = ( session.prepare << ss.str(),
                            into(contactref, i_ref),
                            into(canonical, i_canonical)
      );
      phones.execute();
      while(!rc && phones.fetch()) {
        rc = phoneNr.isMatch(canonical);
        wxLogMessage(wxT("Found %s -> %smatch"),
            wxString::From8BitData(canonical.c_str()),
            !rc ? wxT("no ") : wxEmptyString);
      }
      if (rc)
      {
        wxString  str;
        std::string strFN,strMN,strLN,strNN,strSN,strTitle,strOrg,strMail,strPicture;
        indicator i_fn, i_mn, i_ln, i_nn, i_sn, i_title, i_org, i_mail, i_pic;
        session << "select fn,mn,ln,nn,sn,title,org,email,picture from contacts where id = :cref",
              into(strFN, i_fn), into(strMN, i_mn),
              into(strLN, i_ln), into(strNN, i_nn),
              into(strSN, i_sn), into(strTitle, i_title),
              into(strOrg, i_org), into(strMail, i_mail),
              into(strPicture, i_pic), use(contactref);
        resolvedContact.setDbKey(contactref);
        str.Clear();
        if (i_fn == i_ok) str = wxString::FromUTF8(strFN.c_str(), strFN.length());
        resolvedContact.setFN(str);
        str.Clear();
        if (i_mn == i_ok) str = wxString::FromUTF8(strMN.c_str(), strMN.length());
        resolvedContact.setMN(str);
        str.Clear();
        if (i_ln == i_ok) str = wxString::FromUTF8(strLN.c_str(), strLN.length());
        resolvedContact.setLN(str);
        str.Clear();
        if (i_nn == i_ok) str = wxString::FromUTF8(strNN.c_str(), strNN.length());
        resolvedContact.setNN(str);
        str.Clear();
        if (i_sn == i_ok) str = wxString::FromUTF8(strSN.c_str(), strSN.length());
        resolvedContact.setSN(str);
        str.Clear();
        if (i_title == i_ok) str = wxString::FromUTF8(strTitle.c_str(), strTitle.length());
        resolvedContact.setTitle(str);
        str.Clear();
        if (i_org == i_ok) str = wxString::FromUTF8(strOrg.c_str(), strOrg.length());
        resolvedContact.setOrganization(str);
        str.Clear();
        if (i_mail == i_ok) str = wxString::FromUTF8(strMail.c_str(), strMail.length());
        resolvedContact.setEmail(str);
        str.Clear();
        if (i_pic == i_ok) str = wxString::FromUTF8(strPicture.c_str(), strPicture.length());
        resolvedContact.setImage(str);
        wxLogMessage(wxT("Resolved to: %s"), resolvedContact.getSN());
      }
    }
    catch (const std::exception& e) {
      m_strLastError = e.what();
      wxLogError(wxString::FromUTF8(m_strLastError.data(), m_strLastError.length()));
    }
  }
  return rc;
}
Exemple #30
0
void CSQLiteAddressbook::insertUpdateEntry(CContact& c)
{
  if (c.isDirty())
  {
    if (isOk())
    {
      int contactkey    = (int) c.getDbKey();
      std::string strFN = c.getFN().ToUTF8().data();
      std::string strMN = c.getMN().ToUTF8().data();
      std::string strLN = c.getLN().ToUTF8().data();
      std::string strNN = c.getNN().ToUTF8().data();
      std::string strSN = c.getSN().ToUTF8().data();
      std::string strTitle= c.getTitle().ToUTF8().data();
      std::string strOrg = c.getOrganization().ToUTF8().data();
      std::string strMail = c.getEmail().ToUTF8().data();
      std::string strPic = c.getImage().ToAscii().data();
      soci::session session(m_conn_pool);
      try
      {
        session.begin();
        // Save Contact
        if (contactkey == 0) {
          session << "select value from config where kind='nxtcid' limit 1", into(contactkey);
          size_t next_id = contactkey + 1;
          session << "update config set value = :val where kind='nxtcid'", use(next_id);
          session << "insert into contacts (id,fn,mn,ln,nn,sn,title,org,email,picture) "
                     "values (:id,:fn,:mn,:ln,:nn,:sn,:title,:org,:email,:pic)",
                     use(contactkey), use(strFN), use(strMN), use(strLN), use(strNN),
                     use(strSN), use(strTitle), use(strOrg), use(strMail),
                     use(strPic);
          c.setDbKey(contactkey);
        } else {
          session << "update contacts set fn=:fn,mn=:mn,ln=:ln,nn=:nn,"
                     "sn=:sn,title=:title,org=:org,email=:email,picture=:pic "
                     "where id = :id",
                     use(strFN), use(strMN), use(strLN), use(strNN), use(strSN),
                     use(strTitle), use(strOrg), use(strMail), use(strPic),
                     use(contactkey);
        }
        // Save Numbers
        stringstream  ssKeys;
        TPhoneList& lPhones = c.getPhones();
        if (lPhones.size())
        {
          ssKeys << "delete from numbers where cref = :cref and id not in (";
          for (int pidx = 0; pidx < lPhones.size(); ++pidx)
          {
            long long phonekey = lPhones[pidx].getDbKey();
            int phoneType = lPhones[pidx].getType();
            std::string strCanonical = lPhones[pidx].getNumber().ToAscii().data();
            std::string strNote = lPhones[pidx].getNote().ToUTF8().data();
            if (phonekey == 0) {
              session << "select value from config where kind='nxtnid' limit 1", into(phonekey);
              size_t next_id = phonekey + 1;
              session << "update config set value = :val where kind='nxtnid'", use(next_id);
              session << "insert into numbers (id,cref,type,canonical,note) "
                         "values (:id,:cref,:type,:can,:note)",
                         use(phonekey), use(contactkey), use(phoneType), use(strCanonical),
                         use(strNote);
              lPhones[pidx].setDbKey(phonekey);
            } else {
              session << "update numbers set type=:type,canonical=:can,note=:note "
                         "where id = :id",
                         use(phoneType), use(strCanonical), use(strNote),
                         use(phonekey);
            }
            if (pidx > 0) ssKeys << ",";
            ssKeys << lPhones[pidx].getDbKey();
            lPhones[pidx].setDirty(false);
          }
          ssKeys << ")";
          session << ssKeys.str(), use(contactkey);
        }
        else {
          session << "delete from numbers where cref = :cref", use(contactkey);
        }
        session.commit();
        c.setDirty(false);
        // notifyListeners();
      }
      catch (const std::exception& e) {
        m_strLastError = e.what();
        session.rollback();
        wxMessageBox(wxString::FromUTF8(
            m_strLastError.data(), m_strLastError.length()),
            wxT("SQLite Plugin"), wxOK|wxICON_ERROR);
      }
    }
    else {
      c.setDirty(false);
    }
  }
}