libtdepim

tdefileio.cpp
1// tdefileio.cpp
2// Author: Stefan Taferner <taferner@kde.org>
3// License: GPL
4
5#ifdef HAVE_CONFIG_H
6#include <config.h>
7#endif
8
9#include <tdemessagebox.h>
10#include <kdebug.h>
11
12#include <assert.h>
13#include <tqdir.h>
14
15#include <tdelocale.h>
16#include <kstdguiitem.h>
17
18#include <tqwidget.h>
19#include <tqfile.h>
20#include <tqfileinfo.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23
24#include <tdemacros.h>
25
26namespace KPIM {
27
28//-----------------------------------------------------------------------------
29static void msgDialog(const TQString &msg)
30{
31 KMessageBox::sorry(0, msg, i18n("File I/O Error"));
32}
33
34
35//-----------------------------------------------------------------------------
36TDE_EXPORT TQCString kFileToString(const TQString &aFileName, bool aEnsureNL, bool aVerbose)
37{
38 TQCString result;
39 TQFileInfo info(aFileName);
40 unsigned int readLen;
41 unsigned int len = info.size();
42 TQFile file(aFileName);
43
44 //assert(aFileName!=0);
45 if( aFileName.isEmpty() )
46 return "";
47
48 if (!info.exists())
49 {
50 if (aVerbose)
51 msgDialog(i18n("The specified file does not exist:\n%1").arg(aFileName));
52 return TQCString();
53 }
54 if (info.isDir())
55 {
56 if (aVerbose)
57 msgDialog(i18n("This is a folder and not a file:\n%1").arg(aFileName));
58 return TQCString();
59 }
60 if (!info.isReadable())
61 {
62 if (aVerbose)
63 msgDialog(i18n("You do not have read permissions "
64 "to the file:\n%1").arg(aFileName));
65 return TQCString();
66 }
67 if (len <= 0) return TQCString();
68
69 if (!file.open(IO_Raw|IO_ReadOnly))
70 {
71 if (aVerbose) switch(file.status())
72 {
73 case IO_ReadError:
74 msgDialog(i18n("Could not read file:\n%1").arg(aFileName));
75 break;
76 case IO_OpenError:
77 msgDialog(i18n("Could not open file:\n%1").arg(aFileName));
78 break;
79 default:
80 msgDialog(i18n("Error while reading file:\n%1").arg(aFileName));
81 }
82 return TQCString();
83 }
84
85 result.resize(len + (int)aEnsureNL + 1);
86 readLen = file.readBlock(result.data(), len);
87 if (aEnsureNL && result[len-1]!='\n')
88 {
89 result[len++] = '\n';
90 readLen++;
91 }
92 result[len] = '\0';
93
94 if (readLen < len)
95 {
96 TQString msg = i18n("Could only read %1 bytes of %2.")
97 .arg(readLen).arg(len);
98 msgDialog(msg);
99 return TQCString();
100 }
101
102 return result;
103}
104
105//-----------------------------------------------------------------------------
106#if 0 // unused
107TQByteArray kFileToBytes(const TQString &aFileName, bool aVerbose)
108{
109 TQByteArray result;
110 TQFileInfo info(aFileName);
111 unsigned int readLen;
112 unsigned int len = info.size();
113 TQFile file(aFileName);
114
115 //assert(aFileName!=0);
116 if( aFileName.isEmpty() )
117 return result;
118
119 if (!info.exists())
120 {
121 if (aVerbose)
122 msgDialog(i18n("The specified file does not exist:\n%1")
123 .arg(aFileName));
124 return result;
125 }
126 if (info.isDir())
127 {
128 if (aVerbose)
129 msgDialog(i18n("This is a folder and not a file:\n%1")
130 .arg(aFileName));
131 return result;
132 }
133 if (!info.isReadable())
134 {
135 if (aVerbose)
136 msgDialog(i18n("You do not have read permissions "
137 "to the file:\n%1").arg(aFileName));
138 return result;
139 }
140 if (len <= 0) return result;
141
142 if (!file.open(IO_Raw|IO_ReadOnly))
143 {
144 if (aVerbose) switch(file.status())
145 {
146 case IO_ReadError:
147 msgDialog(i18n("Could not read file:\n%1").arg(aFileName));
148 break;
149 case IO_OpenError:
150 msgDialog(i18n("Could not open file:\n%1").arg(aFileName));
151 break;
152 default:
153 msgDialog(i18n("Error while reading file:\n%1").arg(aFileName));
154 }
155 return result;
156 }
157
158 result.resize(len);
159 readLen = file.readBlock(result.data(), len);
160 kdDebug(5300) << TQString( "len %1" ).arg(len) << endl;
161
162 if (readLen < len)
163 {
164 TQString msg;
165 msg = i18n("Could only read %1 bytes of %2.")
166 .arg(readLen).arg(len);
167 msgDialog(msg);
168 return result;
169 }
170
171 return result;
172}
173#endif
174
175//-----------------------------------------------------------------------------
176TDE_EXPORT bool kBytesToFile(const char* aBuffer, int len,
177 const TQString &aFileName,
178 bool aAskIfExists, bool aBackup, bool aVerbose)
179{
180 // TODO: use KSaveFile
181 TQFile file(aFileName);
182 int writeLen, rc;
183
184 //assert(aFileName!=0);
185 if(aFileName.isEmpty())
186 return FALSE;
187
188 if (file.exists())
189 {
190 if (aAskIfExists)
191 {
192 TQString str;
193 str = i18n("File %1 exists.\nDo you want to replace it?")
194 .arg(aFileName);
195 rc = KMessageBox::warningContinueCancel(0,
196 str, i18n("Save to File"), i18n("&Replace"));
197 if (rc != KMessageBox::Continue) return FALSE;
198 }
199 if (aBackup)
200 {
201 // make a backup copy
202 // TODO: use KSaveFile::backupFile()
203 TQString bakName = aFileName;
204 bakName += '~';
205 TQFile::remove(bakName);
206 if( !TQDir::current().rename(aFileName, bakName) )
207 {
208 // failed to rename file
209 if (!aVerbose) return FALSE;
210 rc = KMessageBox::warningContinueCancel(0,
211 i18n("Failed to make a backup copy of %1.\nContinue anyway?")
212 .arg(aFileName),
213 i18n("Save to File"), KStdGuiItem::save() );
214 if (rc != KMessageBox::Continue) return FALSE;
215 }
216 }
217 }
218
219 if (!file.open(IO_Raw|IO_WriteOnly|IO_Truncate))
220 {
221 if (aVerbose) switch(file.status())
222 {
223 case IO_WriteError:
224 msgDialog(i18n("Could not write to file:\n%1").arg(aFileName));
225 break;
226 case IO_OpenError:
227 msgDialog(i18n("Could not open file for writing:\n%1")
228 .arg(aFileName));
229 break;
230 default:
231 msgDialog(i18n("Error while writing file:\n%1").arg(aFileName));
232 }
233 return FALSE;
234 }
235
236 writeLen = file.writeBlock(aBuffer, len);
237
238 if (writeLen < 0)
239 {
240 if (aVerbose)
241 msgDialog(i18n("Could not write to file:\n%1").arg(aFileName));
242 return FALSE;
243 }
244 else if (writeLen < len)
245 {
246 TQString msg = i18n("Could only write %1 bytes of %2.")
247 .arg(writeLen).arg(len);
248 if (aVerbose)
249 msgDialog(msg);
250 return FALSE;
251 }
252
253 return TRUE;
254}
255
256TDE_EXPORT bool kCStringToFile(const TQCString& aBuffer, const TQString &aFileName,
257 bool aAskIfExists, bool aBackup, bool aVerbose)
258{
259 return kBytesToFile(aBuffer, aBuffer.length(), aFileName, aAskIfExists,
260 aBackup, aVerbose);
261}
262
263TDE_EXPORT bool kByteArrayToFile(const TQByteArray& aBuffer, const TQString &aFileName,
264 bool aAskIfExists, bool aBackup, bool aVerbose)
265{
266 return kBytesToFile(aBuffer, aBuffer.size(), aFileName, aAskIfExists,
267 aBackup, aVerbose);
268}
269
270
271TQString checkAndCorrectPermissionsIfPossible( const TQString &toCheck,
272 const bool recursive, const bool wantItReadable,
273 const bool wantItWritable )
274{
275 // First we have to find out which type the toCheck is. This can be
276 // a directory (follow if recursive) or a file (check permissions).
277 // Symlinks are followed as expected.
278 TQFileInfo fiToCheck(toCheck);
279 fiToCheck.setCaching(false);
280 TQCString toCheckEnc = TQFile::encodeName(toCheck);
281 TQString error;
282 struct stat statbuffer;
283
284 if ( !fiToCheck.exists() ) {
285 error.append( i18n("%1 does not exist")
286 .arg(toCheck) + "\n");
287 }
288
289 // check the access bit of a folder.
290 if ( fiToCheck.isDir() ) {
291 if ( stat( toCheckEnc,&statbuffer ) != 0 ) {
292 kdDebug() << "wantItA: Can't read perms of " << toCheck << endl;
293 }
294 TQDir g( toCheck );
295 if ( !g.isReadable() ) {
296 if ( chmod( toCheckEnc, statbuffer.st_mode + S_IXUSR ) != 0 ) {
297 error.append( i18n("%1 is not accessible and that is "
298 "unchangeable.").arg(toCheck) + "\n");
299 } else {
300 kdDebug() << "Changed access bit for " << toCheck << endl;
301 }
302 }
303 }
304
305 // For each file or folder we can check if the file is readable
306 // and writable, as requested.
307 if ( fiToCheck.isFile() || fiToCheck.isDir() ) {
308
309 if ( !fiToCheck.isReadable() && wantItReadable ) {
310 // Get the current permissions. No need to do anything with an
311 // error, it will het added to errors anyhow, later on.
312 if ( stat(toCheckEnc,&statbuffer) != 0 ) {
313 kdDebug() << "wantItR: Can't read perms of " << toCheck << endl;
314 }
315
316 // Lets try changing it.
317 if ( chmod( toCheckEnc, statbuffer.st_mode + S_IRUSR ) != 0 ) {
318 error.append( i18n("%1 is not readable and that is unchangeable.")
319 .arg(toCheck) + "\n");
320 } else {
321 kdDebug() << "Changed the read bit for " << toCheck << endl;
322 }
323 }
324
325 if ( !fiToCheck.isWritable() && wantItWritable ) {
326 // Gets the current persmissions. Needed because it can be changed
327 // curing previous operation.
328 if (stat(toCheckEnc,&statbuffer) != 0) {
329 kdDebug() << "wantItW: Can't read perms of " << toCheck << endl;
330 }
331
332 // Lets try changing it.
333 if ( chmod (toCheckEnc, statbuffer.st_mode + S_IWUSR ) != 0 ) {
334 error.append( i18n("%1 is not writable and that is unchangeable.")
335 .arg(toCheck) + "\n");
336 } else {
337 kdDebug() << "Changed the write bit for " << toCheck << endl;
338 }
339 }
340 }
341
342 // If it is a folder and recursive is true, then we check the contents of
343 // the folder.
344 if ( fiToCheck.isDir() && recursive ){
345 TQDir g(toCheck);
346 // First check if the folder is readable for us. If not, we get
347 // some ugly crashes.
348 if ( !g.isReadable() ){
349 error.append(i18n("Folder %1 is inaccessible.").arg(toCheck) + "\n");
350 } else {
351 const TQFileInfoList *list = g.entryInfoList();
352 TQFileInfoListIterator it( *list );
353 TQFileInfo *fi;
354 while ((fi = it.current()) != 0) {
355 TQString newToCheck = toCheck + "/" + fi->fileName();
356 TQFileInfo fiNewToCheck(newToCheck);
357 if ( fi->fileName() != "." && fi->fileName() != ".." ) {
358 error.append ( checkAndCorrectPermissionsIfPossible( newToCheck,
359 recursive, wantItReadable, wantItWritable) );
360 }
361 ++it;
362 }
363 }
364 }
365 return error;
366}
367
369 const TQString &toCheck, const bool recursive, const bool wantItReadable,
370 const bool wantItWritable )
371{
372 TQString error = checkAndCorrectPermissionsIfPossible(toCheck, recursive,
373 wantItReadable, wantItWritable);
374 // There is no KMessageBox with Retry, Cancel and Details.
375 // so, I can't provide a functionality to recheck. So it now
376 // it is just a warning.
377 if ( !error.isEmpty() ) {
378 kdDebug() << "checkPermissions found:" << error << endl;
379 KMessageBox::detailedSorry(parent,
380 i18n("Some files or folders do not have "
381 "the right permissions, please correct them "
382 "manually."),
383 error, i18n("Permissions Check"), false);
384 return false;
385 } else {
386 return true;
387 }
388}
389
390}
TDEPIM classes for drag and drop of mails.
TDE_EXPORT bool kBytesToFile(const char *aBuffer, int len, const TQString &aFileName, bool aAskIfExists, bool aBackup, bool aVerbose)
Save a file.
Definition: tdefileio.cpp:176
TDE_EXPORT TQCString kFileToString(const TQString &aFileName, bool aEnsureNL, bool aVerbose)
Load a file.
Definition: tdefileio.cpp:36
TDE_EXPORT bool kByteArrayToFile(const TQByteArray &aBuffer, const TQString &aFileName, bool aAskIfExists, bool aBackup, bool aVerbose)
Does not stop at NUL.
Definition: tdefileio.cpp:263
bool checkAndCorrectPermissionsIfPossibleWithErrorHandling(TQWidget *parent, const TQString &toCheck, const bool recursive, const bool wantItReadable, const bool wantItWritable)
Checks and corrects the permissions of a file or folder, and if requested all files and folders below...
Definition: tdefileio.cpp:368
TQString checkAndCorrectPermissionsIfPossible(const TQString &toCheck, const bool recursive, const bool wantItReadable, const bool wantItWritable)
Checks and corrects the permissions of a file or folder, and if requested all files and folders below...
Definition: tdefileio.cpp:271