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 <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
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
00125 QFile file( aFileName );
00126
00127
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
00145
00146 QString bakName = aFileName;
00147 bakName += '~';
00148 QFile::remove(bakName);
00149 if ( !QDir::current().rename( aFileName, bakName ) ) {
00150
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
00207
00208
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
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
00236
00237 if ( fiToCheck.isFile() || fiToCheck.isDir() ) {
00238
00239 if ( !fiToCheck.isReadable() && wantItReadable ) {
00240
00241
00242 if ( stat( toCheckEnc,&statbuffer ) != 0 ) {
00243 kDebug(5321) << "wantItR: Can't read perms of" << toCheck;
00244 }
00245
00246
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
00257
00258 if ( stat( toCheckEnc,&statbuffer ) != 0 ) {
00259 kDebug(5321) << "wantItW: Can't read perms of" << toCheck;
00260 }
00261
00262
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
00272
00273 if ( fiToCheck.isDir() && recursive ){
00274 QDir g( toCheck );
00275
00276
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
00304
00305
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 );
00341 }
00342 return success;
00343 }
00344
00345
00346
00347 }