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

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"
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.5
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