diff options
Diffstat (limited to 'kmailcvt/filter_pmail.cpp')
-rw-r--r-- | kmailcvt/filter_pmail.cpp | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/kmailcvt/filter_pmail.cpp b/kmailcvt/filter_pmail.cpp new file mode 100644 index 000000000..b45a0be41 --- /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; +} |