~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kcontrol/kfontinst/dbus/Helper.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * KHelper - KDE Font Installer
 
3
 *
 
4
 * Copyright 2003-2010 Craig Drummond <craig@kde.org>
 
5
 *
 
6
 * ----
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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.
 
22
 */
 
23
 
 
24
#include "Helper.h"
 
25
#include "Folder.h"
 
26
#include "FontInst.h"
 
27
#include "Misc.h"
 
28
#include "Utils.h"
 
29
#include <KDE/KDebug>
 
30
#include <QtXml/QDomDocument>
 
31
#include <kio/global.h>
 
32
#include <kde_file.h>
 
33
#include <sys/types.h>
 
34
#include <unistd.h>
 
35
#include <signal.h>
 
36
#include <sys/errno.h>
 
37
 
 
38
#define KFI_DBUG kDebug() << time(0L)
 
39
 
 
40
KDE4_AUTH_HELPER_MAIN("org.kde.fontinst", KFI::Helper)
 
41
 
 
42
namespace KFI
 
43
{
 
44
 
 
45
static Folder theFontFolder;
 
46
 
 
47
typedef void (*SignalHandler)(int);
 
48
 
 
49
static void registerSignalHandler(SignalHandler handler)
 
50
{
 
51
    if (!handler)
 
52
        handler = SIG_DFL;
 
53
 
 
54
    sigset_t mask;
 
55
    sigemptyset(&mask);
 
56
 
 
57
#ifdef SIGSEGV
 
58
    signal(SIGSEGV, handler);
 
59
    sigaddset(&mask, SIGSEGV);
 
60
#endif
 
61
#ifdef SIGFPE
 
62
    signal(SIGFPE, handler);
 
63
    sigaddset(&mask, SIGFPE);
 
64
#endif
 
65
#ifdef SIGILL
 
66
    signal(SIGILL, handler);
 
67
    sigaddset(&mask, SIGILL);
 
68
#endif
 
69
#ifdef SIGABRT
 
70
    signal(SIGABRT, handler);
 
71
    sigaddset(&mask, SIGABRT);
 
72
#endif
 
73
 
 
74
    sigprocmask(SIG_UNBLOCK, &mask, 0);
 
75
}
 
76
 
 
77
static void signalHander(int)
 
78
{
 
79
    registerSignalHandler(0L);
 
80
    theFontFolder.saveDisabled();
 
81
    registerSignalHandler(signalHander);
 
82
}
 
83
 
 
84
static void cleanup()
 
85
{
 
86
    theFontFolder.saveDisabled();
 
87
}
 
88
 
 
89
Helper::Helper()
 
90
{
 
91
    KFI_DBUG;
 
92
    registerSignalHandler(signalHander);
 
93
    qAddPostRoutine(cleanup);
 
94
    theFontFolder.init(true, true);
 
95
    theFontFolder.loadDisabled();
 
96
}
 
97
 
 
98
Helper::~Helper()
 
99
{
 
100
    theFontFolder.saveDisabled();
 
101
}
 
102
 
 
103
ActionReply Helper::manage(const QVariantMap &args)
 
104
{
 
105
    int result=KIO::ERR_UNSUPPORTED_ACTION;
 
106
    QString method=args["method"].toString();
 
107
 
 
108
    KFI_DBUG << method;
 
109
 
 
110
    if("install"==method)
 
111
        result=install(args);
 
112
    else if("uninstall"==method)
 
113
        result=uninstall(args);
 
114
    else if("move"==method)
 
115
        result=move(args);
 
116
    else if("toggle"==method)
 
117
        result=toggle(args);
 
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();
 
124
    else
 
125
        KFI_DBUG << "Uknown action";
 
126
 
 
127
    if(FontInst::STATUS_OK==result)
 
128
        return ActionReply::SuccessReply;
 
129
 
 
130
    ActionReply reply(ActionReply::HelperError);
 
131
    reply.setErrorCode(result);
 
132
    return reply;
 
133
}
 
134
 
 
135
int Helper::install(const QVariantMap &args)
 
136
{
 
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());
 
142
 
 
143
    KFI_DBUG << file << destFolder << name << createAfm;
 
144
 
 
145
    int result=FontInst::STATUS_OK;
 
146
 
 
147
    if(!Misc::dExists(destFolder))
 
148
        result=Misc::createDir(destFolder) ? (int)FontInst::STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
 
149
 
 
150
    if(FontInst::STATUS_OK==result)
 
151
        result=QFile::copy(file, destFolder+name) ? (int)FontInst::STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
 
152
 
 
153
    if(FontInst::STATUS_OK==result)
 
154
    {
 
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);
 
159
    }
 
160
 
 
161
    return result;
 
162
}
 
163
 
 
164
int Helper::uninstall(const QVariantMap &args)
 
165
{
 
166
    QStringList files(args["files"].toStringList());
 
167
    int         result=checkWriteAction(files);
 
168
 
 
169
    if(FontInst::STATUS_OK==result)
 
170
    {
 
171
        QStringList::ConstIterator it(files.constBegin()),
 
172
                                   end(files.constEnd());
 
173
 
 
174
        for(; it!=end; ++it)
 
175
            if(!Misc::fExists(*it) || QFile::remove(*it))
 
176
            {
 
177
                // Also remove any AFM or PFM files...
 
178
                QStringList other;
 
179
                Misc::getAssociatedFiles(*it, other);
 
180
                QStringList::ConstIterator oit(other.constBegin()),
 
181
                                           oend(other.constEnd());
 
182
                for(; oit!=oend; ++oit)
 
183
                    QFile::remove(*oit);
 
184
 
 
185
                theFontFolder.addModifiedDir(Misc::getDir(*it));
 
186
            }
 
187
    }
 
188
 
 
189
    return result;
 
190
}
 
191
 
 
192
static bool renameFontFile(const QString &from, const QString &to, int uid=-1, int gid=-1)
 
193
{
 
194
    if(!QFile::rename(from, to))
 
195
        return false;
 
196
 
 
197
    QByteArray dest(QFile::encodeName(to));
 
198
 
 
199
    Misc::setFilePerms(dest);
 
200
    if(-1!=uid && -1!=gid)
 
201
        ::chown(dest.data(), uid, gid);
 
202
    return true;
 
203
}
 
204
 
 
205
int Helper::move(const QVariantMap &args)
 
206
{
 
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());
 
212
 
 
213
    KFI_DBUG << files << dest << toSystem;
 
214
 
 
215
    int                        result=FontInst::STATUS_OK;
 
216
    QStringList::ConstIterator it(files.constBegin()),
 
217
                               end(files.constEnd());
 
218
 
 
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;
 
223
 
 
224
    if(FontInst::STATUS_OK==result)
 
225
    {
 
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();
 
231
 
 
232
        // Move fonts!
 
233
        for(it=files.constBegin(); it!=end && FontInst::STATUS_OK==result; ++it)
 
234
        {
 
235
            QString name(Utils::modifyName(Misc::getFile(*it))),
 
236
                    destFolder(Utils::getDestFolder(dest, name));
 
237
 
 
238
            if(!Misc::dExists(destFolder))
 
239
            {
 
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);
 
243
            }
 
244
 
 
245
            if(renameFontFile(*it, destFolder+name, toUid, toGid))
 
246
            {
 
247
                movedFiles[*it]=destFolder+name;
 
248
                // Now try to move an associated AFM or PFM files...
 
249
                QStringList assoc;
 
250
 
 
251
                Misc::getAssociatedFiles(*it, assoc);
 
252
 
 
253
                QStringList::ConstIterator ait(assoc.constBegin()),
 
254
                                           aend(assoc.constEnd());
 
255
 
 
256
                for(; ait!=aend && FontInst::STATUS_OK==result; ++ait)
 
257
                {
 
258
                    name=Misc::getFile(*ait);
 
259
                    if(renameFontFile(*ait, destFolder+name, toUid, toGid))
 
260
                        movedFiles[*ait]=destFolder+name;
 
261
                    else
 
262
                        result=KIO::ERR_WRITE_ACCESS_DENIED;
 
263
                }
 
264
            }
 
265
            else
 
266
                result=KIO::ERR_WRITE_ACCESS_DENIED;
 
267
        }
 
268
 
 
269
        if(FontInst::STATUS_OK!=result) // un-move fonts!
 
270
        {
 
271
            QHash<QString, QString>::ConstIterator it(movedFiles.constBegin()),
 
272
                                                   end(movedFiles.constEnd());
 
273
 
 
274
            for(; it!=end; ++it)
 
275
                renameFontFile(it.value(), it.key(), fromUid, fromGid);
 
276
        }
 
277
    }
 
278
    return result;
 
279
}
 
280
 
 
281
int Helper::toggle(const QVariantMap &args)
 
282
{  
 
283
    QDomDocument    doc;
 
284
    doc.setContent(args["xml"].toString());
 
285
    Family          font(doc.documentElement(), true);
 
286
    bool            enable(args["enable"].toBool());
 
287
 
 
288
    KFI_DBUG << font.name() << enable;
 
289
 
 
290
    if(1!=font.styles().count())
 
291
        return KIO::ERR_WRITE_ACCESS_DENIED;
 
292
 
 
293
    int                     result=FontInst::STATUS_OK;
 
294
    FileCont                files((*font.styles().begin()).files()),
 
295
                            toggledFiles;
 
296
    FileCont::ConstIterator it(files.constBegin()),
 
297
                            end(files.constEnd());
 
298
    QHash<File, QString>    movedFonts;
 
299
    QHash<QString, QString> movedAssoc;
 
300
    QSet<QString>           modifiedDirs;
 
301
    // Move fonts!
 
302
    for(; it!=end && FontInst::STATUS_OK==result; ++it)
 
303
    {
 
304
        QString to=Misc::getDir((*it).path())+
 
305
                            QString(enable ? Misc::unhide(Misc::getFile((*it).path()))
 
306
                                           : Misc::hide(Misc::getFile((*it).path())));
 
307
 
 
308
        if(to!=(*it).path())
 
309
        {
 
310
            KFI_DBUG << "MOVE:" << (*it).path() << " to " << to;
 
311
            if(renameFontFile((*it).path(), to))
 
312
            {
 
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...
 
316
                QStringList assoc;
 
317
 
 
318
                movedFonts[*it]=to;
 
319
                Misc::getAssociatedFiles((*it).path(), assoc);
 
320
 
 
321
                QStringList::ConstIterator ait(assoc.constBegin()),
 
322
                                           aend(assoc.constEnd());
 
323
 
 
324
                for(; ait!=aend && FontInst::STATUS_OK==result; ++ait)
 
325
                {
 
326
                    to=Misc::getDir(*ait)+
 
327
                            QString(enable ? Misc::unhide(Misc::getFile(*ait))
 
328
                                           : Misc::hide(Misc::getFile(*ait)));
 
329
 
 
330
                    if(to!=*ait) {
 
331
                        if(renameFontFile(*ait, to))
 
332
                            movedAssoc[*ait]=to;
 
333
                        else
 
334
                            result=KIO::ERR_WRITE_ACCESS_DENIED;
 
335
                    }
 
336
                }
 
337
            }
 
338
            else
 
339
                result=KIO::ERR_WRITE_ACCESS_DENIED;
 
340
        }
 
341
    }
 
342
 
 
343
    theFontFolder.addModifiedDirs(modifiedDirs);
 
344
 
 
345
    if(FontInst::STATUS_OK==result)
 
346
    {
 
347
        FamilyCont::ConstIterator f=theFontFolder.fonts().find(font);
 
348
 
 
349
        if(theFontFolder.fonts().end()==f)
 
350
            f=theFontFolder.addFont(font);
 
351
 
 
352
        StyleCont::ConstIterator st=(*f).styles().find(*font.styles().begin());
 
353
 
 
354
        if((*f).styles().end()==st)
 
355
            st=(*f).add(*font.styles().begin());
 
356
 
 
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.
 
360
        FileCont empty;
 
361
        (*st).setFiles(enable ? empty : toggledFiles);
 
362
        if((*st).files().isEmpty())
 
363
            (*f).remove(*st);
 
364
        if((*f).styles().isEmpty())
 
365
            theFontFolder.removeFont(*f);
 
366
        theFontFolder.setDisabledDirty();
 
367
    }
 
368
    else
 
369
    {
 
370
        QHash<File, QString>::ConstIterator    fit(movedFonts.constBegin()),
 
371
                                               fend(movedFonts.constEnd());
 
372
        QHash<QString, QString>::ConstIterator ait(movedAssoc.constBegin()),
 
373
                                               aend(movedAssoc.constEnd());
 
374
 
 
375
        for(; fit!=fend; ++fit)
 
376
            renameFontFile(fit.value(), fit.key().path());
 
377
        for(; ait!=aend; ++ait)
 
378
            renameFontFile(ait.value(), ait.key());
 
379
    }
 
380
    
 
381
    return result;
 
382
}
 
383
 
 
384
int Helper::removeFile(const QVariantMap &args)
 
385
{
 
386
    QString file(args["file"].toString());
 
387
 
 
388
    KFI_DBUG << file;
 
389
 
 
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;
 
396
 
 
397
    if(FontInst::STATUS_OK==result)
 
398
        theFontFolder.addModifiedDir(dir);
 
399
 
 
400
    return result;
 
401
}
 
402
 
 
403
int Helper::reconfigure()
 
404
{
 
405
    KFI_DBUG;
 
406
 
 
407
    saveDisabled();
 
408
    KFI_DBUG << theFontFolder.isModified();
 
409
    if(theFontFolder.isModified())
 
410
        theFontFolder.configure();
 
411
    return FontInst::STATUS_OK;
 
412
}
 
413
 
 
414
int Helper::saveDisabled()
 
415
{
 
416
    KFI_DBUG;
 
417
    // Load internally calls save!
 
418
    theFontFolder.loadDisabled();
 
419
    return FontInst::STATUS_OK;
 
420
}
 
421
 
 
422
int Helper::checkWriteAction(const QStringList &files)
 
423
{
 
424
    QStringList::ConstIterator it(files.constBegin()),
 
425
                               end(files.constEnd());
 
426
 
 
427
    for(; it!=end; ++it)
 
428
        if(!Misc::dWritable(Misc::getDir(*it)))
 
429
            return KIO::ERR_WRITE_ACCESS_DENIED;
 
430
    return FontInst::STATUS_OK;
 
431
}
 
432
 
 
433
}