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>
00025 #include <KLocale>
00026 #include <KMessageBox>
00027 #include <KStandardGuiItem>
00028 #include <kde_file.h>
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 = i18np( "Could only read 1 byte of %2.",
00114 "Could only read %1 bytes of %2.",
00115 readLen, len );
00116 msgDialog( msg );
00117 result.truncate( readLen );
00118 }
00119
00120 return result;
00121 }
00122
00123
00124 bool kByteArrayToFile( const QByteArray &aBuffer, const QString &aFileName,
00125 bool aAskIfExists, bool aBackup, bool aVerbose )
00126 {
00127
00128 QFile file( aFileName );
00129
00130
00131 if( aFileName.isEmpty() ) {
00132 return false;
00133 }
00134
00135 if ( file.exists() ) {
00136 if ( aAskIfExists ) {
00137 QString str;
00138 str = i18n( "File %1 exists.\nDo you want to replace it?", aFileName );
00139 const int rc =
00140 KMessageBox::warningContinueCancel( 0, str, i18n( "Save to File" ),
00141 KGuiItem( i18n( "&Replace" ) ) );
00142 if ( rc != KMessageBox::Continue ) {
00143 return false;
00144 }
00145 }
00146 if ( aBackup ) {
00147
00148
00149 QString bakName = aFileName;
00150 bakName += '~';
00151 QFile::remove(bakName);
00152 if ( !QDir::current().rename( aFileName, bakName ) ) {
00153
00154 if ( !aVerbose ) {
00155 return false;
00156 }
00157 const int rc =
00158 KMessageBox::warningContinueCancel(
00159 0,
00160 i18n( "Failed to make a backup copy of %1.\nContinue anyway?", aFileName ),
00161 i18n( "Save to File" ), KStandardGuiItem::save() );
00162
00163 if ( rc != KMessageBox::Continue ) {
00164 return false;
00165 }
00166 }
00167 }
00168 }
00169
00170 if ( !file.open( QIODevice::Unbuffered|QIODevice::WriteOnly|QIODevice::Truncate ) ) {
00171 if ( aVerbose ) {
00172 switch( file.error() ) {
00173 case QFile::WriteError:
00174 msgDialog( i18n( "Could not write to file:\n%1", aFileName ) );
00175 break;
00176 case QFile::OpenError:
00177 msgDialog( i18n( "Could not open file for writing:\n%1", aFileName ) );
00178 break;
00179 default:
00180 msgDialog( i18n( "Error while writing file:\n%1", aFileName ) );
00181 }
00182 }
00183 return false;
00184 }
00185
00186 const int writeLen = file.write( aBuffer.data(), aBuffer.size() );
00187
00188 if ( writeLen < 0 ) {
00189 if ( aVerbose ) {
00190 msgDialog( i18n( "Could not write to file:\n%1", aFileName ) );
00191 }
00192 return false;
00193 } else if ( writeLen < aBuffer.size() ) {
00194 QString msg = i18np( "Could only write 1 byte of %2.",
00195 "Could only write %1 bytes of %2.",
00196 writeLen, aBuffer.size() );
00197 if ( aVerbose ) {
00198 msgDialog( msg );
00199 }
00200 return false;
00201 }
00202
00203 return true;
00204 }
00205
00206 QString checkAndCorrectPermissionsIfPossible( const QString &toCheck,
00207 const bool recursive,
00208 const bool wantItReadable,
00209 const bool wantItWritable )
00210 {
00211
00212
00213
00214 QFileInfo fiToCheck(toCheck);
00215 fiToCheck.setCaching(false);
00216 QByteArray toCheckEnc = QFile::encodeName( toCheck );
00217 QString error;
00218 KDE_struct_stat statbuffer;
00219
00220 if ( !fiToCheck.exists() ) {
00221 error.append( i18n( "%1 does not exist", toCheck ) + '\n' );
00222 }
00223
00224
00225 if ( fiToCheck.isDir() ) {
00226 if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00227 kDebug() << "wantItA: Can't read perms of" << toCheck;
00228 }
00229 QDir g( toCheck );
00230 if ( !g.isReadable() ) {
00231 if ( chmod( toCheckEnc, statbuffer.st_mode + S_IXUSR ) != 0 ) {
00232 error.append( i18n( "%1 is not accessible and that is "
00233 "unchangeable.", toCheck ) + '\n' );
00234 } else {
00235 kDebug() << "Changed access bit for" << toCheck;
00236 }
00237 }
00238 }
00239
00240
00241
00242 if ( fiToCheck.isFile() || fiToCheck.isDir() ) {
00243
00244 if ( !fiToCheck.isReadable() && wantItReadable ) {
00245
00246
00247 if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00248 kDebug() << "wantItR: Can't read perms of" << toCheck;
00249 }
00250
00251
00252 if ( chmod( toCheckEnc, statbuffer.st_mode + S_IRUSR ) != 0 ) {
00253 error.append( i18n( "%1 is not readable and that is unchangeable.",
00254 toCheck ) + '\n' );
00255 } else {
00256 kDebug() << "Changed the read bit for" << toCheck;
00257 }
00258 }
00259
00260 if ( !fiToCheck.isWritable() && wantItWritable ) {
00261
00262
00263 if ( KDE_stat( toCheckEnc,&statbuffer ) != 0 ) {
00264 kDebug() << "wantItW: Can't read perms of" << toCheck;
00265 }
00266
00267
00268 if ( chmod ( toCheckEnc, statbuffer.st_mode + S_IWUSR ) != 0 ) {
00269 error.append( i18n( "%1 is not writable and that is unchangeable.", toCheck ) + '\n' );
00270 } else {
00271 kDebug() << "Changed the write bit for" << toCheck;
00272 }
00273 }
00274 }
00275
00276
00277
00278 if ( fiToCheck.isDir() && recursive ){
00279 QDir g( toCheck );
00280
00281
00282 if ( !g.isReadable() ){
00283 error.append( i18n( "Folder %1 is inaccessible.", toCheck ) + '\n' );
00284 } else {
00285 foreach ( const QFileInfo &fi, g.entryInfoList() ) {
00286 QString newToCheck = toCheck + '/' + fi.fileName();
00287 QFileInfo fiNewToCheck(newToCheck);
00288 if ( fi.fileName() != "." && fi.fileName() != ".." ) {
00289 error.append (
00290 checkAndCorrectPermissionsIfPossible( newToCheck, recursive,
00291 wantItReadable, wantItWritable ) );
00292 }
00293 }
00294 }
00295 }
00296 return error;
00297 }
00298
00299 bool checkAndCorrectPermissionsIfPossibleWithErrorHandling( QWidget *parent,
00300 const QString &toCheck,
00301 const bool recursive,
00302 const bool wantItReadable,
00303 const bool wantItWritable )
00304 {
00305 QString error =
00306 checkAndCorrectPermissionsIfPossible( toCheck, recursive, wantItReadable, wantItWritable );
00307
00308
00309
00310
00311 if ( !error.isEmpty() ) {
00312 kDebug() << "checkPermissions found:" << error;
00313 KMessageBox::detailedSorry( parent,
00314 i18n( "Some files or folders do not have the "
00315 "necessary permissions, please correct "
00316 "them manually." ),
00317 error, i18n( "Permissions Check" ), 0 );
00318 return false;
00319 } else {
00320 return true;
00321 }
00322 }
00323
00324 bool removeDirAndContentsRecursively( const QString & path )
00325 {
00326 bool success = true;
00327
00328 QDir d;
00329 d.setPath( path );
00330 d.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );
00331
00332 QFileInfoList list = d.entryInfoList();
00333
00334 Q_FOREACH( const QFileInfo &fi, list ) {
00335 if ( fi.isDir() ) {
00336 if ( fi.fileName() != "." && fi.fileName() != ".." ) {
00337 success = success && removeDirAndContentsRecursively( fi.absoluteFilePath() );
00338 }
00339 } else {
00340 success = success && d.remove( fi.absoluteFilePath() );
00341 }
00342 }
00343
00344 if ( success ) {
00345 success = success && d.rmdir( path );
00346 }
00347 return success;
00348 }
00349
00350 }