~ubuntu-branches/ubuntu/raring/kdepim/raring-proposed

« back to all changes in this revision

Viewing changes to kmailcvt/filter_pmail.cxx

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2012-06-07 07:56:38 UTC
  • mfrom: (0.2.27)
  • Revision ID: package-import@ubuntu.com-20120607075638-0luhdq11z7sgvs4m
Tags: 4:4.8.80-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
                          FilterPMail.cxx  -  Pegasus-Mail import
3
 
                             -------------------
4
 
    begin                : Sat Jan 6 2001
5
 
    copyright            : (C) 2001 by Holger Schurig <holgerschurig@gmx.de>
6
 
                           (C) 2005 by Danny Kukawka <danny.kukawka@web.de>
7
 
 ***************************************************************************/
8
 
 
9
 
/***************************************************************************
10
 
 *                                                                         *
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.                                   *
15
 
 *                                                                         *
16
 
 ***************************************************************************/
17
 
 
18
 
#include <klocale.h>
19
 
#include <kfiledialog.h>
20
 
#include <QRegExp>
21
 
#include <ktemporaryfile.h>
22
 
#include <kdebug.h>
23
 
 
24
 
#include "filter_pmail.hxx"
25
 
 
26
 
 
27
 
FilterPMail::FilterPMail() :
28
 
        Filter(i18n("Import Folders From Pegasus-Mail"),
29
 
               "Holger Schurig <br>( rewritten by Danny Kukawka )",
30
 
               i18n("<p>Select the Pegasus-Mail directory on your system (containing *.CNM, *.PMM and *.MBX files). "
31
 
                    "On many systems this is stored in C:\\pmail\\mail or C:\\pmail\\mail\\admin</p>"
32
 
                    "<p><b>Note:</b> Since it is possible to recreate the folder structure, the folders "
33
 
                    "will be stored under: \"PegasusMail-Import\".</p>"))
34
 
{}
35
 
 
36
 
FilterPMail::~FilterPMail()
37
 
{
38
 
}
39
 
 
40
 
void FilterPMail::import(FilterInfo *info)
41
 
{
42
 
    inf = info;
43
 
 
44
 
    // Select directory from where I have to import files
45
 
    KFileDialog *kfd;
46
 
    kfd = new KFileDialog( QDir::homePath(), "", 0 );
47
 
    kfd->setMode(KFile::Directory | KFile::LocalOnly);
48
 
    kfd->exec();
49
 
    chosenDir = kfd->selectedFile();
50
 
    delete kfd;
51
 
    if (chosenDir.isEmpty()) {
52
 
        info->alert(i18n("No directory selected."));
53
 
        return;
54
 
    }
55
 
 
56
 
    // Count total number of files to be processed
57
 
    info->addLog(i18n("Counting files..."));
58
 
    dir.setPath (chosenDir);
59
 
    const QStringList files = dir.entryList(QStringList("*.[cC][nN][mM]")<<"*.[pP][mM][mM]"<<"*.[mM][bB][xX]", QDir::Files, QDir::Name);
60
 
    totalFiles = files.count();
61
 
    currentFile = 0;
62
 
    kDebug() <<"Count is" << totalFiles;
63
 
 
64
 
    if(!(folderParsed = parseFolderMatrix())) {
65
 
        info->addLog(i18n("Cannot parse the folder structure; continuing import without subfolder support."));
66
 
    }
67
 
 
68
 
    info->addLog(i18n("Importing new mail files ('.cnm')..."));
69
 
    processFiles("*.[cC][nN][mM]", &FilterPMail::importNewMessage);
70
 
    info->addLog(i18n("Importing mail folders ('.pmm')..."));
71
 
    processFiles("*.[pP][mM][mM]", &FilterPMail::importMailFolder);
72
 
    info->addLog(i18n("Importing 'UNIX' mail folders ('.mbx')..."));
73
 
    processFiles("*.[mM][bB][xX]", &FilterPMail::importUnixMailFolder);
74
 
 
75
 
    info->addLog( i18n("Finished importing emails from %1", chosenDir ));
76
 
    info->setCurrent(100);
77
 
    info->setOverall(100);
78
 
}
79
 
 
80
 
/** this looks for all files with the filemask 'mask' and calls the 'workFunc' on each of them */
81
 
void FilterPMail::processFiles(const QString& mask, void(FilterPMail::* workFunc)(const QString&) )
82
 
{
83
 
    if (inf->shouldTerminate()) return;
84
 
 
85
 
    const QStringList files = dir.entryList(QStringList(mask), QDir::Files, QDir::Name);
86
 
    //kDebug() <<"Mask is" << mask <<" count is" << files.count();
87
 
    for ( QStringList::ConstIterator mailFile = files.constBegin(); mailFile != files.constEnd(); ++mailFile ) {
88
 
        // Notify current file
89
 
        QFileInfo mailfileinfo(*mailFile);
90
 
        inf->setFrom(mailfileinfo.fileName());
91
 
 
92
 
        // Clear the other fields
93
 
        inf->setTo(QString());
94
 
        inf->setCurrent(QString());
95
 
        inf->setCurrent(-1);
96
 
 
97
 
        // call worker function, increase progressbar
98
 
        (this->*workFunc)(dir.filePath(*mailFile));
99
 
        ++currentFile;
100
 
        inf->setOverall( (int) ((float) currentFile / totalFiles * 100));
101
 
        inf->setCurrent( 100 );
102
 
        if (inf->shouldTerminate()) return;
103
 
    }
104
 
}
105
 
 
106
 
 
107
 
/** this function imports one *.CNM message */
108
 
void FilterPMail::importNewMessage(const QString& file)
109
 
{
110
 
    QString destFolder("PegasusMail-Import/New Messages");
111
 
    inf->setTo(destFolder);
112
 
 
113
 
    /* comment by Danny Kukawka:
114
 
     * addMessage() == old function, need more time and check for duplicates
115
 
     * addMessage_fastImport == new function, faster and no check for duplicates
116
 
     */
117
 
    if(inf->removeDupMsg)
118
 
        addMessage( inf, destFolder, file );
119
 
    else
120
 
        addMessage_fastImport( inf, destFolder, file );
121
 
}
122
 
 
123
 
 
124
 
/** this function imports one mail folder file (*.PMM) */
125
 
void FilterPMail::importMailFolder(const QString& file)
126
 
{
127
 
    // Format of a PMM file:
128
 
    // First comes a header with 128 bytes. At the beginning is the name of
129
 
    // the folder. Then there are some unknown bytes (strings). At offset 128
130
 
    // the first message starts.
131
 
    //
132
 
    // Each message is terminated by a 0x1A byte. The next message follows
133
 
    // immediately.
134
 
    //
135
 
    // The last message is followed by a 0x1A, too.
136
 
    //
137
 
    // 000000 6d 61 69 6c 73 65 72 76 65 72 2d 70 72 6f 6a 65    mailserver-proje
138
 
    // 000010 63 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ct..............
139
 
    // 000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
140
 
    // 000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
141
 
    // 000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
142
 
    // 000050 00 00 00 00 00 00 36 30 34 37 35 37 32 45 3a 36    ......6047572E:6
143
 
    // 000060 46 34 39 3a 46 4f 4c 30 31 33 35 35 00 00 00 00    F49:FOL01355....
144
 
    // 000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
145
 
    // 000080 52 65 74 75 72 6e 2d 50 61 74 68 3a 20 3c 75 72    Return-Path: <ur
146
 
    // ...
147
 
    // 000cb0 2d 2d 2d 2d 2d 2d 2d 2d 2d 2b 0d 0a 1a 52 65 74    ---------+...Ret
148
 
    // 000cc0 75 72 6e 2d 50 61 74 68 3a 20 3c 62 6f 75 6e 63    urn-Path: <bounc
149
 
    // ...
150
 
    // 04dc50 46 30 33 38 44 2e 36 31 35 44 37 34 44 30 2d 2d    F038D.615D74D0--
151
 
    // 04dc60 0d 0a 1a
152
 
 
153
 
    struct {
154
 
        char folder[86];
155
 
        char id[42];
156
 
    } pmm_head;
157
 
 
158
 
    long l = 0;
159
 
    QFile f(file);
160
 
    if (!f.open(QIODevice::ReadOnly)) {
161
 
        inf->alert(i18n("Unable to open %1, skipping", file));
162
 
    } else {
163
 
        // Get folder name
164
 
        l = f.read((char *) &pmm_head, sizeof(pmm_head));
165
 
        QString folder("PegasusMail-Import/");
166
 
        if(folderParsed)
167
 
            folder.append(getFolderName((QString)pmm_head.id));
168
 
        else
169
 
            folder.append(pmm_head.folder);
170
 
        inf->setTo(folder);
171
 
        inf->addLog(i18n("Importing %1", QString("../") + QString(pmm_head.folder)));
172
 
 
173
 
        QByteArray input(MAX_LINE,'\0');
174
 
        bool first_msg = true;
175
 
 
176
 
        while (!f.atEnd()) {
177
 
            KTemporaryFile tempfile;
178
 
            tempfile.open();
179
 
            inf->setCurrent( (int) ( ( (float) f.pos() / f.size() ) * 100 ) );
180
 
 
181
 
            if(!first_msg) {
182
 
                // set the filepos back to last line minus the separate char (0x1a)
183
 
                f.seek(f.pos() - l + 1);
184
 
            }
185
 
 
186
 
            // no problem to loose the last line in file. This only contains a separate char
187
 
            while ( ! f.atEnd() &&  (l = f.readLine(input.data(),MAX_LINE))) {
188
 
                    if (inf->shouldTerminate()){
189
 
                        return;
190
 
                    }
191
 
                    if ( input.at( 0 ) == 0x1a ) {
192
 
                        break;
193
 
                    } else {
194
 
                        tempfile.write( input, l );
195
 
                    }
196
 
            }
197
 
            tempfile.flush();
198
 
 
199
 
            if(inf->removeDupMsg)
200
 
                addMessage( inf, folder, tempfile.fileName() );
201
 
            else
202
 
                addMessage_fastImport( inf, folder, tempfile.fileName() );
203
 
 
204
 
            first_msg = false;
205
 
        }
206
 
    }
207
 
    f.close();
208
 
}
209
 
 
210
 
 
211
 
/** imports a 'unix' format mail folder (*.MBX) */
212
 
void FilterPMail::importUnixMailFolder(const QString& file)
213
 
{
214
 
    struct {
215
 
        char folder[58];
216
 
        char id[31];
217
 
    } pmg_head;
218
 
 
219
 
    QFile f;
220
 
    QString folder("PegasusMail-Import/"), s(file), separate;
221
 
    QByteArray line(MAX_LINE,'\0');
222
 
    int n = 0, l = 0;
223
 
 
224
 
    /** Get the folder name */
225
 
    s.replace( QRegExp("mbx$"), "pmg");
226
 
    s.replace( QRegExp("MBX$"), "PMG");
227
 
    f.setFileName(s);
228
 
    if (! f.open( QIODevice::ReadOnly ) ) {
229
 
        inf->alert( i18n("Unable to open %1, skipping", s ) );
230
 
        return;
231
 
    } else {
232
 
        f.read((char *) &pmg_head, sizeof(pmg_head));
233
 
        f.close();
234
 
 
235
 
         if(folderParsed)
236
 
            folder.append(getFolderName((QString)pmg_head.id));
237
 
        else
238
 
            folder.append(pmg_head.folder);
239
 
 
240
 
        inf->setTo(folder);
241
 
        inf->setTo(folder);
242
 
    }
243
 
 
244
 
    /** Read in the mbox */
245
 
    f.setFileName(file);
246
 
    if (! f.open( QIODevice::ReadOnly ) ) {
247
 
        inf->alert( i18n("Unable to open %1, skipping", s ) );
248
 
    } else {
249
 
        inf->addLog(i18n("Importing %1", QString("../") + QString(pmg_head.folder)));
250
 
        l = f.readLine( line.data(),MAX_LINE); // read the first line which is unneeded
251
 
        while ( ! f.atEnd() ) {
252
 
            KTemporaryFile tempfile;
253
 
            tempfile.open();
254
 
 
255
 
            // we lost the last line, which is the first line of the new message in
256
 
            // this lopp, but this is ok, because this is the separate line with
257
 
            // "From ???@???" and we can forget them
258
 
            while ( ! f.atEnd() &&  (l = f.readLine(line.data(),MAX_LINE)) && ((separate = line.data()).left(5) != "From ")) {
259
 
                tempfile.write(line.data(), l);
260
 
                if (inf->shouldTerminate()){
261
 
                    return;
262
 
                }
263
 
            }
264
 
            tempfile.flush();
265
 
            if(inf->removeDupMsg)
266
 
                addMessage( inf, folder, tempfile.fileName() );
267
 
            else
268
 
                addMessage_fastImport( inf, folder, tempfile.fileName() );
269
 
 
270
 
            n++;
271
 
            inf->setCurrent(i18n("Message %1", n));
272
 
            inf->setCurrent( (int) ( ( (float) f.pos() / f.size() ) * 100 ) );
273
 
        }
274
 
    }
275
 
    f.close();
276
 
}
277
 
 
278
 
/** Parse the information about folderstructure to folderMatrix */
279
 
bool FilterPMail::parseFolderMatrix()
280
 
{
281
 
    kDebug() <<"Start parsing the foldermatrix.";
282
 
    inf->addLog(i18n("Parsing the folder structure..."));
283
 
 
284
 
    QFile hierarch(chosenDir + "/hierarch.pm");
285
 
    if (! hierarch.open( QIODevice::ReadOnly ) ) {
286
 
        inf->alert( i18n("Unable to open %1, skipping", chosenDir + "hierarch.pm" ) );
287
 
        return false;
288
 
    } else {
289
 
        QStringList tmpList;
290
 
        QByteArray tmpRead;
291
 
        while ( !hierarch.atEnd() ) {
292
 
            tmpRead = hierarch.readLine();
293
 
            if ( tmpRead.isEmpty() )
294
 
                break;
295
 
            QString tmpArray[5];
296
 
            tmpRead.remove(tmpRead.length() -2,2);
297
 
            QStringList tmpList = QString(tmpRead).split(',', QString::SkipEmptyParts);
298
 
            int i = 0;
299
 
            for ( QStringList::Iterator it = tmpList.begin(); it != tmpList.end(); ++it, i++) {
300
 
                QString _tmp = *it;
301
 
                if(i < 5) tmpArray[i] = _tmp.remove('\"');
302
 
                else {
303
 
                    hierarch.close();
304
 
                    return false;
305
 
                }
306
 
            }
307
 
            folderMatrix.append(FolderStructure(tmpArray));
308
 
        }
309
 
    }
310
 
    hierarch.close();
311
 
    return true;
312
 
}
313
 
 
314
 
/** get the foldername for a given file ID from folderMatrix */
315
 
QString FilterPMail::getFolderName(QString ID)
316
 
{
317
 
    bool found = false;
318
 
    QString folder;
319
 
    QString search = ID;
320
 
 
321
 
    while (!found)
322
 
    {
323
 
        for ( FolderStructureIterator it = folderMatrix.begin(); it != folderMatrix.end(); ++it) {
324
 
            FolderStructure tmp = *it;
325
 
 
326
 
            QString _ID = tmp[2];
327
 
            if(_ID == search) {
328
 
                QString _type = tmp[0] + tmp[1];
329
 
                if(( _type == "21")) {
330
 
                    found = true;
331
 
                    break;
332
 
                }
333
 
                else {
334
 
                    folder.prepend((tmp[4] + '/'));
335
 
                    search = tmp[3];
336
 
                }
337
 
            }
338
 
        }
339
 
    }
340
 
    return folder;
341
 
}