summaryrefslogtreecommitdiffstats
path: root/kmailcvt/filter_pmail.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmailcvt/filter_pmail.cpp')
-rw-r--r--kmailcvt/filter_pmail.cpp346
1 files changed, 346 insertions, 0 deletions
diff --git a/kmailcvt/filter_pmail.cpp b/kmailcvt/filter_pmail.cpp
new file mode 100644
index 00000000..b45a0be4
--- /dev/null
+++ b/kmailcvt/filter_pmail.cpp
@@ -0,0 +1,346 @@
+/***************************************************************************
+ FilterPMail.cpp - Pegasus-Mail import
+ -------------------
+ begin : Sat Jan 6 2001
+ copyright : (C) 2001 by Holger Schurig
+ (C) 2005 by Danny Kukawka
+ email : holgerschurig@gmx.de
+ danny.kukawka@web.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <config.h>
+#include <tdelocale.h>
+#include <tdefiledialog.h>
+#include <tqregexp.h>
+#include <tdetempfile.h>
+#include <kdebug.h>
+
+#include "filter_pmail.h"
+
+
+FilterPMail::FilterPMail() :
+ Filter(i18n("Import Folders From Pegasus-Mail"),
+ "Holger Schurig <br>( rewritten by Danny Kukawka )",
+ i18n("<p>Select the Pegasus-Mail directory on your system (containing *.CNM, *.PMM and *.MBX files). "
+ "On many systems this is stored in C:\\pmail\\mail or C:\\pmail\\mail\\admin</p>"
+ "<p><b>Note:</b> Since it is possible to recreate the folder structure, the folders "
+ "will be stored under: \"PegasusMail-Import\".</p>"))
+{}
+
+FilterPMail::~FilterPMail()
+{
+}
+
+void FilterPMail::import(FilterInfo *info)
+{
+ inf = info;
+
+ // Select directory from where I have to import files
+ KFileDialog *kfd;
+ kfd = new KFileDialog( TQDir::homeDirPath(), "", 0, "tdefiledialog", true );
+ kfd->setMode(KFile::Directory | KFile::LocalOnly);
+ kfd->exec();
+ chosenDir = kfd->selectedFile();
+ delete kfd;
+
+ if (chosenDir.isEmpty()) {
+ info->alert(i18n("No directory selected."));
+ return;
+ }
+
+ // Count total number of files to be processed
+ info->addLog(i18n("Counting files..."));
+ dir.setPath (chosenDir);
+ TQStringList files = dir.entryList("*.[cC][nN][mM]; *.[pP][mM][mM]; *.[mM][bB][xX]", TQDir::Files, TQDir::Name);
+ totalFiles = files.count();
+ currentFile = 0;
+ kdDebug() << "Count is " << totalFiles << endl;
+
+ if(!(folderParsed = parseFolderMatrix())) {
+ info->addLog(i18n("Cannot parse the folder structure; continuing import without subfolder support."));
+ }
+
+ info->addLog(i18n("Importing new mail files ('.cnm')..."));
+ processFiles("*.[cC][nN][mM]", &FilterPMail::importNewMessage);
+ info->addLog(i18n("Importing mail folders ('.pmm')..."));
+ processFiles("*.[pP][mM][mM]", &FilterPMail::importMailFolder);
+ info->addLog(i18n("Importing 'UNIX' mail folders ('.mbx')..."));
+ processFiles("*.[mM][bB][xX]", &FilterPMail::importUnixMailFolder);
+
+ info->addLog( i18n("Finished importing emails from %1").arg( chosenDir ));
+ info->setCurrent(100);
+ info->setOverall(100);
+}
+
+/** this looks for all files with the filemask 'mask' and calls the 'workFunc' on each of them */
+void FilterPMail::processFiles(const TQString& mask, void(FilterPMail::* workFunc)(const TQString&) )
+{
+ if (inf->shouldTerminate()) return;
+
+ TQStringList files = dir.entryList(mask, TQDir::Files, TQDir::Name);
+ //kdDebug() << "Mask is " << mask << " count is " << files.count() << endl;
+ for ( TQStringList::Iterator mailFile = files.begin(); mailFile != files.end(); ++mailFile ) {
+ // Notify current file
+ TQFileInfo mailfileinfo(*mailFile);
+ inf->setFrom(mailfileinfo.fileName());
+
+ // Clear the other fields
+ inf->setTo(TQString());
+ inf->setCurrent(TQString());
+ inf->setCurrent(-1);
+
+ // call worker function, increase progressbar
+ (this->*workFunc)(dir.filePath(*mailFile));
+ ++currentFile;
+ inf->setOverall( (int) ((float) currentFile / totalFiles * 100));
+ inf->setCurrent( 100 );
+ if (inf->shouldTerminate()) return;
+ }
+}
+
+
+/** this function imports one *.CNM message */
+void FilterPMail::importNewMessage(const TQString& file)
+{
+ TQString destFolder("PegasusMail-Import/New Messages");
+ inf->setTo(destFolder);
+
+ /* comment by Danny Kukawka:
+ * addMessage() == old function, need more time and check for duplicates
+ * addMessage_fastImport == new function, faster and no check for duplicates
+ */
+ if(inf->removeDupMsg)
+ addMessage( inf, destFolder, file );
+ else
+ addMessage_fastImport( inf, destFolder, file );
+}
+
+
+/** this function imports one mail folder file (*.PMM) */
+void FilterPMail::importMailFolder(const TQString& file)
+{
+ // Format of a PMM file:
+ // First comes a header with 128 bytes. At the beginning is the name of
+ // the folder. Then there are some unknown bytes (strings). At offset 128
+ // the first message starts.
+ //
+ // Each message is terminated by a 0x1A byte. The next message follows
+ // immediately.
+ //
+ // The last message is followed by a 0x1A, too.
+ //
+ // 000000 6d 61 69 6c 73 65 72 76 65 72 2d 70 72 6f 6a 65 mailserver-proje
+ // 000010 63 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ct..............
+ // 000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ // 000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ // 000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ // 000050 00 00 00 00 00 00 36 30 34 37 35 37 32 45 3a 36 ......6047572E:6
+ // 000060 46 34 39 3a 46 4f 4c 30 31 33 35 35 00 00 00 00 F49:FOL01355....
+ // 000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ // 000080 52 65 74 75 72 6e 2d 50 61 74 68 3a 20 3c 75 72 Return-Path: <ur
+ // ...
+ // 000cb0 2d 2d 2d 2d 2d 2d 2d 2d 2d 2b 0d 0a 1a 52 65 74 ---------+...Ret
+ // 000cc0 75 72 6e 2d 50 61 74 68 3a 20 3c 62 6f 75 6e 63 urn-Path: <bounc
+ // ...
+ // 04dc50 46 30 33 38 44 2e 36 31 35 44 37 34 44 30 2d 2d F038D.615D74D0--
+ // 04dc60 0d 0a 1a
+
+ struct {
+ char folder[86];
+ char id[42];
+ } pmm_head;
+
+ long l = 0;
+ TQFile f(file);
+ if (!f.open(IO_ReadOnly)) {
+ inf->alert(i18n("Unable to open %1, skipping").arg(file));
+ } else {
+ // Get folder name
+ l = f.readBlock((char *) &pmm_head, sizeof(pmm_head));
+ TQString folder("PegasusMail-Import/");
+ if(folderParsed)
+ folder.append(getFolderName((TQString)pmm_head.id));
+ else
+ folder.append(pmm_head.folder);
+ inf->setTo(folder);
+ inf->addLog(i18n("Importing %1").arg("../" + TQString(pmm_head.folder)));
+
+ TQByteArray input(MAX_LINE);
+ bool first_msg = true;
+
+ while (!f.atEnd()) {
+ KTempFile tempfile;
+ inf->setCurrent( (int) ( ( (float) f.at() / f.size() ) * 100 ) );
+
+ if(!first_msg) {
+ // set the filepos back to last line minus the seperate char (0x1a)
+ f.at(f.at() - l + 1);
+ }
+
+ // no problem to loose the last line in file. This only contains a seperate char
+ while ( ! f.atEnd() && (l = f.readLine(input.data(),MAX_LINE))) {
+ if (inf->shouldTerminate()){
+ tempfile.close();
+ tempfile.unlink();
+ return;
+ }
+ if(input[0] == 0x1a ) {
+ break;
+ } else {
+ tempfile.file()->writeBlock( input, l );
+ }
+ }
+ tempfile.close();
+
+ if(inf->removeDupMsg)
+ addMessage( inf, folder, tempfile.name() );
+ else
+ addMessage_fastImport( inf, folder, tempfile.name() );
+
+ first_msg = false;
+ tempfile.unlink();
+ }
+ }
+ f.close();
+}
+
+
+/** imports a 'unix' format mail folder (*.MBX) */
+void FilterPMail::importUnixMailFolder(const TQString& file)
+{
+ struct {
+ char folder[58];
+ char id[31];
+ } pmg_head;
+
+ TQFile f;
+ TQString folder("PegasusMail-Import/"), s(file), seperate;
+ TQByteArray line(MAX_LINE);
+ int n = 0, l = 0;
+
+ /** Get the folder name */
+ s.replace( TQRegExp("mbx$"), "pmg");
+ s.replace( TQRegExp("MBX$"), "PMG");
+ f.setName(s);
+ if (! f.open( IO_ReadOnly ) ) {
+ inf->alert( i18n("Unable to open %1, skipping").arg( s ) );
+ return;
+ } else {
+ f.readBlock((char *) &pmg_head, sizeof(pmg_head));
+ f.close();
+
+ if(folderParsed)
+ folder.append(getFolderName((TQString)pmg_head.id));
+ else
+ folder.append(pmg_head.folder);
+
+ inf->setTo(folder);
+ inf->setTo(folder);
+ }
+
+ /** Read in the mbox */
+ f.setName(file);
+ if (! f.open( IO_ReadOnly ) ) {
+ inf->alert( i18n("Unable to open %1, skipping").arg( s ) );
+ } else {
+ inf->addLog(i18n("Importing %1").arg("../" + TQString(pmg_head.folder)));
+ l = f.readLine( line.data(),MAX_LINE); // read the first line which is unneeded
+ while ( ! f.atEnd() ) {
+ KTempFile tempfile;
+
+ // we lost the last line, which is the first line of the new message in
+ // this lopp, but this is ok, because this is the seperate line with
+ // "From ???@???" and we can forget them
+ while ( ! f.atEnd() && (l = f.readLine(line.data(),MAX_LINE)) && ((seperate = line.data()).left(5) != "From ")) {
+ tempfile.file()->writeBlock(line.data(), l);
+ if (inf->shouldTerminate()){
+ tempfile.close();
+ tempfile.unlink();
+ return;
+ }
+ }
+ tempfile.close();
+ if(inf->removeDupMsg)
+ addMessage( inf, folder, tempfile.name() );
+ else
+ addMessage_fastImport( inf, folder, tempfile.name() );
+ tempfile.unlink();
+
+ n++;
+ inf->setCurrent(i18n("Message %1").arg(n));
+ inf->setCurrent( (int) ( ( (float) f.at() / f.size() ) * 100 ) );
+ }
+ }
+ f.close();
+}
+
+/** Parse the information about folderstructure to folderMatrix */
+bool FilterPMail::parseFolderMatrix()
+{
+ kdDebug() << "Start parsing the foldermatrix." << endl;
+ inf->addLog(i18n("Parsing the folder structure..."));
+
+ TQFile hierarch(chosenDir + "/hierarch.pm");
+ if (! hierarch.open( IO_ReadOnly ) ) {
+ inf->alert( i18n("Unable to open %1, skipping").arg( chosenDir + "hierarch.pm" ) );
+ return false;
+ } else {
+ TQStringList tmpList;
+ TQString tmpRead;
+ while ( !hierarch.atEnd() && hierarch.readLine(tmpRead,100)) {
+ TQString tmpArray[5];
+ tmpRead.remove(tmpRead.length() -2,2);
+ TQStringList tmpList = TQStringList::split(",", tmpRead, false);
+ int i = 0;
+ for ( TQStringList::Iterator it = tmpList.begin(); it != tmpList.end(); ++it, i++) {
+ TQString _tmp = *it;
+ if(i < 5) tmpArray[i] = _tmp.remove("\"");
+ else {
+ hierarch.close();
+ return false;
+ }
+ }
+ folderMatrix.append(tmpArray);
+ }
+ }
+ hierarch.close();
+ return true;
+}
+
+/** get the foldername for a given file ID from folderMatrix */
+TQString FilterPMail::getFolderName(TQString ID)
+{
+ bool found = false;
+ TQString folder;
+ TQString search = ID;
+
+ while (!found)
+ {
+ for ( FolderStructureIterator it = folderMatrix.begin(); it != folderMatrix.end(); it++) {
+ FolderStructure tmp = *it;
+
+ TQString _ID = tmp[2];
+ if(_ID == search) {
+ TQString _type = tmp[0] + tmp[1];
+ if(( _type == "21")) {
+ found = true;
+ break;
+ }
+ else {
+ folder.prepend((tmp[4] + "/"));
+ search = tmp[3];
+ }
+ }
+ }
+ }
+ return folder;
+}