1/***************************************************************************
2 kfilereplacelib.cpp - File library
3 -------------------
4 begin : lun mai 3 20:19:52 CEST 1999
5
6 copyright : (C) 1999 by François Dupoux
7 (C) 2003 Andras Mantia <amantia@kde.org>
8 (C) 2004 Emiliano Gulmini <emi_barbarossa@yahoo.it>
9 email : dupoux@dupoux.com
10
11 ***************************************************************************/
12
13/***************************************************************************
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 ***************************************************************************/
21
22//QT
23#include <qstringlist.h>
24#include <qwidget.h>
25#include <q3listview.h>
26#include <qfileinfo.h>
27#include <qpixmap.h>
28
29//KDE
30#include <kdebug.h>
31#include <kmessagebox.h>
32#include <k3listview.h>
33#include <kiconloader.h>
34
35//needed for malloc/free
36#include <stdlib.h>
37
38// local
39#include "kfilereplacelib.h"
40
41/**
42 Format a path, from a path and a filename, or another sub-path (avoid double '/' risks)
43 Parameters::.....* basePath: fist path (can be "/" if root, or "/usr/bin/" or "/usr/bin" for example)
44 .................* fileName: second path (can be "/doc/html/", or "doc/html/" or "doc/html/index.html" for example)
45 Return values:...* Full valid path (without double "/")
46*/
47QString KFileReplaceLib::formatFullPath(const QString& basePath, const QString &fileName)
48{
49 QString fullPath = basePath;
50 QString fname = fileName;
51
52 if (fname.startsWith('/')) // skip beginning '/'
53 fname = fname.remove(0,1);
54
55 if (fullPath.endsWith('/'))
56 fullPath.append(fname);
57 else
58 fullPath.append('/'+fname);
59
60 return fullPath;
61}
62
63/**
64 Add an extension to a filename, or a filepath
65 Parameters::.....* fileName: filename or filepath (it can have already the extension)
66 .................* extension: extension to add without "." (ex: "html", "kfr")
67 Return values:...* Filename / Filepath with the extension
68*/
69QString KFileReplaceLib::addExtension(const QString& fileName, const QString& extension)
70{
71 QString fullExtension = ".";
72 QString fname = fileName;
73
74 fullExtension.append(extension);
75
76 // filename cannot contain ".ext" ==> Add it
77 if(fname.length() <= fullExtension.length())
78 fname.append(fullExtension);
79 else // filename can contain ".ext"
80 {
81 if (fname.right(fullExtension.length()) != fullExtension)
82 fname.append(fullExtension);
83 }
84
85 return fname;
86}
87
88QString KFileReplaceLib::formatFileSize(double size)
89{
90 QString stringSize;
91
92 if(size < 10000)
93 {
94 const int asInt = (int) size;
95 stringSize = i18np("1 byte", "%1 bytes", asInt);
96 }
97 else
98 {
99 stringSize = KGlobal::locale()->formatByteSize(size, 2);
100 }
101 return stringSize;
102}
103
104void KFileReplaceLib::convertOldToNewKFRFormat(const QString& fileName, K3ListView* stringView)
105{
106 //this method convert old format in new XML-based format
107 typedef struct
108 {
109 char pgm[13]; // Must be "KFileReplace" : like MZ for EXE files
110 int stringNumber; // Number of strings in file
111 char reserved[64]; // Reserved for future use
112 } KFRHeader;
113
114 KFRHeader head;
115
116 FILE* f = fopen(QFile::encodeName(fileName),"rb");
117 int err = fread(&head, sizeof(KFRHeader), 1, f);
118 QString pgm(head.pgm);
119
120 if(!f || (err != 1) || (pgm != "KFileReplace"))
121 {
122 KMessageBox::error(0, i18n("<qt>Cannot open the file <b>%1</b> and load the string list. This file seems not to be a valid old kfr file or it is broken.</qt>", fileName));
123 return ;
124 }
125
126 stringView->clear();
127
128 int oldTextSize,
129 newTextSize,
130 errors = 0,
131 stringSize;
132 QStringList l;
133
134 int i ;
135 for (i=0; i < head.stringNumber; i++)
136 {
137 errors += (fread(&oldTextSize, sizeof(int), 1, f)) != 1;
138 errors += (fread(&newTextSize, sizeof(int), 1, f)) != 1;
139 if(errors > 0)
140 KMessageBox::error(0, i18n("Cannot read data."));
141 else
142 {
143 stringSize = ((oldTextSize > newTextSize) ? oldTextSize : newTextSize) + 2;
144 char* oldString = (char*) malloc(stringSize+10),
145 * newString = (char*) malloc(stringSize+10);
146 if (oldString == 0 || newString == 0)
147 KMessageBox::error(0, i18n("Out of memory."));
148 else
149 {
150 memset(oldString, 0, stringSize);
151 memset(newString,0, stringSize);
152
153 if (fread(oldString, oldTextSize, 1, f) != 1)
154 KMessageBox::error(0, i18n("Cannot read data."));
155 else
156 {
157 if (newTextSize > 0) // If there is a Replace text
158 {
159 if (fread(newString, newTextSize, 1, f) != 1)
160 KMessageBox::error(0, i18n("Cannot read data."));
161 else
162 {
163 Q3ListViewItem* lvi = new Q3ListViewItem(stringView);
164 lvi->setText(0,oldString);
165 lvi->setText(1,newString);
166
167 }
168 }
169 }
170 }
171 if(newString)
172 free(newString);
173 if(oldString)
174 free(oldString);
175 }
176 }
177 fclose(f);
178 return ;
179 }
180
181bool KFileReplaceLib::isAnAccessibleFile(const QString& filePath, const QString& fileName, RCOptions* info)
182{
183 QString bkExt = info->m_backupExtension;
184 if(fileName == ".." || fileName == "." || (!bkExt.isEmpty() && fileName.right(bkExt.length()) == bkExt))
185 return false;
186
187 QFileInfo fi;
188 if(filePath.isEmpty())
189 fi.setFile(fileName);
190 else
191 fi.setFile(filePath+'/'+fileName);
192
193 if(fi.isDir())
194 return true;
195
196 int minSize = info->m_minSize,
197 maxSize = info->m_maxSize;
198 QString minDate = info->m_minDate,
199 maxDate = info->m_maxDate,
200 dateAccess = info->m_dateAccess;
201
202 // Avoid files that not match access date requirements
203 QString last = "unknown";
204 if(dateAccess == "Last Writing Access")
205 last = fi.lastModified().toString(Qt::ISODate);
206 if(dateAccess == "Last Reading Access")
207 last = fi.lastRead().toString(Qt::ISODate);
208
209 if(last != "unknown")
210 {
211 if(minDate != "unknown" && maxDate != "unknown")
212 { //If out of range then exit
213 if((minDate > last) || (maxDate < last))
214 return false;
215 }
216 else
217 {
218 if(minDate != "unknown")
219 { //If out of range then exit
220 if(minDate > last)
221 return false;
222 }
223 else
224 {
225 if(maxDate != "unknown")
226 //If out of range then exit
227 if(maxDate < last)
228 return false;
229 }
230 }
231 }
232 // Avoid files that not match size requirements
233 int size = fi.size();
234 if(maxSize != FileSizeOption && minSize != FileSizeOption)
235 if(size > (maxSize*1024) || size < (minSize*1024))
236 return false;
237
238 // Avoid files that not match ownership requirements
239 if(info->m_ownerUserIsChecked)
240 {
241 QString fileOwnerUser;
242 if(info->m_ownerUserType == "Name")
243 fileOwnerUser = fi.owner();
244 else
245 fileOwnerUser = QString::number(fi.ownerId(),10);
246
247 if(info->m_ownerUserBool == "Equals To")
248 {
249 if(info->m_ownerUserValue != fileOwnerUser)
250 return false;
251 }
252 else
253 {
254 if(info->m_ownerUserValue == fileOwnerUser)
255 return false;
256 }
257 }
258
259 if(info->m_ownerGroupIsChecked)
260 {
261 QString fileOwnerGroup;
262 if(info->m_ownerGroupType == "Name")
263 fileOwnerGroup = fi.group();
264 else
265 fileOwnerGroup = QString::number(fi.groupId(),10);
266 if(info->m_ownerGroupBool == "Equals To")
267 {
268 if(info->m_ownerGroupValue != fileOwnerGroup)
269 return false;
270 }
271 else
272 {
273 if(info->m_ownerGroupValue == fileOwnerGroup)
274 return false;
275 }
276 }
277
278 //If we are here then all requirements have been verified
279 return true;
280}
281
282void KFileReplaceLib::setIconForFileEntry(Q3ListViewItem* item, const QString &path)
283{
284 QFileInfo fi(path);
285 QString extension = fi.completeSuffix(),
286 baseName = fi.baseName();
287
288 KeyValueMap extensionMap;
289
290 extensionMap["a"] = "binary";
291 extensionMap["am"] = "shellscript";
292 extensionMap["bz"] = "zip";
293 extensionMap["bz2"] = "zip";
294 extensionMap["c"] = "source_c";
295 extensionMap["cc"] = "source_cpp";
296 extensionMap["cpp"] = "source_cpp";
297 extensionMap["eml"] = "message";
298 extensionMap["exe"] = "exec_wine";
299 extensionMap["gz"] = "zip";
300 extensionMap["h"] = "source_h";
301 extensionMap["htm"] = "html";
302 extensionMap["html"] = "html";
303 extensionMap["in"] = "shellscript";
304 extensionMap["java"] = "source_java";
305 extensionMap["jpg"] = "image";
306 extensionMap["kfr"] = "html";
307 extensionMap["kmdr"] = "widget_doc";
308 extensionMap["kwd"] = "kword_kwd";
309 extensionMap["log"] = "log";
310 extensionMap["moc"] = "source_moc";
311 extensionMap["mp3"] = "sound";
312 extensionMap["o"] = "source_o";
313 extensionMap["pdf"] = "pdf";
314 extensionMap["php"] = "source_php";
315 extensionMap["py"] = "source_py";
316 extensionMap["pl"] = "source_pl";
317 extensionMap["p"] = "source_p";
318 extensionMap["ps"] = "postscript";
319 extensionMap["png"] = "image";
320 extensionMap["sa"] = "binary";
321 extensionMap["sh"] = "shellscript";
322 extensionMap["so"] = "binary";
323 extensionMap["tar"] = "tar";
324 extensionMap["tex"] = "tex";
325 extensionMap["tgz"] = "tgz";
326 extensionMap["txt"] = "txt";
327 extensionMap["ui"] = "widget_doc";
328 extensionMap["uml"] = "umbrellofile";
329 extensionMap["wav"] = "sound";
330 extensionMap["xml"] = "html";
331 extensionMap["xpm"] = "image";
332
333 KeyValueMap::Iterator itExtensionMap;
334
335 for(itExtensionMap = extensionMap.begin(); itExtensionMap != extensionMap.end(); ++itExtensionMap)
336 {
337 if(extension == itExtensionMap.key())
338 {
339 item->setPixmap(0,SmallIcon(itExtensionMap.data()));
340 return;
341 }
342 }
343
344 KeyValueMap baseNameMap;
345
346 baseNameMap["configure"] = "shellscript";
347 baseNameMap["core"] = "core";
348 baseNameMap["makefile"] = "make";
349 baseNameMap["readme"] = "readme";
350 baseNameMap["README"] = "readme";
351 baseNameMap["Readme"] = "readme";
352 baseNameMap["TODO"] = "txt";
353
354 KeyValueMap::Iterator itBaseNameMap;
355
356 for(itBaseNameMap = baseNameMap.begin(); itBaseNameMap != baseNameMap.end(); ++itBaseNameMap)
357 {
358 if(baseName == itBaseNameMap.key())
359 {
360 item->setPixmap(0,SmallIcon(itBaseNameMap.data()));
361 return;
362 }
363 }
364}
365