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

« back to all changes in this revision

Viewing changes to kdm/kcm/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
 *  helper.cpp
 
3
 *
 
4
 *  Copyright (C) 2010 Igor Krivenko <igor@shg.ru>
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 *
 
20
 */
 
21
 
 
22
/*
 
23
 
 
24
 A helper that's run using KAuth and does the system modifications.
 
25
 
 
26
*/
 
27
 
 
28
#include "helper.h"
 
29
 
 
30
#include <config-workspace.h>
 
31
 
 
32
#include <QFile>
 
33
#include <QDir>
 
34
#include <KConfig>
 
35
#include <KConfigGroup>
 
36
#include <KStandardDirs>
 
37
 
 
38
bool secureCopy(const QString &from, const QString &to)
 
39
{
 
40
    QFile srcFile(from);
 
41
    if (!srcFile.open(QIODevice::ReadOnly))
 
42
        return false;
 
43
 
 
44
    // Security check: we don't want to expose contents of files like /etc/shadow
 
45
    if (!(srcFile.permissions() & QFile::ReadOther))
 
46
        return false;
 
47
 
 
48
    QFile dstFile(to);
 
49
    if (!dstFile.open(QIODevice::WriteOnly))
 
50
        return false;
 
51
 
 
52
    const quint64 maxBlockSize = 102400;
 
53
    while (!srcFile.atEnd())
 
54
        if (dstFile.write(srcFile.read(maxBlockSize)) == -1)
 
55
            return false;
 
56
 
 
57
    if (!dstFile.setPermissions(
 
58
                QFile::WriteUser | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther))
 
59
        return false;
 
60
 
 
61
    return true;
 
62
}
 
63
 
 
64
bool createDir(const QString &path)
 
65
{
 
66
    QDir testDir(path);
 
67
    return (testDir.exists()) || (testDir.mkpath(path));
 
68
}
 
69
 
 
70
bool removeDirTree(const QString &rootDir)
 
71
{
 
72
    QDir dir(rootDir);
 
73
    foreach (const QFileInfo &entry, dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot))
 
74
        if (entry.isDir())
 
75
            removeDirTree(entry.absoluteFilePath());
 
76
        else
 
77
            dir.remove(entry.fileName());
 
78
 
 
79
    return dir.rmdir(rootDir);
 
80
}
 
81
 
 
82
bool installDirTree(const QString &srcRootDir, const QString &dstRootDir)
 
83
{
 
84
    QDir srcDir(srcRootDir);
 
85
    QDir dstDir(dstRootDir);
 
86
 
 
87
    if (!dstDir.mkdir(dstRootDir))
 
88
        return false;
 
89
 
 
90
    if (!QFile::setPermissions(dstRootDir,
 
91
               QFile::WriteUser | QFile::ReadUser | QFile::ExeUser |
 
92
               QFile::ReadGroup | QFile::ExeGroup |
 
93
               QFile::ReadOther | QFile::ExeOther))
 
94
        return false;
 
95
 
 
96
    bool res = true;
 
97
    foreach (const QFileInfo &entry, srcDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)) {
 
98
        QString srcFilePath = entry.absoluteFilePath();
 
99
        QString dstFilePath = dstDir.absolutePath() + '/' + entry.fileName();
 
100
 
 
101
        if (entry.isDir()) {
 
102
            if (!installDirTree(srcFilePath, dstFilePath))
 
103
                res = false;
 
104
        } else {
 
105
            if (!secureCopy(srcFilePath, dstFilePath))
 
106
                res = false;
 
107
        }
 
108
    }
 
109
    return res;
 
110
}
 
111
 
 
112
ActionReply Helper::createReply(int code, const QVariantMap *returnData)
 
113
{
 
114
    ActionReply reply;
 
115
 
 
116
    if (code) {
 
117
        reply = ActionReply::HelperError;
 
118
        reply.setErrorCode(code);
 
119
    } else {
 
120
        reply = ActionReply::SuccessReply;
 
121
    }
 
122
 
 
123
    if (returnData)
 
124
        reply.setData(*returnData);
 
125
 
 
126
    return reply;
 
127
}
 
128
 
 
129
ActionReply Helper::save(const QVariantMap &args)
 
130
{
 
131
    QString tempConfigName = args.value("tempkdmrcfile").toString();
 
132
    QString tempBackgroundConfigName = args.value("tempbackgroundrcfile").toString();
 
133
 
 
134
    QString systemConfigName = QString::fromLatin1(KDE_CONFDIR "/kdm/kdmrc");
 
135
    QString systemBackgroundConfigName = KConfig(systemConfigName, KConfig::SimpleConfig)
 
136
            .group("X-*-Greeter").readEntry("BackgroundCfg", KDE_CONFDIR "/kdm/backgroundrc");
 
137
 
 
138
    int code = 0;
 
139
 
 
140
    if (!secureCopy(tempConfigName, systemConfigName))
 
141
        code |= KdmrcInstallError;
 
142
    if (!secureCopy(tempBackgroundConfigName, systemBackgroundConfigName))
 
143
        code |= BackgroundrcInstallError;
 
144
 
 
145
    return createReply(code);
 
146
}
 
147
 
 
148
bool Helper::removeFace(const QString &facesDir, const QString &user)
 
149
{
 
150
    // Security check
 
151
    if (user.contains('/'))
 
152
        return false;
 
153
 
 
154
    return QFile::remove(facesDir + user + ".face.icon");
 
155
}
 
156
 
 
157
bool Helper::installFace(const QString &facesDir, const QString &user, const QString &sourceFile)
 
158
{
 
159
    // Security check
 
160
    if (user.contains('/'))
 
161
        return false;
 
162
 
 
163
    return secureCopy(sourceFile, facesDir + user + ".face.icon");
 
164
}
 
165
 
 
166
ActionReply Helper::managefaces(const QVariantMap &args)
 
167
{
 
168
    int subaction = args.value("subaction").toInt();
 
169
    QString facesDir =
 
170
        KConfig(QString::fromLatin1(KDE_CONFDIR "/kdm/kdmrc"), KConfig::SimpleConfig)
 
171
            .group("X-*-Greeter").readEntry("FaceDir",
 
172
                QString(KStandardDirs::installPath("data") + "kdm/faces" + '/'));
 
173
 
 
174
    int code = 0;
 
175
 
 
176
    switch (subaction) {
 
177
    case CreateFacesDir:
 
178
        code = (createDir(facesDir) ? 0 : CreateFacesDirError);
 
179
        break;
 
180
    case RemoveFace:
 
181
        code = (removeFace(facesDir, args.value("user").toString())
 
182
                ? 0 : RemoveFaceError);
 
183
        break;
 
184
    case InstallFace:
 
185
        code = (installFace(facesDir,
 
186
                            args.value("user").toString(),
 
187
                            args.value("sourcefile").toString())
 
188
                ? 0 : InstallFaceError);
 
189
        break;
 
190
    default:
 
191
        return ActionReply::HelperError;
 
192
    }
 
193
 
 
194
    return createReply(code);
 
195
}
 
196
 
 
197
bool Helper::removeThemes(const QString &themesDir, QStringList &themes)
 
198
{
 
199
    QDir testDir(themesDir);
 
200
    if (!testDir.exists())
 
201
        return false;
 
202
 
 
203
    bool res = true;
 
204
    for (QStringList::iterator theme = themes.begin(); theme < themes.end(); ++theme) {
 
205
        QFileInfo info(*theme);
 
206
        // Security check
 
207
        if (info.absoluteDir() != QDir(themesDir) || !info.exists()) {
 
208
            res = false;
 
209
            continue;
 
210
        }
 
211
 
 
212
        if (removeDirTree(info.absoluteFilePath()))
 
213
            *theme = QString();
 
214
        else
 
215
            res = false;
 
216
    }
 
217
 
 
218
    return res;
 
219
}
 
220
 
 
221
bool Helper::installThemes(const QString &themesDir, QStringList &themes)
 
222
{
 
223
    QDir testDir(themesDir);
 
224
    if (!testDir.exists())
 
225
        return false;
 
226
 
 
227
    bool res = true;
 
228
    for (QStringList::iterator theme = themes.begin(); theme < themes.end(); ) {
 
229
        QFileInfo info(*theme);
 
230
 
 
231
        if (!info.exists()) {
 
232
            res = false;
 
233
            ++theme;
 
234
            continue;
 
235
        }
 
236
 
 
237
        if (installDirTree(info.absoluteFilePath(), themesDir + info.fileName() + '/')) {
 
238
            theme = themes.erase(theme);
 
239
        } else {
 
240
            res = false;
 
241
            ++theme;
 
242
        }
 
243
    }
 
244
 
 
245
    return res;
 
246
}
 
247
 
 
248
ActionReply Helper::managethemes(const QVariantMap &args)
 
249
{
 
250
    int subaction = args.value("subaction").toInt();
 
251
    QString themesDir = KStandardDirs::installPath("data") + "kdm/themes/";
 
252
 
 
253
    int code = 0;
 
254
 
 
255
    switch (subaction) {
 
256
    case CreateThemesDir:
 
257
        code = (createDir(themesDir) ? 0 : CreateThemesDirError);
 
258
        return createReply(code);
 
259
    case RemoveThemes: {
 
260
        QStringList themes = args.value("themes").toStringList();
 
261
        code = (removeThemes(themesDir, themes) ? 0 : RemoveThemesError);
 
262
 
 
263
        QVariantMap returnData;
 
264
        returnData["themes"] = themes;
 
265
        return createReply(code, &returnData);
 
266
    }
 
267
    case InstallThemes: {
 
268
        QStringList themes = args.value("themes").toStringList();
 
269
        code = (installThemes(themesDir, themes) ? 0 : InstallThemesError);
 
270
 
 
271
        QVariantMap returnData;
 
272
        returnData["failedthemes"] = themes;
 
273
        return createReply(code, &returnData);
 
274
    }
 
275
    default:
 
276
        return ActionReply::HelperError;
 
277
    }
 
278
}
 
279
 
 
280
KDE4_AUTH_HELPER_MAIN("org.kde.kcontrol.kcmkdm", Helper)