1 /***************************************************************************
2 filter_opera.cxx - Opera mail import
5 copyright : (C) 2005 by Danny Kukawka
6 email : danny.kukawka@web.de
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 ***************************************************************************/
19 #include <kfiledialog.h>
20 #include <ktemporaryfile.h>
23 #include "filter_opera.hxx"
26 FilterOpera::FilterOpera() :
27 Filter( i18n("Import Opera Emails"),
29 i18n("<p><b>Opera email import filter</b></p>"
30 "<p>This filter will import mails from Opera mail folder. Use this filter "
31 "if you want to import all mails within a account in the Opera maildir.</p>"
32 "<p>Select the directory of the account (usually ~/.opera/mail/store/account*).</p>"
33 "<p><b>Note:</b> Emails will be imported into a folder named after the account "
34 "they came from, prefixed with OPERA-</p>" ))
37 FilterOpera::~FilterOpera()
41 void FilterOpera::importRecursive(const QDir
& mailDir
, FilterInfo
*info
, const QString
&accountName
)
43 // Recursive import of the MBoxes.
44 const QStringList rootSubDirs
= mailDir
.entryList(QStringList("[^\\.]*"), QDir::Dirs
, QDir::Name
); // Removal of . and ..
46 int numSubDirs
= rootSubDirs
.size();
47 if ( numSubDirs
> 0 ) {
48 for(QStringList::ConstIterator filename
= rootSubDirs
.constBegin() ; filename
!= rootSubDirs
.constEnd() ; ++filename
, ++currentDir
) {
49 QDir
importDir ( mailDir
.path() +QDir::separator()+ *filename
);
50 const QStringList files
= importDir
.entryList(QStringList("*.[mM][bB][sS]"), QDir::Files
, QDir::Name
);
51 if ( files
.isEmpty() ) {
52 importRecursive( importDir
,info
,accountName
.isEmpty() ? *filename
: accountName
);
54 importBox( importDir
, files
, info
,accountName
);
60 void FilterOpera::importBox(const QDir
& importDir
, const QStringList
&files
, FilterInfo
*info
, const QString
& accountName
)
62 int overall_status
= 0;
63 int totalFiles
= files
.count();
65 info
->addLog(i18n("Importing new mail files..."));
66 for ( QStringList::ConstIterator mailFile
= files
.constBegin(); mailFile
!= files
.constEnd(); ++mailFile
) {
68 QFile
operaArchiv( importDir
.filePath(*mailFile
) );
69 if (! operaArchiv
.open( QIODevice::ReadOnly
) ) {
70 info
->alert( i18n("Unable to open %1, skipping", *mailFile
) );
72 info
->addLog( i18n("Importing emails from %1...", *mailFile
) );
73 QFileInfo
filenameInfo( importDir
.filePath(*mailFile
) );
75 if ( accountName
.isEmpty() )
76 folderName
= QString( "OPERA-" + importDir
.dirName() );
78 folderName
= QString( "OPERA-" + accountName
);
80 info
->setFrom( *mailFile
);
81 info
->setTo( folderName
);
83 QByteArray
input(MAX_LINE
,'\0');
85 bool first_msg
= true;
87 while ( !operaArchiv
.atEnd() ) {
91 * Don't use QTextStream to read from mbox, better use QDataStream. QTextStream only
92 * support Unicode/Latin1/Locale. So you lost information from emails with
93 * charset!=Unicode/Latin1/Locale (e.g. KOI8-R) and Content-Transfer-Encoding != base64
94 * (e.g. 8Bit). It also not help to convert the QTextStream to Unicode. By this you
95 * get Unicode/UTF-email but KMail can't detect the correct charset.
100 tmp
.write( input
, l
);
101 l
= operaArchiv
.readLine( input
.data(),MAX_LINE
); // read the first line, prevent "From "
102 tmp
.write( input
, l
);
104 while ( ! operaArchiv
.atEnd() && (l
= operaArchiv
.readLine(input
.data(),MAX_LINE
)) && ((separate
= input
.data()).left(5) != "From ")) {
105 /** remove in KMail unneeded Flags from Opera (for example: X-Opera-Status)*/
106 if(separate
.left(8) != "X-Opera-")
107 tmp
.write( input
, l
);
112 if(info
->removeDupMsg
)
113 addMessage( info
, folderName
, tmp
.fileName() );
115 addMessage_fastImport( info
, folderName
, tmp
.fileName() );
116 int currentPercentage
= (int) ( ( (float) operaArchiv
.pos() / filenameInfo
.size() ) * 100 );
117 info
->setCurrent( currentPercentage
);
119 if (currentFile
== 1)
120 overall_status
= (int) ( currentPercentage
* ( (float) currentFile
/ totalFiles
) );
122 overall_status
= (int)(((currentFile
-1)*(100.0/(float)totalFiles
))+(currentPercentage
*(1.0/(float)totalFiles
)));
124 info
->setOverall( overall_status
);
125 if ( info
->shouldTerminate() ) break;
128 info
->addLog( i18n("Finished importing emails from %1", *mailFile
));
129 if (count_duplicates
> 0) {
130 info
->addLog( i18np("1 duplicate message not imported", "%1 duplicate messages not imported", count_duplicates
));
133 count_duplicates
= 0;
136 if ( info
->shouldTerminate() ) break;
141 void FilterOpera::import(FilterInfo
*info
)
143 /** try to go to opera mailfolder in the home of the user */
144 QString startdir
= QDir::homePath() + "/.opera/mail/store/";
147 startdir
= QDir::homePath();
150 //QString mailDir = KFileDialog::getExistingDirectory(QDir::homePath(), info->parent());
152 kfd
= new KFileDialog( startdir
, "", 0);
153 kfd
->setMode(KFile::Directory
| KFile::LocalOnly
);
155 QString operaDir
= kfd
->selectedFile();
158 if (operaDir
.isEmpty()) {
159 info
->alert(i18n("No directory selected."));
162 * If the user only select homedir no import needed because
163 * there should be no files and we surely import wrong files.
165 else if ( operaDir
== QDir::homePath() || operaDir
== (QDir::homePath() + '/')) {
166 info
->addLog(i18n("No files found for import."));
170 QDir
importDir (operaDir
);
171 const QStringList files
= importDir
.entryList(QStringList("*.[mM][bB][sS]"), QDir::Files
, QDir::Name
);
173 // Count total number of files to be processed
174 info
->addLog(i18n("Counting files..."));
176 if(files
.count() > 0) {
177 importBox(importDir
, files
,info
);
179 //opera > 9.10 stores mail in subfolder.
180 importRecursive( importDir
, info
);
183 if (info
->shouldTerminate()) info
->addLog( i18n("Finished import, canceled by user."));
184 info
->setCurrent(100);
185 info
->setOverall(100);