3 * Author : Simon MARTIN <simartin@users.sourceforge.net>
4 * Copyright (c) 2004 Simon MARTIN <simartin@users.sourceforge.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "filter_evolution.hxx"
24 #include <kfiledialog.h>
25 #include <ktemporaryfile.h>
28 /** Default constructor. */
29 FilterEvolution::FilterEvolution(void) :
30 Filter(i18n("Import Evolution 1.x Local Mails and Folder Structure"),
31 "Simon MARTIN<br /><br />( Filter accelerated by Danny Kukawka )",
32 i18n("<p><b>Evolution 1.x import filter</b></p>"
33 "<p>Select the base directory of Evolution's mails (usually ~/evolution/local).</p>"
34 "<p>Since it is possible to recreate the folder structure, the folders "
35 "will be stored under: \"Evolution-Import\".</p>"))
39 FilterEvolution::~FilterEvolution(void)
43 /** Recursive import of Evolution's mboxes. */
44 void FilterEvolution::import(FilterInfo
*info
)
46 // We ask the user to choose Evolution's root directory.
47 QString evolDir
= QDir::homePath() + "/evolution/local";
50 evolDir
= QDir::homePath();
53 mailDir
= KFileDialog::getExistingDirectory(evolDir
, info
->parent());
55 if (mailDir
.isEmpty()) {
56 info
->alert(i18n("No directory selected."));
59 * If the user only select homedir no import needed because
60 * there should be no files and we surely import wrong files.
62 else if ( mailDir
== QDir::homePath() || mailDir
== (QDir::homePath() + '/')) {
63 info
->addLog(i18n("No files found for import."));
66 // Recursive import of the MBoxes.
68 const QStringList rootSubDirs
= dir
.entryList(QStringList("[^\\.]*"), QDir::Dirs
, QDir::Name
); // Removal of . and ..
69 int currentDir
= 1, numSubDirs
= rootSubDirs
.size();
70 for(QStringList::ConstIterator filename
= rootSubDirs
.constBegin() ; filename
!= rootSubDirs
.constEnd() ; ++filename
, ++currentDir
) {
71 importDirContents(info
, dir
.filePath(*filename
), *filename
, QString());
72 info
->setOverall((int) ((float) currentDir
/ numSubDirs
* 100));
75 info
->addLog( i18n("Finished importing emails from %1", mailDir
));
76 info
->setCurrent(100);
77 info
->setOverall(100);
81 * Import of a directory contents.
82 * @param info Information storage for the operation.
83 * @param dirName The name of the directory to import.
84 * @param KMailRootDir The directory's root directory in KMail's folder structure.
85 * @param KMailSubDir The directory's direct ancestor in KMail's folder structure.
87 void FilterEvolution::importDirContents(FilterInfo
*info
, const QString
& dirName
, const QString
& KMailRootDir
, const QString
& KMailSubDir
)
89 // If there is a mbox, we import it
91 if(dir
.exists("mbox")) {
92 importMBox(info
, dirName
+ "/mbox", KMailRootDir
, KMailSubDir
);
94 // If there are subfolders, we import them one by one
95 if(dir
.exists("subfolders")) {
96 QDir
subfolders(dirName
+ "/subfolders");
97 const QStringList subDirs
= subfolders
.entryList(QStringList("[^\\.]*"), QDir::Dirs
, QDir::Name
);
98 for(QStringList::ConstIterator filename
= subDirs
.constBegin() ; filename
!= subDirs
.constEnd() ; ++filename
) {
100 if(!KMailSubDir
.isNull()) {
101 kSubDir
= KMailSubDir
+ '/' + *filename
;
105 importDirContents(info
, subfolders
.filePath(*filename
), KMailRootDir
, kSubDir
);
111 * Import of a MBox file.
112 * @param info Information storage for the operation.
113 * @param dirName The MBox's name.
114 * @param KMailRootDir The directory's root directory in KMail's folder structure.
115 * @param KMailSubDir The directory's equivalent in KMail's folder structure. *
117 void FilterEvolution::importMBox(FilterInfo
*info
, const QString
& mboxName
, const QString
& rootDir
, const QString
& targetDir
)
119 QFile
mbox(mboxName
);
120 bool first_msg
= true;
121 QString tmp_from
= mboxName
;
122 if (!mbox
.open(QIODevice::ReadOnly
)) {
123 info
->alert(i18n("Unable to open %1, skipping", mboxName
));
125 QFileInfo
filenameInfo(mboxName
);
128 if( mboxName
.length() > 20 ) {
129 QString tmp_info
= mboxName
;
130 tmp_info
= tmp_info
.replace( mailDir
, ".." );
131 if (tmp_info
.contains("subfolders/"))
132 tmp_info
.remove("subfolders/");
133 info
->setFrom( tmp_info
);
136 info
->setFrom(mboxName
);
137 if(targetDir
.contains("subfolders/")) {
138 QString tmp_info
= targetDir
;
139 tmp_info
.remove("subfolders/");
140 info
->setTo(tmp_info
);
142 info
->setTo(targetDir
);
144 info
->addLog(i18n("Importing emails from %1...", tmp_from
));
146 QByteArray
input(MAX_LINE
,'\0');
149 while (!mbox
.atEnd()) {
153 * Don't use QTextStream to read from mbox, better use QDataStream. QTextStream only
154 * support Unicode/Latin1/Locale. So you lost information from emails with
155 * charset!=Unicode/Latin1/Locale (e.g. KOI8-R) and Content-Transfer-Encoding != base64
156 * (e.g. 8Bit). It also not help to convert the QTextStream to Unicode. By this you
157 * get Unicode/UTF-email but KMail can't detect the correct charset.
162 tmp
.write( input
, l
);
163 l
= mbox
.readLine( input
.data(),MAX_LINE
); // read the first line, prevent "From "
164 tmp
.write( input
, l
);
166 while ( ! mbox
.atEnd() && (l
= mbox
.readLine(input
.data(),MAX_LINE
)) && ((separate
= input
.data()).left(5) != "From ")) {
167 tmp
.write( input
, l
);
172 QString destFolder
= rootDir
;
173 if(!targetDir
.isNull()) {
174 destFolder
= "Evolution-Import/" + destFolder
+ '/' + targetDir
;
176 destFolder
= "Evolution-Import/" + destFolder
;
179 /* comment by Danny Kukawka:
180 * addMessage() == old function, need more time and check for duplicates
181 * addMessage_fastImport == new function, faster and no check for duplicates
183 if(info
->removeDupMsg
)
184 addMessage( info
, destFolder
, tmp
.fileName() );
186 addMessage_fastImport( info
, destFolder
, tmp
.fileName() );
188 int currentPercentage
= (int) (((float) mbox
.pos() / filenameInfo
.size()) * 100);
189 info
->setCurrent(currentPercentage
);
190 if (info
->shouldTerminate()) return;
193 if (count_duplicates
> 0) {
194 info
->addLog( i18np("1 duplicate message not imported", "%1 duplicate messages not imported", count_duplicates
));
196 count_duplicates
= 0;