00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00126 QFile file( aFileName );
00127
00128
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
00146
00147 QString bakName = aFileName;
00148 bakName += '~';
00149 QFile::remove(bakName);
00150 if ( !QDir::current().rename( aFileName, bakName ) ) {
00151
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
00208
00209
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
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
00237
00238 if ( fiToCheck.isFile() || fiToCheck.isDir() ) {
00239
00240 if ( !fiToCheck.isReadable() && wantItReadable ) {
00241
00242
00243 if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00244 kDebug() << "wantItR: Can't read perms of" << toCheck;
00245 }
00246
00247
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
00258
00259 if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00260 kDebug() << "wantItW: Can't read perms of" << toCheck;
00261 }
00262
00263
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
00273
00274 if ( fiToCheck.isDir() && recursive ){
00275 QDir g( toCheck );
00276
00277
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
00305
00306
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 QFileInfo fi;
00330
00331 Q_FOREACH( fi, list ) {
00332 if ( fi.isDir() ) {
00333 if ( fi.fileName() != "." && fi.fileName() != ".." ) {
00334 success = success && removeDirAndContentsRecursively( fi.absoluteFilePath() );
00335 }
00336 } else {
00337 success = success && d.remove( fi.absoluteFilePath() );
00338 }
00339 }
00340
00341 if ( success ) {
00342 success = success && d.rmdir( path );
00343 }
00344 return success;
00345 }
00346
00347 }