• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

kpimutils

  • sources
  • kde-4.14
  • kdepimlibs
  • kpimutils
kfileio.cpp
1 /*
2  Copyright (c) 2005 Tom Albers <tomalbers@kde.nl>
3  Copyright (c) 1997-1999 Stefan Taferner <taferner@kde.org>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 */
20 
21 #include "kfileio.h"
22 #include "kpimutils_export.h"
23 
24 #include <KDebug>
25 #include <KLocalizedString>
26 #include <KMessageBox>
27 #include <KStandardGuiItem>
28 #include <kde_file.h> //krazy:exclude=camelcase
29 
30 #include <QDir>
31 #include <QByteArray>
32 #include <QWidget>
33 #include <QFile>
34 #include <QFileInfo>
35 
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <assert.h>
39 
40 namespace KPIMUtils {
41 
42 //-----------------------------------------------------------------------------
43 static void msgDialog( const QString &msg )
44 {
45  KMessageBox::sorry( 0, msg, i18n( "File I/O Error" ) );
46 }
47 
48 //-----------------------------------------------------------------------------
49 QByteArray kFileToByteArray( const QString &aFileName, bool aEnsureNL,
50  bool aVerbose )
51 {
52  QByteArray result;
53  QFileInfo info( aFileName );
54  unsigned int readLen;
55  unsigned int len = info.size();
56  QFile file( aFileName );
57 
58  //assert(aFileName!=0);
59  if ( aFileName.isEmpty() ) {
60  return "";
61  }
62 
63  if ( !info.exists() ) {
64  if ( aVerbose ) {
65  msgDialog( i18n( "The specified file does not exist:\n%1", aFileName ) );
66  }
67  return QByteArray();
68  }
69  if ( info.isDir() ) {
70  if ( aVerbose ) {
71  msgDialog( i18n( "This is a folder and not a file:\n%1", aFileName ) );
72  }
73  return QByteArray();
74  }
75  if ( !info.isReadable() ) {
76  if ( aVerbose ) {
77  msgDialog( i18n( "You do not have read permissions to the file:\n%1", aFileName ) );
78  }
79  return QByteArray();
80  }
81  if ( len == 0 ) {
82  return QByteArray();
83  }
84 
85  if ( !file.open( QIODevice::Unbuffered|QIODevice::ReadOnly ) ) {
86  if ( aVerbose ) {
87  switch ( file.error() ) {
88  case QFile::ReadError:
89  msgDialog( i18n( "Could not read file:\n%1", aFileName ) );
90  break;
91  case QFile::OpenError:
92  msgDialog( i18n( "Could not open file:\n%1", aFileName ) );
93  break;
94  default:
95  msgDialog( i18n( "Error while reading file:\n%1", aFileName ) );
96  }
97  }
98  return QByteArray();
99  }
100 
101  result.resize( len + int( aEnsureNL ) );
102  readLen = file.read( result.data(), len );
103  if ( aEnsureNL ) {
104  if ( result[readLen-1] != '\n' ) {
105  result[readLen++] = '\n';
106  len++;
107  } else {
108  result.truncate( len );
109  }
110  }
111 
112  if ( readLen < len ) {
113  QString msg = i18np( "Could only read 1 byte of %2.",
114  "Could only read %1 bytes of %2.",
115  readLen, len );
116  msgDialog( msg );
117  result.truncate( readLen );
118  }
119 
120  return result;
121 }
122 
123 //-----------------------------------------------------------------------------
124 bool kByteArrayToFile( const QByteArray &aBuffer, const QString &aFileName,
125  bool aAskIfExists, bool aBackup, bool aVerbose )
126 {
127  // TODO: use KSaveFile
128  QFile file( aFileName );
129 
130  //assert(aFileName!=0);
131  if ( aFileName.isEmpty() ) {
132  return false;
133  }
134 
135  if ( file.exists() ) {
136  if ( aAskIfExists ) {
137  QString str;
138  str = i18n( "File %1 exists.\nDo you want to replace it?", aFileName );
139  const int rc =
140  KMessageBox::warningContinueCancel( 0, str, i18n( "Save to File" ),
141  KGuiItem( i18n( "&Replace" ) ) );
142  if ( rc != KMessageBox::Continue ) {
143  return false;
144  }
145  }
146  if ( aBackup ) {
147  // make a backup copy
148  // TODO: use KSaveFile::backupFile()
149  QString bakName = aFileName;
150  bakName += QLatin1Char('~');
151  QFile::remove( bakName );
152  if ( !QDir::current().rename( aFileName, bakName ) ) {
153  // failed to rename file
154  if ( !aVerbose ) {
155  return false;
156  }
157  const int rc =
158  KMessageBox::warningContinueCancel(
159  0,
160  i18n( "Failed to make a backup copy of %1.\nContinue anyway?", aFileName ),
161  i18n( "Save to File" ), KStandardGuiItem::save() );
162 
163  if ( rc != KMessageBox::Continue ) {
164  return false;
165  }
166  }
167  }
168  }
169 
170  if ( !file.open( QIODevice::Unbuffered|QIODevice::WriteOnly|QIODevice::Truncate ) ) {
171  if ( aVerbose ) {
172  switch ( file.error() ) {
173  case QFile::WriteError:
174  msgDialog( i18n( "Could not write to file:\n%1", aFileName ) );
175  break;
176  case QFile::OpenError:
177  msgDialog( i18n( "Could not open file for writing:\n%1", aFileName ) );
178  break;
179  default:
180  msgDialog( i18n( "Error while writing file:\n%1", aFileName ) );
181  }
182  }
183  return false;
184  }
185 
186  const int writeLen = file.write( aBuffer.data(), aBuffer.size() );
187 
188  if ( writeLen < 0 ) {
189  if ( aVerbose ) {
190  msgDialog( i18n( "Could not write to file:\n%1", aFileName ) );
191  }
192  return false;
193  } else if ( writeLen < aBuffer.size() ) {
194  QString msg = i18np( "Could only write 1 byte of %2.",
195  "Could only write %1 bytes of %2.",
196  writeLen, aBuffer.size() );
197  if ( aVerbose ) {
198  msgDialog( msg );
199  }
200  return false;
201  }
202 
203  return true;
204 }
205 
206 QString checkAndCorrectPermissionsIfPossible( const QString &toCheck,
207  const bool recursive,
208  const bool wantItReadable,
209  const bool wantItWritable )
210 {
211  // First we have to find out which type the toCheck is. This can be
212  // a directory (follow if recursive) or a file (check permissions).
213  // Symlinks are followed as expected.
214  QFileInfo fiToCheck( toCheck );
215  fiToCheck.setCaching( false );
216  QByteArray toCheckEnc = QFile::encodeName( toCheck );
217  QString error;
218  KDE_struct_stat statbuffer;
219 
220  if ( !fiToCheck.exists() ) {
221  error.append( i18n( "%1 does not exist", toCheck ) + QLatin1Char('\n') );
222  }
223 
224  // check the access bit of a folder.
225  if ( fiToCheck.isDir() ) {
226  if ( KDE_stat( toCheckEnc, &statbuffer ) != 0 ) {
227  kDebug() << "wantItA: Can't read perms of" << toCheck;
228  }
229  QDir g( toCheck );
230  if ( !g.isReadable() ) {
231  if ( chmod( toCheckEnc, statbuffer.st_mode + S_IXUSR ) != 0 ) {
232  error.append( i18n( "%1 is not accessible and that is "
233  "unchangeable.", toCheck ) + QLatin1Char('\n') );
234  } else {
235  kDebug() << "Changed access bit for" << toCheck;
236  }
237  }
238  }
239 
240  // For each file or folder we can check if the file is readable
241  // and writable, as requested.
242  if ( fiToCheck.isFile() || fiToCheck.isDir() ) {
243 
244  if ( !fiToCheck.isReadable() && wantItReadable ) {
245  // Get the current permissions. No need to do anything with an
246  // error, it will het added to errors anyhow, later on.
247  if ( KDE_stat( toCheckEnc, &statbuffer ) != 0 ) {
248  kDebug() << "wantItR: Can't read perms of" << toCheck;
249  }
250 
251  // Lets try changing it.
252  if ( chmod( toCheckEnc, statbuffer.st_mode + S_IRUSR ) != 0 ) {
253  error.append( i18n( "%1 is not readable and that is unchangeable.",
254  toCheck ) + QLatin1Char('\n') );
255  } else {
256  kDebug() << "Changed the read bit for" << toCheck;
257  }
258  }
259 
260  if ( !fiToCheck.isWritable() && wantItWritable ) {
261  // Gets the current persmissions. Needed because it can be changed
262  // curing previous operation.
263  if ( KDE_stat( toCheckEnc, &statbuffer ) != 0 ) {
264  kDebug() << "wantItW: Can't read perms of" << toCheck;
265  }
266 
267  // Lets try changing it.
268  if ( chmod ( toCheckEnc, statbuffer.st_mode + S_IWUSR ) != 0 ) {
269  error.append( i18n( "%1 is not writable and that is unchangeable.", toCheck ) + QLatin1Char('\n') );
270  } else {
271  kDebug() << "Changed the write bit for" << toCheck;
272  }
273  }
274  }
275 
276  // If it is a folder and recursive is true, then we check the contents of
277  // the folder.
278  if ( fiToCheck.isDir() && recursive ) {
279  QDir g( toCheck );
280  // First check if the folder is readable for us. If not, we get
281  // some ugly crashes.
282  if ( !g.isReadable() ) {
283  error.append( i18n( "Folder %1 is inaccessible.", toCheck ) + QLatin1Char('\n') );
284  } else {
285  foreach ( const QFileInfo &fi, g.entryInfoList() ) {
286  QString newToCheck = toCheck + QLatin1Char('/') + fi.fileName();
287  if ( fi.fileName() != QLatin1String(".") && fi.fileName() != QLatin1String("..") ) {
288  error.append (
289  checkAndCorrectPermissionsIfPossible( newToCheck, recursive,
290  wantItReadable, wantItWritable ) );
291  }
292  }
293  }
294  }
295  return error;
296 }
297 
298 bool checkAndCorrectPermissionsIfPossibleWithErrorHandling( QWidget *parent,
299  const QString &toCheck,
300  const bool recursive,
301  const bool wantItReadable,
302  const bool wantItWritable )
303 {
304  QString error =
305  checkAndCorrectPermissionsIfPossible( toCheck, recursive, wantItReadable, wantItWritable );
306 
307  // There is no KMessageBox with Retry, Cancel and Details.
308  // so, I can't provide a functionality to recheck. So it now
309  // it is just a warning.
310  if ( !error.isEmpty() ) {
311  kDebug() << "checkPermissions found:" << error;
312  KMessageBox::detailedSorry( parent,
313  i18n( "Some files or folders do not have the "
314  "necessary permissions, please correct "
315  "them manually." ),
316  error, i18n( "Permissions Check" ), 0 );
317  return false;
318  } else {
319  return true;
320  }
321 }
322 
323 bool removeDirAndContentsRecursively( const QString & path )
324 {
325  bool success = true;
326 
327  QDir d;
328  d.setPath( path );
329  d.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );
330 
331  QFileInfoList list = d.entryInfoList();
332 
333  Q_FOREACH ( const QFileInfo &fi, list ) {
334  if ( fi.isDir() ) {
335  if ( fi.fileName() != QLatin1String(".") && fi.fileName() != QLatin1String("..") ) {
336  success = success && removeDirAndContentsRecursively( fi.absoluteFilePath() );
337  }
338  } else {
339  success = success && d.remove( fi.absoluteFilePath() );
340  }
341  }
342 
343  if ( success ) {
344  success = success && d.rmdir( path ); // nuke ourselves, we should be empty now
345  }
346  return success;
347 }
348 
349 }
QWidget
QString::append
QString & append(QChar ch)
QByteArray
QFile::remove
bool remove()
QDir::remove
bool remove(const QString &fileName)
QFile
QByteArray::resize
void resize(int size)
QDir::setFilter
void setFilter(QFlags< QDir::Filter > filters)
QDir::rmdir
bool rmdir(const QString &dirName) const
QFileInfo::isDir
bool isDir() const
QFileInfo::fileName
QString fileName() const
QDir::entryInfoList
QFileInfoList entryInfoList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
QFileInfo::absoluteFilePath
QString absoluteFilePath() const
QString::isEmpty
bool isEmpty() const
QByteArray::truncate
void truncate(int pos)
QString
QFileInfo
QLatin1Char
QDir
QLatin1String
QByteArray::data
char * data()
QDir::current
QDir current()
QByteArray::size
int size() const
QDir::setPath
void setPath(const QString &path)
QFile::encodeName
QByteArray encodeName(const QString &fileName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:25 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kpimutils

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

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal