diff --git a/akonadi/collectionstatistics.cpp b/akonadi/collectionstatistics.cpp index f36e45170..2e0504058 100644 --- a/akonadi/collectionstatistics.cpp +++ b/akonadi/collectionstatistics.cpp @@ -1,110 +1,110 @@ /* Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collectionstatistics.h" #include #include using namespace Akonadi; /** * @internal */ class CollectionStatistics::Private : public QSharedData { public: Private() : QSharedData(), count( -1 ), unreadCount( -1 ), size( -1 ) {} Private( const Private &other ) : QSharedData( other ) { count = other.count; - unreadCount = other.count; + unreadCount = other.unreadCount; size = other.size; } qint64 count; qint64 unreadCount; qint64 size; }; CollectionStatistics::CollectionStatistics() : d( new Private ) { } CollectionStatistics::CollectionStatistics(const CollectionStatistics &other) : d( other.d ) { } CollectionStatistics::~CollectionStatistics() { } qint64 CollectionStatistics::count( ) const { return d->count; } void CollectionStatistics::setCount( qint64 count ) { d->count = count; } qint64 CollectionStatistics::unreadCount( ) const { return d->unreadCount; } void CollectionStatistics::setUnreadCount( qint64 count ) { d->unreadCount = count; } qint64 CollectionStatistics::size( ) const { return d->size; } void CollectionStatistics::setSize( qint64 size ) { d->size = size; } CollectionStatistics& CollectionStatistics::operator =(const CollectionStatistics & other) { d = other.d; return *this; } QDebug operator<<( QDebug d, const CollectionStatistics& s ) { return d << "CollectionStatistics:" << endl << " count:" << s.count() << endl << " unread count:" << s.unreadCount() << endl << " size:" << s.size(); } diff --git a/kabc/plugins/dir/dir.desktop b/kabc/plugins/dir/dir.desktop index 8d463aae3..b53082700 100644 --- a/kabc/plugins/dir/dir.desktop +++ b/kabc/plugins/dir/dir.desktop @@ -1,47 +1,49 @@ [Desktop Entry] Name=Folder +Name[ca]=Carpeta Name[da]=Mappe Name[de]=Ordner Name[el]=Φάκελος Name[es]=Carpeta Name[et]=Kataloog Name[ga]=Fillteán Name[gl]=Cartafol Name[km]=ថត Name[lv]=Mape Name[nb]=Mappe Name[nds]=Orner Name[nn]=Mappe Name[pt]=Pasta Name[pt_BR]=Pasta Name[sv]=Katalog Name[tr]=Dizin Name[uk]=Тека Name[x-test]=xxFolderxx Name[zh_CN]=文件夹 Name[zh_TW]=資料夾 Comment=Provides access to contacts, each stored in a single file, in a given folder. Supports standard VCard file and other formats depending on availability of plugins. +Comment[ca]=Proporciona l'accés als contactes, cada un emmagatzemat en un fitxer individual, en una carpeta donada. Accepta els fitxers estàndard VCard i altres formats depenent de la disponibilitat dels connectors. Comment[da]=Giver adgang til kontakter, hver lagret i en enkelt fil, i en given mappe. Understøtter standard VCard-fil og andre formater afhængigt af tilgængeligheden af plugins. Comment[de]=Ermöglicht Zugriff auf Kontakte, die in einzelnen Dateien in einem vorgegebenen Ordner gespeichert sind. Unterstützt Standard-VCard-Dateien und andere Formate abhängig von den verfügbaren Modulen. Comment[el]=Προσφέρει πρόσβαση σε επαφές, αποθηκευμένες σε ξεχωριστά αρχεία, σε ένα 
δοσμένο φάκελο. Υποστηρίζει τυπικά αρχεία VCard και άλλες μορφές αρχείων ανάλογα με τη διαθεσιμότητα των πρόσθετων. Comment[es]=Provee acceso a los contactos, cada uno almacenado en un archivo diferente, dentro de un directorio determinado. Soporta archivos VCard estándar y otros formatos dependiendo de la disponibilidad de los complementos Comment[et]=Võimaldab kasutada eraldi failidesse salvestatud kontakte määratud kataloogis. Toetab standardseid VCard-faile ja teisi vorminguid sõltuvalt pluginate olemasolust. Comment[ga]=Soláthraíonn sé seo rochtain ar theagmhálacha, gach ceann stóráilte i gcomhad aonair, i bhfillteán sonraithe. Tacaítear le comhaid v-Chárta agus le formáidí eile, ag brath ar na breiseáin atá ar fáil. Comment[gl]=Dá acceso aos contactos, cada un gardado nun ficheiro nun cartafol dado. Admite ficheiros vCard estándar e outros formatos, en función da dispoñibilidade de extensións. Comment[km]=ផ្ដល់​ការ​ចូលដំណើរការ​ទៅ​កាន់​ទំនាក់ទំនង ដែល​ទំនាក់ទំនង​នីមួយៗ​ត្រូវ​បានផ្ទុកនៅ​ក្នុង​ឯកសារ​តែ​មួយ នៅ​ក្នុង​ថត​ដែល​បានផ្ដល់​ឲ្យ ។ គាំទ្រ​ឯកសារ VCard និង​ទ្រង់ទ្រាយ​ផ្សេងៗ​ ដោយ​អាស្រ័យ​លើ​កម្មវិធី​ជំនួយ​ដែល​មាន ។ Comment[lv]=Nodrošina pieeju kontaktiem, kas katrs saglabāts individuālā failā norādītajā mapē. Atbalsta standarta VCard failus un citus formātus, atkarībā no pieejamajiem spraudņiem. Comment[nb]=Gir tilgang til kontakter, lagret hver for seg i en enkelt fil, i en gitt mappe. Støtter standard vCard og andre formater avhengig av tilgjengelige programtillegg. Comment[nds]=Stellt Togriep op Kontakten praat, elkeen binnen een Datei binnen en angeven Orner. Ünnerstütt VCard-Dateien un anner Formaten na de verföögboren Modulen. Comment[nn]=Gjev tilgang til kontaktar i ei viss mappe, der dei er lagra i kvar sine filer. Standard vCard-filer er støtta, i tillegg til andre format, avhengig av kva programtillegg som er i bruk. Comment[pt]=Oferece o acesso aos contactos, estando cada um guardado num único ficheiro de uma dada pasta. Suporta os ficheiros VCard normais, assim como outros formatos, dependendo da disponibilidade dos 'plugins'. Comment[pt_BR]=Fornece acesso aos contatos, cada um armazenado em um único arquivo, em uma pasta informada. Suporta o formato de arquivos VCard padrão e outros formatos, dependendo da disponibilidade de plug-ins. Comment[sv]=Ger tillgång till kontakter, var och en lagrad i en enstaka fil, i en given katalog. Stöder vCard-standardfiler och andra format, beroende på tillgängliga insticksprogram. Comment[uk]=Надає доступ до контактів, кожен з яких зберігається у окремому файлі у вказаній теці. Підтримує стандартні файли VCard та файли у інших форматах, залежно від наявності відповідних додатків. Comment[x-test]=xxProvides access to contacts, each stored in a single file, in a given folder. Supports standard VCard file and other formats depending on availability of plugins.xx Comment[zh_CN]=提供对被存储在指定目录下的单独一个文件中的联系人的访问支持。支持标准 VCard 文件和其它插件所允许的格式。 Comment[zh_TW]=提供存取特定目錄下,個別儲存在單一檔案中的聯絡人的功能。支援標準的 VCard 檔,以及外掛程式所提供的其它格式檔案。 X-KDE-Library=kabc_directory Type=Service X-KDE-ServiceTypes=KResources/Plugin X-KDE-ResourceFamily=contact X-KDE-ResourceType=dir diff --git a/kabc/plugins/file/file.desktop b/kabc/plugins/file/file.desktop index 7a2d4e9dc..b40a82369 100644 --- a/kabc/plugins/file/file.desktop +++ b/kabc/plugins/file/file.desktop @@ -1,68 +1,69 @@ [Desktop Entry] Name=File Name[be]=Файл Name[ca]=Fitxer Name[cs]=Soubor Name[da]=Fil Name[de]=Datei Name[el]=Αρχείο Name[es]=Archivo Name[et]=Fail Name[fr]=Fichier Name[ga]=Comhad Name[gl]=Ficheiro Name[hne]=फाइल Name[hu]=Fájl Name[ja]=ファイル Name[km]=ឯកសារ Name[lt]=Failas Name[lv]=Fails Name[nb]=Fil Name[nds]=Datei Name[nl]=Bestand Name[nn]=Fil Name[oc]=Fichièr Name[pa]=ਫਾਇਲ Name[pl]=Plik Name[pt]=Ficheiro Name[pt_BR]=Arquivo Name[ro]=Fișier Name[ru]=Файл Name[se]=Fiila Name[sk]=Súbor Name[sl]=Datoteka Name[sr]=Фајл Name[sr@latin]=Fajl Name[sv]=Fil Name[th]=แฟ้ม Name[tr]=Dosya Name[uk]=Файл Name[x-test]=xxFilexx Name[zh_CN]=文件 Name[zh_TW]=檔案 Comment=Provides access to contacts stored in a single local file. Supports standard VCard files and other formats depending on available plugins. +Comment[ca]=Proporciona l'accés als contactes emmagatzemats en un fitxer individual. Accepta els fitxers estàndard VCard i altres formats, depenent dels connectors disponibles. Comment[da]=Giver adgang til kontakter, hver lagret i en enkelt fil. Understøtter standard VCard-fil og andre formater afhængigt af tilgængelige af plugins. Comment[de]=Ermöglicht Zugriff auf Kontakte, die in einer einzigen Dateien lokal gespeichert sind. Unterstützt Standard-VCard-Dateien und andere Formate abhängig von den verfügbaren Modulen. Comment[el]=Προσφέρει πρόσβαση σε επαφές, αποθηκευμένες σε ένα τοπικό αρχείο. Υποστηρίζει τυπικά αρχεία VCard και άλλες μορφές αρχείων ανάλογα με τη διαθεσιμότητα των πρόσθετων. Comment[es]=Provee acceso a los contactos almacenados en un único archivo local. Soporta archivos VCard estándar y otros formatos dependiendo de la disponibilidad de los componentes. Comment[et]=Võimaldab kasutada kohalikku faili salvestatud kontakte. Toetab standardseid VCard-faile ja teisi vorminguid sõltuvalt pluginate olemasolust. Comment[ga]=Soláthraíonn sé seo rochtain ar theagmhálacha, stóráilte i gcomhad aonair. Tacaítear le comhaid v-Chárta agus formáidí eile, ag brath ar na breiseáin atá ar fáil. Comment[gl]=Dá acceso a contactos gardados nun único ficheiro local. Admite ficheiros vCard estándar e outros formatos en función das extensións dispoñíbeis. Comment[ja]=単一のローカルファイルに保存されている連絡先へのアクセスを提供します。標準の VCard ファイルと、利用可能なプラグインに応じたフォーマットをサポートします。 Comment[km]=ផ្ដល់​កា​រចូលដំណើរការ​ទៅ​ទំនាក់ទំនង​​នៅ​ក្នុង​ឯកសារ​មូលដ្ឋាន​តែ​មួយ ។ គាំទ្រ​ឯកសារ VCard ស្តង់ដារ និង​ទ្រង់ទ្រាយ​ផ្សេងៗ​ ដោយ​អាស្រ័យ​លើ​កម្មវិធី​ជំនួយ​ដែល​មាន ។ Comment[lv]=Nodrošina piekļuvi kontaktiem, kas glabājas vienā lokālā failā. Atbalsta standarta VCard failus un citus formātus, atkarībā no pieejamajiem spraudņiem. Comment[nb]=Gir tilgang til kontakter, lagret i en enkelt lokal fil. Støtter standard vCard og andre formater avhengig av tilgjengelige programtillegg. Comment[nds]=Stellt Togriep op Kontakten praat, de in een enkel lokaal Datei wohrt warrt. Ünnerstütt VCard-Dateien un anner Formaten na de 'verföögboren Modulen. Comment[nn]=Gjev tilgang til kontaktar lagra i ei einskild lokal fil. Standard vCard-filer er støtta, i tillegg til andre format, avhengig av kva programtillegg som er i bruk. Comment[pt]=Oferece o acesso aos contactos, estando todos guardados num único ficheiro local. Suporta os ficheiros VCard normais, assim como outros formatos, dependendo da disponibilidade dos 'plugins'. Comment[pt_BR]=Fornece acesso aos contatos armazenados em um único arquivo local. Suporta o formato de arquivos VCard padrão e outros formatos, dependendo da disponibilidade de plug-ins. Comment[sv]=Ger tillgång till kontakter lagrade i en enda lokal fil. Stöder vCard-standardfiler och andra format, beroende på tillgängliga insticksprogram. Comment[uk]=Надає доступ до контактів, які зберігаються у окремому локальному файлі. Підтримує стандартні файли VCard та файли у інших форматах, залежно від наявності відповідних додатків. Comment[x-test]=xxProvides access to contacts stored in a single local file. Supports standard VCard files and other formats depending on available plugins.xx Comment[zh_CN]=提供对被存储在单独的本地文件中的联系人的访问支持。支持标准 VCard 文件和其它插件所允许的格式。 Comment[zh_TW]=提供存取儲存在單一檔案中的聯絡人的功能。支援標準的 VCard 檔,以及外掛程式所提供的其它格式檔案。 X-KDE-Library=kabc_file Type=Service X-KDE-ServiceTypes=KResources/Plugin X-KDE-ResourceFamily=contact X-KDE-ResourceType=file diff --git a/kabc/plugins/net/net.desktop b/kabc/plugins/net/net.desktop index 18d4c1a87..dee85a987 100644 --- a/kabc/plugins/net/net.desktop +++ b/kabc/plugins/net/net.desktop @@ -1,70 +1,71 @@ [Desktop Entry] Name=Network Name[be]=Сетка Name[ca]=Xarxa Name[cs]=Síť Name[da]=Netværk Name[de]=Netzwerk Name[el]=Δίκτυο Name[es]=Red Name[et]=Võrk Name[fr]=Réseau Name[ga]=Líonra Name[gl]=Rede Name[hne]=नेटवर्क Name[hu]=Hálózat Name[it]=Rete Name[ja]=ネットワーク Name[km]=បណ្តាញ Name[lt]=Tinklas Name[lv]=Tīkls Name[nb]=Nettverk Name[nds]=Nettwark Name[nl]=Netwerk Name[nn]=Nettverk Name[oc]=Ret Name[pa]=ਨੈੱਟਵਰਕ Name[pl]=Sieć Name[pt]=Rede Name[pt_BR]=Rede Name[ro]=Rețea Name[ru]=Сетевой файл Name[se]=Fierbmi Name[sk]=Sieť Name[sl]=Omrežje Name[sr]=Мрежа Name[sr@latin]=Mreža Name[sv]=Nätverk Name[th]=ระบบเครือข่าย Name[tr]=Ağ Name[uk]=Мережа Name[x-test]=xxNetworkxx Name[zh_CN]=网络 Name[zh_TW]=網路 Comment=Provides access to contacts in remote files using KDE's network framework KIO. Supports standard VCard files and other formats depending on available plugins. +Comment[ca]=Proporciona l'accés als contactes en fitxers remots usant la infraestructura KIO de xarxa del KDE. Accepta els fitxers estàndard VCard i altres formats, depenent dels connectors disponibles. Comment[da]=Giver adgang til kontakter i eksterne filer med brug af KDE's netværks-framework KIO. Understøtter standard VCard-filer og andre formater afhængigt af tilgængelige plugins. Comment[de]=Ermöglicht Zugriff auf Kontakte in entfernten Dateien durch das KIO-Netzwerksystem von KDE. Unterstützt Standard-VCard-Dateien und andere Formate abhängig von den verfügbaren Modulen. Comment[el]=Προσφέρει πρόσβαση σε επαφές σε απομακρυσμένα αρχεία με τη χρήση του συστήματος KIO του KDE. Υποστηρίζει τυπικά αρχεία VCard και άλλες μορφές αρχείων ανάλογα με τη διαθεσιμότητα των πρόσθετων. Comment[es]=Provee acceso a los contactos en un archivo remoto utilizando la infraestructura de red KIO de KDE. Soporta archivos VCard estándar y otros formatos dependiendo en la disponibilidad de los complementos. Comment[et]=Võimaldab kasutada võrgufaile KDE võrguraamistiku KIO abil. Toetab standardseid VCard-faile ja teisi vorminguid sõltuvalt pluginate olemasolust. Comment[ga]=Soláthraíonn sé seo rochtain ar theagmhálacha i gcianchomhaid tríd an gcreatlach líonra KIO atá cuid de KDE. Tacaítear le comhaid v-Chárta agus formáidí eile, ag brath ar na breiseáin atá ar fáil. Comment[gl]=Dá acceso a contactos gardados en ficheiros remotos mediante a infraestrutura de rede KIO, de KDE. Admite ficheiros vCard estándar e outros formatos en función das extensións dispoñíbeis. Comment[ja]=KDE のネットワークフレームワーク KIO を使って、リモートファイルに保存されている連絡先へのアクセスを提供します。標準の VCard ファイルと、利用可能なプラグインに応じたフォーマットをサポートします。 Comment[km]=ផ្ដល់​កា​រចូលដំណើរការ​ទៅកាន់​ទំនាក់ទំនង​ក្នុង​​ឯកសារ​ពី​ចម្ងាយ ដោយ​ប្រើ KIO ​គ្រោងការណ៍​បណ្ដាញ​របស់ KDE ។ គាំទ្រ​ឯកសារ VCard ស្តង់ដារ និង​ទ្រង់ទ្រាយ​ផ្សេងៗ​ទៀត ដោយ​អាស្រ័យ​លើ​កម្មវិធី​ជំនួយ​ដែល​លមាន ។ Comment[lv]=Nodrošina piekļuvi kontaktiem attālinātos failus, izmantojot KDE tīklošanas ietvaru KIO. Atbalsta standarta VCard failus un citus formātus, atkarībā no pieejamajiem spraudņiem. Comment[nb]=Gir tilgang til kontakter i nettverksfiler, ved bruk av KDEs rammeverk KIO for nettverk. Støtter standard vCard og andre formater avhengig av tilgjengelige programtillegg. Comment[nds]=Stellt Togriep op Kontakten binnen feern Dateien praat, bruukt KDE sien Nettwark-Rahmenwark KIO. Ünnerstütt VCard-Dateien un anner Formaten na de verföögboren Modulen. Comment[nn]=Gjev tilgang til kontaktar i nettverksfiler ved å bruka KIO, nettverksrammeverket frå KDE. Standard vCard-filer er støtta, i tillegg til andre format, avhengig av kva programtillegg som er i bruk. Comment[pt]=Oferece o acesso aos contactos em ficheiros remotos, disponíveis através de um KIO da plataforma de rede do KDE. Suporta os ficheiros VCard normais, assim como outros formatos, dependendo da disponibilidade dos 'plugins'. Comment[pt_BR]=Fornece acesso aos contatos em arquivos remotos usando o KIO framework da rede do KDE. O suporte à arquivos VCard padrão e outros formatos dependem da disponibilidade de plug-ins. Comment[sv]=Ger tillgång till kontakter i fjärrfiler med användning av KDE:s I/O-ramverk. Stöder vCard-standardfiler och andra format, beroende på tillgängliga insticksprogram. Comment[tr]=KDE'nin ağ iskeleti KIO'yu kullanarak uzak dosyalardaki kişilere erişim sağlar. Mevcut eklentilere bağlı olarak standart VCard dosyalarını ve diğer dosya biçimleri destekler. Comment[uk]=Надає доступ до контактів, які зберігаються у віддалених файлах, за допомогою мережевих засобів KIO KDE. Підтримує стандартні файли VCard та файли у інших форматах, залежно від наявності відповідних додатків. Comment[x-test]=xxProvides access to contacts in remote files using KDE's network framework KIO. Supports standard VCard files and other formats depending on available plugins.xx Comment[zh_CN]=通过 KDE 的网络透明框架 KIO,提供对被存储在远程文件中的联系人的访问支持。支持标准 VCard 文件和其它插件所允许的格式。 Comment[zh_TW]=提供存取使用 KDE 網路架構 KIO 儲存在遠端檔案中的聯絡人。支援標準的 VCard 檔,以及外掛程式所提供的其它格式檔案。 X-KDE-Library=kabc_net Type=Service X-KDE-ServiceTypes=KResources/Plugin X-KDE-ResourceFamily=contact X-KDE-ResourceType=net diff --git a/kioslave/nntp/nntp.cpp b/kioslave/nntp/nntp.cpp index 42e5570da..3269f7beb 100644 --- a/kioslave/nntp/nntp.cpp +++ b/kioslave/nntp/nntp.cpp @@ -1,964 +1,964 @@ /* This file is part of KDE Copyright (C) 2000 by Wolfram Diestel Copyright (C) 2005 by Tim Way - Copyright (C) 2005 by Volker Krause + Copyright (C) 2005 by Volker Krause This is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. */ #include "nntp.h" #include #include #include #include #include #include #include #include #include #include #include #define DBG_AREA 7114 #define DBG kDebug(DBG_AREA) #define ERR kError(DBG_AREA) using namespace KIO; extern "C" { int KDE_EXPORT kdemain(int argc, char **argv); } int kdemain(int argc, char **argv) { KComponentData componentData("kio_nntp"); if (argc != 4) { fprintf(stderr, "Usage: kio_nntp protocol domain-socket1 domain-socket2\n"); exit(-1); } NNTPProtocol *slave; // Are we going to use SSL? if (strcasecmp(argv[1], "nntps") == 0) { slave = new NNTPProtocol(argv[2], argv[3], true); } else { slave = new NNTPProtocol(argv[2], argv[3], false); } slave->dispatchLoop(); delete slave; return 0; } /****************** NNTPProtocol ************************/ NNTPProtocol::NNTPProtocol ( const QByteArray & pool, const QByteArray & app, bool isSSL ) : TCPSlaveBase((isSSL ? "nntps" : "nntp"), pool, app, isSSL ), isAuthenticated( false ) { DBG << "=============> NNTPProtocol::NNTPProtocol"; readBufferLen = 0; m_defaultPort = isSSL ? DEFAULT_NNTPS_PORT : DEFAULT_NNTP_PORT; m_port = m_defaultPort; } NNTPProtocol::~NNTPProtocol() { DBG << "<============= NNTPProtocol::~NNTPProtocol"; // close connection nntp_close(); } void NNTPProtocol::setHost ( const QString & host, quint16 port, const QString & user, const QString & pass ) { DBG << ( ! user.isEmpty() ? (user+'@') : QString("")) << host << ":" << ( ( port == 0 ) ? m_defaultPort : port ); if ( isConnected() && (mHost != host || m_port != port || mUser != user || mPass != pass) ) nntp_close(); mHost = host; m_port = ( ( port == 0 ) ? m_defaultPort : port ); mUser = user; mPass = pass; } void NNTPProtocol::get( const KUrl& url ) { DBG << url.prettyUrl(); QString path = QDir::cleanPath(url.path()); // path should be like: /group/ or /group/ if ( path.startsWith( QDir::separator() ) ) path.remove( 0, 1 ); int pos = path.indexOf( QDir::separator() ); QString group; QString msg_id; if ( pos > 0 ) { group = path.left( pos ); msg_id = path.mid( pos + 1 ); } if ( group.isEmpty() || msg_id.isEmpty() ) { error(ERR_DOES_NOT_EXIST,path); return; } int res_code; DBG << "group:" << group << "msg:" << msg_id; if ( !nntp_open() ) return; // select group if necessary if ( mCurrentGroup != group && !group.isEmpty() ) { infoMessage( i18n("Selecting group %1...", group ) ); res_code = sendCommand( "GROUP " + group ); if ( res_code == 411 ){ error( ERR_DOES_NOT_EXIST, path ); mCurrentGroup.clear(); return; } else if ( res_code != 211 ) { unexpected_response( res_code, "GROUP" ); mCurrentGroup.clear(); return; } mCurrentGroup = group; } // get article infoMessage( i18n("Downloading article...") ); res_code = sendCommand( "ARTICLE " + msg_id ); if ( res_code == 423 || res_code == 430 ) { error( ERR_DOES_NOT_EXIST, path ); return; } else if (res_code != 220) { unexpected_response(res_code,"ARTICLE"); return; } // read and send data char tmp[MAX_PACKET_LEN]; while ( true ) { if ( !waitForResponse( readTimeout() ) ) { error( ERR_SERVER_TIMEOUT, mHost ); nntp_close(); return; } int len = readLine( tmp, MAX_PACKET_LEN ); const char* buffer = tmp; if ( len <= 0 ) break; if ( len == 3 && tmp[0] == '.' && tmp[1] == '\r' && tmp[2] == '\n') break; if ( len > 1 && tmp[0] == '.' && tmp[1] == '.' ) { ++buffer; --len; } data( QByteArray::fromRawData( buffer, len ) ); } // end of data data(QByteArray()); // finish finished(); } void NNTPProtocol::put( const KUrl &/*url*/, int /*permissions*/, KIO::JobFlags /*flags*/ ) { if ( !nntp_open() ) return; if ( post_article() ) finished(); } void NNTPProtocol::special(const QByteArray& data) { // 1 = post article int cmd; QDataStream stream(data); if ( !nntp_open() ) return; stream >> cmd; if (cmd == 1) { if (post_article()) finished(); } else { error(ERR_UNSUPPORTED_ACTION,i18n("Invalid special command %1", cmd)); } } bool NNTPProtocol::post_article() { DBG; // send post command infoMessage( i18n("Sending article...") ); int res_code = sendCommand( "POST" ); if (res_code == 440) { // posting not allowed error(ERR_WRITE_ACCESS_DENIED, mHost); return false; } else if (res_code != 340) { // 340: ok, send article unexpected_response(res_code,"POST"); return false; } // send article now int result; bool last_chunk_had_line_ending = true; do { QByteArray buffer; dataReq(); result = readData( buffer ); DBG << "receiving data:" << buffer; // treat the buffer data if ( result > 0 ) { // translate "\r\n." to "\r\n.." int pos = 0; if ( last_chunk_had_line_ending && buffer[0] == '.' ) { buffer.insert( 0, '.' ); pos += 2; } last_chunk_had_line_ending = ( buffer.endsWith( "\r\n" ) ); while ( (pos = buffer.indexOf( "\r\n.", pos )) > 0) { buffer.insert( pos + 2, '.' ); pos += 4; } // send data to socket, write() doesn't send the terminating 0 write( buffer, buffer.length() ); DBG << "writing:" << buffer; } } while ( result > 0 ); // error occurred? if (result<0) { ERR << "error while getting article data for posting"; nntp_close(); return false; } // send end mark write( "\r\n.\r\n", 5 ); // get answer res_code = evalResponse( readBuffer, readBufferLen ); if (res_code == 441) { // posting failed error(ERR_COULD_NOT_WRITE, mHost); return false; } else if (res_code != 240) { unexpected_response(res_code,"POST"); return false; } return true; } void NNTPProtocol::stat( const KUrl& url ) { DBG << url.prettyUrl(); UDSEntry entry; QString path = QDir::cleanPath(url.path()); QRegExp regGroup = QRegExp("^\\/?[a-z0-9\\.\\-_]+\\/?$",Qt::CaseInsensitive); QRegExp regMsgId = QRegExp("^\\/?[a-z0-9\\.\\-_]+\\/<\\S+>$", Qt::CaseInsensitive); int pos; QString group; QString msg_id; // / = group list if (path.isEmpty() || path == "/") { DBG << "root"; fillUDSEntry( entry, QString(), 0, false, ( S_IWUSR | S_IWGRP | S_IWOTH ) ); // /group = message list } else if (regGroup.indexIn(path) == 0) { if ( path.startsWith( '/' ) ) path.remove(0,1); if ((pos = path.indexOf('/')) > 0) group = path.left(pos); else group = path; DBG << "group:" << group; // postingAllowed should be ored here with "group not moderated" flag // as size the num of messages (GROUP cmd) could be given fillUDSEntry( entry, group, 0, false, ( S_IWUSR | S_IWGRP | S_IWOTH ) ); // /group/ = message } else if (regMsgId.indexIn(path) == 0) { pos = path.indexOf('<'); group = path.left(pos); msg_id = KUrl::fromPercentEncoding( path.right(path.length()-pos).toLatin1() ); if ( group.startsWith( '/' ) ) group.remove( 0, 1 ); if ((pos = group.indexOf('/')) > 0) group = group.left(pos); DBG << "group:" << group << "msg:" << msg_id; fillUDSEntry( entry, msg_id, 0, true ); // invalid url } else { error(ERR_DOES_NOT_EXIST,path); return; } statEntry(entry); finished(); } void NNTPProtocol::listDir( const KUrl& url ) { DBG << url.prettyUrl(); if ( !nntp_open() ) return; QString path = QDir::cleanPath(url.path()); if (path.isEmpty()) { KUrl newURL(url); newURL.setPath("/"); DBG << "redirecting to" << newURL.prettyUrl(); redirection(newURL); finished(); return; } else if ( path == "/" ) { fetchGroups( url.queryItem( "since" ), url.queryItem( "desc" ) == "true" ); finished(); } else { // if path = /group int pos; QString group; if ( path.startsWith( '/' ) ) path.remove( 0, 1 ); if ((pos = path.indexOf('/')) > 0) group = path.left(pos); else group = path; QString first = url.queryItem( "first" ); QString max = url.queryItem( "max" ); if ( fetchGroup( group, first.toULong(), max.toULong() ) ) finished(); } } void NNTPProtocol::fetchGroups( const QString &since, bool desc ) { int expected; int res; if ( since.isEmpty() ) { // full listing infoMessage( i18n("Downloading group list...") ); res = sendCommand( "LIST" ); expected = 215; } else { // incremental listing infoMessage( i18n("Looking for new groups...") ); res = sendCommand( "NEWGROUPS " + since ); expected = 231; } if ( res != expected ) { unexpected_response( res, "LIST" ); return; } // read newsgroups line by line QByteArray line; QString group; int pos, pos2; long msg_cnt; long access; UDSEntry entry; QHash entryMap; // read in data and process each group. one line at a time while ( true ) { if ( ! waitForResponse( readTimeout() ) ) { error( ERR_SERVER_TIMEOUT, mHost ); nntp_close(); return; } readBufferLen = readLine ( readBuffer, MAX_PACKET_LEN ); line = QByteArray( readBuffer, readBufferLen ); if ( line == ".\r\n" ) break; // group name if ((pos = line.indexOf(' ')) > 0) { group = line.left(pos); // number of messages line.remove(0,pos+1); long last = 0; access = 0; if (((pos = line.indexOf(' ')) > 0 || (pos = line.indexOf('\t')) > 0) && ((pos2 = line.indexOf(' ',pos+1)) > 0 || (pos2 = line.indexOf('\t',pos+1)) > 0)) { last = line.left(pos).toLongLong(); long first = line.mid(pos+1,pos2-pos-1).toLongLong(); msg_cnt = abs(last-first+1); // group access rights switch ( line[pos2 + 1] ) { case 'n': access = 0; break; case 'm': access = S_IWUSR | S_IWGRP; break; case 'y': access = S_IWUSR | S_IWGRP | S_IWOTH; break; } } else { msg_cnt = 0; } entry.clear(); fillUDSEntry( entry, group, msg_cnt, false, access ); if ( !desc ) listEntry( entry, false ); else entryMap.insert( group, entry ); } } // handle group descriptions QHash::Iterator it = entryMap.begin(); if ( desc ) { infoMessage( i18n("Downloading group descriptions...") ); totalSize( entryMap.size() ); } while ( desc ) { // request all group descriptions if ( since.isEmpty() ) res = sendCommand( "LIST NEWSGROUPS" ); else { // request only descriptions for new groups if ( it == entryMap.end() ) break; res = sendCommand( "LIST NEWSGROUPS " + it.key() ); ++it; if( res == 503 ) { // Information not available (RFC 2980 §2.1.6), try next group continue; } } if ( res != 215 ) { // No group description available or not implemented break; } // download group descriptions while ( true ) { if ( ! waitForResponse( readTimeout() ) ) { error( ERR_SERVER_TIMEOUT, mHost ); nntp_close(); return; } readBufferLen = readLine ( readBuffer, MAX_PACKET_LEN ); line = QByteArray( readBuffer, readBufferLen ); if ( line == ".\r\n" ) break; //DBG << " fetching group description: " << QString( line ).trimmed(); int pos = line.indexOf( ' ' ); pos = pos < 0 ? line.indexOf( '\t' ) : qMin( pos, line.indexOf( '\t' ) ); group = line.left( pos ); QString groupDesc = line.right( line.length() - pos ).trimmed(); if ( entryMap.contains( group ) ) { entry = entryMap.take( group ); entry.insert( KIO::UDSEntry::UDS_EXTRA, groupDesc ); listEntry( entry, false ); } } if ( since.isEmpty() ) break; } // take care of groups without descriptions for ( QHash::Iterator it = entryMap.begin(); it != entryMap.end(); ++it ) listEntry( it.value(), false ); entry.clear(); listEntry( entry, true ); } bool NNTPProtocol::fetchGroup( QString &group, unsigned long first, unsigned long max ) { int res_code; QString resp_line; // select group infoMessage( i18n("Selecting group %1...", group ) ); res_code = sendCommand( "GROUP " + group ); if ( res_code == 411 ) { error( ERR_DOES_NOT_EXIST, group ); mCurrentGroup.clear(); return false; } else if ( res_code != 211 ) { unexpected_response( res_code, "GROUP" ); mCurrentGroup.clear(); return false; } mCurrentGroup = group; // repsonse to "GROUP " command is 211 then find the message count (cnt) // and the first and last message followed by the group name unsigned long firstSerNum, lastSerNum; resp_line = QString::fromLatin1( readBuffer ); QRegExp re ( "211\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"); if ( re.indexIn( resp_line ) != -1 ) { firstSerNum = re.cap( 2 ).toLong(); lastSerNum = re.cap( 3 ).toLong(); } else { error( ERR_INTERNAL, i18n("Could not extract message serial numbers from server response:\n%1", resp_line ) ); return false; } if (firstSerNum == 0) return true; first = qMax( first, firstSerNum ); if ( max > 0 && lastSerNum - first > max ) first = lastSerNum - max + 1; DBG << "Starting from serial number: " << first << " of " << firstSerNum << " - " << lastSerNum; setMetaData( "FirstSerialNumber", QString::number( firstSerNum ) ); setMetaData( "LastSerialNumber", QString::number( lastSerNum ) ); infoMessage( i18n("Downloading new headers...") ); totalSize( lastSerNum - first ); bool notSupported = true; if ( fetchGroupXOVER( first, notSupported ) ) return true; else if ( notSupported ) return fetchGroupRFC977( first ); return false; } bool NNTPProtocol::fetchGroupRFC977( unsigned long first ) { UDSEntry entry; // set article pointer to first article and get msg-id of it int res_code = sendCommand( "STAT " + QString::number( first ) ); QString resp_line = readBuffer; if (res_code != 223) { unexpected_response(res_code,"STAT"); return false; } //STAT res_line: 223 nnn ... QString msg_id; int pos, pos2; if ((pos = resp_line.indexOf('<')) > 0 && (pos2 = resp_line.indexOf('>',pos+1))) { msg_id = resp_line.mid(pos,pos2-pos+1); fillUDSEntry( entry, msg_id, 0, true ); listEntry( entry, false ); } else { error(ERR_INTERNAL,i18n("Could not extract first message id from server response:\n%1", resp_line)); return false; } // go through all articles while (true) { res_code = sendCommand("NEXT"); if (res_code == 421) { // last artice reached entry.clear(); listEntry( entry, true ); return true; } else if (res_code != 223) { unexpected_response(res_code,"NEXT"); return false; } //res_line: 223 nnn ... resp_line = readBuffer; if ((pos = resp_line.indexOf('<')) > 0 && (pos2 = resp_line.indexOf('>',pos+1))) { msg_id = resp_line.mid(pos,pos2-pos+1); entry.clear(); fillUDSEntry( entry, msg_id, 0, true ); listEntry( entry, false ); } else { error(ERR_INTERNAL,i18n("Could not extract message id from server response:\n%1", resp_line)); return false; } } return true; // Not reached } bool NNTPProtocol::fetchGroupXOVER( unsigned long first, bool ¬Supported ) { notSupported = false; QString line; QStringList headers; int res = sendCommand( "LIST OVERVIEW.FMT" ); if ( res == 215 ) { while ( true ) { if ( ! waitForResponse( readTimeout() ) ) { error( ERR_SERVER_TIMEOUT, mHost ); nntp_close(); return false; } readBufferLen = readLine ( readBuffer, MAX_PACKET_LEN ); line = QString::fromLatin1( readBuffer, readBufferLen ); if ( line == ".\r\n" ) break; headers << line.trimmed(); DBG << "OVERVIEW.FMT:" << line.trimmed(); } } else { // fallback to defaults headers << "Subject:" << "From:" << "Date:" << "Message-ID:" << "References:" << "Bytes:" << "Lines:"; } res = sendCommand( "XOVER " + QString::number( first ) + '-' ); if ( res == 420 ) return true; // no articles selected if ( res == 500 ) notSupported = true; // unknwon command if ( res != 224 ) return false; long msgSize; QString name; UDSEntry entry; int udsType; QStringList fields; while ( true ) { if ( ! waitForResponse( readTimeout() ) ) { error( ERR_SERVER_TIMEOUT, mHost ); nntp_close(); return false; } readBufferLen = readLine ( readBuffer, MAX_PACKET_LEN ); line = QString::fromLatin1( readBuffer, readBufferLen ); if ( line == ".\r\n" ) { entry.clear(); listEntry( entry, true ); return true; } fields = line.split( '\t', QString::KeepEmptyParts); msgSize = 0; entry.clear(); udsType = KIO::UDSEntry::UDS_EXTRA; QStringList::ConstIterator it = headers.constBegin(); QStringList::ConstIterator it2 = fields.constBegin(); // first entry is the serial number name = (*it2); ++it2; for ( ; it != headers.constEnd() && it2 != fields.constEnd(); ++it, ++it2 ) { if ( (*it) == "Bytes:" ) { msgSize = (*it2).toLong(); continue; } QString atomStr; if ( (*it).endsWith( "full" ) ) if ( (*it2).trimmed().isEmpty() ) atomStr = (*it).left( (*it).indexOf( ':' ) + 1 ); // strip of the 'full' suffix else atomStr = (*it2).trimmed(); else atomStr = (*it) + ' ' + (*it2).trimmed(); entry.insert( udsType++, atomStr ); if ( udsType >= KIO::UDSEntry::UDS_EXTRA_END ) break; } fillUDSEntry( entry, name, msgSize, true ); listEntry( entry, false ); } return true; // not reached } void NNTPProtocol::fillUDSEntry( UDSEntry& entry, const QString& name, long size, bool is_article, long access ) { long posting=0; // entry name entry.insert(KIO::UDSEntry::UDS_NAME, name); // entry size entry.insert(KIO::UDSEntry::UDS_SIZE, size); // file type entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, is_article? S_IFREG : S_IFDIR); // access permissions posting = postingAllowed? access : 0; long long accessVal = (is_article)? (S_IRUSR | S_IRGRP | S_IROTH) : (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH | posting); entry.insert(KIO::UDSEntry::UDS_ACCESS, accessVal); entry.insert(KIO::UDSEntry::UDS_USER, mUser.isEmpty() ? QString::fromLatin1("root") : mUser); /* entry->insert(UDS_GROUP, QString::fromLatin1("root")); */ // MIME type if (is_article) { entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("message/news") ); } } void NNTPProtocol::nntp_close () { if ( isConnected() ) { write( "QUIT\r\n", 6 ); disconnectFromHost(); isAuthenticated = false; } mCurrentGroup.clear(); } bool NNTPProtocol::nntp_open() { // if still connected reuse connection if ( isConnected() ) { DBG << "reusing old connection"; return true; } DBG << " nntp_open -- creating a new connection to" << mHost << ":" << m_port; // create a new connection (connectToHost() includes error handling) infoMessage( i18n("Connecting to server...") ); if ( connectToHost( (isAutoSsl() ? "nntps" : "nntp"), mHost.toLatin1(), m_port ) ) { DBG << " nntp_open -- connection is open"; // read greeting int res_code = evalResponse( readBuffer, readBufferLen ); /* expect one of 200 server ready - posting allowed 201 server ready - no posting allowed */ if ( ! ( res_code == 200 || res_code == 201 ) ) { unexpected_response(res_code,"CONNECT"); return false; } DBG << " nntp_open -- greating was read res_code :" << res_code; res_code = sendCommand("MODE READER"); // TODO: not in RFC 977, so we should not abort here if ( !(res_code == 200 || res_code == 201) ) { unexpected_response( res_code, "MODE READER" ); return false; } // let local class know whether posting is allowed or not postingAllowed = (res_code == 200); // activate TLS if requested if ( metaData("tls") == "on" ) { if ( sendCommand( "STARTTLS" ) != 382 ) { error( ERR_COULD_NOT_CONNECT, i18n("This server does not support TLS") ); return false; } if ( !startSsl() ) { error( ERR_COULD_NOT_CONNECT, i18n("TLS negotiation failed") ); return false; } } // *try* to authenticate now (see bug#167718) authenticate(); return true; } return false; } int NNTPProtocol::sendCommand( const QString &cmd ) { int res_code = 0; if ( !nntp_open() ) { ERR << "NOT CONNECTED, cannot send cmd" << cmd; return 0; } DBG << "cmd:" << cmd; write( cmd.toLatin1(), cmd.length() ); // check the command for proper termination if ( !cmd.endsWith( "\r\n" ) ) write( "\r\n", 2 ); res_code = evalResponse( readBuffer, readBufferLen ); // if authorization needed send user info if (res_code == 480) { DBG << "auth needed, sending user info"; if ( mUser.isEmpty() || mPass.isEmpty() ) { KIO::AuthInfo authInfo; authInfo.username = mUser; authInfo.password = mPass; if ( openPasswordDialog( authInfo ) ) { mUser = authInfo.username; mPass = authInfo.password; } } if ( mUser.isEmpty() || mPass.isEmpty() ) return res_code; res_code = authenticate(); if (res_code != 281) { // error should be handled by invoking function return res_code; } // ok now, resend command write( cmd.toLatin1(), cmd.length() ); if ( !cmd.endsWith( "\r\n" ) ) write( "\r\n", 2 ); res_code = evalResponse( readBuffer, readBufferLen ); } return res_code; } int NNTPProtocol::authenticate() { int res_code = 0; if( isAuthenticated ) { // already authenticated return 281; } if( mUser.isEmpty() || mPass.isEmpty() ) { return 281; // failsafe : maybe add a "relax" mode to optionally ask user/pwd. } // send username to server and confirm response write( "AUTHINFO USER ", 14 ); write( mUser.toLatin1(), mUser.length() ); write( "\r\n", 2 ); res_code = evalResponse( readBuffer, readBufferLen ); if( res_code == 281 ) { // no password needed (RFC 2980 3.1.1 does not required one) return res_code; } if (res_code != 381) { // error should be handled by invoking function return res_code; } // send password write( "AUTHINFO PASS ", 14 ); write( mPass.toLatin1(), mPass.length() ); write( "\r\n", 2 ); res_code = evalResponse( readBuffer, readBufferLen ); if( res_code == 281 ) { isAuthenticated = true; } return res_code; } void NNTPProtocol::unexpected_response( int res_code, const QString &command ) { ERR << "Unexpected response to" << command << "command: (" << res_code << ")" << readBuffer; KIO::Error errCode; switch ( res_code ) { case 480: errCode = ERR_COULD_NOT_LOGIN; break; default: errCode = ERR_INTERNAL; } error( errCode, i18n("Unexpected server response to %1 command:\n%2", command, readBuffer ) ); nntp_close(); } int NNTPProtocol::evalResponse ( char *data, ssize_t &len ) { if ( !waitForResponse( responseTimeout() ) ) { error( ERR_SERVER_TIMEOUT , mHost ); nntp_close(); return -1; } len = readLine( data, MAX_PACKET_LEN ); if ( len < 3 ) return -1; // get the first three characters. should be the response code int respCode = ( ( data[0] - 48 ) * 100 ) + ( ( data[1] - 48 ) * 10 ) + ( ( data[2] - 48 ) ); DBG << "got:" << respCode; return respCode; } /* not really necessary, because the slave has to use the KIO::Error's instead, but let this here for documentation of the NNTP response codes and may by later use. QString& NNTPProtocol::errorStr(int resp_code) { QString ret; switch (resp_code) { case 100: ret = "help text follows"; break; case 199: ret = "debug output"; break; case 200: ret = "server ready - posting allowed"; break; case 201: ret = "server ready - no posting allowed"; break; case 202: ret = "slave status noted"; break; case 205: ret = "closing connection - goodbye!"; break; case 211: ret = "group selected"; break; case 215: ret = "list of newsgroups follows"; break; case 220: ret = "article retrieved - head and body follow"; break; case 221: ret = "article retrieved - head follows"; break; case 222: ret = "article retrieved - body follows"; break; case 223: ret = "article retrieved - request text separately"; break; case 230: ret = "list of new articles by message-id follows"; break; case 231: ret = "list of new newsgroups follows"; break; case 235: ret = "article transferred ok"; break; case 240: ret = "article posted ok"; break; case 335: ret = "send article to be transferred"; break; case 340: ret = "send article to be posted"; break; case 400: ret = "service discontinued"; break; case 411: ret = "no such news group"; break; case 412: ret = "no newsgroup has been selected"; break; case 420: ret = "no current article has been selected"; break; case 421: ret = "no next article in this group"; break; case 422: ret = "no previous article in this group"; break; case 423: ret = "no such article number in this group"; break; case 430: ret = "no such article found"; break; case 435: ret = "article not wanted - do not send it"; break; case 436: ret = "transfer failed - try again later"; break; case 437: ret = "article rejected - do not try again"; break; case 440: ret = "posting not allowed"; break; case 441: ret = "posting failed"; break; case 500: ret = "command not recognized"; break; case 501: ret = "command syntax error"; break; case 502: ret = "access restriction or permission denied"; break; case 503: ret = "program fault - command not performed"; break; default: ret = QString("unknown NNTP response code %1").arg(resp_code); } return ret; } */ diff --git a/kioslave/nntp/nntp.h b/kioslave/nntp/nntp.h index 9abcdcd2c..9fa28d174 100644 --- a/kioslave/nntp/nntp.h +++ b/kioslave/nntp/nntp.h @@ -1,141 +1,141 @@ /* This file is part of KDE Copyright (C) 2000 by Wolfram Diestel Copyright (C) 2005 by Tim Way - Copyright (C) 2005 by Volker Krause + Copyright (C) 2005 by Volker Krause This is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. */ #ifndef _NNTP_H #define _NNTP_H #include #include #define MAX_PACKET_LEN 8192 /* TODO: - test special post command - progress information in get, and maybe post - remove unnecessary debug stuff */ class NNTPProtocol:public KIO::TCPSlaveBase { public: /** Default Constructor * @param isSSL is a true or false to indicate whether ssl is to be used */ NNTPProtocol ( const QByteArray & pool, const QByteArray & app, bool isSSL ); virtual ~NNTPProtocol(); virtual void get(const KUrl& url ); virtual void put( const KUrl& url, int permissions, KIO::JobFlags flags ); virtual void stat(const KUrl& url ); virtual void listDir(const KUrl& url ); virtual void setHost(const QString& host, quint16 port, const QString& user, const QString& pass); /** * Special command: 1 = post article * it takes no other args, the article data are * requested by dataReq() and should be valid * as in RFC850. It's not checked for correctness here. * @deprecated use put() for posting */ virtual void special(const QByteArray& data); protected: /** * Send a command to the server. Returns the response code and * the response line */ int sendCommand( const QString &cmd ); /** * Attempt to properly shut down the NNTP connection by sending * "QUIT\r\n" before closing the socket. */ void nntp_close (); /** * Attempt to initiate a NNTP connection via a TCP socket, if no existing * connection could be reused. */ bool nntp_open(); /** * Post article. Invoked by special() and put() */ bool post_article(); private: QString mHost, mUser, mPass; quint16 m_port, m_defaultPort; bool postingAllowed, isAuthenticated; char readBuffer[MAX_PACKET_LEN]; ssize_t readBufferLen; /// Current selected newsgroup QString mCurrentGroup; /** * Fetch all new groups since the given date or (if the date is empty) * all available groups. * @param since Date as specified in RFC 977 for the NEWGROUPS command * @param desc Fetch group description (needs more memory) */ void fetchGroups( const QString &since, bool desc ); /** * Fetch message listing from the given newsgroup. * This will use RFC2980 XOVER if available, plain RFC977 STAT/NEXT * otherwise. * @param group The newsgroup name * @param first Serial number of the first message, 0 lists all messages. * @param max Maximal number of returned messages, 0 means unlimited. * @return true on success, false otherwise. */ bool fetchGroup ( QString &group, unsigned long first = 0, unsigned long max = 0 ); /** * Fetch message listing from the current group using RFC977 STAT/NEXT * commands. * @param first message number of the first article * @return true on success, false otherwise. */ bool fetchGroupRFC977( unsigned long first ); /** * Fetch message listing from the current group using the RFC2980 XOVER * command. * Additional headers provided by XOVER are added as UDS_EXTRA entries * to the listing. * @param first message number of the first article * @param notSupported boolean reference to indicate if command failed * due to missing XOVER support on the server. * @return true on success, false otherwise */ bool fetchGroupXOVER( unsigned long first, bool ¬Supported ); /// creates an UDSEntry with file information used in stat and listDir void fillUDSEntry ( KIO::UDSEntry & entry, const QString & name, long size, bool is_article, long access = 0 ); /// error handling for unexpected responses void unexpected_response ( int res_code, const QString & command ); /** * grabs the response line from the server. used after most send_cmd calls. max * length for the returned string ( char *data ) is 4096 characters including * the "\r\n" terminator. */ int evalResponse ( char *data, ssize_t &len ); /** * Try to authenticate to the server. * @return the response code from the server if the mUser/mPassword * are available; 281 (successfull authentication) otherwise. */ int authenticate(); }; #endif diff --git a/kldap/tests/testkldap.h b/kldap/tests/testkldap.h index 700279384..c680ecc27 100644 --- a/kldap/tests/testkldap.h +++ b/kldap/tests/testkldap.h @@ -1,57 +1,57 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TESTKLDAP_H #define TESTKLDAP_H #include #include #include #include using namespace KLDAP; class KLdapTest : public QObject { Q_OBJECT private Q_SLOTS: //void testKLdap(); void initTestCase(); void cleanupTestCase(); void testLdapUrl(); void testBer(); void testLdapConnection(); void testLdapSearch(); void testLdapDN(); void testLdapModel(); public Q_SLOTS: void searchResult( KLDAP::LdapSearch *search ); void searchData( KLDAP::LdapSearch *search, const KLDAP::LdapObject &obj ); private: QString m_url; LdapSearch *m_search; LdapObjects m_objects; LdapModel *m_model; }; #endif diff --git a/kmime/tests/contentindextest.cpp b/kmime/tests/contentindextest.cpp index c1dfcff4f..ac6ff7f18 100644 --- a/kmime/tests/contentindextest.cpp +++ b/kmime/tests/contentindextest.cpp @@ -1,91 +1,91 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "contentindextest.h" #include #include using namespace KMime; #include QTEST_KDEMAIN( ContentIndexTest, NoGUI ) void ContentIndexTest::testToString() { KMime::ContentIndex ci; QCOMPARE( ci.toString(), QString() ); ci.push( 1 ); QCOMPARE( ci.toString(), QString( "1" ) ); ci.push( 2 ); QCOMPARE( ci.toString(), QString( "2.1" ) ); } void ContentIndexTest::testFromString( ) { ContentIndex ci1; QVERIFY( !ci1.isValid() ); ContentIndex ci2( "1.2.bla" ); QVERIFY( !ci2.isValid() ); ContentIndex ci3( "1" ); QVERIFY( ci3.isValid() ); QCOMPARE( ci3.pop(), 1u ); QVERIFY( !ci3.isValid() ); ContentIndex ci4( "3.2" ); QVERIFY( ci4.isValid() ); QCOMPARE( ci4.pop(), 3u ); QCOMPARE( ci4.pop(), 2u ); QVERIFY( !ci4.isValid() ); } void ContentIndexTest::testContent( ) { Content *c1 = new Content(); QCOMPARE( c1->content( ContentIndex() ), c1 ); QCOMPARE( c1->content( ContentIndex( "1" ) ), (Content*)0 ); QCOMPARE( c1->indexForContent( c1 ), ContentIndex() ); Content *c11 = new Content(); // this makes c1 multipart/mixed, ie. c11 will be the second child! c1->addContent( c11 ); QCOMPARE( c1->content( ContentIndex( "2" ) ), c11 ); QCOMPARE( c1->content( ContentIndex( "3" ) ), (Content*)0 ); QCOMPARE( c1->content( ContentIndex( "2.1" ) ), (Content*)0 ); QCOMPARE( c1->indexForContent( c1 ), ContentIndex() ); QCOMPARE( c1->indexForContent( c11 ), ContentIndex( "2" ) ); QCOMPARE( c1->indexForContent( c1->contents().first() ), ContentIndex( "1" ) ); Content *c12 = new Content(); c1->addContent( c12 ); // c12 becomes multipart/mixed, ie. c12 will be the second child! Content *c121 = new Content(); c12->addContent( c121 ); QCOMPARE( c1->content( ContentIndex( "3" ) ), c12 ); QCOMPARE( c1->content( ContentIndex( "3.2" ) ), c121 ); QCOMPARE( c1->indexForContent( c121 ), ContentIndex( "3.2" ) ); QCOMPARE( c121->index(), ContentIndex( "3.2" ) ); QCOMPARE( c1->indexForContent( (Content*)0 ), ContentIndex() ); } #include "contentindextest.moc" diff --git a/kmime/tests/contentindextest.h b/kmime/tests/contentindextest.h index 2f5ea7b92..0a22b16c2 100644 --- a/kmime/tests/contentindextest.h +++ b/kmime/tests/contentindextest.h @@ -1,34 +1,34 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KMIME_CONTENTINDEXTEXT_H #define KMIME_CONTENTINDEXTEXT_H #include class ContentIndexTest : public QObject { Q_OBJECT private Q_SLOTS: void testToString(); void testFromString(); void testContent(); }; #endif diff --git a/kmime/tests/kmime_content_test.cpp b/kmime/tests/kmime_content_test.cpp index a531ef845..f4799acbd 100644 --- a/kmime/tests/kmime_content_test.cpp +++ b/kmime/tests/kmime_content_test.cpp @@ -1,446 +1,446 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kmime_content_test.h" #include #include #include #include using namespace KMime; QTEST_KDEMAIN( KMimeContentTest, NoGUI ) void KMimeContentTest::testGetHeaderInstance( ) { // stuff that looks trivial but breaks if you mess with virtual method signatures (see r534381) Headers::From *myfrom = new Headers::From(); QCOMPARE( myfrom->type(), "From" ); Headers::Base *mybase = myfrom; QCOMPARE( mybase->type(), "From" ); // getHeaderInstance() is protected, so we need to test it via KMime::Message Message *c = new Message(); Headers::From *f1 = c->from( true ); Headers::From *f2 = c->from( true ); QCOMPARE( f1, f2 ); delete c; } void KMimeContentTest::testSetContent() { Content *c = new Content(); QVERIFY( !c->hasContent() ); // head and body present c->setContent( "head1\nhead2\n\nbody1\n\nbody2\n" ); QVERIFY( c->hasContent() ); QCOMPARE( c->head(), QByteArray( "head1\nhead2\n" ) ); QCOMPARE( c->body(), QByteArray( "body1\n\nbody2\n" ) ); QList list; list << "head1" << "head2" << "" << "body1" << "" << "body2"; c->setContent( list ); QVERIFY( c->hasContent() ); QCOMPARE( c->head(), QByteArray( "head1\nhead2\n" ) ); QCOMPARE( c->body(), QByteArray( "body1\n\nbody2\n" ) ); // ### the final \n is questionable // empty content c->setContent( QByteArray() ); QVERIFY( !c->hasContent() ); QVERIFY( c->head().isEmpty() ); QVERIFY( c->body().isEmpty() ); // empty head c->setContent( "\nbody1\n\nbody2\n" ); QVERIFY( c->hasContent() ); QVERIFY( c->head().isEmpty() ); QCOMPARE( c->body(), QByteArray( "body1\n\nbody2\n" ) ); list.clear(); list << "" << "body1" << "" << "body2"; c->setContent( list ); QVERIFY( c->hasContent() ); QVERIFY( c->head().isEmpty() ); QCOMPARE( c->body(), QByteArray( "body1\n\nbody2\n" ) ); // empty body c->setContent( "head1\nhead2\n\n" ); QVERIFY( c->hasContent() ); QCOMPARE( c->head(), QByteArray( "head1\nhead2\n" ) ); QVERIFY( c->body().isEmpty() ); list.clear(); list << "head1" << "head2" << ""; c->setContent( list ); QVERIFY( c->hasContent() ); QCOMPARE( c->head(), QByteArray( "head1\nhead2\n" ) ); QVERIFY( c->body().isEmpty() ); } void KMimeContentTest::testMultipleHeaderExtraction() { QByteArray data = "From: Nathaniel Borenstein \n" "To: Ned Freed \n" "Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)\n" "Subject: Sample message\n" "Received: from ktown.kde.org ([192.168.100.1])\n" "Received: from dev1.kde.org ([192.168.100.2])\n" "\t by ktown.kde.org ([192.168.100.1])\n" "Received: from dev2.kde.org ([192.168.100.3])\n" " by ktown.kde.org ([192.168.100.1])\n"; Message *msg = new Message(); msg->setContent( data ); // FAILS identically to KMimeContentTest::testMultipartMixed // QCOMPARE( msg->encodedContent(), data ); msg->parse(); QList result = msg->headersByType( "Received" ); QCOMPARE( result.count(), 3 ); QCOMPARE( result[0]->asUnicodeString(), QString("from ktown.kde.org ([192.168.100.1])") ); QCOMPARE( result[1]->asUnicodeString(), QString("from dev1.kde.org ([192.168.100.2]) by ktown.kde.org ([192.168.100.1])") ); QCOMPARE( result[2]->asUnicodeString(), QString("from dev2.kde.org ([192.168.100.3]) by ktown.kde.org ([192.168.100.1])") ); } void KMimeContentTest::testMultipartMixed() { // example taken from RFC 2046, section 5.1.1. QByteArray data = "From: Nathaniel Borenstein \n" "To: Ned Freed \n" "Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)\n" "Subject: Sample message\n" "MIME-Version: 1.0\n" "Content-type: multipart/mixed; boundary=\"simple boundary\"\n" "\n" "This is the preamble. It is to be ignored, though it\n" "is a handy place for composition agents to include an\n" "explanatory note to non-MIME conformant readers.\n" "\n" "--simple boundary\n" "\n" "This is implicitly typed plain US-ASCII text.\n" "It does NOT end with a linebreak.\n" "--simple boundary\n" "Content-type: text/plain; charset=us-ascii\n" "\n" "This is explicitly typed plain US-ASCII text.\n" "It DOES end with a linebreak.\n" "\n" "--simple boundary--\n" "\n" "This is the epilogue. It is also to be ignored.\n"; QByteArray part1 = "This is implicitly typed plain US-ASCII text.\n" "It does NOT end with a linebreak."; QByteArray part2 = "This is explicitly typed plain US-ASCII text.\n" "It DOES end with a linebreak.\n"; // slightly diffrent from original data QByteArray assembled = "From: Nathaniel Borenstein \n" "Subject: Sample message\n" "To: Ned Freed \n" "Date: Sun, 21 Mar 1993 23:56:48 -0800\n" "MIME-Version: 1.0\n" "Content-Type: multipart/mixed; boundary=\"simple boundary\"\n" "\n" "\n" "--simple boundary\n" "\n" "This is implicitly typed plain US-ASCII text.\n" "It does NOT end with a linebreak.\n" "--simple boundary\n" "Content-Type: text/plain; charset=\"us-ascii\"\n" "\n" "This is explicitly typed plain US-ASCII text.\n" "It DOES end with a linebreak.\n" "\n" "--simple boundary--\n"; // test parsing Message *msg = new Message(); msg->setContent( data ); QCOMPARE( msg->encodedContent(), data ); msg->parse(); QVERIFY( msg->contentType()->isMultipart() ); Content::List list = msg->contents(); QCOMPARE( list.count(), 2 ); Content *c = list.takeFirst(); QCOMPARE( c->body(), part1 ); c = list.takeFirst(); QCOMPARE( c->body(), part2 ); // assemble again msg->assemble(); QCOMPARE( msg->encodedContent(), assembled ); delete msg; // assembling from scratch msg = new Message(); msg->from()->from7BitString( "Nathaniel Borenstein " ); msg->to()->from7BitString( "Ned Freed " ); msg->subject()->from7BitString( "Sample message" ); msg->date()->from7BitString( "Sun, 21 Mar 1993 23:56:48 -0800 (PST)" ); msg->setBody( part1 ); c = new Content(); c->setBody( part2 ); c->contentType()->setMimeType( "text/plain" ); c->contentType()->setCharset( "us-ascii" ); msg->addContent( c ); msg->contentType()->setBoundary( "simple boundary" ); list = msg->contents(); QCOMPARE( list.count(), 2 ); c = list.takeFirst(); QCOMPARE( c->body(), part1 ); c = list.takeFirst(); QCOMPARE( c->body(), part2 ); msg->assemble(); QCOMPARE( msg->encodedContent(), assembled ); } void KMimeContentTest::testImplicitMultipartGeneration() { Content *c1 = new Content(); c1->contentType()->from7BitString( "text/plain" ); c1->setBody( "textpart" ); Content *c2 = new Content(); c2->contentType()->from7BitString( "text/html" ); c2->setBody( "htmlpart" ); c1->addContent( c2 ); // c1 implicitly converted into a multipart/mixed node QCOMPARE( c1->contentType()->mimeType(), QByteArray("multipart/mixed") ); QVERIFY( c1->body().isEmpty() ); Content *c = c1->contents().at( 0 ); // former c1 QCOMPARE( c->contentType()->mimeType(), QByteArray("text/plain") ); QCOMPARE( c->body(), QByteArray("textpart") ); QCOMPARE( c1->contents().at( 1 ), c2 ); } void KMimeContentTest::testExplicitMultipartGeneration() { Content *c1 = new Content(); c1->contentType()->from7BitString( "multipart/mixed" ); Content *c2 = new Content(); c2->contentType()->from7BitString( "text/plain" ); c2->setBody( "textpart" ); Content *c3 = new Content(); c3->contentType()->from7BitString( "text/html" ); c3->setBody( "htmlpart" ); c1->addContent( c2 ); c1->addContent( c3 ); // c1 should not be changed QCOMPARE( c1->contentType()->mimeType(), QByteArray("multipart/mixed") ); QVERIFY( c1->body().isEmpty() ); QCOMPARE( c1->contents().at( 0 ), c2 ); QCOMPARE( c1->contents().at( 1 ), c3 ); } void KMimeContentTest::testParsingUuencoded() { const QByteArray body = "This is a test message that should appears as a text/plain part\n" "once this message is parsed and convert to a MIME tree.\n" "\n" "\n"; const QString imageName = "Name of the encoded file (oxygen 22x22 kde.png)"; const QByteArray uuencodedMsg = "Path: news.example.net!not-for-mail\n" "From: Coin coin \n" "Newsgroups: test.kmime.uuencoded\n" "Subject: Kmime test\n" "Date: Thu, 14 Apr 2005 20:12:47 -0700\n" "Message-ID: \n" "X-Newsreader: Forte Agent 2.0/32.640\n" "Lines: 1283\n" "Organization: Ament\n" "Xref: news.example.net test.kmime.uuencoded:4584\n" "\n" "This is a test message that should appears as a text/plain part\n" "once this message is parsed and convert to a MIME tree.\n" "\n" "begin 644 Name of the encoded file (oxygen 22x22 kde.png)\n" "MB5!.1PT*&@H````-24A$4@```!8````6\"`8```#$M&P[````!'-\"250(\"`@(\n" "M?`ADB`````EP2%ES```#=@```W8!?=6\"S````!ET15AT4V]F='=A^U1FZM2*X2V035`Q5.9UM3S:>&Z__]?36N1],G.QRQ[_QS:6C!YX\\R)\n" "M;C]FS/&)EU&=IH<.PEQ\"\",LUJMK*2K9VT9UVZ.V9D62)H.TK#RE4:;\n" "M1$1..L\"H&WSY\\)$#K*X-(%0,!ST6!EV&W91>&B-B^=>;.Z@*\"WL'#`8[NIG@$<=8(RXI2@5)MF,8;^'F!B5&$]$HX[9=L')\n" "MCW>)G.'I,W/Z>Q;()QF??K_B;,*Y\\S-^,XGPE&\"3/F`,N\\08*:L\"%8=U\"6H2\n" "M@D3X8&F\"H6@@31+B.*'T4%3*`\\O;1,[AG$.S\"5_\\\n" "MQ\"K.6OYVJ>*5&QT\"!I4(%W>_VZ$,@::%5H6Z5L1:&766K%GJ6R/625TKK4+E\n" "M`[,XY==_N$'9P.E?O,&6ZR`BB`AK*PD@&($B+\\CKFKRNJ6I/6;6(M83E-6O:\n" "MN&>-L\\Q+3]6V%%7#=&/,P;TISYZ]PL4JIJ@;0`#AF>?'/F]QRWWL7N;M7LCW-:)J*-C2`T*>/$5LJ*$$]=963.!\"4M@UL9H:FAK8%\n" "M5064IA5^=/8FEZ[EW/+MS]])K\\SQ=8GW-2)*1H8QA09V^:9\"M>6A9R[RR=.O\n" "M<>'-.7>N6-1;0F,((:\"J&&)<.N+TLY?)2\\^@8WC\\4X?0VA/J$@T!J0G\"L4<&\n" "M@[7C-Q975U,;)0QZ(U96]O/@>X0'/KC,X[_3YC%FVPW2Z1613\n" "M]HSV<77]E3\\\"K:@JLO]#*]W%X\\_W]]YS?[>_)XU=A#,6:P0DH-KB38;7G,CV\n" "MB;1+)%WBN$MD$U2$?+[57+OTTJLW7S_SI6I\\X8*H*K>(B`-&P'Y``.'_H[QE\n" ";$[@.>-WU'U(#IV=EWM`H`````$E%3D2N0F\"\"\n" "`\n" "end\n" "\n"; Message *msg = new Message(); msg->setContent( uuencodedMsg ); msg->parse(); Content::List contents = msg->contents(); // text + image QCOMPARE( contents.size(), 2 ); Content *c = 0; // Check the first text part c = contents.at( 0 ); QVERIFY( c->contentType()->isPlainText() ); QCOMPARE( c->body(), body ); // Check the image part c = contents.at( 1 ); QVERIFY( !c->contentType()->isText() ); QCOMPARE( c->contentType()->name(), imageName ); delete msg; } void KMimeContentTest::testParent() { Content *c1 = new Content(); c1->contentType()->from7BitString( "multipart/mixed" ); Content *c2 = new Content(); c2->contentType()->from7BitString( "text/plain" ); c2->setBody( "textpart" ); Content *c3 = new Content(); c3->contentType()->from7BitString( "text/html" ); c3->setBody( "htmlpart" ); Content *c4 = new Content(); c4->contentType()->from7BitString( "text/html" ); c4->setBody( "htmlpart2" ); Content *c5 = new Content(); c5->contentType()->from7BitString( "multipart/mixed" ); //c2 doesn't have a parent yet QCOMPARE(c2->parent(), (Content*)(0L)); c1->addContent( c2 ); c1->addContent( c3 ); c1->addContent( c4 ); // c1 is the parent of those QCOMPARE( c2->parent(), c1 ); QCOMPARE( c3->parent(), c1 ); //test removal c1->removeContent(c2, false); QCOMPARE(c2->parent(), (Content*)(0L)); QCOMPARE(c1->contents().at( 0 ), c3 ); //check if the content is moved correctly to another parent c5->addContent( c4 ); QCOMPARE(c4->parent(), c5); QCOMPARE(c1->contents().count(), 0); //yes, it should be 0 QCOMPARE(c5->contents().at( 0 ), c4); // example taken from RFC 2046, section 5.1.1. QByteArray data = "From: Nathaniel Borenstein \n" "To: Ned Freed \n" "Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)\n" "Subject: Sample message\n" "MIME-Version: 1.0\n" "Content-type: multipart/mixed; boundary=\"simple boundary\"\n" "\n" "This is the preamble. It is to be ignored, though it\n" "is a handy place for composition agents to include an\n" "explanatory note to non-MIME conformant readers.\n" "\n" "--simple boundary\n" "\n" "This is implicitly typed plain US-ASCII text.\n" "It does NOT end with a linebreak.\n" "--simple boundary\n" "Content-type: text/plain; charset=us-ascii\n" "\n" "This is explicitly typed plain US-ASCII text.\n" "It DOES end with a linebreak.\n" "\n" "--simple boundary--\n" "\n" "This is the epilogue. It is also to be ignored.\n"; // test parsing Message *msg = new Message(); msg->setContent( data ); msg->parse(); QCOMPARE( msg->parent(), (Content*)(0L)); QCOMPARE( msg->contents().at( 0 )->parent(), msg); QCOMPARE( msg->contents().at( 1 )->parent(), msg); delete msg; } #include "kmime_content_test.moc" diff --git a/kmime/tests/kmime_content_test.h b/kmime/tests/kmime_content_test.h index 0085cda2a..148a4e499 100644 --- a/kmime/tests/kmime_content_test.h +++ b/kmime/tests/kmime_content_test.h @@ -1,43 +1,43 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KMIME_CONTENT_TEST_H #define KMIME_CONTENT_TEST_H #include class KMimeContentTest : public QObject { Q_OBJECT private Q_SLOTS: void testGetHeaderInstance(); void testSetContent(); void testMultipartMixed(); void testImplicitMultipartGeneration(); void testExplicitMultipartGeneration(); void testMultipleHeaderExtraction(); /** Tests that a message with uuencoded content is parsed correctly and if a corresponding MIME structure is created. */ void testParsingUuencoded(); void testParent(); }; #endif diff --git a/kmime/tests/kmime_util_test.cpp b/kmime/tests/kmime_util_test.cpp index ab6d0beab..0170cd706 100644 --- a/kmime/tests/kmime_util_test.cpp +++ b/kmime/tests/kmime_util_test.cpp @@ -1,63 +1,63 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "kmime_util_test.h" #include "kmime_util_test.moc" #include using namespace KMime; QTEST_KDEMAIN( KMimeUtilTest, NoGUI ) void KMimeUtilTest::testUnfoldHeader() { // empty header QCOMPARE( KMime::unfoldHeader( "" ), QByteArray() ); // identity QCOMPARE( KMime::unfoldHeader( "bla" ), QByteArray( "bla" ) ); // single folding QCOMPARE( KMime::unfoldHeader( "bla\nblub" ), QByteArray( "bla blub" ) ); QCOMPARE( KMime::unfoldHeader( "bla\n \t blub" ), QByteArray( "bla blub" ) ); QCOMPARE( KMime::unfoldHeader( "bla \r\nblub" ), QByteArray( "bla blub" ) ); // multiple folding QCOMPARE( KMime::unfoldHeader( "bla\nbla\nblub" ), QByteArray( "bla bla blub" ) ); QCOMPARE( KMime::unfoldHeader( "bla \r\n bla \r\n blub" ), QByteArray( "bla bla blub" ) ); QCOMPARE( KMime::unfoldHeader( "bla\n" ), QByteArray( "bla" ) ); } void KMimeUtilTest::testExtractHeader() { QByteArray header( "To: \nSubject: =?UTF-8?Q?_Notification_for_appointment:?=\n =?UTF-8?Q?_Test?=\nMIME-Version: 1.0" ); // basic tests QVERIFY( extractHeader( header, "Foo" ).isEmpty() ); QCOMPARE( extractHeader( header, "To" ), QByteArray("") ); // case insensitive matching QCOMPARE( extractHeader( header, "mime-version" ), QByteArray( "1.0" ) ); // extraction of multi-line headers QCOMPARE( extractHeader( header, "Subject" ), QByteArray("=?UTF-8?Q?_Notification_for_appointment:?= =?UTF-8?Q?_Test?=") ); // missing space after ':' QCOMPARE( extractHeader( "From:", "From" ), QByteArray( "" ) ); } diff --git a/kmime/tests/kmime_util_test.h b/kmime/tests/kmime_util_test.h index 4f9cd9bb6..04c5ceabe 100644 --- a/kmime/tests/kmime_util_test.h +++ b/kmime/tests/kmime_util_test.h @@ -1,33 +1,33 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KMIME_UTIL_TEST_H #define KMIME_UTIL_TEST_H #include class KMimeUtilTest : public QObject { Q_OBJECT private Q_SLOTS: void testUnfoldHeader(); void testExtractHeader(); }; #endif diff --git a/kmime/tests/rfc2047test.cpp b/kmime/tests/rfc2047test.cpp index 3bf968740..27ff7e16f 100644 --- a/kmime/tests/rfc2047test.cpp +++ b/kmime/tests/rfc2047test.cpp @@ -1,108 +1,108 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "rfc2047test.h" #include "rfc2047test.moc" #include using namespace KMime; QTEST_KDEMAIN( RFC2047Test, NoGUI ) void RFC2047Test::testRFC2047decode() { QByteArray encCharset; // empty QCOMPARE( KMime::decodeRFC2047String( QByteArray(), encCharset, "utf-8", false ), QString() ); // identity QCOMPARE( KMime::decodeRFC2047String( "bla", encCharset, "utf-8", false ), QString( "bla" ) ); // utf-8 QCOMPARE( KMime::decodeRFC2047String( "=?utf-8?q?Ingo=20Kl=C3=B6cker?= ", encCharset, "utf-8", false ), QString::fromUtf8( "Ingo Klöcker " ) ); QCOMPARE( KMime::decodeRFC2047String( "=?utf-8?q?Ingo=20Kl=C3=B6cker?= ", encCharset, "iso8859-1", false ), QString::fromUtf8( "Ingo Klöcker " ) ); QCOMPARE( KMime::decodeRFC2047String( "=?utf-8?q?Ingo=20Kl=C3=B6cker?=", encCharset, "utf-8", false ), QString::fromUtf8( "Ingo Klöcker" ) ); QCOMPARE( encCharset, QByteArray( "UTF-8" ) ); // whitespaces between two encoded words QCOMPARE( KMime::decodeRFC2047String( "=?utf-8?q?Ingo=20Kl=C3=B6cker?= =?utf-8?q?Ingo=20Kl=C3=B6cker?=", encCharset, "utf-8", false ), QString::fromUtf8( "Ingo KlöckerIngo Klöcker" ) ); QCOMPARE( decodeRFC2047String( "=?utf-8?q?Ingo=20Kl=C3=B6cker?= foo =?utf-8?q?Ingo=20Kl=C3=B6cker?=", encCharset ), QString::fromUtf8( "Ingo Klöcker foo Ingo Klöcker" ) ); // iso-8859-x QCOMPARE( KMime::decodeRFC2047String( "=?ISO-8859-1?Q?Andr=E9s_Ot=F3n?=", encCharset, "utf-8", false ), QString::fromUtf8( "Andrés Otón" ) ); QCOMPARE( encCharset, QByteArray( "ISO-8859-1" ) ); QCOMPARE( KMime::decodeRFC2047String( "=?iso-8859-2?q?Rafa=B3_Rzepecki?=", encCharset, "utf-8", false ), QString::fromUtf8( "Rafał Rzepecki" ) ); QCOMPARE( encCharset, QByteArray( "ISO-8859-2" ) ); QCOMPARE( KMime::decodeRFC2047String( "=?iso-8859-9?Q?S=2E=C7a=F0lar?= Onur", encCharset, "utf-8", false ), QString::fromUtf8( "S.Çağlar Onur" ) ); QCOMPARE( encCharset, QByteArray( "ISO-8859-9" ) ); QCOMPARE( KMime::decodeRFC2047String( "Rafael =?iso-8859-15?q?Rodr=EDguez?=", encCharset, "utf-8", false ), QString::fromUtf8( "Rafael Rodríguez" ) ); QCOMPARE( encCharset, QByteArray( "ISO-8859-15" ) ); // wrong charset + charset overwrite QCOMPARE( KMime::decodeRFC2047String( "=?iso-8859-1?q?Ingo=20Kl=C3=B6cker?=", encCharset, "utf-8", true ), QString::fromUtf8( "Ingo Klöcker" ) ); // language parameter according to RFC 2231, section 5 QCOMPARE( decodeRFC2047String( "From: =?US-ASCII*EN?Q?Keith_Moore?= ", encCharset ), QString::fromUtf8( "From: Keith Moore " ) ); QCOMPARE( encCharset, QByteArray( "US-ASCII" ) ); // broken qp endoding (using lowercase) QCOMPARE( decodeRFC2047String( "Subject: =?iso-8859-1?Q?Belangrijk=3a=20Verhuizing=20FTP=20server?=", encCharset ), QString::fromUtf8( "Subject: Belangrijk: Verhuizing FTP server" ) ); QCOMPARE( encCharset, QByteArray( "ISO-8859-1" ) ); // mixed charsets, based on bug 125542 but pasted from above instead since I'm unable to enter those asian symbols QCOMPARE( decodeRFC2047String( "Subject: =?utf-8?q?Ingo=20Kl=C3=B6cker?= unencoded words =?iso-8859-9?Q?S=2E=C7a=F0lar?=", encCharset ), QString::fromUtf8( "Subject: Ingo Klöcker unencoded words S.Çağlar" ) ); QCOMPARE( encCharset, QByteArray( "ISO-8859-9" ) ); } void RFC2047Test::testInvalidDecode() { QByteArray encCharset; // invalid / incomplete encoded data QCOMPARE( decodeRFC2047String( "=", encCharset ), QString::fromUtf8("=") ); QCOMPARE( decodeRFC2047String( "=?", encCharset ), QString::fromUtf8("=?") ); QCOMPARE( decodeRFC2047String( "=?a?b?=", encCharset ), QString::fromUtf8("=?a?b?=") ); QCOMPARE( decodeRFC2047String( "=?a?b?c?", encCharset ), QString::fromUtf8("=?a?b?c?") ); QCOMPARE( decodeRFC2047String( "=?a??c?=", encCharset ), QString::fromUtf8("=?a??c?=") ); } void RFC2047Test::testRFC2047encode() { // empty QCOMPARE( KMime::encodeRFC2047String( QString(), "utf-8" ), QByteArray() ); // identity QCOMPARE( KMime::encodeRFC2047String( "bla", "utf-8" ), QByteArray( "bla" ) ); // utf-8 // expected value is probably wrong, libkmime will chose 'B' instead of 'Q' encoding QEXPECT_FAIL( "", "libkmime will chose 'B' instead of 'Q' encoding", Continue ); QCOMPARE( KMime::encodeRFC2047String( QString::fromUtf8( "Ingo Klöcker " ), "utf-8" ).constData(), "=?utf-8?q?Ingo=20Kl=C3=B6cker?= " ); } diff --git a/kmime/tests/rfc2047test.h b/kmime/tests/rfc2047test.h index 1a017761b..415075fe7 100644 --- a/kmime/tests/rfc2047test.h +++ b/kmime/tests/rfc2047test.h @@ -1,34 +1,34 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef RFC2047TEST_H #define RFC2047TEST_H #include class RFC2047Test : public QObject { Q_OBJECT private Q_SLOTS: void testRFC2047decode(); void testInvalidDecode(); void testRFC2047encode(); }; #endif diff --git a/kresources/tests/idmappertest.h b/kresources/tests/idmappertest.h index eaafa883c..35a757a12 100644 --- a/kresources/tests/idmappertest.h +++ b/kresources/tests/idmappertest.h @@ -1,32 +1,32 @@ /* - Copyright (c) 2006 Volker Krause + Copyright (c) 2006 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef IDMAPPERTEST_H #define IDMAPPERTEST_H #include class IdMapperTest : public QObject { Q_OBJECT private Q_SLOTS: void testIdMapper(); }; #endif