File indexing completed on 2024-04-28 15:18:45
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(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 // It's UTF-8 by default in Qt6 0036 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0037 ini.setIniCodec("UTF-8"); 0038 #endif 0039 if (ini.status()) { 0040 qCritical("Error loading file: %s", argv[1]); 0041 return 1; 0042 } 0043 0044 if (argc == 3) { 0045 // Support an optional 2nd argument pointing to the output file 0046 // 0047 // This is safer to use in build systems than 0048 // "kauth-policy-gen foo.actions > foo.policy" because when using a 0049 // redirection "foo.policy" is created even if kauth-policy-gen fails. 0050 // This means the first call to make fails, but a second call succeeds 0051 // because an empty "foo.policy" exists. 0052 if (!freopen(argv[2], "w", stdout)) { 0053 qCritical("Failed to open %s for writing: %s", argv[2], strerror(errno)); 0054 return 1; 0055 } 0056 } 0057 0058 output(parse(ini), parseDomain(ini)); 0059 } 0060 0061 QList<Action> parse(QSettings &ini) 0062 { 0063 QList<Action> actions; 0064 0065 // example: [org.kde.kcontrol.kcmfoo.save] 0066 const QRegularExpression actionExp(QRegularExpression::anchoredPattern(QStringLiteral("[0-9a-z]+(\\.[0-9a-z]+)*"))); 0067 0068 // example: Description[ca]=Mòdul de control del Foo. 0069 const QRegularExpression descriptionExp(QRegularExpression::anchoredPattern(QStringLiteral("description(?:\\[(\\w+)\\])?")), 0070 QRegularExpression::CaseInsensitiveOption); 0071 0072 // example: Name[ca]=Mòdul de control del Foo 0073 const QRegularExpression nameExp(QRegularExpression::anchoredPattern(QStringLiteral("name(?:\\[(\\w+)\\])?")), QRegularExpression::CaseInsensitiveOption); 0074 0075 // example: Policy=auth_admin 0076 const QRegularExpression policyExp(QRegularExpression::anchoredPattern(QStringLiteral("(?:yes|no|auth_self|auth_admin)"))); 0077 0078 const auto listChilds = ini.childGroups(); 0079 for (const QString &name : listChilds) { 0080 Action action; 0081 0082 if (name == QLatin1String("Domain")) { 0083 continue; 0084 } 0085 0086 if (!actionExp.match(name).hasMatch()) { 0087 qCritical("Wrong action syntax: %s\n", name.toLatin1().data()); 0088 exit(1); 0089 } 0090 0091 action.name = name; 0092 ini.beginGroup(name); 0093 0094 const auto listChildKeys = ini.childKeys(); 0095 for (const QString &key : listChildKeys) { 0096 QRegularExpressionMatch match; 0097 if ((match = descriptionExp.match(key)).hasMatch()) { 0098 QString lang = match.captured(1); 0099 0100 if (lang.isEmpty()) { 0101 lang = QString::fromLatin1("en"); 0102 } 0103 0104 action.descriptions.insert(lang, ini.value(key).toString()); 0105 0106 } else if ((match = nameExp.match(key)).hasMatch()) { 0107 QString lang = match.captured(1); 0108 0109 if (lang.isEmpty()) { 0110 lang = QString::fromLatin1("en"); 0111 } 0112 0113 action.messages.insert(lang, ini.value(key).toString()); 0114 0115 } else if (key.toLower() == QLatin1String("policy")) { 0116 QString policy = ini.value(key).toString(); 0117 if (!policyExp.match(policy).hasMatch()) { 0118 qCritical("Wrong policy: %s", policy.toLatin1().data()); 0119 exit(1); 0120 } 0121 action.policy = policy; 0122 0123 } else if (key.toLower() == QLatin1String("policyinactive")) { 0124 QString policyInactive = ini.value(key).toString(); 0125 if (!policyExp.match(policyInactive).hasMatch()) { 0126 qCritical("Wrong policy: %s", policyInactive.toLatin1().data()); 0127 exit(1); 0128 } 0129 action.policyInactive = policyInactive; 0130 0131 } else if (key.toLower() == QLatin1String("persistence")) { 0132 QString persistence = ini.value(key).toString(); 0133 if (persistence != QLatin1String("session") && persistence != QLatin1String("always")) { 0134 qCritical("Wrong persistence: %s", persistence.toLatin1().data()); 0135 exit(1); 0136 } 0137 action.persistence = persistence; 0138 } 0139 } 0140 0141 if (action.policy.isEmpty() || action.messages.isEmpty() || action.descriptions.isEmpty()) { 0142 qCritical("Missing option in action: %s", name.toLatin1().data()); 0143 exit(1); 0144 } 0145 ini.endGroup(); 0146 0147 actions.append(action); 0148 } 0149 0150 return actions; 0151 } 0152 0153 QMap<QString, QString> parseDomain(QSettings &ini) 0154 { 0155 QMap<QString, QString> rethash; 0156 0157 if (ini.childGroups().contains(QString::fromLatin1("Domain"))) { 0158 if (ini.contains(QString::fromLatin1("Domain/Name"))) { 0159 rethash[QString::fromLatin1("vendor")] = ini.value(QString::fromLatin1("Domain/Name")).toString(); 0160 } 0161 if (ini.contains(QString::fromLatin1("Domain/URL"))) { 0162 rethash[QString::fromLatin1("vendorurl")] = ini.value(QString::fromLatin1("Domain/URL")).toString(); 0163 } 0164 if (ini.contains(QString::fromLatin1("Domain/Icon"))) { 0165 rethash[QString::fromLatin1("icon")] = ini.value(QString::fromLatin1("Domain/Icon")).toString(); 0166 } 0167 } 0168 0169 return rethash; 0170 }