diff options
Diffstat (limited to 'plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp')
-rw-r--r-- | plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp b/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp new file mode 100644 index 0000000000..0f75c0df43 --- /dev/null +++ b/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp @@ -0,0 +1,581 @@ +/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+© 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+===============================================================================
+
+File name : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/ex_import/classExImContactBase.cpp $
+Revision : $Revision: 210 $
+Last change on : $Date: 2010-10-02 22:27:36 +0400 (Сб, 02 окт 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+#include "commonheaders.h"
+#include "..\svc_contactinfo.h"
+#include "classExImContactBase.h"
+#include "mir_rfcCodecs.h"
+
+HANDLE CListFindGroup(LPCSTR pszGroup)
+{
+ CHAR buf[4];
+ BYTE i;
+ DBVARIANT dbv;
+
+ for (i = 0; i < 255; i++) {
+ _itoa(i, buf, 10);
+ if (DB::Setting::GetUString(NULL, "CListGroups", buf, &dbv))
+ break;
+ if (dbv.pszVal && pszGroup && !_stricmp(dbv.pszVal + 1, pszGroup)) {
+ DB::Variant::Free(&dbv);
+ return (HANDLE)(INT_PTR)(i+1);
+ }
+ DB::Variant::Free(&dbv);
+ }
+ return INVALID_HANDLE_VALUE;
+}
+
+/**
+ * name: CExImContactBase
+ * class: CExImContactBase
+ * desc: default constructor
+ * param: none
+ * return: nothing
+ **/
+CExImContactBase::CExImContactBase()
+{
+ _pszNick = NULL;
+ _pszDisp = NULL;
+ _pszGroup = NULL;
+ _pszProto = NULL;
+ _pszProtoOld = NULL;
+ _pszAMPro = NULL;
+ _pszUIDKey = NULL;
+ _dbvUIDHash = NULL;
+ ZeroMemory(&_dbvUID, sizeof(DBVARIANT));
+ _hContact = INVALID_HANDLE_VALUE;
+ _isNewContact = FALSE;
+}
+
+/**
+ * name: ~CExImContactBase
+ * class: CExImContactBase
+ * desc: default denstructor
+ * param: none
+ * return: nothing
+ **/
+CExImContactBase::~CExImContactBase()
+{
+ MIR_FREE(_pszNick);
+ MIR_FREE(_pszDisp);
+ MIR_FREE(_pszGroup);
+ MIR_FREE(_pszProtoOld);
+ MIR_FREE(_pszProto);
+ MIR_FREE(_pszAMPro);
+ MIR_FREE(_pszUIDKey);
+ DB::Variant::Free(&_dbvUID);
+}
+
+/**
+ * name: fromDB
+ * class: CExImContactBase
+ * desc: get contact information from database
+ * param: hContact - handle to contact whose information to read
+ * return: TRUE if successful or FALSE otherwise
+ **/
+BOOLEAN CExImContactBase::fromDB(HANDLE hContact)
+{
+ BOOLEAN ret = FALSE;
+ BOOLEAN isChatRoom = FALSE;
+ LPSTR pszProto;
+ LPCSTR uidSetting;
+ DBVARIANT dbv;
+
+ _hContact = hContact;
+ _dbvUIDHash = 0;
+ MIR_FREE(_pszProtoOld);
+ MIR_FREE(_pszProto);
+ MIR_FREE(_pszAMPro);
+ MIR_FREE(_pszNick);
+ MIR_FREE(_pszDisp);
+ MIR_FREE(_pszGroup);
+ MIR_FREE(_pszUIDKey);
+ DB::Variant::Free(&_dbvUID);
+ ZeroMemory(&_dbvUID, sizeof(DBVARIANT));
+
+ // OWNER
+ if (!_hContact) return TRUE;
+
+ // Proto
+ if (!(pszProto = DB::Contact::Proto(_hContact))) return FALSE;
+ _pszProto = mir_strdup(pszProto);
+
+ // AM_BaseProto
+ if (!DB::Setting::GetUString(NULL, pszProto, "AM_BaseProto", &dbv )) {
+ _pszAMPro = mir_strdup(dbv.pszVal);
+ DB::Variant::Free(&dbv);
+ }
+
+ // unique id (for ChatRoom)
+ if (isChatRoom = DB::Setting::GetByte(_hContact, pszProto, "ChatRoom", 0)) {
+ uidSetting = "ChatRoomID";
+ _pszUIDKey = mir_strdup(uidSetting);
+ if (!DB::Setting::GetAsIs(_hContact, pszProto, uidSetting, &_dbvUID)) {
+ ret = TRUE;
+ }
+ }
+ // unique id (normal)
+ else {
+ uidSetting = (LPCSTR)CallProtoService(pszProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ // valid
+ if (uidSetting != NULL && (INT_PTR)uidSetting != CALLSERVICE_NOTFOUND) {
+ _pszUIDKey = mir_strdup(uidSetting);
+ if (!DB::Setting::GetAsIs(_hContact, pszProto, uidSetting, &_dbvUID)) {
+ ret = TRUE;
+ }
+ }
+ // fails because the protocol is no longer installed
+ else {
+ // assert(ret == TRUE);
+ ret = TRUE;
+ }
+ }
+
+ // nickname
+ if (!DB::Setting::GetUString(_hContact, pszProto, SET_CONTACT_NICK, &dbv)) {
+ _pszNick = mir_strdup(dbv.pszVal);
+ DB::Variant::Free(&dbv);
+ }
+
+ if (_hContact && ret) {
+ // Clist Group
+ if (!DB::Setting::GetUString(_hContact, MOD_CLIST, "Group", &dbv)) {
+ _pszGroup = mir_strdup(dbv.pszVal);
+ DB::Variant::Free(&dbv);
+ }
+ // Clist DisplayName
+ if (!DB::Setting::GetUString(_hContact, MOD_CLIST, SET_CONTACT_MYHANDLE, &dbv)) {
+ _pszDisp = mir_strdup(dbv.pszVal);
+ DB::Variant::Free(&dbv);
+ }
+ }
+ return ret;
+}
+
+/**
+ * name: fromIni
+ * class: CExImContactBase
+ * desc: get contact information from a row of a ini file
+ * param: row - the rows data
+ * return: TRUE if successful or FALSE otherwise
+ **/
+BOOLEAN CExImContactBase::fromIni(LPSTR& row)
+{
+ LPSTR p1, p2 = NULL;
+ LPSTR pszUIDValue, pszUIDSetting, pszProto = NULL;
+ LPSTR pszBuf = &row[0];
+ size_t cchBuf = strlen(row);
+
+ MIR_FREE(_pszProtoOld);
+ MIR_FREE(_pszProto);
+ MIR_FREE(_pszAMPro);
+ MIR_FREE(_pszNick);
+ MIR_FREE(_pszDisp);
+ MIR_FREE(_pszGroup);
+ MIR_FREE(_pszUIDKey);
+ DB::Variant::Free(&_dbvUID);
+ ZeroMemory(&_dbvUID, sizeof(DBVARIANT));
+ _dbvUIDHash = 0;
+
+ // read uid value
+ if (cchBuf > 10 && (p1 = mir_strrchr(pszBuf, '*{')) && (p2 = mir_strchr(p1, '}*')) && p1 + 2 < p2) {
+ pszUIDValue = p1 + 1;
+ *p1 = *(p2 - 1) = 0;
+
+ // insulate the uid setting from buffer pointer
+ if (cchBuf > 0 && (p1 = mir_strrchr(pszBuf, '*<')) && (p2 = mir_strchr(p1, '>*')) && p1 + 2 < p2) {
+ pszUIDSetting = p1 + 1;
+ *p1 = *(p2 - 1) = 0;
+
+ // insulate the protocol name from buffer pointer
+ if (cchBuf > 0 && (p1 = mir_strrchr(pszBuf, '*(')) && (p2 = mir_strchr(p1, ')*')) && p1 + 2 < p2) {
+ pszProto = p1 + 1;
+ *(--p1) = *(p2 - 1) = 0;
+
+ // DBVT_DWORD
+ if (strspn(pszUIDValue, "0123456789") == mir_strlen(pszUIDValue)) {
+ _dbvUID.dVal = _atoi64(pszUIDValue);
+ _dbvUID.type = DBVT_DWORD;
+ }
+ else {
+ // DBVT_UTF8
+ _dbvUID.pszVal = mir_strdup(pszUIDValue);
+ _dbvUID.type = DBVT_UTF8;
+ }
+ _pszUIDKey = mir_strdup(pszUIDSetting);
+ _pszProto = mir_strdup(pszProto);
+ } //end insulate the protocol name from buffer pointer
+ } //end insulate the uid setting from buffer pointer
+ } //end read uid value
+
+ // create valid nickname
+ _pszNick = mir_strdup(pszBuf);
+ size_t i = strlen(_pszNick)-1;
+ while (i > 0 && (_pszNick[i] == ' ' || _pszNick[i] == '\t')) {
+ _pszNick[i] = 0;
+ i--;
+ }
+ // finally try to find contact in contact list
+ findHandle();
+ return FALSE;
+}
+
+/**
+ * name: toDB
+ * class: CExImContactBase
+ * desc: searches the database for a contact representing the one
+ * identified by this class or creates a new one if it was not found
+ * param: hMetaContact - a meta contact to add this contact to
+ * return: handle of the contact if successful
+ **/
+HANDLE CExImContactBase::toDB()
+{
+ DBCONTACTWRITESETTING cws;
+
+ // create new contact if none exists
+ if (_hContact == INVALID_HANDLE_VALUE && _pszProto && _pszUIDKey && _dbvUID.type != DBVT_DELETED) {
+ PROTOACCOUNT* pszAccount = 0;
+ if(NULL == (pszAccount = ProtoGetAccount( _pszProto ))) {
+ //account does not exist
+ _hContact = INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
+ }
+ if (!IsAccountEnabled(pszAccount)) {
+ ;
+ }
+ // create new contact
+ _hContact = DB::Contact::Add();
+ if (!_hContact) {
+ _hContact = INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
+ }
+ // Add the protocol to the new contact
+ if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)_hContact, (LPARAM)_pszProto)) {
+ DB::Contact::Delete(_hContact);
+ _hContact = INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
+ }
+ // write uid to protocol module
+ cws.szModule = _pszProto;
+ cws.szSetting = _pszUIDKey;
+ cws.value = _dbvUID;
+ if (CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)_hContact, (LPARAM)&cws)) {
+ DB::Contact::Delete(_hContact);
+ _hContact = INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
+ }
+ // write nick and display name
+ if (_pszNick) DB::Setting::WriteUString(_hContact, _pszProto, SET_CONTACT_NICK, _pszNick);
+ if (_pszDisp) DB::Setting::WriteUString(_hContact, MOD_CLIST, SET_CONTACT_MYHANDLE, _pszDisp);
+
+ // add group
+ if (_pszGroup) {
+ DB::Setting::WriteUString(_hContact, MOD_CLIST, "Group", _pszGroup);
+ if (CListFindGroup(_pszGroup) == INVALID_HANDLE_VALUE) {
+ WPARAM hGroup = (WPARAM)CallService(MS_CLIST_GROUPCREATE, 0, 0);
+ if (hGroup) {
+ // renaming twice is stupid but the only way to avoid error dialog telling shit like
+ // a group with that name does exist
+ CallService(MS_CLIST_GROUPRENAME, (WPARAM)hGroup, (LPARAM)_pszGroup);
+ }
+ }
+ }
+ }
+ return _hContact;
+}
+
+/**
+ * name: toIni
+ * class: CExImContactBase
+ * desc: writes the line to an opened ini file which identifies the contact
+ * whose information are stored in this class
+ * param: file - pointer to the opened file
+ * return: nothing
+ **/
+VOID CExImContactBase::toIni(FILE* file, int modCount)
+{
+ // getting dbeditor++ NickFromHContact(hContact)
+ static char name[512] = "";
+ char* ret = 0;
+
+ if (_hContact){
+ int loaded = _pszUIDKey ? 1 : 0;
+ if (_pszProto == NULL || !loaded) {
+ if (_pszProto){
+ if (_pszNick)
+ mir_snprintf(name, sizeof(name),"%s (%s)", _pszNick, _pszProto);
+ else
+ mir_snprintf(name, sizeof(name),"(UNKNOWN) (%s)", _pszProto);
+ }
+ else
+ mir_snprintf(name, sizeof(name),"(UNKNOWN)");
+ }
+ else {
+ // Proto loadet - GetContactName(hContact,pszProto,0)
+ LPSTR pszCI = NULL;
+ CONTACTINFO ci;
+ ZeroMemory(&ci, sizeof(ci));
+
+ ci.cbSize = sizeof(ci);
+ ci.hContact = _hContact;
+ ci.szProto = _pszProto;
+ ci.dwFlag = CNF_DISPLAY;
+
+ if (!GetContactInfo(NULL, (LPARAM) &ci)) {
+ // CNF_DISPLAY always returns a string type
+ pszCI = (LPSTR)ci.pszVal;
+ }
+ LPSTR pszUID = uid2String(FALSE);
+ if (_pszUIDKey && pszUID)
+ mir_snprintf(name, sizeof(name), "%s *(%s)*<%s>*{%s}*", pszCI, _pszProto, _pszUIDKey, pszUID);
+ else
+ mir_snprintf(name, sizeof(name), "%s (%s)", pszCI, _pszProto);
+
+ mir_free(pszCI);
+ mir_free(pszUID);
+ } // end else (Proto loadet)
+
+ // it is not the best solution (but still works if only basic modules export) - need rework
+ if (modCount > 3)
+ fprintf(file, "CONTACT: %s\n", name);
+ else
+ fprintf(file, "FROM CONTACT: %s\n", name);
+
+ } // end *if (_hContact)
+ else {
+ fprintf(file, "SETTINGS:\n");
+ }
+}
+
+BOOLEAN CExImContactBase::compareUID(DBVARIANT *dbv)
+{
+ DWORD hash = 0;
+ switch (dbv->type) {
+ case DBVT_BYTE:
+ if (dbv->bVal == _dbvUID.bVal) {
+ _dbvUID.type = dbv->type;
+ return TRUE;
+ }
+ break;
+ case DBVT_WORD:
+ if (dbv->wVal == _dbvUID.wVal) {
+ _dbvUID.type = dbv->type;
+ return TRUE;
+ }
+ break;
+ case DBVT_DWORD:
+ if (dbv->dVal == _dbvUID.dVal) {
+ _dbvUID.type = dbv->type;
+ return TRUE;
+ }
+ break;
+ case DBVT_ASCIIZ:
+ hash = hashSetting_M2(dbv->pszVal);
+ case DBVT_WCHAR:
+ if (!hash) hash = hashSettingW_M2((const char *)dbv->pwszVal);
+ case DBVT_UTF8:
+ if (!hash) {
+ LPWSTR tmp = mir_utf8decodeW(dbv->pszVal);
+ hash = hashSettingW_M2((const char *)tmp);
+ mir_free(tmp);
+ }
+ if(hash == _dbvUIDHash) return TRUE;
+ break;
+ case DBVT_BLOB: //'n' cpbVal and pbVal are valid
+ if (_dbvUID.type == dbv->type &&
+ _dbvUID.cpbVal == dbv->cpbVal &&
+ memcmp(_dbvUID.pbVal, dbv->pbVal, dbv->cpbVal) == 0) {
+ return TRUE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+LPSTR CExImContactBase::uid2String(BOOLEAN bPrependType)
+{
+ CHAR szUID[MAX_PATH];
+ LPSTR ptr = szUID;
+
+ switch (_dbvUID.type) {
+ case DBVT_BYTE: //'b' bVal and cVal are valid
+ if (bPrependType) *ptr++ = 'b';
+ _itoa(_dbvUID.bVal, ptr, 10);
+ break;
+ case DBVT_WORD: //'w' wVal and sVal are valid
+ if (bPrependType) *ptr++ = 'w';
+ _itoa(_dbvUID.wVal, ptr, 10);
+ break;
+ case DBVT_DWORD: //'d' dVal and lVal are valid
+ if (bPrependType) *ptr++ = 'd';
+ _itoa(_dbvUID.dVal, ptr, 10);
+ break;
+ case DBVT_WCHAR: //'u' pwszVal is valid
+ {
+ LPSTR r = mir_utf8encodeW(_dbvUID.pwszVal);
+ if (bPrependType) {
+ LPSTR t = (LPSTR)mir_alloc(strlen(r)+2);
+ t[0] = 'u';
+ strcpy(t+1, r);
+ mir_free(r);
+ r = t;
+ }
+ return r;
+ }
+ case DBVT_UTF8: //'u' pszVal is valid
+ {
+ if (bPrependType) *ptr++ = 'u';
+ mir_strncpy(ptr, _dbvUID.pszVal, SIZEOF(szUID)-1);
+ }
+ break;
+ case DBVT_ASCIIZ: {
+ LPSTR r = mir_utf8encode(_dbvUID.pszVal);
+ if (bPrependType) {
+ LPSTR t = (LPSTR)mir_alloc(strlen(r)+2);
+ t[0] = 's';
+ strcpy(t+1, r);
+ mir_free(r);
+ r = t;
+ }
+ return r;
+ }
+ case DBVT_BLOB: //'n' cpbVal and pbVal are valid
+ {
+ if (bPrependType) { //True = XML
+ INT_PTR baselen = Base64EncodeGetRequiredLength(_dbvUID.cpbVal, BASE64_FLAG_NOCRLF);
+ LPSTR t = (LPSTR)mir_alloc(baselen + 5 + bPrependType);
+ assert(t != NULL);
+ if (Base64Encode(_dbvUID.pbVal, _dbvUID.cpbVal, t + bPrependType, &baselen, BASE64_FLAG_NOCRLF)) {
+ if (baselen){
+ t[baselen + bPrependType] = 0;
+ if (bPrependType) t[0] = 'n';
+ return t;
+ }
+ }
+ mir_free(t);
+ return NULL;
+ }
+ else { //FALSE = INI
+ WORD j;
+ INT_PTR baselen = (_dbvUID.cpbVal * 3);
+ LPSTR t = (LPSTR)mir_alloc(3 + baselen);
+ ZeroMemory(t, (3 + baselen));
+ for (j = 0; j < _dbvUID.cpbVal; j++) {
+ mir_snprintf((t + bPrependType + (j * 3)), 4,"%02X ", (BYTE)_dbvUID.pbVal[j]);
+ }
+ if (t){
+ if (bPrependType) t[0] = 'n';
+ return t;
+ }
+ else {
+ mir_free(t);
+ return NULL;
+ }
+ }
+ break;
+ }
+ default:
+ return NULL;
+ }
+ return mir_strdup(szUID);
+}
+
+BOOLEAN CExImContactBase::isMeta() const
+{
+ return DB::Module::IsMeta(_pszProto);
+}
+
+BOOLEAN CExImContactBase::isHandle(HANDLE hContact)
+{
+ LPCSTR pszProto;
+ DBVARIANT dbv;
+ BOOLEAN isEqual = FALSE;
+
+ // owner contact ?
+ if (!_pszProto) return hContact == NULL;
+
+ // compare protocols
+ pszProto = DB::Contact::Proto(hContact);
+ if (pszProto == NULL || (INT_PTR)pszProto == CALLSERVICE_NOTFOUND || mir_stricmp(pszProto, _pszProto))
+ return FALSE;
+
+ // compare uids
+ if (_pszUIDKey) {
+ // get uid
+ if (DB::Setting::GetAsIs(hContact, pszProto,_pszUIDKey, &dbv))
+ return FALSE;
+
+ isEqual = compareUID (&dbv);
+ DB::Variant::Free(&dbv);
+ }
+ // compare nicknames if no UID
+ else if (!DB::Setting::GetUString(hContact, _pszProto, SET_CONTACT_NICK, &dbv)) {
+ if (dbv.type == DBVT_UTF8 && dbv.pszVal && !mir_stricmp(dbv.pszVal,_pszNick)) {
+ LPTSTR ptszNick = mir_utf8decodeT(_pszNick);
+ LPTSTR ptszProto = mir_a2t(_pszProto);
+ INT ans = MsgBox(NULL, MB_ICONQUESTION|MB_YESNO, LPGENT("Question"), LPGENT("contact identificaion"),
+ LPGENT("The contact %s(%s) has no unique id in the vCard,\nbut there is a contact in your clist with the same nick and protocol.\nDo you wish to use this contact?"),
+ ptszNick, ptszProto);
+ MIR_FREE(ptszNick);
+ MIR_FREE(ptszProto);
+ isEqual = ans == IDYES;
+ }
+ DB::Variant::Free(&dbv);
+ }
+ return isEqual;
+}
+
+/**
+ * name: handle
+ * class: CExImContactBase
+ * desc: return the handle of the contact
+ * whose information are stored in this class
+ * param: none
+ * return: handle if successful, INVALID_HANDLE_VALUE otherwise
+ **/
+HANDLE CExImContactBase::findHandle()
+{
+ HANDLE hContact;
+
+ for (hContact = DB::Contact::FindFirst();
+ hContact != NULL;
+ hContact = DB::Contact::FindNext(hContact))
+ {
+ if (isHandle(hContact)) {
+ _hContact = hContact;
+ _isNewContact = FALSE;
+ return hContact;
+ }
+ }
+ _isNewContact = TRUE;
+ _hContact = INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
+}
|