You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
347 lines
12 KiB
347 lines
12 KiB
/*
|
|
This file is part of KAddressbook.
|
|
Copyright (c) 2003 - 2004 Helge Deller <deller@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License version 2 as
|
|
published by the Free Software Foundation.
|
|
|
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
As a special exception, permission is given to link this program
|
|
with any edition of TQt, and distribute the resulting executable,
|
|
without including the source code for TQt in the source distribution.
|
|
|
|
|
|
Description:
|
|
This import/export filter reads and writes addressbook entries in the
|
|
gmx format which is natively used by the german freemail provider GMX.
|
|
The big advantage of this format is, that it stores it's information
|
|
very consistent and makes parsing pretty simple. Furthermore, most
|
|
information needed by KABC is available when compared to other formats.
|
|
For further information please visit http://www.gmx.com
|
|
*/
|
|
|
|
#include <tqfile.h>
|
|
#include <tqmap.h>
|
|
|
|
#include <tdefiledialog.h>
|
|
#include <tdeio/netaccess.h>
|
|
#include <tdelocale.h>
|
|
#include <kmdcodec.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdetempfile.h>
|
|
#include <kurl.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include "gmx_xxport.h"
|
|
|
|
K_EXPORT_KADDRESSBOOK_XXFILTER_CATALOG( libkaddrbk_gmx_xxport, GMXXXPort, "libkaddrbk_gmx_xxport" )
|
|
|
|
#define GMX_FILESELECTION_STRING "*.gmxa|" + i18n( "GMX addressbook file (*.gmxa)" )
|
|
|
|
GMXXXPort::GMXXXPort( TDEABC::AddressBook *ab, TQWidget *parent, const char *name )
|
|
: KAB::XXPort( ab, parent, name )
|
|
{
|
|
createImportAction( i18n( "Import GMX Address Book..." ) );
|
|
createExportAction( i18n( "Export GMX Address Book..." ) );
|
|
}
|
|
|
|
static bool checkDateTime( const TQString &dateStr, TQDateTime &dt )
|
|
{
|
|
if (dateStr.isEmpty())
|
|
return false;
|
|
dt = TQDateTime::fromString(dateStr, Qt::ISODate);
|
|
if (dt.isValid() && dt.date().year()>1901)
|
|
return true;
|
|
dt.setDate(TQDate());
|
|
return false;
|
|
}
|
|
|
|
/* import */
|
|
|
|
TDEABC::AddresseeList GMXXXPort::importContacts( const TQString& ) const
|
|
{
|
|
TDEABC::AddresseeList addrList;
|
|
|
|
TQString fileName = KFileDialog::getOpenFileName( ":xxport_gmx",
|
|
GMX_FILESELECTION_STRING, 0 );
|
|
if ( fileName.isEmpty() )
|
|
return addrList;
|
|
|
|
TQFile file( fileName );
|
|
if ( !file.open( IO_ReadOnly ) ) {
|
|
TQString msg = i18n( "<qt>Unable to open <b>%1</b> for reading.</qt>" );
|
|
KMessageBox::error( parentWidget(), msg.arg( fileName ) );
|
|
return addrList;
|
|
}
|
|
|
|
TQDateTime dt;
|
|
TQTextStream gmxStream( &file );
|
|
gmxStream.setEncoding( TQTextStream::Latin1 );
|
|
TQString line, line2;
|
|
line = gmxStream.readLine();
|
|
line2 = gmxStream.readLine();
|
|
if (!line.startsWith("AB_ADDRESSES:") || !line2.startsWith("Address_id")) {
|
|
KMessageBox::error( parentWidget(), i18n("%1 is not a GMX address book file.").arg(fileName) );
|
|
return addrList;
|
|
}
|
|
|
|
TQStringList strList;
|
|
typedef TQMap<TQString, TDEABC::Addressee *> AddressMap;
|
|
AddressMap addrMap;
|
|
|
|
// "Address_id,Nickname,Firstname,Lastname,Title,Birthday,Comments,Change_date,Status,Address_link_id,Categories"
|
|
line = gmxStream.readLine();
|
|
while (!line.startsWith("####") && !gmxStream.atEnd()) {
|
|
while (1) {
|
|
strList = TQStringList::split('#', line, true);
|
|
if (strList.count() >= 11)
|
|
break;
|
|
line.append('\n');
|
|
line.append(gmxStream.readLine());
|
|
};
|
|
|
|
TDEABC::Addressee *addr = new TDEABC::Addressee;
|
|
addr->setNickName(strList[1]);
|
|
addr->setGivenName(strList[2]);
|
|
addr->setFamilyName(strList[3]);
|
|
addr->setTitle(strList[4]);
|
|
|
|
if (addr->formattedName().isEmpty())
|
|
addr->setFormattedName(addr->realName());
|
|
|
|
if (checkDateTime(strList[5],dt)) addr->setBirthday(dt);
|
|
addr->setNote(strList[6]);
|
|
if (checkDateTime(strList[7],dt)) addr->setRevision(dt);
|
|
// addr->setStatus(strList[8]); Status
|
|
// addr->xxx(strList[9]); Address_link_id
|
|
// addr->setCategory(strList[10]); Categories
|
|
addrMap[strList[0]] = addr;
|
|
|
|
line = gmxStream.readLine();
|
|
}
|
|
|
|
// now read the address records
|
|
line = gmxStream.readLine();
|
|
if (!line.startsWith("AB_ADDRESS_RECORDS:")) {
|
|
kdWarning() << "Could not find address records!\n";
|
|
return addrList;
|
|
}
|
|
// Address_id,Record_id,Street,Country,Zipcode,City,Phone,Fax,Mobile,Mobile_type,Email,
|
|
// Homepage,Position,Comments,Record_type_id,Record_type,Company,Department,Change_date,Preferred,Status
|
|
line = gmxStream.readLine();
|
|
line = gmxStream.readLine();
|
|
|
|
while (!line.startsWith("####") && !gmxStream.atEnd()) {
|
|
while (1) {
|
|
strList = TQStringList::split('#', line, true);
|
|
if (strList.count() >= 21)
|
|
break;
|
|
line.append('\n');
|
|
line.append(gmxStream.readLine());
|
|
};
|
|
|
|
TDEABC::Addressee *addr = addrMap[strList[0]];
|
|
if (addr) {
|
|
for ( TQStringList::Iterator it = strList.begin(); it != strList.end(); ++it )
|
|
*it = (*it).simplifyWhiteSpace();
|
|
// strList[1] = Record_id (numbered item, ignore here)
|
|
int id = strList[14].toInt(); // Record_type_id (0=work,1=home,2=other)
|
|
int type = (id==0) ? TDEABC::Address::Work : TDEABC::Address::Home;
|
|
if (!strList[19].isEmpty() && strList[19].toInt()!=0)
|
|
type |= TDEABC::Address::Pref; // Preferred address (seems to be bitfield for telephone Prefs)
|
|
TDEABC::Address adr = addr->address(type);
|
|
adr.setStreet(strList[2]);
|
|
adr.setCountry(strList[3]);
|
|
adr.setPostalCode(strList[4]);
|
|
adr.setLocality(strList[5]);
|
|
addr->insertPhoneNumber( TDEABC::PhoneNumber(strList[6], TDEABC::PhoneNumber::Home) );
|
|
addr->insertPhoneNumber( TDEABC::PhoneNumber(strList[7], TDEABC::PhoneNumber::Fax) );
|
|
int celltype = TDEABC::PhoneNumber::Cell;
|
|
// strList[9]=Mobile_type // always 0 or -1(default phone).
|
|
if (strList[9].toInt()) celltype |= TDEABC::PhoneNumber::Pref;
|
|
addr->insertPhoneNumber( TDEABC::PhoneNumber(strList[8], celltype) );
|
|
addr->insertEmail(strList[10]);
|
|
if (!strList[11].isEmpty()) addr->setUrl(strList[11]);
|
|
if (!strList[12].isEmpty()) addr->setRole(strList[12]);
|
|
// strList[13]=Comments
|
|
// strList[14]=Record_type_id (0,1,2) - see above
|
|
// strList[15]=Record_type (name of this additional record entry)
|
|
if (!strList[16].isEmpty()) addr->setOrganization(strList[16]); // Company
|
|
if (!strList[17].isEmpty()) addr->insertCustom(
|
|
"KADDRESSBOOK", "X-Department", strList[17]); // Department
|
|
if (checkDateTime(strList[18],dt)) addr->setRevision(dt); // Change_date
|
|
// strList[19]=Preferred (see above)
|
|
// strList[20]=Status (should always be "1")
|
|
addr->insertAddress(adr);
|
|
} else {
|
|
kdWarning() << "unresolved line: " << line << endl;
|
|
}
|
|
|
|
line = gmxStream.readLine();
|
|
}
|
|
|
|
// now add the addresses to to addrList
|
|
for ( AddressMap::Iterator it = addrMap.begin(); it != addrMap.end(); ++it ) {
|
|
TDEABC::Addressee *addr = it.data();
|
|
addrList.append(*addr);
|
|
delete addr;
|
|
}
|
|
|
|
file.close();
|
|
return addrList;
|
|
}
|
|
|
|
|
|
/* export */
|
|
|
|
bool GMXXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString& )
|
|
{
|
|
KURL url = KFileDialog::getSaveURL( ":xxport_gmx", GMX_FILESELECTION_STRING );
|
|
if ( url.isEmpty() )
|
|
return true;
|
|
|
|
if ( !url.isLocalFile() ) {
|
|
KTempFile tmpFile;
|
|
if ( tmpFile.status() != 0 ) {
|
|
TQString txt = i18n( "<qt>Unable to open file <b>%1</b>.%2.</qt>" );
|
|
KMessageBox::error( parentWidget(), txt.arg( url.url() )
|
|
.arg( strerror( tmpFile.status() ) ) );
|
|
return false;
|
|
}
|
|
|
|
doExport( tmpFile.file(), list );
|
|
tmpFile.close();
|
|
|
|
return TDEIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
|
|
} else {
|
|
TQString filename = url.path();
|
|
TQFile file( filename );
|
|
|
|
if ( !file.open( IO_WriteOnly ) ) {
|
|
TQString txt = i18n( "<qt>Unable to open file <b>%1</b>.</qt>" );
|
|
KMessageBox::error( parentWidget(), txt.arg( filename ) );
|
|
return false;
|
|
}
|
|
|
|
doExport( &file, list );
|
|
file.close();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
static const TQString dateString( const TQDateTime &dt )
|
|
{
|
|
if (!dt.isValid())
|
|
return TQString::fromLatin1("1000-01-01 00:00:00");
|
|
TQString d(dt.toString(Qt::ISODate));
|
|
d[10] = ' '; // remove the "T" in the middle of the string
|
|
return d;
|
|
}
|
|
|
|
void GMXXXPort::doExport( TQFile *fp, const TDEABC::AddresseeList &list )
|
|
{
|
|
if (!fp || !list.count())
|
|
return;
|
|
|
|
TQTextStream t( fp );
|
|
t.setEncoding( TQTextStream::Latin1 );
|
|
|
|
TDEABC::AddresseeList::ConstIterator it;
|
|
typedef TQMap<int, const TDEABC::Addressee *> AddressMap;
|
|
AddressMap addrMap;
|
|
const TDEABC::Addressee *addr;
|
|
|
|
t << "AB_ADDRESSES:\n";
|
|
t << "Address_id,Nickname,Firstname,Lastname,Title,Birthday,Comments,"
|
|
"Change_date,Status,Address_link_id,Categories\n";
|
|
|
|
int no = 0;
|
|
const TQChar DELIM('#');
|
|
for ( it = list.begin(); it != list.end(); ++it ) {
|
|
addr = &(*it);
|
|
if (addr->isEmpty())
|
|
continue;
|
|
addrMap[++no] = addr;
|
|
t << no << DELIM // Address_id
|
|
<< addr->nickName() << DELIM // Nickname
|
|
<< addr->givenName() << DELIM // Firstname
|
|
<< addr->familyName() << DELIM // Lastname
|
|
<< addr->title() << DELIM // Title
|
|
<< dateString(addr->birthday()) << DELIM // Birthday
|
|
<< addr->note() /*.replace('\n',"\r\n")*/ << DELIM // Comments
|
|
<< dateString(addr->revision()) << DELIM // Change_date
|
|
<< "1##0\n"; // Status, Address_link_id, Categories
|
|
}
|
|
|
|
t << "####\n";
|
|
t << "AB_ADDRESS_RECORDS:\n";
|
|
t << "Address_id,Record_id,Street,Country,Zipcode,City,Phone,Fax,Mobile,"
|
|
"Mobile_type,Email,Homepage,Position,Comments,Record_type_id,Record_type,"
|
|
"Company,Department,Change_date,Preferred,Status\n";
|
|
|
|
no = 1;
|
|
while ( (addr = addrMap[no]) != NULL ) {
|
|
for (unsigned int record_id=0; record_id<3; record_id++) {
|
|
|
|
TDEABC::Address address;
|
|
TDEABC::PhoneNumber phone, fax, cell;
|
|
|
|
|
|
if (record_id == 0) {
|
|
address = addr->address(TDEABC::Address::Work);
|
|
phone = addr->phoneNumber(TDEABC::PhoneNumber::Work);
|
|
fax = addr->phoneNumber(TDEABC::PhoneNumber::Fax);
|
|
cell = addr->phoneNumber(TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Cell);
|
|
} else {
|
|
address = addr->address(TDEABC::Address::Home);
|
|
phone = addr->phoneNumber(TDEABC::PhoneNumber::Home);
|
|
cell = addr->phoneNumber(TDEABC::PhoneNumber::Cell);
|
|
}
|
|
|
|
const TQStringList emails = addr->emails();
|
|
TQString email;
|
|
if (emails.count()>record_id) email = emails[record_id];
|
|
|
|
t << no << DELIM // Address_id
|
|
<< record_id << DELIM // Record_id
|
|
<< address.street() << DELIM // Street
|
|
<< address.country() << DELIM // Country
|
|
<< address.postalCode() << DELIM // Zipcode
|
|
<< address.locality() << DELIM // City
|
|
<< phone.number() << DELIM // Phone
|
|
<< fax.number() << DELIM // Fax
|
|
<< cell.number() << DELIM // Mobile
|
|
<< ((cell.type()&TDEABC::PhoneNumber::Pref)?-1:0) << DELIM // Mobile_type
|
|
<< email << DELIM // Email
|
|
<< ((record_id==0)?addr->url().url():TQString()) << DELIM // Homepage
|
|
<< ((record_id==0)?addr->role():TQString()) << DELIM // Position
|
|
<< DELIM // Comments
|
|
<< record_id << DELIM // Record_type_id (0,1,2) - see above
|
|
<< DELIM // Record_type (name of this additional record entry)
|
|
<< ((record_id==0)?addr->organization():TQString()) << DELIM // Company
|
|
<< ((record_id==0)?addr->custom("KADDRESSBOOK", "X-Department"):TQString()) << DELIM // Department
|
|
<< dateString(addr->revision()) << DELIM // Change_date
|
|
<< 5 << DELIM // Preferred
|
|
<< 1 << endl; // Status (should always be "1")
|
|
}
|
|
|
|
++no;
|
|
};
|
|
|
|
t << "####";
|
|
}
|
|
|
|
#include "gmx_xxport.moc"
|
|
|