22#include "folderutil.h" 
   23#include "kmfolderdir.h" 
   24#include "kmfolderimap.h" 
   27#include "progressmanager.h" 
   33#include <tdemessagebox.h> 
   42KMail::ImportJob::ImportJob( TQWidget *parentWidget )
 
   43  : TQObject( parentWidget ),
 
   46    mParentWidget( parentWidget ),
 
   47    mNumberOfImportedMessages( 0 ),
 
   50    mCurrentMessageFile( 0 ),
 
   56KMail::ImportJob::~ImportJob()
 
   58  if ( mArchive && mArchive->isOpened() ) {
 
   65void KMail::ImportJob::setFile( 
const KURL &archiveFile )
 
   67  mArchiveFile = archiveFile;
 
   70void KMail::ImportJob::setRootFolder( 
KMFolder *rootFolder )
 
   72  mRootFolder = rootFolder;
 
   75void KMail::ImportJob::finish()
 
   77  kdDebug(5006) << 
"Finished import job." << endl;
 
   78  mProgressItem->setComplete();
 
   80  TQString text = i18n( 
"Importing the archive file '%1' into the folder '%2' succeeded." )
 
   81                     .arg( mArchiveFile.path() ).arg( mRootFolder->name() );
 
   82  text += 
"\n" + i18n( 
"1 message was imported.", 
"%n messages were imported.", mNumberOfImportedMessages );
 
   83  KMessageBox::information( mParentWidget, text, i18n( 
"Import finished." ) );
 
   87void KMail::ImportJob::cancelJob()
 
   89  abort( i18n( 
"The operation was canceled by the user." ) );
 
   92void KMail::ImportJob::abort( 
const TQString &errorMessage )
 
   98  TQString text = i18n( 
"Failed to import the archive into folder '%1'." ).arg( mRootFolder->name() );
 
   99  text += 
"\n" + errorMessage;
 
  100  if ( mProgressItem ) {
 
  101    mProgressItem->setComplete();
 
  105  KMessageBox::sorry( mParentWidget, text, i18n( 
"Importing archive failed." ) );
 
  109KMFolder * KMail::ImportJob::createSubFolder( 
KMFolder *parent, 
const TQString &folderName, mode_t permissions )
 
  111  KMFolder *newFolder = FolderUtil::createSubFolder( parent, parent->
child(), folderName, TQString(),
 
  112                                                     KMFolderTypeMaildir );
 
  114    abort( i18n( 
"Unable to create subfolder for folder '%1'." ).arg( parent->name() ) );
 
  121    chmod( newFolder->
location().latin1(), permissions | S_IXUSR );
 
  122    chmod( newFolder->
subdirLocation().latin1(), permissions | S_IXUSR );
 
  129void KMail::ImportJob::enqueueMessages( 
const KArchiveDirectory *dir, 
KMFolder *folder )
 
  131  const KArchiveDirectory *messageDir = 
dynamic_cast<const KArchiveDirectory*
>( dir->entry( 
"cur" ) );
 
  133    Messages messagesToQueue;
 
  134    messagesToQueue.parent = folder;
 
  135    const TQStringList entries = messageDir->entries();
 
  136    for ( uint i = 0; i < entries.size(); i++ ) {
 
  137      const KArchiveEntry *entry = messageDir->entry( entries[i] );
 
  139      if ( entry->isDirectory() ) {
 
  140        kdWarning(5006) << 
"Unexpected subdirectory in archive folder " << dir->name() << endl;
 
  143        kdDebug(5006) << 
"Queueing message " << entry->name() << endl;
 
  144        const KArchiveFile *file = 
static_cast<const KArchiveFile*
>( entry );
 
  145        messagesToQueue.files.append( file );
 
  148    mQueuedMessages.append( messagesToQueue );
 
  151    kdWarning(5006) << 
"No 'cur' subdirectory for archive directory " << dir->name() << endl;
 
  155void KMail::ImportJob::messageAdded()
 
  157  mNumberOfImportedMessages++;
 
  158  if ( mCurrentFolder->folderType() == KMFolderTypeMaildir ||
 
  159       mCurrentFolder->folderType() == KMFolderTypeCachedImap ) {
 
  160    const TQString messageFile = mCurrentFolder->location() + 
"/cur/" + mCurrentMessage->fileName();
 
  162    if ( TQFile::exists( messageFile ) ) {
 
  163      chmod( messageFile.latin1(), mCurrentMessageFile->permissions() );
 
  170      kdWarning(5006) << 
"Unable to change permissions for newly created file: " << messageFile << endl;
 
  176  mCurrentMessageFile = 0;
 
  177  TQTimer::singleShot( 0, 
this, TQ_SLOT( importNextMessage() ) );
 
  180void KMail::ImportJob::importNextMessage()
 
  185  if ( mQueuedMessages.isEmpty() ) {
 
  186    kdDebug(5006) << 
"importNextMessage(): Processed all messages in the queue." << endl;
 
  187    if ( mCurrentFolder ) {
 
  188      mCurrentFolder->close( 
"ImportJob" );
 
  191    importNextDirectory();
 
  195  Messages &messages = mQueuedMessages.front();
 
  196  if ( messages.files.isEmpty() ) {
 
  197    mQueuedMessages.pop_front();
 
  203  if ( folder != mCurrentFolder ) {
 
  204    kdDebug(5006) << 
"importNextMessage(): Processed all messages in the current folder of the queue." << endl;
 
  205    if ( mCurrentFolder ) {
 
  206      mCurrentFolder->
close( 
"ImportJob" );
 
  208    mCurrentFolder = folder;
 
  209    if ( mCurrentFolder->open( 
"ImportJob" ) != 0 ) {
 
  210      abort( i18n( 
"Unable to open folder '%1'." ).arg( mCurrentFolder->name() ) );
 
  213    kdDebug(5006) << 
"importNextMessage(): Current folder of queue is now: " << mCurrentFolder->name() << endl;
 
  214    mProgressItem->setStatus( i18n( 
"Importing folder %1" ).arg( mCurrentFolder->name() ) );
 
  217  mProgressItem->setProgress( ( mProgressItem->progress() + 5 ) );
 
  219  mCurrentMessageFile = messages.files.first();
 
  220  Q_ASSERT( mCurrentMessageFile );
 
  221  messages.files.removeFirst();
 
  224  mCurrentMessage->fromByteArray( mCurrentMessageFile->data(), 
true  );
 
  232  if ( mCurrentFolder->folderType() != KMFolderTypeImap ) {
 
  233    if ( mCurrentFolder->addMsg( mCurrentMessage, &retIndex ) != 0 ) {
 
  234      abort( i18n( 
"Failed to add a message to the folder '%1'." ).arg( mCurrentFolder->name() ) );
 
  240    ImapJob *imapJob = 
new ImapJob( mCurrentMessage, ImapJob::tPutMessage,
 
  241                                    dynamic_cast<KMFolderImap*
>( mCurrentFolder->storage() ) );
 
  242    connect( imapJob, TQ_SIGNAL(result(KMail::FolderJob*)),
 
  243             TQ_SLOT(messagePutResult(KMail::FolderJob*)) );
 
  248void KMail::ImportJob::messagePutResult( KMail::FolderJob *job )
 
  253  if ( job->error() ) {
 
  254    abort( i18n( 
"Failed to upload a message to the IMAP server." ) );
 
  258    KMFolderImap *imap = 
dynamic_cast<KMFolderImap*
>( mCurrentFolder->storage() );
 
  263    imap->addMsgQuiet( mCurrentMessage );
 
  271static TQString folderNameForDirectoryName( 
const TQString &dirName )
 
  273  Q_ASSERT( dirName.startsWith( 
"." ) );
 
  274  const TQString end = 
".directory";
 
  275  const int expectedIndex = dirName.length() - end.length();
 
  276  if ( dirName.lower().find( end ) != expectedIndex )
 
  278  TQString returnName = dirName.left( dirName.length() - end.length() );
 
  279  returnName = returnName.right( returnName.length() - 1 );
 
  283KMFolder* KMail::ImportJob::getOrCreateSubFolder( 
KMFolder *parentFolder, 
const TQString &subFolderName,
 
  284                                           mode_t subFolderPermissions )
 
  287    abort( i18n( 
"Unable to create subfolder for folder '%1'." ).arg( parentFolder->name() ) );
 
  295    subFolder = createSubFolder( parentFolder, subFolderName, subFolderPermissions );
 
  300void KMail::ImportJob::importNextDirectory()
 
  305  if ( mQueuedDirectories.isEmpty() ) {
 
  310  Folder folder = mQueuedDirectories.first();
 
  311  KMFolder *currentFolder = folder.parent;
 
  312  mQueuedDirectories.pop_front();
 
  313  kdDebug(5006) << 
"importNextDirectory(): Working on directory " << folder.archiveDir->name() << endl;
 
  315  TQStringList entries = folder.archiveDir->entries();
 
  316  for ( uint i = 0; i < entries.size(); i++ ) {
 
  317    const KArchiveEntry *entry = folder.archiveDir->entry( entries[i] );
 
  319    kdDebug(5006) << 
"Queueing entry " << entry->name() << endl;
 
  320    if ( entry->isDirectory() ) {
 
  321      const KArchiveDirectory *dir = 
static_cast<const KArchiveDirectory*
>( entry );
 
  322      if ( !dir->name().startsWith( 
"." ) ) {
 
  324        kdDebug(5006) << 
"Queueing messages in folder " << entry->name() << endl;
 
  325        KMFolder *subFolder = getOrCreateSubFolder( currentFolder, entry->name(), entry->permissions() );
 
  329        enqueueMessages( dir, subFolder );
 
  335        const TQString folderName = folderNameForDirectoryName( entry->name() );
 
  336        if ( folderName.isEmpty() ) {
 
  337          abort( i18n( 
"Unexpected subdirectory named '%1'." ).arg( entry->name() ) );
 
  340        KMFolder *subFolder = getOrCreateSubFolder( currentFolder, folderName, entry->permissions() );
 
  345        newFolder.archiveDir = dir;
 
  346        newFolder.parent = subFolder;
 
  347        kdDebug(5006) << 
"Enqueueing directory " << entry->name() << endl;
 
  348        mQueuedDirectories.push_back( newFolder );
 
  360void KMail::ImportJob::start()
 
  362  Q_ASSERT( mRootFolder );
 
  363  Q_ASSERT( mArchiveFile.isValid() );
 
  365  KMimeType::Ptr mimeType = KMimeType::findByURL( mArchiveFile, 0, 
true  );
 
  366  if ( !mimeType->patterns().grep( 
"tar", 
false  ).isEmpty() )
 
  367    mArchive = 
new KTar( mArchiveFile.path() );
 
  368  else if ( !mimeType->patterns().grep( 
"zip", 
false ).isEmpty() )
 
  369    mArchive = 
new KZip( mArchiveFile.path() );
 
  371    abort( i18n( 
"The file '%1' does not appear to be a valid archive." ).arg( mArchiveFile.path() ) );
 
  375  if ( !mArchive->open( IO_ReadOnly ) ) {
 
  376    abort( i18n( 
"Unable to open archive file '%1'" ).arg( mArchiveFile.path() ) );
 
  380  mProgressItem = KPIM::ProgressManager::createProgressItem(
 
  382      i18n( 
"Importing Archive" ),
 
  385  mProgressItem->setUsesBusyIndicator( 
true );
 
  386  connect( mProgressItem, TQ_SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
 
  387           this, TQ_SLOT(cancelJob()) );
 
  390  nextFolder.archiveDir = mArchive->directory();
 
  391  nextFolder.parent = mRootFolder;
 
  392  mQueuedDirectories.push_back( nextFolder );
 
  393  importNextDirectory();
 
  396#include "importjob.moc" 
virtual KMFolderNode * hasNamedFolder(const TQString &name)
Returns folder with given name or zero if it does not exist.
 
TQString subdirLocation() const
Returns full path to sub directory file.
 
void close(const char *owner, bool force=false)
Close folder.
 
KMFolderDir * createChildFolder()
Create a child folder directory and associates it with this folder.
 
TQString location() const
Returns full path to folder file.
 
KMFolderDir * child() const
Returns the folder directory associated with this node or 0 if no such directory exists.