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

« back to all changes in this revision

Viewing changes to kcontrol/kfontinst/kio/KioFonts.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
 * KFontInst - KDE Font Installer
 
3
 *
 
4
 * Copyright 2003-2007 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 <QtCore/QFile>
 
25
#include <QtCore/QCoreApplication>
 
26
#include <KDE/KComponentData>
 
27
#include <KDE/KDebug>
 
28
#include <KDE/KMimeType>
 
29
#include <KDE/KStandardDirs>
 
30
#include <KDE/KTemporaryFile>
 
31
#include <KDE/KTempDir>
 
32
#include <KDE/KZip>
 
33
#include <kde_file.h>
 
34
#include <unistd.h>
 
35
#include <pwd.h>
 
36
#include <grp.h>
 
37
#include <errno.h>
 
38
#include <sys/stat.h>
 
39
#include <fcntl.h>
 
40
#include "KioFonts.h"
 
41
#include "KfiConstants.h"
 
42
#include "FontInstInterface.h"
 
43
#include "FontInst.h"
 
44
#include "Fc.h"
 
45
#include "Misc.h"
 
46
#include "XmlStrings.h"
 
47
#include "Family.h"
 
48
#include "Style.h"
 
49
#include "File.h"
 
50
#include "config-workspace.h"
 
51
 
 
52
#define MAX_IPC_SIZE     (1024*32)
 
53
#define KFI_DBUG         kDebug(7000) << '(' << time(NULL) << ')'
 
54
 
 
55
static const int constReconfigTimeout = 10;
 
56
 
 
57
extern "C" {
 
58
 
 
59
KDE_EXPORT int kdemain(int argc, char **argv)
 
60
{
 
61
    if (argc != 4)
 
62
    {
 
63
        fprintf(stderr, "Usage: kio_"KFI_KIO_FONTS_PROTOCOL
 
64
                        " protocol domain-socket1 domain-socket2\n");
 
65
        exit(-1);
 
66
    }
 
67
 
 
68
    KLocale::setMainCatalog(KFI_CATALOGUE);
 
69
 
 
70
    KComponentData   componentData("kio_"KFI_KIO_FONTS_PROTOCOL);
 
71
    KFI::CKioFonts   slave(argv[2], argv[3]);
 
72
    QCoreApplication app(argc, argv);
 
73
 
 
74
    slave.dispatchLoop();
 
75
 
 
76
    return 0;
 
77
}
 
78
 
 
79
}
 
80
 
 
81
namespace KFI
 
82
{
 
83
 
 
84
inline bool isSysFolder(const QString &folder)
 
85
{
 
86
    return i18n(KFI_KIO_FONTS_SYS)==folder || KFI_KIO_FONTS_SYS==folder;
 
87
}
 
88
 
 
89
inline bool isUserFolder(const QString &folder)
 
90
{
 
91
    return i18n(KFI_KIO_FONTS_USER)==folder || KFI_KIO_FONTS_USER==folder;
 
92
}
 
93
 
 
94
static CKioFonts::EFolder getFolder(const QStringList &list)
 
95
{
 
96
    if(list.size()>0)
 
97
    {
 
98
        QString folder=list[0];
 
99
 
 
100
        if(isSysFolder(folder))
 
101
            return CKioFonts::FOLDER_SYS;
 
102
        else if(isUserFolder(folder))
 
103
            return CKioFonts::FOLDER_USER;
 
104
        return CKioFonts::FOLDER_UNKNOWN;
 
105
    }
 
106
 
 
107
    return CKioFonts::FOLDER_ROOT;
 
108
}
 
109
 
 
110
static int getSize(const QString &file)
 
111
{
 
112
    KDE_struct_stat buff;
 
113
    QByteArray      f(QFile::encodeName(file));
 
114
 
 
115
    if(-1!=KDE_lstat(f.constData(), &buff))
 
116
    {
 
117
        if (S_ISLNK(buff.st_mode))
 
118
        {
 
119
            char buffer2[1000];
 
120
            int n=readlink(f.constData(), buffer2, 1000);
 
121
            if(n!= -1)
 
122
                buffer2[n]='\0';
 
123
 
 
124
            if(-1==KDE_stat(f.constData(), &buff))
 
125
                return -1;
 
126
        }
 
127
        return buff.st_size;
 
128
    }
 
129
 
 
130
    return -1;
 
131
}
 
132
 
 
133
static bool writeAll(int fd, const char *buf, size_t len)
 
134
{
 
135
   while(len>0)
 
136
   {
 
137
      ssize_t written=write(fd, buf, len);
 
138
      if (written<0 && EINTR!=errno)
 
139
          return false;
 
140
      buf+=written;
 
141
      len-=written;
 
142
   }
 
143
   return true;
 
144
}
 
145
 
 
146
static bool isScalable(const QString &str)
 
147
{
 
148
    return Misc::checkExt(str, "ttf") || Misc::checkExt(str, "otf") || Misc::checkExt(str, "ttc") ||
 
149
           Misc::checkExt(str, "pfa") || Misc::checkExt(str, "pfb");
 
150
}
 
151
 
 
152
static const char * const constExtensions[]=
 
153
            {".ttf", KFI_FONTS_PACKAGE, ".otf", ".pfa", ".pfb", ".ttc",
 
154
             ".pcf", ".pcf.gz", ".bdf", ".bdf.gz", NULL };
 
155
 
 
156
static QString removeKnownExtension(const KUrl &url)
 
157
{
 
158
    QString fname(url.fileName());
 
159
    int     pos;
 
160
 
 
161
    for(int i=0; constExtensions[i]; ++i)
 
162
        if(-1!=(pos=fname.lastIndexOf(QString::fromLatin1(constExtensions[i]), -1, Qt::CaseInsensitive)))
 
163
            return fname.left(pos);
 
164
    return fname;
 
165
}
 
166
 
 
167
 
 
168
CKioFonts::CKioFonts(const QByteArray &pool, const QByteArray &app)
 
169
         : KIO::SlaveBase(KFI_KIO_FONTS_PROTOCOL, pool, app)
 
170
         , itsInterface(new FontInstInterface())
 
171
         , itsTempDir(0L)
 
172
{
 
173
    KFI_DBUG;
 
174
}
 
175
 
 
176
CKioFonts::~CKioFonts()
 
177
{
 
178
    KFI_DBUG;
 
179
    delete itsInterface;
 
180
    delete itsTempDir;
 
181
}
 
182
 
 
183
void CKioFonts::listDir(const KUrl &url)
 
184
{
 
185
    KFI_DBUG << url.prettyUrl();
 
186
 
 
187
    QStringList   pathList(url.path(KUrl::RemoveTrailingSlash).split('/', QString::SkipEmptyParts));
 
188
    EFolder       folder=Misc::root() ? FOLDER_SYS : getFolder(pathList);
 
189
    KIO::UDSEntry entry;
 
190
    int           size=0;
 
191
 
 
192
    switch(folder)
 
193
    {
 
194
        case FOLDER_ROOT:
 
195
            KFI_DBUG << "List root folder";
 
196
            size=2;
 
197
            totalSize(2);
 
198
            createUDSEntry(entry, FOLDER_SYS);
 
199
            listEntry(entry, false);
 
200
            createUDSEntry(entry, FOLDER_USER);
 
201
            listEntry(entry, false);
 
202
            break;
 
203
        case FOLDER_SYS:
 
204
        case FOLDER_USER:
 
205
            size=listFolder(entry, folder);
 
206
            break;
 
207
        default:
 
208
            break;
 
209
    }
 
210
 
 
211
    if(FOLDER_UNKNOWN!=folder)
 
212
    {
 
213
        listEntry(size ? entry : KIO::UDSEntry(), true);
 
214
        finished();
 
215
    }
 
216
    else
 
217
        error(KIO::ERR_DOES_NOT_EXIST, url.prettyUrl());
 
218
}
 
219
 
 
220
void CKioFonts::put(const KUrl &url, int /*permissions*/, KIO::JobFlags /*flags*/)
 
221
{
 
222
    KFI_DBUG << url.prettyUrl();
 
223
    QStringList pathList(url.path(KUrl::RemoveTrailingSlash).split('/', QString::SkipEmptyParts));
 
224
    EFolder     folder(getFolder(pathList));
 
225
 
 
226
    if(!Misc::root() && FOLDER_ROOT==folder)
 
227
        error(KIO::ERR_SLAVE_DEFINED,
 
228
                i18n("Can only install fonts to either \"%1\" or \"%2\".",
 
229
                i18n(KFI_KIO_FONTS_USER), i18n(KFI_KIO_FONTS_SYS)));
 
230
    else if(Misc::isPackage(url.fileName()))
 
231
        error(KIO::ERR_SLAVE_DEFINED, i18n("You cannot install a fonts package directly.\n"
 
232
                                           "Please extract %1, and install the components individually.",
 
233
                                           url.prettyUrl()));
 
234
    else
 
235
    {
 
236
        if(!itsTempDir)
 
237
        {
 
238
            itsTempDir=new KTempDir(KStandardDirs::locateLocal("tmp",
 
239
                                    QString::fromLatin1("kio_fonts_")+QString::number(getpid())));
 
240
            itsTempDir->setAutoRemove(true);
 
241
        }
 
242
 
 
243
        QString tempFile(itsTempDir->name()+QChar('/')+url.fileName());
 
244
        QFile   dest(tempFile);
 
245
 
 
246
        if (dest.open(QIODevice::WriteOnly))
 
247
        {
 
248
            int result;
 
249
            // Loop until we got 0 (end of data)
 
250
            do
 
251
            {
 
252
                QByteArray buffer;
 
253
 
 
254
                dataReq(); // Request for data
 
255
                result = readData(buffer);
 
256
                if(result > 0 && !writeAll(dest.handle(), buffer.constData(), buffer.size()))
 
257
                {
 
258
                    if(ENOSPC==errno) // disk full
 
259
                    {
 
260
                        error(KIO::ERR_DISK_FULL, dest.fileName());
 
261
                        result = -2; // means: remove dest file
 
262
                    }
 
263
                    else
 
264
                    {
 
265
                        error(KIO::ERR_COULD_NOT_WRITE, dest.fileName());
 
266
                        result = -1;
 
267
                    }
 
268
                }
 
269
            }
 
270
            while(result>0);
 
271
 
 
272
            if (result<0)
 
273
            {
 
274
                dest.close();
 
275
                ::exit(255);
 
276
            }
 
277
 
 
278
            handleResp(itsInterface->install(tempFile, Misc::root() || FOLDER_SYS==folder),
 
279
                       url.fileName(), tempFile);
 
280
            QFile::remove(tempFile);
 
281
        }
 
282
        else
 
283
            error(EACCES==errno ? KIO::ERR_WRITE_ACCESS_DENIED : KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.fileName());
 
284
    }
 
285
}
 
286
 
 
287
void CKioFonts::get(const KUrl &url)
 
288
{
 
289
    KFI_DBUG << url.prettyUrl();
 
290
    QStringList pathList(url.path(KUrl::RemoveTrailingSlash).split('/', QString::SkipEmptyParts));
 
291
    EFolder     folder(getFolder(pathList));
 
292
    Family      family(getFont(url, folder));
 
293
 
 
294
    if(!family.name().isEmpty() && 1==family.styles().count())
 
295
    {
 
296
        StyleCont::ConstIterator style(family.styles().begin());
 
297
        FileCont::ConstIterator  it((*style).files().begin()),
 
298
                                 end((*style).files().end());
 
299
 
 
300
        //
 
301
        // The thumbnail job always donwloads non-local files to /tmp/... and passes this file name to
 
302
        // the thumbnail creator. However, in the case of fonts which are split among many files, this
 
303
        // wont work. Therefore, when the thumbnail code asks for the font to donwload, just return
 
304
        // the family and style info for enabled fonts, and the filename for disabled fonts. This way
 
305
        // the font-thumbnail creator can read this and just ask Xft/fontconfig for the font data.
 
306
        if("1"==metaData("thumbnail"))
 
307
        {
 
308
            QByteArray  array;
 
309
            QTextStream stream(&array, QIODevice::WriteOnly);
 
310
 
 
311
            emit mimeType("text/plain");
 
312
 
 
313
            bool hidden(true);
 
314
 
 
315
            for(; it!=end && hidden; ++it)
 
316
                if(!Misc::isHidden(Misc::getFile((*it).path())))
 
317
                    hidden=false;
 
318
 
 
319
            if(hidden)
 
320
            {
 
321
                //
 
322
                // OK, its a disabled font - if possible try to return the location of the font file
 
323
                // itself.
 
324
                bool found=false;
 
325
                it=(*style).files().begin();
 
326
                end=(*style).files().end();
 
327
                for(; it!=end && hidden; ++it)
 
328
                    if(isScalable((*it).path()))
 
329
                    {
 
330
                        KFI_DBUG << "hasMetaData(\"thumbnail\"), so return FILE: "
 
331
                                    << (*it).path() << " / " << (*it).index();
 
332
                        stream << KFI_PATH_KEY << (*it).path() << endl
 
333
                               << KFI_FACE_KEY << (*it).index() << endl;
 
334
                        found=true;
 
335
                        break;
 
336
                    }
 
337
 
 
338
                if(!found)
 
339
                {
 
340
                    KFI_DBUG << "hasMetaData(\"thumbnail\"), so return Url: " << url;
 
341
                    stream << url.prettyUrl();
 
342
                }
 
343
            }
 
344
            else
 
345
            {
 
346
                KFI_DBUG << "hasMetaData(\"thumbnail\"), so return DETAILS: " << family.name() << " / "
 
347
                         << (*style).value();
 
348
 
 
349
                stream << KFI_NAME_KEY << family.name() << endl
 
350
                       << KFI_STYLE_KEY << (*style).value() << endl;
 
351
            }
 
352
 
 
353
            totalSize(array.size());
 
354
            data(array);
 
355
            processedSize(array.size());
 
356
            data(QByteArray());
 
357
            processedSize(array.size());
 
358
            finished();
 
359
            KFI_DBUG << "Finished thumbnail...";
 
360
            return;
 
361
        }
 
362
 
 
363
        QSet<QString>   files;
 
364
        QString         realPath;
 
365
        KDE_struct_stat buff;
 
366
        bool            multiple=false;
 
367
 
 
368
        for(; it!=end; ++it)
 
369
        {
 
370
            QStringList assoc;
 
371
 
 
372
            files.insert((*it).path());
 
373
 
 
374
            Misc::getAssociatedFiles((*it).path(), assoc);
 
375
 
 
376
            QStringList::ConstIterator ait(assoc.constBegin()),
 
377
                                       aend(assoc.constEnd());
 
378
 
 
379
            for(; ait!=aend; ++ait)
 
380
                files.insert(*ait);
 
381
        }
 
382
 
 
383
        if(1==files.count())
 
384
            realPath=(*files.begin());
 
385
        else   // Font is made up of multiple files - so create .zip of them all!
 
386
        {
 
387
            KTemporaryFile tmpFile;
 
388
 
 
389
            if(tmpFile.open())
 
390
            {
 
391
                KZip zip(tmpFile.fileName());
 
392
 
 
393
                tmpFile.setAutoRemove(false);
 
394
                realPath=tmpFile.fileName();
 
395
 
 
396
                if(zip.open(QIODevice::WriteOnly))
 
397
                {
 
398
                    QMap<QString, QString>                map=Misc::getFontFileMap(files);
 
399
                    QMap<QString, QString>::ConstIterator it(map.constBegin()),
 
400
                                                          end(map.constEnd());
 
401
 
 
402
                    for(; it!=end; ++it)
 
403
                        zip.addLocalFile(it.value(), it.key());
 
404
 
 
405
                    multiple=true;
 
406
                    zip.close();
 
407
                }
 
408
            }
 
409
        }
 
410
 
 
411
        QByteArray realPathC(QFile::encodeName(realPath));
 
412
        KFI_DBUG << "real: " << realPathC;
 
413
 
 
414
        if (-2==KDE_stat(realPathC.constData(), &buff))
 
415
            error(EACCES==errno ? KIO::ERR_ACCESS_DENIED : KIO::ERR_DOES_NOT_EXIST, url.prettyUrl());
 
416
        else if (S_ISDIR(buff.st_mode))
 
417
            error(KIO::ERR_IS_DIRECTORY, url.prettyUrl());
 
418
        else if (!S_ISREG(buff.st_mode))
 
419
            error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyUrl());
 
420
        else
 
421
        {
 
422
            int fd = KDE_open(realPathC.constData(), O_RDONLY);
 
423
 
 
424
            if (fd < 0)
 
425
                error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyUrl());
 
426
            else
 
427
            {
 
428
                // Determine the mimetype of the file to be retrieved, and emit it.
 
429
                // This is mandatory in all slaves (for KRun/BrowserRun to work).
 
430
                emit mimeType(KMimeType::findByPath(realPathC, buff.st_mode)->name());
 
431
 
 
432
                totalSize(buff.st_size);
 
433
 
 
434
                KIO::filesize_t processed=0;
 
435
                char            buffer[MAX_IPC_SIZE];
 
436
                QByteArray      array;
 
437
 
 
438
                while(1)
 
439
                {
 
440
                    int n=::read(fd, buffer, MAX_IPC_SIZE);
 
441
 
 
442
                    if (-1==n)
 
443
                    {
 
444
                        if (EINTR==errno)
 
445
                            continue;
 
446
 
 
447
                        error(KIO::ERR_COULD_NOT_READ, url.prettyUrl());
 
448
                        ::close(fd);
 
449
                        if(multiple)
 
450
                            ::unlink(realPathC);
 
451
                        return;
 
452
                    }
 
453
                    if (0==n)
 
454
                        break; // Finished
 
455
 
 
456
                    array=array.fromRawData(buffer, n);
 
457
                    data(array);
 
458
                    array.clear();
 
459
 
 
460
                    processed+=n;
 
461
                    processedSize(processed);
 
462
                }
 
463
 
 
464
                data(QByteArray());
 
465
                ::close(fd);
 
466
                processedSize(buff.st_size);
 
467
                finished();
 
468
            }
 
469
        }
 
470
        if(multiple)
 
471
            ::unlink(realPathC);
 
472
    }
 
473
    else
 
474
        error(KIO::ERR_COULD_NOT_READ, url.prettyUrl());
 
475
}
 
476
 
 
477
void CKioFonts::copy(const KUrl &, const KUrl &, int, KIO::JobFlags)
 
478
{
 
479
    error(KIO::ERR_SLAVE_DEFINED, i18n("Cannot copy fonts"));
 
480
}
 
481
 
 
482
void CKioFonts::rename(const KUrl &, const KUrl &, KIO::JobFlags)
 
483
{
 
484
    error(KIO::ERR_SLAVE_DEFINED, i18n("Cannot move fonts"));
 
485
}
 
486
 
 
487
void CKioFonts::del(const KUrl &url, bool isFile)
 
488
{
 
489
    KFI_DBUG << url.prettyUrl();
 
490
    QStringList pathList(url.path(KUrl::RemoveTrailingSlash).split('/', QString::SkipEmptyParts));
 
491
    EFolder     folder(getFolder(pathList));
 
492
    QString     name(removeKnownExtension(url));
 
493
 
 
494
    if(!isFile)
 
495
        error(KIO::ERR_SLAVE_DEFINED, i18n("Only fonts may be deleted."));
 
496
    else if(!Misc::root() && FOLDER_ROOT==folder)
 
497
        error(KIO::ERR_SLAVE_DEFINED,
 
498
                i18n("Can only remove fonts from either \"%1\" or \"%2\".",
 
499
                i18n(KFI_KIO_FONTS_USER), i18n(KFI_KIO_FONTS_SYS)));
 
500
    else if(!name.isEmpty())
 
501
        handleResp(itsInterface->uninstall(name, Misc::root() || FOLDER_SYS==folder), name);
 
502
    else
 
503
        error(KIO::ERR_DOES_NOT_EXIST, url.prettyUrl());
 
504
}
 
505
 
 
506
void CKioFonts::stat(const KUrl &url)
 
507
{
 
508
    KFI_DBUG << url.prettyUrl();
 
509
 
 
510
    QStringList   pathList(url.path(KUrl::RemoveTrailingSlash).split('/', QString::SkipEmptyParts));
 
511
    EFolder       folder=getFolder(pathList);
 
512
    KIO::UDSEntry entry;
 
513
    bool          ok=true;
 
514
 
 
515
    switch(pathList.count())
 
516
    {
 
517
        case 0:
 
518
            createUDSEntry(entry, FOLDER_ROOT);
 
519
            break;
 
520
        case 1:
 
521
            if(Misc::root())
 
522
                ok=createStatEntry(entry, url, FOLDER_SYS);
 
523
            else if(FOLDER_SYS==folder || FOLDER_USER==folder)
 
524
                createUDSEntry(entry, folder);
 
525
            else
 
526
            {
 
527
                error(KIO::ERR_SLAVE_DEFINED,
 
528
                        i18n("Please specify \"%1\" or \"%2\".",
 
529
                        i18n(KFI_KIO_FONTS_USER), i18n(KFI_KIO_FONTS_SYS)));
 
530
                return;
 
531
            }
 
532
            break;
 
533
        default:
 
534
            ok=createStatEntry(entry, url, folder);
 
535
    }
 
536
 
 
537
    if(ok)
 
538
    {
 
539
        statEntry(entry);
 
540
        finished();
 
541
    }
 
542
    else
 
543
    {
 
544
        error(KIO::ERR_DOES_NOT_EXIST, url.prettyUrl());
 
545
        return;
 
546
    }
 
547
}
 
548
 
 
549
void CKioFonts::special(const QByteArray &a)
 
550
{
 
551
    if(a.size())
 
552
        error(KIO::ERR_UNSUPPORTED_ACTION, i18n("No special methods supported."));
 
553
    else
 
554
    {
 
555
        setTimeoutSpecialCommand(-1);
 
556
        itsInterface->reconfigure();
 
557
    }
 
558
}
 
559
 
 
560
int CKioFonts::listFolder(KIO::UDSEntry &entry, EFolder folder)
 
561
{
 
562
    KFI_DBUG << folder;
 
563
 
 
564
    int                       styleCount(0);
 
565
    KFI::Families             families(itsInterface->list(FOLDER_SYS==folder));
 
566
    FamilyCont::ConstIterator family(families.items.begin()),
 
567
                              end(families.items.end());
 
568
 
 
569
    KFI_DBUG << "Num families:" << families.items.count();
 
570
 
 
571
    for(; family!=end; ++family)
 
572
    {
 
573
        StyleCont::ConstIterator styleIt((*family).styles().begin()),
 
574
                                 styleEnd((*family).styles().end());
 
575
 
 
576
        styleCount+=(*family).styles().count();
 
577
        for(; styleIt!=styleEnd; ++styleIt)
 
578
        {
 
579
            createUDSEntry(entry, folder, *family, *styleIt);
 
580
            listEntry(entry, false);
 
581
        }
 
582
    }
 
583
 
 
584
    totalSize(styleCount);
 
585
    return styleCount;
 
586
}
 
587
 
 
588
QString CKioFonts::getUserName(uid_t uid)
 
589
{
 
590
    if (!itsUserCache.contains(uid))
 
591
    {
 
592
        struct passwd *user = getpwuid(uid);
 
593
        if(user)
 
594
            itsUserCache.insert(uid, QString::fromLatin1(user->pw_name));
 
595
        else
 
596
            return QString::number(uid);
 
597
    }
 
598
    return itsUserCache[uid];
 
599
}
 
600
 
 
601
QString CKioFonts::getGroupName(gid_t gid)
 
602
{
 
603
    if (!itsGroupCache.contains(gid))
 
604
    {
 
605
        struct group *grp = getgrgid(gid);
 
606
        if(grp)
 
607
            itsGroupCache.insert(gid, QString::fromLatin1(grp->gr_name));
 
608
        else
 
609
            return QString::number(gid);
 
610
    }
 
611
    return itsGroupCache[gid];
 
612
}
 
613
 
 
614
bool CKioFonts::createStatEntry(KIO::UDSEntry &entry, const KUrl &url, EFolder folder)
 
615
{
 
616
    Family fam(getFont(url, folder));
 
617
 
 
618
    if(!fam.name().isEmpty() && 1==fam.styles().count())
 
619
    {
 
620
        createUDSEntry(entry, folder, fam, *fam.styles().begin());
 
621
        return true;
 
622
    }
 
623
 
 
624
    return false;
 
625
}
 
626
 
 
627
void CKioFonts::createUDSEntry(KIO::UDSEntry &entry, EFolder folder)
 
628
{
 
629
    KFI_DBUG << QString(FOLDER_SYS==folder ? i18n(KFI_KIO_FONTS_SYS) : i18n(KFI_KIO_FONTS_USER));
 
630
    entry.clear();
 
631
    entry.insert(KIO::UDSEntry::UDS_NAME, FOLDER_ROOT==folder || Misc::root()
 
632
                                            ? i18n("Fonts")
 
633
                                            : FOLDER_SYS==folder
 
634
                                                ? i18n(KFI_KIO_FONTS_SYS)
 
635
                                                : i18n(KFI_KIO_FONTS_USER));
 
636
    entry.insert(KIO::UDSEntry::UDS_ACCESS, !Misc::root() && FOLDER_SYS==folder ? 0444 : 0744);
 
637
    entry.insert(KIO::UDSEntry::UDS_USER, Misc::root() || FOLDER_SYS==folder
 
638
                                            ? QString::fromLatin1("root")
 
639
                                            : getUserName(getuid()));
 
640
    entry.insert(KIO::UDSEntry::UDS_GROUP, Misc::root() || FOLDER_SYS==folder
 
641
                                            ? QString::fromLatin1("root")
 
642
                                            : getGroupName(getgid()));
 
643
    entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
 
644
    entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("inode/directory"));
 
645
}
 
646
 
 
647
bool CKioFonts::createUDSEntry(KIO::UDSEntry &entry, EFolder folder, const Family &family, const Style &style)
 
648
{
 
649
    int                     size=0;
 
650
    QString                 name(FC::createName(family.name(), style.value()));
 
651
    FileCont::ConstIterator file(style.files().begin()),
 
652
                            fileEnd(style.files().end());
 
653
    QList<File>             files;
 
654
    bool                    hidden=true,
 
655
                            haveExtraFiles=false;
 
656
 
 
657
    KFI_DBUG << name;
 
658
 
 
659
    for(; file!=fileEnd; ++file)
 
660
    {
 
661
        size+=getSize((*file).path());
 
662
        // TODO: Make scalable a property of the file?
 
663
        // Then isScalable() is not needed!!!
 
664
        if(isScalable((*file).path()))
 
665
            files.prepend(*file);
 
666
        else
 
667
            files.append(*file);
 
668
 
 
669
        if(hidden && !Misc::isHidden(Misc::getFile((*file).path())))
 
670
            hidden=false;
 
671
 
 
672
        QStringList assoc;
 
673
        Misc::getAssociatedFiles((*file).path(), assoc);
 
674
 
 
675
        QStringList::ConstIterator oit(assoc.constBegin()),
 
676
                                   oend(assoc.constEnd());
 
677
 
 
678
        if(!haveExtraFiles && !assoc.isEmpty())
 
679
            haveExtraFiles=true;
 
680
 
 
681
        for(; oit!=oend; ++oit)
 
682
            size+=getSize(*oit);
 
683
    }
 
684
 
 
685
    entry.clear();
 
686
 
 
687
    entry.insert(KIO::UDSEntry::UDS_NAME, name);
 
688
    entry.insert(KIO::UDSEntry::UDS_SIZE, size);
 
689
    entry.insert(UDS_EXTRA_FC_STYLE, style.value());
 
690
 
 
691
    QList<File>::ConstIterator it(files.constBegin()),
 
692
                               end(files.constEnd());
 
693
 
 
694
    for(; it!=end; ++it)
 
695
    {
 
696
        QByteArray      cPath(QFile::encodeName((*it).path()));
 
697
        KDE_struct_stat buff;
 
698
 
 
699
        if(-1!=KDE_lstat(cPath, &buff))
 
700
        {
 
701
            QString fileName(Misc::getFile((*it).path())),
 
702
                    mt;
 
703
            int     dotPos(fileName.lastIndexOf('.'));
 
704
            QString extension(-1==dotPos ? QString() : fileName.mid(dotPos));
 
705
 
 
706
            if(QString::fromLatin1(".gz")==extension)
 
707
            {
 
708
                dotPos=fileName.lastIndexOf('.', dotPos-1);
 
709
                extension=-1==dotPos ? QString() : fileName.mid(dotPos);
 
710
            }
 
711
 
 
712
            if(QString::fromLatin1(".ttf")==extension || QString::fromLatin1(".ttc")==extension)
 
713
                mt="application/x-font-ttf";
 
714
            else if(QString::fromLatin1(".otf")==extension)
 
715
                mt="application/x-font-otf";
 
716
            else if(QString::fromLatin1(".pfa")==extension || QString::fromLatin1(".pfb")==extension)
 
717
                mt="application/x-font-type1";
 
718
            else if(QString::fromLatin1(".pcf.gz")==extension || QString::fromLatin1(".pcf")==extension)
 
719
                mt="application/x-font-pcf";
 
720
            else if(QString::fromLatin1(".bdf.gz")==extension || QString::fromLatin1(".bdf")==extension)
 
721
                mt="application/x-font-bdf";
 
722
            else
 
723
            {
 
724
                // File extension check failed, use kmimetype to read contents...
 
725
                KMimeType::Ptr mime=KMimeType::findByPath((*it).path());
 
726
                QStringList    patterns=mime->patterns();
 
727
                mt=mime->name();
 
728
                if(patterns.size()>0)
 
729
                    extension=(*patterns.begin()).remove("*");
 
730
            }
 
731
 
 
732
            entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, buff.st_mode&S_IFMT);
 
733
            entry.insert(KIO::UDSEntry::UDS_ACCESS, buff.st_mode&07777);
 
734
            entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, buff.st_mtime);
 
735
            entry.insert(KIO::UDSEntry::UDS_ACCESS_TIME, buff.st_atime);
 
736
            entry.insert(KIO::UDSEntry::UDS_USER, getUserName(buff.st_uid));
 
737
            entry.insert(KIO::UDSEntry::UDS_GROUP, getGroupName(buff.st_gid));
 
738
            entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, mt);
 
739
 
 
740
            if(hidden)
 
741
            {
 
742
                entry.insert(KIO::UDSEntry::UDS_HIDDEN, 1);
 
743
                entry.insert(UDS_EXTRA_FILE_NAME, (*it).path());
 
744
                entry.insert(UDS_EXTRA_FILE_FACE, (*it).path());
 
745
            }
 
746
 
 
747
            QString path(QString::fromLatin1("/"));
 
748
 
 
749
            if(!Misc::root())
 
750
            {
 
751
                path+=FOLDER_SYS==folder ? i18n(KFI_KIO_FONTS_SYS) : i18n(KFI_KIO_FONTS_USER);
 
752
                path+=QString::fromLatin1("/");
 
753
            }
 
754
            path+=name;
 
755
 
 
756
            if(files.count()>1 || haveExtraFiles)
 
757
                path+=QString::fromLatin1(KFI_FONTS_PACKAGE);
 
758
            else
 
759
                path+=extension;
 
760
 
 
761
            KUrl url(KUrl::fromPath(path));
 
762
 
 
763
            url.setProtocol(KFI_KIO_FONTS_PROTOCOL);
 
764
            entry.insert(KIO::UDSEntry::UDS_URL, url.url());
 
765
            return true;
 
766
        }
 
767
    }
 
768
 
 
769
    return false;
 
770
}
 
771
 
 
772
Family CKioFonts::getFont(const KUrl &url, EFolder folder)
 
773
{
 
774
    QString name(removeKnownExtension(url));
 
775
 
 
776
    KFI_DBUG << url << name;
 
777
 
 
778
    return itsInterface->stat(name, FOLDER_SYS==folder);
 
779
}
 
780
 
 
781
void CKioFonts::handleResp(int resp, const QString &file, const QString &tempFile)
 
782
{
 
783
    switch(resp)
 
784
    {
 
785
        case FontInst::STATUS_NO_SYS_CONNECTION:
 
786
            error(KIO::ERR_SLAVE_DEFINED, i18n("Failed to start the system daemon"));
 
787
            break;
 
788
        case FontInst::STATUS_SERVICE_DIED:
 
789
            error(KIO::ERR_SLAVE_DEFINED, i18n("Backend died"));
 
790
            break;
 
791
        case FontInst::STATUS_BITMAPS_DISABLED:
 
792
            error(KIO::ERR_SLAVE_DEFINED,
 
793
                  i18n("%1 is a bitmap font, and these have been disabled on your system.", file));
 
794
            break;
 
795
        case FontInst::STATUS_ALREADY_INSTALLED:
 
796
            error(KIO::ERR_SLAVE_DEFINED,
 
797
                  i18n("%1 contains the font <b>%2</b>, which is already installed on your system.", file,
 
798
                  FC::getName(tempFile)));
 
799
            break;
 
800
        case FontInst::STATUS_NOT_FONT_FILE:
 
801
            error(KIO::ERR_SLAVE_DEFINED, i18n("%1 is not a font.", file));
 
802
            break;
 
803
        case FontInst::STATUS_PARTIAL_DELETE:
 
804
            error(KIO::ERR_SLAVE_DEFINED, i18n("Could not remove all files associated with %1", file));
 
805
            break;
 
806
        case FontInst::STATUS_OK:
 
807
            finished();
 
808
            break;
 
809
        default:
 
810
            error(resp, file);
 
811
    }
 
812
 
 
813
    if(FontInst::STATUS_OK==resp)
 
814
        setTimeoutSpecialCommand(constReconfigTimeout);
 
815
}
 
816
 
 
817
}