1 /***************************************************************************
2 filter_evolution_v2.cxx - Evolution 2.0.x mail import
5 copyright : (C) 2005 by Danny Kukawka <danny.kukawka@web.de>
6 (inspired and partly copied from filter_evolution)
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
18 #include "filter_evolution_v2.hxx"
21 #include <kfiledialog.h>
22 #include <ktemporaryfile.h>
25 /** Default constructor. */
26 FilterEvolution_v2::FilterEvolution_v2(void) :
27 Filter(i18n("Import Evolution 2.x Local Mails and Folder Structure"),
29 i18n("<p><b>Evolution 2.x import filter</b></p>"
30 "<p>Select the base directory of your local Evolution mailfolder (usually ~/.evolution/mail/local/).</p>"
31 "<p><b>Note:</b> Never choose a Folder which <u>does not</u> contain mbox-files (for example "
32 "a maildir): if you do, you will get many new folders.</p>"
33 "<p>Since it is possible to recreate the folder structure, the folders "
34 "will be stored under: \"Evolution-Import\".</p>"))
38 FilterEvolution_v2::~FilterEvolution_v2(void)
42 /** Recursive import of Evolution's mboxes. */
43 void FilterEvolution_v2::import(FilterInfo
*info
)
46 * We ask the user to choose Evolution's root directory.
47 * This should be usually ~/.evolution/mail/local/
49 QString evolDir
= QDir::homePath() + "/.evolution/mail/local";
52 evolDir
= QDir::homePath();
55 //QString mailDir = KFileDialog::getExistingDirectory(QDir::homePath(), info->parent());
57 kfd
= new KFileDialog( evolDir
, "", 0 );
58 kfd
->setMode(KFile::Directory
| KFile::LocalOnly
);
60 mailDir
= kfd
->selectedFile();
62 if (mailDir
.isEmpty()) {
63 info
->alert(i18n("No directory selected."));
66 * If the user only select homedir no import needed because
67 * there should be no files and we surely import wrong files.
69 else if ( mailDir
== QDir::homePath() || mailDir
== (QDir::homePath() + '/')) {
70 info
->addLog(i18n("No files found for import."));
74 /** Recursive import of the MailArchives */
76 const QStringList rootSubDirs
= dir
.entryList(QStringList("[^\\.]*"), QDir::Dirs
, QDir::Name
); // Removal of . and ..
77 int currentDir
= 1, numSubDirs
= rootSubDirs
.size();
78 for(QStringList::ConstIterator filename
= rootSubDirs
.constBegin() ; filename
!= rootSubDirs
.constEnd() ; ++filename
, ++currentDir
) {
79 if (info
->shouldTerminate()) break;
80 importDirContents(info
, dir
.filePath(*filename
), *filename
, *filename
);
81 info
->setOverall((int) ((float) currentDir
/ numSubDirs
* 100));
84 /** import last but not least all archives from the root-dir */
85 QDir
importDir (mailDir
);
86 const QStringList files
= importDir
.entryList(QStringList("[^\\.]*"), QDir::Files
, QDir::Name
);
87 for ( QStringList::ConstIterator mailFile
= files
.constBegin(); mailFile
!= files
.constEnd(); ++mailFile
) {
88 if (info
->shouldTerminate()) break;
89 QString temp_mailfile
= *mailFile
;
90 if (temp_mailfile
.endsWith(QLatin1String(".cmeta")) || temp_mailfile
.endsWith(QLatin1String(".ev-summary")) ||
91 temp_mailfile
.endsWith(QLatin1String(".ibex.index")) || temp_mailfile
.endsWith(QLatin1String(".ibex.index.data")) ) {}
93 info
->addLog( i18n("Start import file %1...", temp_mailfile
) );
94 importMBox(info
, mailDir
+ temp_mailfile
, temp_mailfile
, QString());
98 info
->addLog( i18n("Finished importing emails from %1", mailDir
));
99 if(count_duplicates
> 0) {
100 info
->addLog( i18np("1 duplicate message not imported", "%1 duplicate messages not imported", count_duplicates
));
102 if (info
->shouldTerminate()) info
->addLog( i18n("Finished import, canceled by user."));
104 info
->setCurrent(100);
105 info
->setOverall(100);
110 * Import of a directory contents.
111 * @param info Information storage for the operation.
112 * @param dirName The name of the directory to import.
113 * @param KMailRootDir The directory's root directory in KMail's folder structure.
114 * @param KMailSubDir The directory's direct ancestor in KMail's folder structure.
116 void FilterEvolution_v2::importDirContents(FilterInfo
*info
, const QString
& dirName
, const QString
& KMailRootDir
, const QString
& KMailSubDir
)
118 if (info
->shouldTerminate()) return;
120 /** Here Import all archives in the current dir */
123 QDir
importDir (dirName
);
124 const QStringList files
= importDir
.entryList(QStringList("[^\\.]*"), QDir::Files
, QDir::Name
);
125 for ( QStringList::ConstIterator mailFile
= files
.constBegin(); mailFile
!= files
.constEnd(); ++mailFile
) {
126 QString temp_mailfile
= *mailFile
;
127 if (temp_mailfile
.endsWith(QLatin1String(".cmeta")) || temp_mailfile
.endsWith(QLatin1String(".ev-summary")) ||
128 temp_mailfile
.endsWith(QLatin1String(".ibex.index")) || temp_mailfile
.endsWith(QLatin1String(".ibex.index.data")) ) {}
130 info
->addLog( i18n("Start import file %1...", temp_mailfile
) );
131 importMBox(info
, (dirName
+ '/' + temp_mailfile
) , KMailRootDir
, KMailSubDir
);
135 /** If there are subfolders, we import them one by one */
136 QDir
subfolders(dirName
);
137 const QStringList subDirs
= subfolders
.entryList(QStringList("[^\\.]*"), QDir::Dirs
, QDir::Name
);
138 for(QStringList::ConstIterator filename
= subDirs
.constBegin() ; filename
!= subDirs
.constEnd() ; ++filename
) {
140 if(!KMailSubDir
.isNull()) {
141 kSubDir
= KMailSubDir
+ '/' + *filename
;
145 importDirContents(info
, subfolders
.filePath(*filename
), KMailRootDir
, kSubDir
);
150 * Import of a MBox file.
151 * @param info Information storage for the operation.
152 * @param dirName The MBox's name.
153 * @param KMailRootDir The directory's root directory in KMail's folder structure.
154 * @param KMailSubDir The directory's equivalent in KMail's folder structure. *
156 void FilterEvolution_v2::importMBox(FilterInfo
*info
, const QString
& mboxName
, const QString
& rootDir
, const QString
& targetDir
)
158 QFile
mbox(mboxName
);
159 bool first_msg
= true;
160 if (!mbox
.open(QIODevice::ReadOnly
)) {
161 info
->alert(i18n("Unable to open %1, skipping", mboxName
));
163 QFileInfo
filenameInfo(mboxName
);
166 if( mboxName
.length() > 20 ) {
167 QString tmp_info
= mboxName
;
168 tmp_info
= tmp_info
.replace( mailDir
, "../" );
169 if (tmp_info
.contains(".sbd"))
170 tmp_info
.remove(".sbd");
171 info
->setFrom( tmp_info
);
173 info
->setFrom(mboxName
);
174 if(targetDir
.contains(".sbd")) {
175 QString tmp_info
= targetDir
;
176 tmp_info
.remove(".sbd");
177 info
->setTo(tmp_info
);
179 info
->setTo(targetDir
);
181 QByteArray
input(MAX_LINE
, '\0');
184 while (!mbox
.atEnd()) {
187 /** @todo check if the file is really a mbox, maybe search for 'from' string at start */
189 * Don't use QTextStream to read from mbox, better use QDataStream. QTextStream only
190 * support Unicode/Latin1/Locale. So you lost information from emails with
191 * charset!=Unicode/Latin1/Locale (e.g. KOI8-R) and Content-Transfer-Encoding != base64
192 * (e.g. 8Bit). It also not help to convert the QTextStream to Unicode. By this you
193 * get Unicode/UTF-email but KMail can't detect the correct charset.
198 tmp
.write( input
, l
);
199 l
= mbox
.readLine( input
.data(),MAX_LINE
); // read the first line, prevent "From "
200 tmp
.write( input
, l
);
202 while ( ! mbox
.atEnd() && (l
= mbox
.readLine(input
.data(),MAX_LINE
)) && ((separate
= input
.data()).left(5) != "From ")) {
203 tmp
.write( input
, l
);
209 QString _targetDir
= targetDir
;
210 if(!targetDir
.isNull()) {
211 if(_targetDir
.contains(".sbd"))
212 _targetDir
.remove(".sbd");
213 destFolder
+= "Evolution-Import/" + _targetDir
+ '/' + filenameInfo
.completeBaseName(); // mboxName;
215 destFolder
= "Evolution-Import/" + rootDir
;
216 if(destFolder
.contains(".sbd"))
217 destFolder
.remove(".sbd");
221 if(info
->removeDupMsg
)
222 addMessage( info
, destFolder
, tmp
.fileName() );
224 addMessage_fastImport( info
, destFolder
, tmp
.fileName() );
226 int currentPercentage
= (int) (((float) mbox
.pos() / filenameInfo
.size()) * 100);
227 info
->setCurrent(currentPercentage
);
228 if (info
->shouldTerminate()) break;