diff options
| author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 | 
|---|---|---|
| committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 | 
| commit | 48540940b6c28bb4378abfeb500ec45a625b37b6 (patch) | |
| tree | 2ef294c0763e802f91d868bdef4229b6868527de /plugins/UserInfoEx/ex_import/svc_ExImXML.cpp | |
| parent | 5c350913f011e119127baeb32a6aedeb4f0d33bc (diff) | |
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/UserInfoEx/ex_import/svc_ExImXML.cpp')
| -rw-r--r-- | plugins/UserInfoEx/ex_import/svc_ExImXML.cpp | 453 | 
1 files changed, 453 insertions, 0 deletions
diff --git a/plugins/UserInfoEx/ex_import/svc_ExImXML.cpp b/plugins/UserInfoEx/ex_import/svc_ExImXML.cpp new file mode 100644 index 0000000000..dca52f1685 --- /dev/null +++ b/plugins/UserInfoEx/ex_import/svc_ExImXML.cpp @@ -0,0 +1,453 @@ +/*
 +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/svc_ExImXML.cpp $
 +Revision       : $Revision: 187 $
 +Last change on : $Date: 2010-09-08 16:05:54 +0400 (ะกั, 08 ัะตะฝ 2010) $
 +Last change by : $Author: ing.u.horn $
 +
 +===============================================================================
 +*/
 +#include "commonheaders.h"
 +
 +#define XMLCARD_VERSION	"1.1"
 +
 +/**
 + * system & local includes:
 + **/
 +#include "dlg_ExImModules.h"
 +#include "classExImContactXML.h"
 +#include "svc_ExImport.h"
 +
 +LRESULT CALLBACK DlgProc_DataHistory(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +	switch (msg) 
 +	{
 +		case WM_INITDIALOG:
 +		{
 +			const ICONCTRL idIcon[] = {
 +				{ ICO_DLG_EXPORT,	WM_SETICON,		NULL		},
 +				{ ICO_DLG_EXPORT,	STM_SETIMAGE,	ICO_DLGLOGO	},
 +				{ ICO_BTN_EXPORT,	BM_SETIMAGE,	IDOK		},
 +				{ ICO_BTN_CANCEL,	BM_SETIMAGE,	IDCANCEL	}
 +			};
 +			const INT numIconsToSet = DB::Setting::GetByte(SET_ICONS_BUTTONS, 1) ? SIZEOF(idIcon) : 2;
 +			IcoLib_SetCtrlIcons(hDlg, idIcon, numIconsToSet);
 +
 +			TranslateDialogDefault(hDlg);
 +			SendDlgItemMessage(hDlg, IDOK, BUTTONTRANSLATE, NULL, NULL);
 +			SendDlgItemMessage(hDlg, IDCANCEL, BUTTONTRANSLATE, NULL, NULL);
 +			break;
 +		}
 +		case WM_CTLCOLORSTATIC:
 +			switch (GetWindowLongPtr((HWND)lParam, GWLP_ID)) {
 +				case STATIC_WHITERECT:
 +				case ICO_DLGLOGO:
 +				case IDC_INFO:
 +					SetBkColor((HDC)wParam, RGB(255, 255, 255));
 +					return (INT_PTR)GetStockObject(WHITE_BRUSH);
 +			}
 +			return FALSE;
 +		case WM_COMMAND:
 +			if (HIWORD(wParam) == BN_CLICKED) {
 +				switch (LOWORD(wParam)) {
 +					case IDCANCEL:
 +						EndDialog(hDlg, 0);
 +						break;
 +					case IDOK: {
 +						WORD hiWord = 0;
 +
 +						if (IsDlgButtonChecked(hDlg, IDC_CHECK1))
 +							hiWord |= EXPORT_DATA;
 +						if (IsDlgButtonChecked(hDlg, IDC_CHECK2))
 +							hiWord |= EXPORT_HISTORY;
 +						EndDialog(hDlg, (INT_PTR)MAKELONG(IDOK, hiWord));
 +						break;
 +					}
 +				}
 +			}
 +			break;
 +	}
 +	return FALSE;
 +}
 +
 +/***********************************************************************************************************
 + * exporting stuff
 + ***********************************************************************************************************/
 +
 +/**
 + * name:	Export
 + * desc:	globally accessible function which does the whole export stuff.
 + * params:	hContact	- handle to the contact who is to export
 + *			pszFileName	- full qualified path to the xml file which is destination for the export process
 + * return:	0 on success, 1 otherwise
 + **/
 +INT CFileXml::Export(lpExImParam ExImContact, LPCSTR pszFileName)
 +{
 +	FILE *xmlfile;
 +	DB::CEnumList Modules;
 +	LONG cbHeader;
 +	SYSTEMTIME now;
 +	DWORD result;
 +	HANDLE hContact;
 +
 +	result = (DWORD)DialogBox(ghInst, 
 +							MAKEINTRESOURCE(IDD_EXPORT_DATAHISTORY),
 +							NULL, (DLGPROC)DlgProc_DataHistory);
 +	if (LOWORD(result) != IDOK)
 +	{
 +		return 0;
 +	}
 +	_wExport = HIWORD(result);
 +
 +	// show dialog to enable user to select modules for export
 +	if (!(_wExport & EXPORT_DATA) ||
 +		!DlgExImModules_SelectModulesToExport(ExImContact, &Modules, NULL)) 
 +	{
 +
 +		xmlfile = fopen(pszFileName, "wt");
 +		if (!xmlfile)
 +		{
 +			MsgErr(NULL, LPGENT("Can't create xml file!\n%S"), pszFileName);
 +			return 1;
 +		}
 +		
 +		GetLocalTime(&now);
 +
 +		// write xml header raw as it is without using the tinyxml api
 +		fprintf(xmlfile, 
 +			"%c%c%c<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
 +			"<XMLCard ver=\""XMLCARD_VERSION"\" ref=\"%04d-%02d-%02d %02d:%02d:%02d\">\n",
 +			0xefU, 0xbbU, 0xbfU, now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond
 +		);
 +		// remember the header's size
 +		cbHeader = ftell(xmlfile);
 +
 +		CExImContactXML vContact(this);
 +
 +		// write data
 +		if ( ExImContact->Typ == EXIM_CONTACT) {
 +			// export single contact
 +			_hContactToWorkOn = ExImContact->hContact;
 +			if (vContact.fromDB(ExImContact->hContact)) {
 +				vContact.Export(xmlfile, &Modules);
 +			}
 +		}
 +		else {
 +			// other export mode
 +			_hContactToWorkOn = INVALID_HANDLE_VALUE;
 +#ifdef _DEBUG
 +			LARGE_INTEGER freq, t1, t2;
 +
 +			QueryPerformanceFrequency(&freq);
 +			QueryPerformanceCounter(&t1);
 +#endif
 +			// export owner contact
 +			if (ExImContact->Typ == EXIM_ALL && vContact.fromDB(NULL)) {
 +				vContact.Export(xmlfile, &Modules);
 +			}
 +			// loop for all other contact
 +			for (hContact = DB::Contact::FindFirst();
 +				hContact != NULL;
 +				hContact = DB::Contact::FindNext(hContact))
 +			{
 +				switch (ExImContact->Typ)
 +				{
 +					case EXIM_ALL:
 +					case EXIM_GROUP:
 +						// dont export meta subcontacts by default
 +						if (!DB::MetaContact::IsSub(hContact)) {
 +							if (vContact.fromDB(hContact)) {
 +								vContact.Export(xmlfile, &Modules);
 +							}
 +						}
 +						break;
 +					case EXIM_SUBGROUP:
 +						// dont export meta subcontacts by default and
 +						// export only contact with selectet group name
 +						if (!DB::MetaContact::IsSub(hContact) && 
 +							mir_tcsncmp(ExImContact->ptszName, DB::Setting::GetTString(hContact, "CList", "Group"), mir_tcslen(ExImContact->ptszName))== 0)
 +							{
 +							if (vContact.fromDB(hContact)) {
 +								vContact.Export(xmlfile, &Modules);
 +							}
 +						}
 +						break;
 +					case EXIM_ACCOUNT:
 +						// export only contact with selectet account name
 +						if (!mir_strncmp(ExImContact->pszName, DB::Contact::Proto(hContact), mir_strlen(ExImContact->pszName))) {
 +							if (vContact.fromDB(hContact)) {
 +								vContact.Export(xmlfile, &Modules);
 +							}
 +						}
 +						break;
 +				}
 +			} // *end for
 +#ifdef _DEBUG
 +			QueryPerformanceCounter(&t2);
 +			MsgErr(NULL, LPGENT("Export took %f msec"),
 +				(long double)(t2.QuadPart - t1.QuadPart) / freq.QuadPart * 1000.);
 +#endif
 +		}// *end other export mode
 +
 +		// nothing exported?
 +		if (cbHeader == ftell(xmlfile)) {
 +			fclose(xmlfile);
 +			DeleteFileA(pszFileName);
 +			return 1;
 +		}
 +		fputs("</XMLCard>\n", xmlfile);
 +		fclose(xmlfile);
 +	}
 +	return 0;
 +}
 +
 +
 +/***********************************************************************************************************
 + * importing stuff
 + ***********************************************************************************************************/
 +
 +CFileXml::CFileXml()
 +{
 +	_numContactsTodo		= 0;
 +	_numContactsDone		= 0;
 +	_numSettingsTodo		= 0;
 +	_numSettingsDone		= 0;
 +	_numEventsTodo			= 0;
 +	_numEventsDone			= 0;
 +	_numEventsDuplicated	= 0;
 +}
 +
 +/**
 + * name:	ImportOwner
 + * desc:	Interpretes an xmlnode as owner contact, finds a corresponding contact in database
 + *			or adds a new one including all xml childnodes.
 + * params:	xContact	- xmlnode representing the contact
 + *			stat		- structure used to collect some statistics
 + * return:	ERROR_OK on success or one other element of ImportError to tell the type of failure
 + **/
 +INT CFileXml::ImportOwner(TiXmlElement* xContact)
 +{
 +	CExImContactXML vContact(this);
 +
 +	if (vContact = xContact) {
 +		vContact.Import();
 +		return ERROR_OK;
 +	}
 +	return ERROR_NOT_ADDED;
 +}
 +
 +/**
 + * name:	ImportContacts
 + * desc:	Parse all child nodes of an given parent node and try to import all found contacts
 + * params:	xmlParent	 - xmlnode representing the parent of the list of contacts
 + *			hContact	 - handle to the contact, who is the owner of the setting to import
 + *			stat		 - structure used to collect some statistics
 + * return:	ERROR_OK if at least one contact was successfully imported
 + **/
 +INT CFileXml::ImportContacts(TiXmlElement* xmlParent)
 +{
 +	TiXmlElement *xContact;
 +	CExImContactXML vContact(this);
 +	INT result;
 +	LPTSTR pszNick;
 +
 +	// import contacts
 +	for (xContact = xmlParent->FirstChildElement(); xContact != NULL; xContact = xContact->NextSiblingElement()) {
 +		if (!mir_stricmp(xContact->Value(), XKEY_CONTACT)) {
 +			// update progressbar and abort if user clicked cancel
 +			pszNick = mir_utf8decodeT(xContact->Attribute("nick"));
 +			// user clicked abort button
 +			if (_progress.UpdateContact(LPGENT("Contact: %s (%S)"), pszNick, xContact->Attribute("proto"))) {
 +				result = vContact.LoadXmlElemnt(xContact);
 +				switch (result) {
 +					case ERROR_OK:
 +						// init contact class and import if matches the user desires
 +						if (_hContactToWorkOn == INVALID_HANDLE_VALUE || vContact.handle() == _hContactToWorkOn) {
 +							result = vContact.Import(_hContactToWorkOn != INVALID_HANDLE_VALUE);
 +							switch (result) {
 +								case ERROR_OK:
 +									_numContactsDone++;
 +									break;
 +								case ERROR_ABORTED:
 +									if (pszNick) mir_free(pszNick);
 +									return ERROR_ABORTED;
 +#ifdef _DEBUG
 +								default:
 +									MsgErr(NULL, LPGENT("Importing %s caused error %d"), pszNick, result);
 +									break;
 +#endif
 +							}
 +						}
 +						break;
 +					case ERROR_ABORTED:
 +						if (pszNick) mir_free(pszNick);
 +						return ERROR_ABORTED;
 +#ifdef _DEBUG
 +					default:
 +						MsgErr(NULL, LPGENT("Loading contact %s from xml failed with error %d"), pszNick, result);
 +						break;
 +#endif
 +				}
 +			}
 +			if (pszNick) mir_free(pszNick);
 +		}
 +		// import owner contact
 +		else if (_hContactToWorkOn == INVALID_HANDLE_VALUE && !mir_stricmp(xContact->Value(), XKEY_OWNER) && (vContact = xContact)) {
 +			result = vContact.Import();
 +			switch (result) {
 +				case ERROR_OK:
 +					_numContactsDone++;
 +					break;
 +				case ERROR_ABORTED:
 +					return ERROR_ABORTED;
 +#ifdef _DEBUG
 +				default:
 +					MsgErr(NULL, LPGENT("Importing Owner caused error %d"), result);
 +#endif
 +			}
 +		}
 +	}
 +	return ERROR_OK;
 +}
 +
 +/**
 + * name:	CountContacts
 + * desc:	Counts the number of contacts stored in the file
 + * params:	xContact	- the contact, who is the owner of the keys to count
 + * return:	nothing
 + **/
 +DWORD CFileXml::CountContacts(TiXmlElement* xmlParent)
 +{
 +	DWORD dwCount = 0;
 +	TiXmlNode *xContact;
 +
 +	try {
 +		// count contacts in file for progress bar
 +		for (xContact = xmlParent->FirstChild(); xContact != NULL; xContact = xContact->NextSibling()) {
 +			if (!mir_stricmp(xContact->Value(), XKEY_CONTACT) || !mir_stricmp(xContact->Value(), XKEY_OWNER)) {
 +				dwCount += CountContacts(xContact->ToElement()) + 1;
 +			}
 +		}
 +	}
 +	catch(...) {
 +		return 0;
 +	}
 +	return dwCount;
 +}
 +
 +/**
 + * name:	Import
 + * desc:	Interpretes an xmlnode as owner contact, finds a corresponding contact in database
 + *			or adds a new one including all xml childnodes.
 + * params:	hContact	- handle to the contact, who is the owner of the setting to import
 + *			pszFileName	- full qualified path to the xml file which is to import
 + * return:	ERROR_OK on success or one other element of ImportError to tell the type of failure
 + **/
 +INT CFileXml::Import(HANDLE hContact, LPCSTR pszFileName)
 +{
 +	TiXmlDocument doc;
 +	TiXmlElement *xmlCard = NULL;
 +
 +	try {
 +		_hContactToWorkOn = hContact;
 +		// load xml file
 +		if (!doc.LoadFile(pszFileName)) {
 +			MsgErr(NULL, LPGENT("Parser is unable to load XMLCard \"%s\"\nError: %d\nDescription: %s"),
 +				pszFileName, doc.ErrorId(), doc.ErrorDesc());
 +			return 1;
 +		}
 +		// is xmlfile a XMLCard ?
 +		if ((xmlCard = doc.FirstChildElement("XMLCard")) == NULL) {
 +			MsgErr(NULL, LPGENT("The selected file is no valid XMLCard"));
 +			return 1;
 +		}
 +		// check version
 +		if (mir_strcmp(xmlCard->Attribute("ver"), XMLCARD_VERSION)) {
 +			MsgErr(NULL, LPGENT("The version of the XMLCard is not supported by UserInfoEx"));
 +			return 1;
 +		}
 +
 +		// is owner contact to import ?
 +		if (_hContactToWorkOn == NULL) {
 +			INT ret;
 +			
 +			// disable database safty mode to speed up the operation
 +			CallService(MS_DB_SETSAFETYMODE, 0, 0);
 +			// import owner contact
 +			ret = ImportOwner(xmlCard->FirstChildElement(XKEY_OWNER));
 +			// as soon as possible enable safty mode again!
 +			CallService(MS_DB_SETSAFETYMODE, 1, 0);
 +
 +			if (!ret) {
 +				MsgBox(NULL, MB_ICONINFORMATION, 
 +					LPGENT("Complete"),
 +					LPGENT("Import complete"),
 +					LPGENT("Owner contact successfully imported."));
 +				return 0;
 +			} else {
 +				MsgErr(NULL, LPGENT("Selected XMLCard does not contain an owner contact!"));
 +				return 1;
 +			}
 +		}
 +		else {
 +#ifdef _DEBUG
 +			LARGE_INTEGER freq, t1, t2;
 +
 +			QueryPerformanceFrequency(&freq);
 +			QueryPerformanceCounter(&t1);
 +#endif
 +			// count contacts in file for progress bar
 +			_numContactsTodo = CountContacts(xmlCard);
 +			if (_numContactsTodo > 0) {
 +				_progress.SetContactCount(_numContactsTodo);
 +				// disable database safty mode to speed up the operation
 +				CallService(MS_DB_SETSAFETYMODE, 0, 0);
 +				// import the contacts
 +				ImportContacts(xmlCard);
 +				// as soon as possible enable safty mode again!
 +				CallService(MS_DB_SETSAFETYMODE, 1, 0);
 +			}
 +			// finally hide the progress dialog
 +			_progress.Hide();
 +
 +#ifdef _DEBUG
 +			QueryPerformanceCounter(&t2);
 +			MsgErr(NULL, LPGENT("Import took %f msec"),
 +				(long double)(t2.QuadPart - t1.QuadPart) / freq.QuadPart * 1000.);
 +#endif
 +			// show results
 +			MsgBox(NULL, MB_ICONINFORMATION, LPGENT("Import complete"), LPGENT("Some basic statistics"), 
 +				LPGENT("added contacts: %u / %u\nadded settings: %u / %u\nadded events %u / %u\nduplicated events: %u"),
 +				_numContactsDone, _numContactsTodo,
 +				_numSettingsDone, _numSettingsTodo,
 +				_numEventsDone, _numEventsTodo,
 +				_numEventsDuplicated);
 +			
 +		}
 +	}	
 +	catch(...) {
 +		MsgErr(NULL, LPGENT("FATAL: An exception was thrown while importing contacts from xmlCard!"));
 +		return 1;
 +	}
 +	return 0;
 +}
  | 
