diff options
author | Rozhuk Ivan <rozhuk.im@gmail.com> | 2014-11-26 23:06:03 +0000 |
---|---|---|
committer | Rozhuk Ivan <rozhuk.im@gmail.com> | 2014-11-26 23:06:03 +0000 |
commit | 15cb1c735a559b88c7ede033510d8f106eb9e314 (patch) | |
tree | 990f59a238a88f5f8494b5094a2bd1dedb018d0a /plugins/UserInfoEx/src/ex_import | |
parent | e94cb836621c0c4432ad7670ea18619812088a10 (diff) |
UInfoEx: code cleanup, req for review
git-svn-id: http://svn.miranda-ng.org/main/trunk@11108 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/UserInfoEx/src/ex_import')
-rw-r--r-- | plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp | 1075 | ||||
-rw-r--r-- | plugins/UserInfoEx/src/ex_import/svc_ExImINI.cpp | 1049 |
2 files changed, 1064 insertions, 1060 deletions
diff --git a/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp b/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp index 71dd6bee93..ead8d33c9d 100644 --- a/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp +++ b/plugins/UserInfoEx/src/ex_import/classExImContactBase.cpp @@ -1,535 +1,540 @@ -/*
-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.
-*/
-
-#include "..\commonheaders.h"
-
-/**
- * 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_CONTACT_ID;
- _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_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
- **/
-BYTE CExImContactBase::fromDB(MCONTACT hContact)
-{
- BYTE ret = FALSE;
- BYTE 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_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_free(&dbv);
- }
-
- // unique id (for ChatRoom)
- if (isChatRoom = db_get_b(_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_free(&dbv);
- }
-
- if (_hContact && ret) {
- // Clist Group
- if (!DB::Setting::GetUString(_hContact, MOD_CLIST, "Group", &dbv)) {
- _pszGroup = mir_strdup(dbv.pszVal);
- db_free(&dbv);
- }
- // Clist DisplayName
- if (!DB::Setting::GetUString(_hContact, MOD_CLIST, SET_CONTACT_MYHANDLE, &dbv)) {
- _pszDisp = mir_strdup(dbv.pszVal);
- db_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
- **/
-BYTE 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_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
- **/
-MCONTACT CExImContactBase::toDB()
-{
- // create new contact if none exists
- if (_hContact == INVALID_CONTACT_ID && _pszProto && _pszUIDKey && _dbvUID.type != DBVT_DELETED) {
- PROTOACCOUNT* pszAccount = 0;
- if (NULL == (pszAccount = ProtoGetAccount( _pszProto ))) {
- //account does not exist
- return _hContact = INVALID_CONTACT_ID;
- }
- if (!IsAccountEnabled(pszAccount)) {
- ;
- }
- // create new contact
- _hContact = DB::Contact::Add();
- if (!_hContact) {
- return _hContact = INVALID_CONTACT_ID;
- }
- // Add the protocol to the new contact
- if (CallService(MS_PROTO_ADDTOCONTACT, _hContact, (LPARAM)_pszProto)) {
- DB::Contact::Delete(_hContact);
- return _hContact = INVALID_CONTACT_ID;
- }
- // write uid to protocol module
- if (db_set(_hContact, _pszProto, _pszUIDKey, &_dbvUID)) {
- DB::Contact::Delete(_hContact);
- return _hContact = INVALID_CONTACT_ID;
- }
- // write nick and display name
- if (_pszNick) db_set_utf(_hContact, _pszProto, SET_CONTACT_NICK, _pszNick);
- if (_pszDisp) db_set_utf(_hContact, MOD_CLIST, SET_CONTACT_MYHANDLE, _pszDisp);
-
- // add group
- if (_pszGroup) {
- ptrT ptszGroup( mir_utf8decodeT(_pszGroup));
- db_set_ts(_hContact, MOD_CLIST, "Group", ptszGroup);
- if ( Clist_GroupExists(ptszGroup) == NULL) {
- HANDLE hGroup = Clist_CreateGroup(NULL, NULL);
- 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)ptszGroup);
- }
- }
- }
- }
- 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");
- }
-}
-
-BYTE 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(BYTE 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 = mir_base64_encode_bufsize(_dbvUID.cpbVal);
- LPSTR t = (LPSTR)mir_alloc(baselen + 5 + bPrependType);
- assert(t != NULL);
- if ( mir_base64_encodebuf(_dbvUID.pbVal, _dbvUID.cpbVal, t + bPrependType, 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);
-}
-
-BYTE CExImContactBase::isMeta() const
-{
- return DB::Module::IsMeta(_pszProto);
-}
-
-BYTE CExImContactBase::isHandle(MCONTACT hContact)
-{
- LPCSTR pszProto;
- DBVARIANT dbv;
- BYTE isEqual = FALSE;
-
- // owner contact ?
- if (!_pszProto) return hContact == NULL;
-
- // compare protocols
- pszProto = DB::Contact::Proto(hContact);
- if (pszProto == NULL || (INT_PTR)pszProto == CALLSERVICE_NOTFOUND || lstrcmpA(pszProto, _pszProto))
- return FALSE;
-
- // compare uids
- if (_pszUIDKey) {
- // get uid
- if (DB::Setting::GetAsIs(hContact, pszProto,_pszUIDKey, &dbv))
- return FALSE;
-
- isEqual = compareUID (&dbv);
- db_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 identification"),
- LPGENT("The contact %s(%s) has no unique ID in the vCard,\nbut there is a contact in your contact list 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_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
- **/
-MCONTACT CExImContactBase::findHandle()
-{
- for (MCONTACT hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) {
- if (isHandle(hContact)) {
- _hContact = hContact;
- _isNewContact = FALSE;
- return hContact;
- }
- }
- _isNewContact = TRUE;
- return _hContact = INVALID_CONTACT_ID;
-}
+/* +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. +*/ + +#include "..\commonheaders.h" + +/** + * 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_CONTACT_ID; + _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_free(&_dbvUID); + ZeroMemory(&_dbvUID, sizeof(DBVARIANT)); +} + +/** + * 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 + **/ +BYTE CExImContactBase::fromDB(MCONTACT hContact) +{ + BYTE ret = FALSE; + BYTE 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_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_free(&dbv); + } + + // unique id (for ChatRoom) + if (isChatRoom = db_get_b(_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_free(&dbv); + } + + if (_hContact && ret) { + // Clist Group + if (!DB::Setting::GetUString(_hContact, MOD_CLIST, "Group", &dbv)) { + _pszGroup = mir_strdup(dbv.pszVal); + db_free(&dbv); + } + // Clist DisplayName + if (!DB::Setting::GetUString(_hContact, MOD_CLIST, SET_CONTACT_MYHANDLE, &dbv)) { + _pszDisp = mir_strdup(dbv.pszVal); + db_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 + **/ +BYTE 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_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 + **/ +MCONTACT CExImContactBase::toDB() +{ + // create new contact if none exists + if (_hContact == INVALID_CONTACT_ID && _pszProto && _pszUIDKey && _dbvUID.type != DBVT_DELETED) { + PROTOACCOUNT* pszAccount = 0; + if (NULL == (pszAccount = ProtoGetAccount( _pszProto ))) { + //account does not exist + return _hContact = INVALID_CONTACT_ID; + } + if (!IsAccountEnabled(pszAccount)) { + ; + } + // create new contact + _hContact = DB::Contact::Add(); + if (!_hContact) { + return _hContact = INVALID_CONTACT_ID; + } + // Add the protocol to the new contact + if (CallService(MS_PROTO_ADDTOCONTACT, _hContact, (LPARAM)_pszProto)) { + DB::Contact::Delete(_hContact); + return _hContact = INVALID_CONTACT_ID; + } + // write uid to protocol module + if (db_set(_hContact, _pszProto, _pszUIDKey, &_dbvUID)) { + DB::Contact::Delete(_hContact); + return _hContact = INVALID_CONTACT_ID; + } + // write nick and display name + if (_pszNick) db_set_utf(_hContact, _pszProto, SET_CONTACT_NICK, _pszNick); + if (_pszDisp) db_set_utf(_hContact, MOD_CLIST, SET_CONTACT_MYHANDLE, _pszDisp); + + // add group + if (_pszGroup) { + ptrT ptszGroup( mir_utf8decodeT(_pszGroup)); + db_set_ts(_hContact, MOD_CLIST, "Group", ptszGroup); + if ( Clist_GroupExists(ptszGroup) == NULL) { + HANDLE hGroup = Clist_CreateGroup(NULL, NULL); + 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)ptszGroup); + } + } + } + } + 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"); + } +} + +BYTE 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(BYTE bPrependType) +{ + CHAR szUID[4096]; + LPSTR ptr = szUID; + LPSTR r; + SIZE_T baselen; + + 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 + r = mir_utf8encodeW(_dbvUID.pwszVal); + if (r == NULL) + return NULL; + if (bPrependType == FALSE) + return r; + *ptr++ = 'u'; + mir_strncpy(ptr, r, sizeof(szUID) - 1); + mir_free(r); + break; + case DBVT_UTF8: //'u' pszVal is valid + if (bPrependType) + *ptr++ = 'u'; + mir_strncpy(ptr, _dbvUID.pszVal, sizeof(szUID) - 1); + break; + case DBVT_ASCIIZ: + r = mir_utf8encode(_dbvUID.pszVal); + if (r == NULL) + return NULL; + if (bPrependType == FALSE) + return r; + *ptr++ = 's'; + mir_strncpy(ptr, r, sizeof(szUID) - 1); + mir_free(r); + break; + case DBVT_BLOB: //'n' cpbVal and pbVal are valid + if (bPrependType) { //True = XML + baselen = mir_base64_encode_bufsize(_dbvUID.cpbVal); + r = (LPSTR)mir_alloc((baselen + 8)); + if (r == NULL) + return NULL; + ZeroMemory((r + baselen), 8); + ptr = r; + if (bPrependType) { // Allways true. + ptr[0] = 'n'; + ptr ++; + } + if (!mir_base64_encodebuf(_dbvUID.pbVal, _dbvUID.cpbVal, ptr, baselen)) { + mir_free(r); + return NULL; + } + return r; + } + else { //FALSE = INI + baselen = ((_dbvUID.cpbVal * 3) + 8); + r = (LPSTR)mir_alloc(baselen); + if (r == NULL) + return NULL; + ZeroMemory(r, baselen); + ptr = r; + if (bPrependType) { // XXX dead code. + ptr[0] = 'n'; + ptr ++; + } + for (SIZE_T j = 0; j < _dbvUID.cpbVal; j ++, ptr += 3) { + mir_snprintf(ptr, ((r + baselen) - ptr), "%02X ", (BYTE)_dbvUID.pbVal[j]); + } + return r; + } + break; + default: + return NULL; + } + return mir_strdup(szUID); +} + +BYTE CExImContactBase::isMeta() const +{ + return DB::Module::IsMeta(_pszProto); +} + +BYTE CExImContactBase::isHandle(MCONTACT hContact) +{ + LPCSTR pszProto; + DBVARIANT dbv; + BYTE isEqual = FALSE; + + // owner contact ? + if (!_pszProto) return hContact == NULL; + + // compare protocols + pszProto = DB::Contact::Proto(hContact); + if (pszProto == NULL || (INT_PTR)pszProto == CALLSERVICE_NOTFOUND || lstrcmpA(pszProto, _pszProto)) + return FALSE; + + // compare uids + if (_pszUIDKey) { + // get uid + if (DB::Setting::GetAsIs(hContact, pszProto,_pszUIDKey, &dbv)) + return FALSE; + + isEqual = compareUID (&dbv); + db_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 identification"), + LPGENT("The contact %s(%s) has no unique ID in the vCard,\nbut there is a contact in your contact list 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_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 + **/ +MCONTACT CExImContactBase::findHandle() +{ + for (MCONTACT hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) { + if (isHandle(hContact)) { + _hContact = hContact; + _isNewContact = FALSE; + return hContact; + } + } + _isNewContact = TRUE; + return _hContact = INVALID_CONTACT_ID; +} diff --git a/plugins/UserInfoEx/src/ex_import/svc_ExImINI.cpp b/plugins/UserInfoEx/src/ex_import/svc_ExImINI.cpp index 458e41d901..7c126562fa 100644 --- a/plugins/UserInfoEx/src/ex_import/svc_ExImINI.cpp +++ b/plugins/UserInfoEx/src/ex_import/svc_ExImINI.cpp @@ -1,525 +1,524 @@ -/*
-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.
-*/
-
-/**
- * system & local includes:
- **/
-
-#include "..\commonheaders.h"
-
-/***********************************************************************************************************
- * exporting stuff
- ***********************************************************************************************************/
-
-/**
- * name: ExportModule
- * desc: write all settings from a database module to file
- * param: hContact - handle of contact the module is owned from
- * pszModule - name of the module to save
- * file - file to write the settings to
- * return nothing
- **/
-static void ExportModule(MCONTACT hContact, LPCSTR pszModule, FILE* file)
-{
- DB::CEnumList Settings;
-
- if (!Settings.EnumSettings(hContact, pszModule))
- {
- DBVARIANT dbv;
- LPSTR here;
- WORD j;
- int i;
- LPSTR pszSetting;
- //char tmp[32];
-
- // print the module header..
- fprintf(file, "\n[%s]\n", pszModule);
-
- for (i = 0; i < Settings.getCount(); i++)
- {
- pszSetting = Settings[i];
-
- if (!DB::Setting::GetAsIs(hContact, pszModule, pszSetting, &dbv))
- {
- switch (dbv.type)
- {
- case DBVT_BYTE:
- {
- fprintf(file, "%s=b%u\n", pszSetting, dbv.bVal);
- }
- break;
-
- case DBVT_WORD:
- {
- fprintf(file, "%s=w%u\n", pszSetting, dbv.wVal);
- }
- break;
-
- case DBVT_DWORD:
- {
- fprintf(file, "%s=d%u\n", pszSetting, dbv.dVal);
- }
- break;
-
- case DBVT_ASCIIZ:
- case DBVT_UTF8:
- {
- for (here = dbv.pszVal; here && *here; here++)
- {
- switch (*here) {
- // convert \r to STX
- case '\r':
- *here = 2;
- break;
-
- // convert \n to ETX
- case '\n':
- *here = 3;
- }
- }
- if (dbv.type == DBVT_UTF8)
- fprintf(file, "%s=u%s\n", pszSetting, dbv.pszVal);
- else
- fprintf(file, "%s=s%s\n", pszSetting, dbv.pszVal);
- }
- break;
-
- case DBVT_BLOB:
- {
- fprintf(file, "%s=n", pszSetting);
- for (j = 0; j < dbv.cpbVal; j++)
- {
- fprintf(file, "%02X ", (BYTE)dbv.pbVal[j]);
- }
- fputc('\n', file);
- }
- break;
- }
- db_free(&dbv);
- }
- }
- }
-}
-
-/**
- * name: ExportContact
- * desc: Exports a certain contact to an ini file.
- * param: hContact - contact to export or -1 to export all contacts
- * pModules - module to export, NULL to export all modules of a contact
- * file - ini file to write the contact to
- **/
-static BYTE ExportContact(MCONTACT hContact, DB::CEnumList* pModules, FILE* file)
-{
- CExImContactBase vcc;
-
- if (pModules)
- {
- if ((vcc = hContact) >= NULL)
- {
- int i;
- LPSTR p;
-
- vcc.toIni(file, pModules->getCount()-1);
-
- for (i = 0; i < pModules->getCount(); i++)
- {
- p = (*pModules)[i];
-
- /*Filter/
- if (mir_stricmp(p, "Protocol"))*/
- {
- ExportModule(hContact, p, file);
- }
- }
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * name: SvcExImINI_Export
- * desc: Exports a certain contact or all contacts to an ini file.
- * param: hContact - contact to export or -1 to export all contacts
- * pszFileName - ini-filename to write the contact to
- **/
-int SvcExImINI_Export(lpExImParam ExImContact, LPCSTR pszFileName)
-{
- FILE* file;
- errno_t err;
- DB::CEnumList Modules;
- SYSTEMTIME now;
- MCONTACT hContact;
-
- if (!DlgExImModules_SelectModulesToExport(ExImContact, &Modules, NULL))
- {
- if ((err = fopen_s(&file, pszFileName, "wt")) != NULL)
- {
- MsgErr(NULL,
- LPGENT("The ini-file \"%s\"\nfor saving contact information could not be opened."),
- pszFileName);
- return 1;
- }
-
- SetCursor(LoadCursor(NULL, IDC_WAIT));
-
- // write header
- GetLocalTime(&now);
- fprintf(file,
- ";DATE = %04d-%02d-%02d %02d:%02d:%02d\n\n",
- now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond
- );
-
- if (Modules.getCount() == 0)
- {
- Modules.EnumModules();
- }
-
- // hContact == -1 export entire db.
- if (ExImContact->Typ != EXIM_CONTACT)
- {
- // Owner
- ExportContact(NULL, &Modules, file);
- fprintf(file, "\n\n");
- // Contacts
- for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact))
- {
- ExportContact(hContact, &Modules, file);
- fprintf(file, "\n\n");
- }
- }
- // export only one contact
- else
- {
- ExportContact(ExImContact->hContact, &Modules, file);
- }
-
- if (file)
- fclose(file);
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- }
- return 0;
-}
-
-/***********************************************************************************************************
- * importing stuff
- ***********************************************************************************************************/
-
-LPSTR strnrchr(LPSTR string, int ch, DWORD len)
-{
- LPSTR start = (LPSTR)string;
-
- string += len; /* find end of string */
- /* search towards front */
- while (--string != start && *string != (CHAR)ch);
- if (*string == (CHAR)ch) /* char found ? */
- return ((LPSTR)string);
- return(NULL);
-}
-
-/**
- * name: ImportreadLine
- * desc: read exactly one line into a buffer and return its pointer. Size of buffer is managed.
- * param: file - pointer to a file
- * string - the string to write the read line to
- * return: pointer to the buffer on success or NULL on error
- **/
-static DWORD ImportreadLine(FILE* file, LPSTR &str)
-{
- CHAR c;
- DWORD l = 0;
- BYTE bComment = 0;
-
- str[0] = 0;
- while (!feof(file)) {
- switch (c = fgetc(file)) {
- case EOF:
- // reading error
- if (ferror(file)) {
- MIR_FREE(str);
- return 0;
- }
- // end of line & file
- return l;
-
- case '\r':
- case '\n':
- // ignore empty lines
- if (l == 0) {
- bComment = 0;
- continue;
- }
- return l;
-
- case ';':
- // found a comment line
- bComment |= l == 0;
- case '\t':
- case ' ':
- // ignore space and tab at the beginning of the line
- if (l == 0) break;
-
- default:
- if (!bComment) {
- str = mir_strncat_c(str, c);
- l++;
- }
- break;
- }
- }
- return 0;
-}
-
-/**
- * name: ImportFindContact
- * desc: This function decodes the given line, which is already identified to be a contact line.
- * The resulting information is matcht to the given hContact if it isn't NULL.
- * Otherwise all existing contacts are matched.
- * param: hContact - handle to contact to match or NULL to match all existing
- * pszBuf - pointer to the buffer holding the string of the current line in the ini.-file
- * cchBuf - character count of the buffer
- * return: handle to the contact that matches the information or NULL if no match
- **/
-static MCONTACT ImportFindContact(MCONTACT hContact, LPSTR &strBuf, BYTE bCanCreate)
-{
- CExImContactBase vcc;
-
- vcc.fromIni(strBuf);
- if (vcc.handle() != INVALID_CONTACT_ID) {
- //if (vcc.isHandle(hContact))
- // return hContact;
- return vcc.handle();
- }
- else if (bCanCreate)
- return vcc.toDB();
-
- return vcc.handle();
-}
-
-/**
- * name: ImportSetting
- * desc: This function writes a line identified as a setting to the database
- * param: hContact - handle to contact to match or NULL to match all existing
- * pszModule - module to write the setting to
- * strLine - string with the setting and its value to write to db
- * return: 0 if writing was ok, 1 otherwise
- **/
-int ImportSetting(MCONTACT hContact, LPCSTR pszModule, LPSTR &strLine)
-{
- DBVARIANT dbv;
- LPSTR end, value;
- size_t numLines = 0;
- size_t brk;
- LPSTR pszLine = strLine;
-
- // check Module and filter "Protocol"
- if (!pszModule || !*pszModule || mir_strncmp(pszModule,"Protocol",8) == 0)
- return 1;
- if ((end = value = mir_strchr(pszLine, '=')) == NULL)
- return 1;
-
- // truncate setting string if it has spaces at the end
- do {
- if (end == pszLine)
- return 1;
- *(end--) = 0;
- }
- while (*end == '\t' || *end == ' ' || *end < 27);
-
- // skip spaces from the beginning of the value
- do {
- value++;
- // if the value is empty, delete it from db
- if (*value == '\0')
- return db_unset(hContact, pszModule, pszLine);
- } while (*value == '\t' || *value == ' ');
-
- // decode database type and value
- switch (*(value++)) {
- case 'b':
- case 'B':
- if (brk = strspn(value, "0123456789-"))
- *(value + brk) = 0;
- dbv.type = DBVT_BYTE;
- dbv.bVal = (BYTE)atoi(value);
- break;
- case 'w':
- case 'W':
- if (brk = strspn(value, "0123456789-"))
- *(value + brk) = 0;
- dbv.type = DBVT_WORD;
- dbv.wVal = (WORD)atoi(value);
- break;
- case 'd':
- case 'D':
- if (brk = strspn(value, "0123456789-"))
- *(value + brk) = 0;
- dbv.type = DBVT_DWORD;
- dbv.dVal = (DWORD)_atoi64(value);
- break;
- case 's':
- case 'S':
- case 'u':
- case 'U':
- for (end = value; end && *end; end++) {
- switch (*end) {
- // convert STX back to \r
- case 2:
- *end = '\r';
- break;
- // convert ETX back to \n
- case 3:
- *end = '\n';
- break;
- }
- }
- switch (*(value - 1)) {
- case 's':
- case 'S':
- dbv.type = DBVT_ASCIIZ;
- dbv.pszVal = value;
- break;
- case 'u':
- case 'U':
- dbv.type = DBVT_UTF8;
- dbv.pszVal = value;
- break;
- }
- break;
- case 'n':
- case 'N':
- {
- PBYTE dest;
- dbv.type = DBVT_BLOB;
- dbv.cpbVal = (WORD)mir_strlen(value) / 3;
- dbv.pbVal = (PBYTE)value;
- for ( dest = dbv.pbVal, value = strtok(value, " ");
- value && *value;
- value = strtok(NULL, " "))
- *(dest++) = (BYTE)strtol(value, NULL, 16);
- *dest = 0;
- break;
- }
- default:
- dbv.type = DBVT_DELETED;
- //return 1;
- }
- return db_set(hContact, pszModule, pszLine, &dbv);
-}
-
-/**
- * name: Import
- * desc: This function imports an ini file
- * param: hContact - handle to contact to match or NULL to match all existing
- * file - module to write the setting to
- * strLine - string with the setting and its value to write to db
- * return: 0 if writing was ok, 1 otherwise
- **/
-int SvcExImINI_Import(MCONTACT hContact, LPCSTR pszFileName)
-{
- FILE *file;
- MCONTACT hNewContact = INVALID_CONTACT_ID;
- DWORD end,
- numLines = 0;
- CHAR szModule[MAXSETTING] = {0};
- WORD numContactsInFile = 0, // number of contacts in the inifile
- numContactsAdded = 0; // number of contacts, that were added to the database
- CHAR *strBuf = (CHAR *) mir_alloc(1);
- *strBuf = 0;
-
- if (file = fopen(pszFileName, "rt")) {
- SetCursor(LoadCursor(NULL, IDC_WAIT));
-
- while (ImportreadLine(file, strBuf)) {
- numLines++;
-
- // contact was found and imported
- if (hContact != INVALID_CONTACT_ID && hNewContact != INVALID_CONTACT_ID)
- break;
-
- // importing settings is only valid vor the main menu item
- if (hContact == INVALID_CONTACT_ID) {
- if (!strncmp(strBuf, "SETTINGS:", 9)) {
- *szModule = 0;
- hNewContact = NULL;
- continue;
- }
- }
-
- // there are some modules of a contact (import only if contact exist)
- if (!strncmp(strBuf, "FROM CONTACT:", 13)) {
- strBuf = mir_strnerase(strBuf, 0, 13);
- while (strBuf[0] == ' ' || strBuf[0] == '\t')
- strBuf = mir_strnerase(strBuf, 0, 1);
-
- numContactsInFile++;
- if ((hNewContact = ImportFindContact(hContact, strBuf, FALSE)) != INVALID_CONTACT_ID)
- numContactsAdded++;
- continue;
- }
-
- // there is a contact to import / add
- if (!strncmp(strBuf, "CONTACT:", 8)) {
- strBuf = mir_strnerase(strBuf, 0, 8);
- while (strBuf[0] == ' ' || strBuf[0] == '\t')
- strBuf = mir_strnerase(strBuf, 0, 1);
-
- *szModule = 0;
- numContactsInFile++;
- if ((hNewContact = ImportFindContact(hContact, strBuf, TRUE)) != INVALID_CONTACT_ID)
- numContactsAdded++;
- continue;
- }
-
- // read modules and settings only for valid contacts
- if (hNewContact != INVALID_CONTACT_ID) {
- // found a module line
- if (strBuf[0] == '[' && (end = (strchr(strBuf, ']') - strBuf)) > 0) {
- mir_strncpy(szModule, &strBuf[1], end);
- continue;
- }
- // try to import a setting
- ImportSetting(hNewContact, szModule, strBuf);
- }
- } //end while
- fclose(file);
- mir_free(strBuf);
- SetCursor(LoadCursor(NULL, IDC_ARROW));
-
- // the contact was not found in the file
- if (numContactsInFile > 0 && !numContactsAdded) {
- MsgErr(NULL,
- LPGENT("None of the %d contacts, stored in the ini-file, match the selected contact!\nNothing will be imported"),
- numContactsInFile);
- }
- // Import complete
- else{
- MsgBox(NULL, MB_ICON_INFO, LPGENT("Import complete"), LPGENT("Some basic statistics"),
- LPGENT("Added %d of %d contacts stored in the ini-file."),
- numContactsAdded, numContactsInFile);
- }
- return 0;
- }
- MsgErr(NULL,
- LPGENT("The ini-file \"%s\"\nfor reading contact information could not be opened."),
- pszFileName);
- return 1;
-}
+/* +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. +*/ + +/** + * system & local includes: + **/ + +#include "..\commonheaders.h" + +/*********************************************************************************************************** + * exporting stuff + ***********************************************************************************************************/ + +/** + * name: ExportModule + * desc: write all settings from a database module to file + * param: hContact - handle of contact the module is owned from + * pszModule - name of the module to save + * file - file to write the settings to + * return nothing + **/ +static void ExportModule(MCONTACT hContact, LPCSTR pszModule, FILE* file) +{ + DB::CEnumList Settings; + + if (!Settings.EnumSettings(hContact, pszModule)) + { + DBVARIANT dbv; + LPSTR here; + WORD j; + int i; + LPSTR pszSetting; + //char tmp[32]; + + // print the module header.. + fprintf(file, "\n[%s]\n", pszModule); + + for (i = 0; i < Settings.getCount(); i++) + { + pszSetting = Settings[i]; + + if (!DB::Setting::GetAsIs(hContact, pszModule, pszSetting, &dbv)) + { + switch (dbv.type) + { + case DBVT_BYTE: + { + fprintf(file, "%s=b%u\n", pszSetting, dbv.bVal); + } + break; + + case DBVT_WORD: + { + fprintf(file, "%s=w%u\n", pszSetting, dbv.wVal); + } + break; + + case DBVT_DWORD: + { + fprintf(file, "%s=d%u\n", pszSetting, dbv.dVal); + } + break; + + case DBVT_ASCIIZ: + case DBVT_UTF8: + { + for (here = dbv.pszVal; here && *here; here++) + { + switch (*here) { + // convert \r to STX + case '\r': + *here = 2; + break; + + // convert \n to ETX + case '\n': + *here = 3; + } + } + if (dbv.type == DBVT_UTF8) + fprintf(file, "%s=u%s\n", pszSetting, dbv.pszVal); + else + fprintf(file, "%s=s%s\n", pszSetting, dbv.pszVal); + } + break; + + case DBVT_BLOB: + { + fprintf(file, "%s=n", pszSetting); + for (j = 0; j < dbv.cpbVal; j++) + { + fprintf(file, "%02X ", (BYTE)dbv.pbVal[j]); + } + fputc('\n', file); + } + break; + } + db_free(&dbv); + } + } + } +} + +/** + * name: ExportContact + * desc: Exports a certain contact to an ini file. + * param: hContact - contact to export or -1 to export all contacts + * pModules - module to export, NULL to export all modules of a contact + * file - ini file to write the contact to + **/ +static BYTE ExportContact(MCONTACT hContact, DB::CEnumList* pModules, FILE* file) +{ + CExImContactBase vcc; + + if (pModules) + { + if ((vcc = hContact) >= NULL) + { + int i; + LPSTR p; + + vcc.toIni(file, pModules->getCount()-1); + + for (i = 0; i < pModules->getCount(); i++) + { + p = (*pModules)[i]; + + /*Filter/ + if (mir_stricmp(p, "Protocol"))*/ + { + ExportModule(hContact, p, file); + } + } + return TRUE; + } + } + return FALSE; +} + +/** + * name: SvcExImINI_Export + * desc: Exports a certain contact or all contacts to an ini file. + * param: hContact - contact to export or -1 to export all contacts + * pszFileName - ini-filename to write the contact to + **/ +int SvcExImINI_Export(lpExImParam ExImContact, LPCSTR pszFileName) +{ + FILE* file; + errno_t err; + DB::CEnumList Modules; + SYSTEMTIME now; + MCONTACT hContact; + + if (!DlgExImModules_SelectModulesToExport(ExImContact, &Modules, NULL)) + { + if ((err = fopen_s(&file, pszFileName, "wt")) != NULL) + { + MsgErr(NULL, + LPGENT("The ini-file \"%s\"\nfor saving contact information could not be opened."), + pszFileName); + return 1; + } + + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + // write header + GetLocalTime(&now); + fprintf(file, + ";DATE = %04d-%02d-%02d %02d:%02d:%02d\n\n", + now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond + ); + + if (Modules.getCount() == 0) + { + Modules.EnumModules(); + } + + // hContact == -1 export entire db. + if (ExImContact->Typ != EXIM_CONTACT) + { + // Owner + ExportContact(NULL, &Modules, file); + fprintf(file, "\n\n"); + // Contacts + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) + { + ExportContact(hContact, &Modules, file); + fprintf(file, "\n\n"); + } + } + // export only one contact + else + { + ExportContact(ExImContact->hContact, &Modules, file); + } + + fclose(file); + SetCursor(LoadCursor(NULL, IDC_ARROW)); + } + return 0; +} + +/*********************************************************************************************************** + * importing stuff + ***********************************************************************************************************/ + +LPSTR strnrchr(LPSTR string, int ch, DWORD len) +{ + LPSTR start = (LPSTR)string; + + string += len; /* find end of string */ + /* search towards front */ + while (--string != start && *string != (CHAR)ch); + if (*string == (CHAR)ch) /* char found ? */ + return ((LPSTR)string); + return(NULL); +} + +/** + * name: ImportreadLine + * desc: read exactly one line into a buffer and return its pointer. Size of buffer is managed. + * param: file - pointer to a file + * string - the string to write the read line to + * return: pointer to the buffer on success or NULL on error + **/ +static DWORD ImportreadLine(FILE* file, LPSTR &str) +{ + CHAR c; + DWORD l = 0; + BYTE bComment = 0; + + str[0] = 0; + while (!feof(file)) { + switch (c = fgetc(file)) { + case EOF: + // reading error + if (ferror(file)) { + MIR_FREE(str); + return 0; + } + // end of line & file + return l; + + case '\r': + case '\n': + // ignore empty lines + if (l == 0) { + bComment = 0; + continue; + } + return l; + + case ';': + // found a comment line + bComment |= l == 0; + case '\t': + case ' ': + // ignore space and tab at the beginning of the line + if (l == 0) break; + + default: + if (!bComment) { + str = mir_strncat_c(str, c); + l++; + } + break; + } + } + return 0; +} + +/** + * name: ImportFindContact + * desc: This function decodes the given line, which is already identified to be a contact line. + * The resulting information is matcht to the given hContact if it isn't NULL. + * Otherwise all existing contacts are matched. + * param: hContact - handle to contact to match or NULL to match all existing + * pszBuf - pointer to the buffer holding the string of the current line in the ini.-file + * cchBuf - character count of the buffer + * return: handle to the contact that matches the information or NULL if no match + **/ +static MCONTACT ImportFindContact(MCONTACT hContact, LPSTR &strBuf, BYTE bCanCreate) +{ + CExImContactBase vcc; + + vcc.fromIni(strBuf); + if (vcc.handle() != INVALID_CONTACT_ID) { + //if (vcc.isHandle(hContact)) + // return hContact; + return vcc.handle(); + } + else if (bCanCreate) + return vcc.toDB(); + + return vcc.handle(); +} + +/** + * name: ImportSetting + * desc: This function writes a line identified as a setting to the database + * param: hContact - handle to contact to match or NULL to match all existing + * pszModule - module to write the setting to + * strLine - string with the setting and its value to write to db + * return: 0 if writing was ok, 1 otherwise + **/ +int ImportSetting(MCONTACT hContact, LPCSTR pszModule, LPSTR &strLine) +{ + DBVARIANT dbv; + LPSTR end, value; + size_t numLines = 0; + size_t brk; + LPSTR pszLine = strLine; + + // check Module and filter "Protocol" + if (!pszModule || !*pszModule || mir_strncmp(pszModule,"Protocol",8) == 0) + return 1; + if ((end = value = mir_strchr(pszLine, '=')) == NULL) + return 1; + + // truncate setting string if it has spaces at the end + do { + if (end == pszLine) + return 1; + *(end--) = 0; + } + while (*end == '\t' || *end == ' ' || *end < 27); + + // skip spaces from the beginning of the value + do { + value++; + // if the value is empty, delete it from db + if (*value == '\0') + return db_unset(hContact, pszModule, pszLine); + } while (*value == '\t' || *value == ' '); + + // decode database type and value + switch (*(value++)) { + case 'b': + case 'B': + if (brk = strspn(value, "0123456789-")) + *(value + brk) = 0; + dbv.type = DBVT_BYTE; + dbv.bVal = (BYTE)atoi(value); + break; + case 'w': + case 'W': + if (brk = strspn(value, "0123456789-")) + *(value + brk) = 0; + dbv.type = DBVT_WORD; + dbv.wVal = (WORD)atoi(value); + break; + case 'd': + case 'D': + if (brk = strspn(value, "0123456789-")) + *(value + brk) = 0; + dbv.type = DBVT_DWORD; + dbv.dVal = (DWORD)_atoi64(value); + break; + case 's': + case 'S': + case 'u': + case 'U': + for (end = value; end && *end; end++) { + switch (*end) { + // convert STX back to \r + case 2: + *end = '\r'; + break; + // convert ETX back to \n + case 3: + *end = '\n'; + break; + } + } + switch (*(value - 1)) { + case 's': + case 'S': + dbv.type = DBVT_ASCIIZ; + dbv.pszVal = value; + break; + case 'u': + case 'U': + dbv.type = DBVT_UTF8; + dbv.pszVal = value; + break; + } + break; + case 'n': + case 'N': + { + PBYTE dest; + dbv.type = DBVT_BLOB; + dbv.cpbVal = (WORD)mir_strlen(value) / 3; + dbv.pbVal = (PBYTE)value; + for ( dest = dbv.pbVal, value = strtok(value, " "); + value && *value; + value = strtok(NULL, " ")) + *(dest++) = (BYTE)strtol(value, NULL, 16); + *dest = 0; + break; + } + default: + dbv.type = DBVT_DELETED; + //return 1; + } + return db_set(hContact, pszModule, pszLine, &dbv); +} + +/** + * name: Import + * desc: This function imports an ini file + * param: hContact - handle to contact to match or NULL to match all existing + * file - module to write the setting to + * strLine - string with the setting and its value to write to db + * return: 0 if writing was ok, 1 otherwise + **/ +int SvcExImINI_Import(MCONTACT hContact, LPCSTR pszFileName) +{ + FILE *file; + MCONTACT hNewContact = INVALID_CONTACT_ID; + DWORD end, + numLines = 0; + CHAR szModule[MAXSETTING] = {0}; + WORD numContactsInFile = 0, // number of contacts in the inifile + numContactsAdded = 0; // number of contacts, that were added to the database + CHAR *strBuf = (CHAR *) mir_alloc(1); + *strBuf = 0; + + if (file = fopen(pszFileName, "rt")) { + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + while (ImportreadLine(file, strBuf)) { + numLines++; + + // contact was found and imported + if (hContact != INVALID_CONTACT_ID && hNewContact != INVALID_CONTACT_ID) + break; + + // importing settings is only valid vor the main menu item + if (hContact == INVALID_CONTACT_ID) { + if (!strncmp(strBuf, "SETTINGS:", 9)) { + *szModule = 0; + hNewContact = NULL; + continue; + } + } + + // there are some modules of a contact (import only if contact exist) + if (!strncmp(strBuf, "FROM CONTACT:", 13)) { + strBuf = mir_strnerase(strBuf, 0, 13); + while (strBuf[0] == ' ' || strBuf[0] == '\t') + strBuf = mir_strnerase(strBuf, 0, 1); + + numContactsInFile++; + if ((hNewContact = ImportFindContact(hContact, strBuf, FALSE)) != INVALID_CONTACT_ID) + numContactsAdded++; + continue; + } + + // there is a contact to import / add + if (!strncmp(strBuf, "CONTACT:", 8)) { + strBuf = mir_strnerase(strBuf, 0, 8); + while (strBuf[0] == ' ' || strBuf[0] == '\t') + strBuf = mir_strnerase(strBuf, 0, 1); + + *szModule = 0; + numContactsInFile++; + if ((hNewContact = ImportFindContact(hContact, strBuf, TRUE)) != INVALID_CONTACT_ID) + numContactsAdded++; + continue; + } + + // read modules and settings only for valid contacts + if (hNewContact != INVALID_CONTACT_ID) { + // found a module line + if (strBuf[0] == '[' && (end = (strchr(strBuf, ']') - strBuf)) > 0) { + mir_strncpy(szModule, &strBuf[1], end); + continue; + } + // try to import a setting + ImportSetting(hNewContact, szModule, strBuf); + } + } //end while + fclose(file); + mir_free(strBuf); + SetCursor(LoadCursor(NULL, IDC_ARROW)); + + // the contact was not found in the file + if (numContactsInFile > 0 && !numContactsAdded) { + MsgErr(NULL, + LPGENT("None of the %d contacts, stored in the ini-file, match the selected contact!\nNothing will be imported"), + numContactsInFile); + } + // Import complete + else{ + MsgBox(NULL, MB_ICON_INFO, LPGENT("Import complete"), LPGENT("Some basic statistics"), + LPGENT("Added %d of %d contacts stored in the ini-file."), + numContactsAdded, numContactsInFile); + } + return 0; + } + MsgErr(NULL, + LPGENT("The ini-file \"%s\"\nfor reading contact information could not be opened."), + pszFileName); + return 1; +} |