• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

kpimutils

kfileio.cpp

00001 /*
00002   Copyright (c) 2005 Tom Albers <tomalbers@kde.nl>
00003   Copyright (c) 1997-1999 Stefan Taferner <taferner@kde.org>
00004 
00005   This library is free software; you can redistribute it and/or modify it
00006   under the terms of the GNU Library General Public License as published by
00007   the Free Software Foundation; either version 2 of the License, or (at your
00008   option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful, but WITHOUT
00011   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013   License for more details.
00014 
00015   You should have received a copy of the GNU Library General Public License
00016   along with this library; see the file COPYING.LIB.  If not, write to the
00017   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018   02110-1301, USA.
00019 */
00020 
00021 #include "kfileio.h"
00022 #include "kpimutils_export.h"
00023 
00024 #include <kdebug.h>
00025 #include <kde_file.h>
00026 #include <klocale.h>
00027 #include <kmessagebox.h>
00028 #include <KStandardGuiItem>
00029 
00030 #include <QDir>
00031 #include <QByteArray>
00032 #include <QWidget>
00033 #include <QFile>
00034 #include <QFileInfo>
00035 
00036 #include <sys/stat.h>
00037 #include <sys/types.h>
00038 #include <assert.h>
00039 
00040 namespace KPIMUtils {
00041 
00042 //-----------------------------------------------------------------------------
00043 static void msgDialog( const QString &msg )
00044 {
00045   KMessageBox::sorry( 0, msg, i18n( "File I/O Error" ) );
00046 }
00047 
00048 //-----------------------------------------------------------------------------
00049 QByteArray kFileToByteArray( const QString &aFileName, bool aEnsureNL,
00050                              bool aVerbose )
00051 {
00052   QByteArray result;
00053   QFileInfo info( aFileName );
00054   unsigned int readLen;
00055   unsigned int len = info.size();
00056   QFile file( aFileName );
00057 
00058   //assert(aFileName!=0);
00059   if( aFileName.isEmpty() ) {
00060     return "";
00061   }
00062 
00063   if ( !info.exists() ) {
00064     if ( aVerbose ) {
00065       msgDialog( i18n( "The specified file does not exist:\n%1", aFileName ) );
00066     }
00067     return QByteArray();
00068   }
00069   if ( info.isDir() ) {
00070     if ( aVerbose ) {
00071       msgDialog( i18n( "This is a folder and not a file:\n%1", aFileName ) );
00072     }
00073     return QByteArray();
00074   }
00075   if ( !info.isReadable() ) {
00076     if ( aVerbose ) {
00077       msgDialog( i18n( "You do not have read permissions to the file:\n%1", aFileName ) );
00078     }
00079     return QByteArray();
00080   }
00081   if ( len <= 0 ) {
00082     return QByteArray();
00083   }
00084 
00085   if ( !file.open( QIODevice::Unbuffered|QIODevice::ReadOnly ) ) {
00086     if ( aVerbose ) {
00087       switch( file.error() ) {
00088       case QFile::ReadError:
00089         msgDialog( i18n( "Could not read file:\n%1", aFileName ) );
00090         break;
00091       case QFile::OpenError:
00092         msgDialog( i18n( "Could not open file:\n%1", aFileName ) );
00093         break;
00094       default:
00095         msgDialog( i18n( "Error while reading file:\n%1", aFileName ) );
00096       }
00097     }
00098     return QByteArray();
00099   }
00100 
00101   result.resize( len + int( aEnsureNL ) );
00102   readLen = file.read( result.data(), len );
00103   if ( aEnsureNL ) {
00104     if ( result[readLen-1] != '\n' ) {
00105       result[readLen++] = '\n';
00106       len++;
00107     } else {
00108       result.truncate( len );
00109     }
00110   }
00111 
00112   if ( readLen < len ) {
00113     QString msg = i18n( "Could only read %1 bytes of %2.", readLen, len );
00114     msgDialog( msg );
00115     result.truncate( readLen );
00116   }
00117 
00118   return result;
00119 }
00120 
00121 //-----------------------------------------------------------------------------
00122 bool kByteArrayToFile( const QByteArray &aBuffer, const QString &aFileName,
00123                        bool aAskIfExists, bool aBackup, bool aVerbose )
00124 {
00125   // TODO: use KSaveFile
00126   QFile file( aFileName );
00127 
00128   //assert(aFileName!=0);
00129   if( aFileName.isEmpty() ) {
00130     return false;
00131   }
00132 
00133   if ( file.exists() ) {
00134     if ( aAskIfExists ) {
00135       QString str;
00136       str = i18n( "File %1 exists.\nDo you want to replace it?", aFileName );
00137       const int rc =
00138         KMessageBox::warningContinueCancel( 0, str, i18n( "Save to File" ),
00139                                             KGuiItem( i18n( "&Replace" ) ) );
00140       if ( rc != KMessageBox::Continue ) {
00141         return false;
00142       }
00143     }
00144     if ( aBackup ) {
00145       // make a backup copy
00146       // TODO: use KSaveFile::backupFile()
00147       QString bakName = aFileName;
00148       bakName += '~';
00149       QFile::remove(bakName);
00150       if ( !QDir::current().rename( aFileName, bakName ) ) {
00151     // failed to rename file
00152         if ( !aVerbose ) {
00153           return false;
00154         }
00155         const int rc =
00156           KMessageBox::warningContinueCancel(
00157             0,
00158             i18n( "Failed to make a backup copy of %1.\nContinue anyway?", aFileName ),
00159             i18n( "Save to File" ), KStandardGuiItem::save() );
00160 
00161         if ( rc != KMessageBox::Continue ) {
00162           return false;
00163         }
00164       }
00165     }
00166   }
00167 
00168   if ( !file.open( QIODevice::Unbuffered|QIODevice::WriteOnly|QIODevice::Truncate ) ) {
00169     if ( aVerbose ) {
00170       switch( file.error() ) {
00171       case QFile::WriteError:
00172         msgDialog( i18n( "Could not write to file:\n%1", aFileName ) );
00173         break;
00174       case QFile::OpenError:
00175         msgDialog( i18n( "Could not open file for writing:\n%1", aFileName ) );
00176         break;
00177       default:
00178         msgDialog( i18n( "Error while writing file:\n%1", aFileName ) );
00179       }
00180     }
00181     return false;
00182   }
00183 
00184   const int writeLen = file.write( aBuffer.data(), aBuffer.size() );
00185 
00186   if ( writeLen < 0 ) {
00187     if ( aVerbose ) {
00188       msgDialog( i18n( "Could not write to file:\n%1", aFileName ) );
00189     }
00190     return false;
00191   } else if ( writeLen < aBuffer.size() ) {
00192     QString msg = i18n( "Could only write %1 bytes of %2.", writeLen, aBuffer.size() );
00193     if ( aVerbose ) {
00194       msgDialog( msg );
00195     }
00196     return false;
00197   }
00198 
00199   return true;
00200 }
00201 
00202 QString checkAndCorrectPermissionsIfPossible( const QString &toCheck,
00203                                               const bool recursive,
00204                                               const bool wantItReadable,
00205                                               const bool wantItWritable )
00206 {
00207   // First we have to find out which type the toCheck is. This can be
00208   // a directory (follow if recursive) or a file (check permissions).
00209   // Symlinks are followed as expected.
00210   QFileInfo fiToCheck(toCheck);
00211   fiToCheck.setCaching(false);
00212   QByteArray toCheckEnc = QFile::encodeName( toCheck );
00213   QString error;
00214   KDE_struct_stat statbuffer;
00215 
00216   if ( !fiToCheck.exists() ) {
00217     error.append( i18n( "%1 does not exist", toCheck ) + '\n' );
00218   }
00219 
00220   // check the access bit of a folder.
00221   if ( fiToCheck.isDir() ) {
00222     if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00223       kDebug() << "wantItA: Can't read perms of" << toCheck;
00224     }
00225     QDir g( toCheck );
00226     if ( !g.isReadable() ) {
00227       if ( chmod( toCheckEnc, statbuffer.st_mode + S_IXUSR ) != 0 ) {
00228         error.append( i18n( "%1 is not accessible and that is "
00229                             "unchangeable.", toCheck ) + '\n' );
00230       } else {
00231         kDebug() << "Changed access bit for" << toCheck;
00232       }
00233     }
00234   }
00235 
00236   // For each file or folder  we can check if the file is readable
00237   // and writable, as requested.
00238   if ( fiToCheck.isFile() || fiToCheck.isDir() ) {
00239 
00240     if ( !fiToCheck.isReadable() && wantItReadable ) {
00241       // Get the current permissions. No need to do anything with an
00242       // error, it will het added to errors anyhow, later on.
00243       if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00244         kDebug() << "wantItR: Can't read perms of" << toCheck;
00245       }
00246 
00247       // Lets try changing it.
00248       if ( chmod( toCheckEnc, statbuffer.st_mode + S_IRUSR ) != 0 ) {
00249         error.append( i18n( "%1 is not readable and that is unchangeable.",
00250                             toCheck ) + '\n' );
00251       } else {
00252         kDebug() << "Changed the read bit for" << toCheck;
00253       }
00254     }
00255 
00256     if ( !fiToCheck.isWritable() && wantItWritable ) {
00257       // Gets the current persmissions. Needed because it can be changed
00258       // curing previous operation.
00259       if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00260         kDebug() << "wantItW: Can't read perms of" << toCheck;
00261       }
00262 
00263       // Lets try changing it.
00264       if ( chmod ( toCheckEnc, statbuffer.st_mode + S_IWUSR ) != 0 ) {
00265         error.append( i18n( "%1 is not writable and that is unchangeable.", toCheck ) + '\n' );
00266       } else {
00267         kDebug() << "Changed the write bit for" << toCheck;
00268       }
00269     }
00270   }
00271 
00272   // If it is a folder and recursive is true, then we check the contents of
00273   // the folder.
00274   if ( fiToCheck.isDir() && recursive ){
00275     QDir g( toCheck );
00276     // First check if the folder is readable for us. If not, we get
00277     // some ugly crashes.
00278     if ( !g.isReadable() ){
00279       error.append( i18n( "Folder %1 is inaccessible.", toCheck ) + '\n' );
00280     } else {
00281       foreach ( const QFileInfo &fi, g.entryInfoList() ) {
00282         QString newToCheck = toCheck + '/' + fi.fileName();
00283         QFileInfo fiNewToCheck(newToCheck);
00284         if ( fi.fileName() != "." && fi.fileName() != ".." ) {
00285           error.append (
00286             checkAndCorrectPermissionsIfPossible( newToCheck, recursive,
00287                                                   wantItReadable, wantItWritable ) );
00288         }
00289       }
00290     }
00291   }
00292   return error;
00293 }
00294 
00295 bool checkAndCorrectPermissionsIfPossibleWithErrorHandling( QWidget *parent,
00296                                                             const QString &toCheck,
00297                                                             const bool recursive,
00298                                                             const bool wantItReadable,
00299                                                             const bool wantItWritable )
00300 {
00301   QString error =
00302     checkAndCorrectPermissionsIfPossible( toCheck, recursive, wantItReadable, wantItWritable );
00303 
00304   // There is no KMessageBox with Retry, Cancel and Details.
00305   // so, I can't provide a functionality to recheck. So it now
00306   // it is just a warning.
00307   if ( !error.isEmpty() ) {
00308     kDebug() << "checkPermissions found:" << error;
00309     KMessageBox::detailedSorry( parent,
00310                                 i18n( "Some files or folders do not have the "
00311                                       "necessary permissions, please correct "
00312                                       "them manually." ),
00313                                 error, i18n( "Permissions Check" ), false );
00314     return false;
00315   } else {
00316     return true;
00317   }
00318 }
00319 
00320 bool removeDirAndContentsRecursively( const QString & path )
00321 {
00322   bool success = true;
00323 
00324   QDir d;
00325   d.setPath( path );
00326   d.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );
00327 
00328   QFileInfoList list = d.entryInfoList();
00329 
00330   Q_FOREACH( const QFileInfo &fi, list ) {
00331     if ( fi.isDir() ) {
00332       if ( fi.fileName() != "." && fi.fileName() != ".." ) {
00333         success = success && removeDirAndContentsRecursively( fi.absoluteFilePath() );
00334       }
00335     } else {
00336       success = success && d.remove( fi.absoluteFilePath() );
00337     }
00338   }
00339 
00340   if ( success ) {
00341     success = success && d.rmdir( path ); // nuke ourselves, we should be empty now
00342   }
00343   return success;
00344 }
00345 
00346 }

kpimutils

Skip menu "kpimutils"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.8
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal