File indexing completed on 2024-04-14 03:50:32
0001 /* 0002 SPDX-FileCopyrightText: 2008 Nicola Gigante <nicola.gigante@gmail.com> 0003 SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "policy-gen.h" 0009 0010 #include <QCoreApplication> 0011 #include <QDebug> 0012 #include <QFile> 0013 #include <QRegularExpression> 0014 #include <QSettings> 0015 #include <QStringList> 0016 0017 #include <cerrno> 0018 #include <cstdio> 0019 0020 using namespace std; 0021 0022 QList<Action> parse(QSettings &ini); 0023 QMap<QString, QString> parseDomain(const QSettings &ini); 0024 0025 int main(int argc, char **argv) 0026 { 0027 QCoreApplication app(argc, argv); 0028 0029 if (argc < 2) { 0030 qCritical("Too few arguments"); 0031 return 1; 0032 } 0033 0034 QSettings ini(QFile::decodeName(argv[1]), QSettings::IniFormat); 0035 if (ini.status()) { 0036 qCritical("Error loading file: %s", argv[1]); 0037 return 1; 0038 } 0039 0040 if (argc == 3) { 0041 // Support an optional 2nd argument pointing to the output file 0042 // 0043 // This is safer to use in build systems than 0044 // "kauth-policy-gen foo.actions > foo.policy" because when using a 0045 // redirection "foo.policy" is created even if kauth-policy-gen fails. 0046 // This means the first call to make fails, but a second call succeeds 0047 // because an empty "foo.policy" exists. 0048 if (!freopen(argv[2], "w", stdout)) { 0049 qCritical("Failed to open %s for writing: %s", argv[2], strerror(errno)); 0050 return 1; 0051 } 0052 } 0053 0054 output(parse(ini), parseDomain(ini)); 0055 } 0056 0057 QList<Action> parse(QSettings &ini) 0058 { 0059 QList<Action> actions; 0060 0061 // example: [org.kde.kcontrol.kcmfoo.save] 0062 const QRegularExpression actionExp(QRegularExpression::anchoredPattern(QStringLiteral("[0-9a-z]+(\\.[0-9a-z]+)*"))); 0063 0064 // example: Description[ca]=Mòdul de control del Foo. 0065 const QRegularExpression descriptionExp(QRegularExpression::anchoredPattern(QStringLiteral("description(?:\\[(\\w+)\\])?")), 0066 QRegularExpression::CaseInsensitiveOption); 0067 0068 // example: Name[ca]=Mòdul de control del Foo 0069 const QRegularExpression nameExp(QRegularExpression::anchoredPattern(QStringLiteral("name(?:\\[(\\w+)\\])?")), QRegularExpression::CaseInsensitiveOption); 0070 0071 // example: Policy=auth_admin 0072 const QRegularExpression policyExp(QRegularExpression::anchoredPattern(QStringLiteral("(?:yes|no|auth_self|auth_admin)"))); 0073 0074 const auto listChilds = ini.childGroups(); 0075 for (const QString &name : listChilds) { 0076 Action action; 0077 0078 if (name == QLatin1String("Domain")) { 0079 continue; 0080 } 0081 0082 if (!actionExp.match(name).hasMatch()) { 0083 qCritical("Wrong action syntax: %s\n", name.toLatin1().data()); 0084 exit(1); 0085 } 0086 0087 action.name = name; 0088 ini.beginGroup(name); 0089 0090 const auto listChildKeys = ini.childKeys(); 0091 for (const QString &key : listChildKeys) { 0092 QRegularExpressionMatch match; 0093 if ((match = descriptionExp.match(key)).hasMatch()) { 0094 QString lang = match.captured(1); 0095 0096 if (lang.isEmpty()) { 0097 lang = QString::fromLatin1("en"); 0098 } 0099 0100 action.descriptions.insert(lang, ini.value(key).toString()); 0101 0102 } else if ((match = nameExp.match(key)).hasMatch()) { 0103 QString lang = match.captured(1); 0104 0105 if (lang.isEmpty()) { 0106 lang = QString::fromLatin1("en"); 0107 } 0108 0109 action.messages.insert(lang, ini.value(key).toString()); 0110 0111 } else if (key.toLower() == QLatin1String("policy")) { 0112 QString policy = ini.value(key).toString(); 0113 if (!policyExp.match(policy).hasMatch()) { 0114 qCritical("Wrong policy: %s", policy.toLatin1().data()); 0115 exit(1); 0116 } 0117 action.policy = policy; 0118 0119 } else if (key.toLower() == QLatin1String("policyinactive")) { 0120 QString policyInactive = ini.value(key).toString(); 0121 if (!policyExp.match(policyInactive).hasMatch()) { 0122 qCritical("Wrong policy: %s", policyInactive.toLatin1().data()); 0123 exit(1); 0124 } 0125 action.policyInactive = policyInactive; 0126 0127 } else if (key.toLower() == QLatin1String("persistence")) { 0128 QString persistence = ini.value(key).toString(); 0129 if (persistence != QLatin1String("session") && persistence != QLatin1String("always")) { 0130 qCritical("Wrong persistence: %s", persistence.toLatin1().data()); 0131 exit(1); 0132 } 0133 action.persistence = persistence; 0134 } 0135 } 0136 0137 if (action.policy.isEmpty() || action.messages.isEmpty() || action.descriptions.isEmpty()) { 0138 qCritical("Missing option in action: %s", name.toLatin1().data()); 0139 exit(1); 0140 } 0141 ini.endGroup(); 0142 0143 actions.append(action); 0144 } 0145 0146 return actions; 0147 } 0148 0149 QMap<QString, QString> parseDomain(const QSettings &ini) 0150 { 0151 QMap<QString, QString> rethash; 0152 0153 if (ini.childGroups().contains(QString::fromLatin1("Domain"))) { 0154 if (ini.contains(QString::fromLatin1("Domain/Name"))) { 0155 rethash[QString::fromLatin1("vendor")] = ini.value(QString::fromLatin1("Domain/Name")).toString(); 0156 } 0157 if (ini.contains(QString::fromLatin1("Domain/URL"))) { 0158 rethash[QString::fromLatin1("vendorurl")] = ini.value(QString::fromLatin1("Domain/URL")).toString(); 0159 } 0160 if (ini.contains(QString::fromLatin1("Domain/Icon"))) { 0161 rethash[QString::fromLatin1("icon")] = ini.value(QString::fromLatin1("Domain/Icon")).toString(); 0162 } 0163 } 0164 0165 return rethash; 0166 }