2
* KHelper - KDE Font Installer
4
* Copyright 2003-2010 Craig Drummond <craig@kde.org>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; see the file COPYING. If not, write to
20
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
* Boston, MA 02110-1301, USA.
30
#include <QtXml/QDomDocument>
31
#include <kio/global.h>
33
#include <sys/types.h>
36
#include <sys/errno.h>
38
#define KFI_DBUG kDebug() << time(0L)
40
KDE4_AUTH_HELPER_MAIN("org.kde.fontinst", KFI::Helper)
45
static Folder theFontFolder;
47
typedef void (*SignalHandler)(int);
49
static void registerSignalHandler(SignalHandler handler)
58
signal(SIGSEGV, handler);
59
sigaddset(&mask, SIGSEGV);
62
signal(SIGFPE, handler);
63
sigaddset(&mask, SIGFPE);
66
signal(SIGILL, handler);
67
sigaddset(&mask, SIGILL);
70
signal(SIGABRT, handler);
71
sigaddset(&mask, SIGABRT);
74
sigprocmask(SIG_UNBLOCK, &mask, 0);
77
static void signalHander(int)
79
registerSignalHandler(0L);
80
theFontFolder.saveDisabled();
81
registerSignalHandler(signalHander);
86
theFontFolder.saveDisabled();
92
registerSignalHandler(signalHander);
93
qAddPostRoutine(cleanup);
94
theFontFolder.init(true, true);
95
theFontFolder.loadDisabled();
100
theFontFolder.saveDisabled();
103
ActionReply Helper::manage(const QVariantMap &args)
105
int result=KIO::ERR_UNSUPPORTED_ACTION;
106
QString method=args["method"].toString();
110
if("install"==method)
111
result=install(args);
112
else if("uninstall"==method)
113
result=uninstall(args);
114
else if("move"==method)
116
else if("toggle"==method)
118
else if("removeFile"==method)
119
result=removeFile(args);
120
else if("reconfigure"==method)
121
result=reconfigure();
122
else if("saveDisabled"==method)
123
result=saveDisabled();
125
KFI_DBUG << "Uknown action";
127
if(FontInst::STATUS_OK==result)
128
return ActionReply::SuccessReply;
130
ActionReply reply(ActionReply::HelperError);
131
reply.setErrorCode(result);
135
int Helper::install(const QVariantMap &args)
137
QString file(args["file"].toString()),
138
name(args["name"].toString()),
139
destFolder(args["destFolder"].toString());
140
bool createAfm(args["createAfm"].toBool());
141
int type(args["type"].toInt());
143
KFI_DBUG << file << destFolder << name << createAfm;
145
int result=FontInst::STATUS_OK;
147
if(!Misc::dExists(destFolder))
148
result=Misc::createDir(destFolder) ? (int)FontInst::STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
150
if(FontInst::STATUS_OK==result)
151
result=QFile::copy(file, destFolder+name) ? (int)FontInst::STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
153
if(FontInst::STATUS_OK==result)
155
Misc::setFilePerms(QFile::encodeName(destFolder+name));
156
if((Utils::FILE_SCALABLE==type || Utils::FILE_PFM==type) && createAfm)
157
Utils::createAfm(destFolder+name, (KFI::Utils::EFileType)type);
158
theFontFolder.addModifiedDir(destFolder);
164
int Helper::uninstall(const QVariantMap &args)
166
QStringList files(args["files"].toStringList());
167
int result=checkWriteAction(files);
169
if(FontInst::STATUS_OK==result)
171
QStringList::ConstIterator it(files.constBegin()),
172
end(files.constEnd());
175
if(!Misc::fExists(*it) || QFile::remove(*it))
177
// Also remove any AFM or PFM files...
179
Misc::getAssociatedFiles(*it, other);
180
QStringList::ConstIterator oit(other.constBegin()),
181
oend(other.constEnd());
182
for(; oit!=oend; ++oit)
185
theFontFolder.addModifiedDir(Misc::getDir(*it));
192
static bool renameFontFile(const QString &from, const QString &to, int uid=-1, int gid=-1)
194
if(!QFile::rename(from, to))
197
QByteArray dest(QFile::encodeName(to));
199
Misc::setFilePerms(dest);
200
if(-1!=uid && -1!=gid)
201
::chown(dest.data(), uid, gid);
205
int Helper::move(const QVariantMap &args)
207
QStringList files(args["files"].toStringList());
208
bool toSystem(args["toSystem"].toBool());
209
QString dest(args["dest"].toString());
210
int uid(args["uid"].toInt()),
211
gid(args["gid"].toInt());
213
KFI_DBUG << files << dest << toSystem;
215
int result=FontInst::STATUS_OK;
216
QStringList::ConstIterator it(files.constBegin()),
217
end(files.constEnd());
219
// Cant move hidden fonts - need to unhide first.
220
for(; it!=end && FontInst::STATUS_OK==result; ++it)
221
if(Misc::isHidden(Misc::getFile(*it)))
222
result=KIO::ERR_UNSUPPORTED_ACTION;
224
if(FontInst::STATUS_OK==result)
226
QHash<QString, QString> movedFiles;
227
int toUid=toSystem ? getuid() : uid,
228
fromUid=toSystem ? uid : getuid(),
229
toGid=toSystem ? getgid() : gid,
230
fromGid=toSystem ? gid : getgid();
233
for(it=files.constBegin(); it!=end && FontInst::STATUS_OK==result; ++it)
235
QString name(Utils::modifyName(Misc::getFile(*it))),
236
destFolder(Utils::getDestFolder(dest, name));
238
if(!Misc::dExists(destFolder))
240
result=Misc::createDir(destFolder) ? (int)FontInst::STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
241
if(FontInst::STATUS_OK==result)
242
::chown(QFile::encodeName(destFolder).data(), toUid, toGid);
245
if(renameFontFile(*it, destFolder+name, toUid, toGid))
247
movedFiles[*it]=destFolder+name;
248
// Now try to move an associated AFM or PFM files...
251
Misc::getAssociatedFiles(*it, assoc);
253
QStringList::ConstIterator ait(assoc.constBegin()),
254
aend(assoc.constEnd());
256
for(; ait!=aend && FontInst::STATUS_OK==result; ++ait)
258
name=Misc::getFile(*ait);
259
if(renameFontFile(*ait, destFolder+name, toUid, toGid))
260
movedFiles[*ait]=destFolder+name;
262
result=KIO::ERR_WRITE_ACCESS_DENIED;
266
result=KIO::ERR_WRITE_ACCESS_DENIED;
269
if(FontInst::STATUS_OK!=result) // un-move fonts!
271
QHash<QString, QString>::ConstIterator it(movedFiles.constBegin()),
272
end(movedFiles.constEnd());
275
renameFontFile(it.value(), it.key(), fromUid, fromGid);
281
int Helper::toggle(const QVariantMap &args)
284
doc.setContent(args["xml"].toString());
285
Family font(doc.documentElement(), true);
286
bool enable(args["enable"].toBool());
288
KFI_DBUG << font.name() << enable;
290
if(1!=font.styles().count())
291
return KIO::ERR_WRITE_ACCESS_DENIED;
293
int result=FontInst::STATUS_OK;
294
FileCont files((*font.styles().begin()).files()),
296
FileCont::ConstIterator it(files.constBegin()),
297
end(files.constEnd());
298
QHash<File, QString> movedFonts;
299
QHash<QString, QString> movedAssoc;
300
QSet<QString> modifiedDirs;
302
for(; it!=end && FontInst::STATUS_OK==result; ++it)
304
QString to=Misc::getDir((*it).path())+
305
QString(enable ? Misc::unhide(Misc::getFile((*it).path()))
306
: Misc::hide(Misc::getFile((*it).path())));
310
KFI_DBUG << "MOVE:" << (*it).path() << " to " << to;
311
if(renameFontFile((*it).path(), to))
313
modifiedDirs.insert(Misc::getDir(enable ? to : (*it).path()));
314
toggledFiles.insert(File(to, (*it).foundry(), (*it).index()));
315
// Now try to move an associated AFM or PFM files...
319
Misc::getAssociatedFiles((*it).path(), assoc);
321
QStringList::ConstIterator ait(assoc.constBegin()),
322
aend(assoc.constEnd());
324
for(; ait!=aend && FontInst::STATUS_OK==result; ++ait)
326
to=Misc::getDir(*ait)+
327
QString(enable ? Misc::unhide(Misc::getFile(*ait))
328
: Misc::hide(Misc::getFile(*ait)));
331
if(renameFontFile(*ait, to))
334
result=KIO::ERR_WRITE_ACCESS_DENIED;
339
result=KIO::ERR_WRITE_ACCESS_DENIED;
343
theFontFolder.addModifiedDirs(modifiedDirs);
345
if(FontInst::STATUS_OK==result)
347
FamilyCont::ConstIterator f=theFontFolder.fonts().find(font);
349
if(theFontFolder.fonts().end()==f)
350
f=theFontFolder.addFont(font);
352
StyleCont::ConstIterator st=(*f).styles().find(*font.styles().begin());
354
if((*f).styles().end()==st)
355
st=(*f).add(*font.styles().begin());
357
// This helper only needs to store list of disabled fonts,
358
// for writing back to disk - therefore no need to store
359
// list of enabled font files.
361
(*st).setFiles(enable ? empty : toggledFiles);
362
if((*st).files().isEmpty())
364
if((*f).styles().isEmpty())
365
theFontFolder.removeFont(*f);
366
theFontFolder.setDisabledDirty();
370
QHash<File, QString>::ConstIterator fit(movedFonts.constBegin()),
371
fend(movedFonts.constEnd());
372
QHash<QString, QString>::ConstIterator ait(movedAssoc.constBegin()),
373
aend(movedAssoc.constEnd());
375
for(; fit!=fend; ++fit)
376
renameFontFile(fit.value(), fit.key().path());
377
for(; ait!=aend; ++ait)
378
renameFontFile(ait.value(), ait.key());
384
int Helper::removeFile(const QVariantMap &args)
386
QString file(args["file"].toString());
390
QString dir(Misc::getDir(file));
391
int result=Misc::fExists(file)
392
? QFile::remove(file)
393
? (int)FontInst::STATUS_OK
394
: (int)KIO::ERR_WRITE_ACCESS_DENIED
395
: (int)KIO::ERR_DOES_NOT_EXIST;
397
if(FontInst::STATUS_OK==result)
398
theFontFolder.addModifiedDir(dir);
403
int Helper::reconfigure()
408
KFI_DBUG << theFontFolder.isModified();
409
if(theFontFolder.isModified())
410
theFontFolder.configure();
411
return FontInst::STATUS_OK;
414
int Helper::saveDisabled()
417
// Load internally calls save!
418
theFontFolder.loadDisabled();
419
return FontInst::STATUS_OK;
422
int Helper::checkWriteAction(const QStringList &files)
424
QStringList::ConstIterator it(files.constBegin()),
425
end(files.constEnd());
428
if(!Misc::dWritable(Misc::getDir(*it)))
429
return KIO::ERR_WRITE_ACCESS_DENIED;
430
return FontInst::STATUS_OK;