File indexing completed on 2024-06-16 04:55:55

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     crypto/checksumsutils_p.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "checksumsutils_p.h"
0011 #include <Libkleo/ChecksumDefinition>
0012 
0013 #include <QFile>
0014 #include <QTextStream>
0015 
0016 std::vector<QRegularExpression> ChecksumsUtils::get_patterns(const std::vector<std::shared_ptr<Kleo::ChecksumDefinition>> &checksumDefinitions)
0017 {
0018     std::vector<QRegularExpression> result;
0019     for (const auto &cd : checksumDefinitions) {
0020         if (!cd) {
0021             continue;
0022         }
0023         const QStringList &patterns = cd->patterns();
0024         result.reserve(result.size() + patterns.size());
0025         std::transform(patterns.cbegin(), patterns.cend(), std::back_inserter(result), [](const QString &pattern) {
0026             return QRegularExpression(QRegularExpression::anchoredPattern(pattern), s_regex_cs);
0027         });
0028     }
0029 
0030     return result;
0031 }
0032 
0033 static QString decode(const QString &encoded)
0034 {
0035     QString decoded;
0036     decoded.reserve(encoded.size());
0037     bool shift = false;
0038     for (const QChar ch : encoded)
0039         if (shift) {
0040             switch (ch.toLatin1()) {
0041             case '\\':
0042                 decoded += QLatin1Char('\\');
0043                 break;
0044             case 'n':
0045                 decoded += QLatin1Char('\n');
0046                 break;
0047             default:
0048                 qCDebug(KLEOPATRA_LOG) << "invalid escape sequence" << '\\' << ch << "(interpreted as '" << ch << "')";
0049                 decoded += ch;
0050                 break;
0051             }
0052             shift = false;
0053         } else {
0054             if (ch == QLatin1Char('\\')) {
0055                 shift = true;
0056             } else {
0057                 decoded += ch;
0058             }
0059         }
0060     return decoded;
0061 }
0062 
0063 std::vector<ChecksumsUtils::File> ChecksumsUtils::parse_sum_file(const QString &fileName)
0064 {
0065     std::vector<File> files;
0066     QFile f(fileName);
0067     if (!f.open(QIODevice::ReadOnly)) {
0068         return {};
0069     }
0070 
0071     QTextStream s(&f);
0072     static const QRegularExpression rx(QRegularExpression::anchoredPattern(uR"((\\?)([a-f0-9A-F]+) ([ *])([^\\n]+)\\n*)"));
0073     while (!s.atEnd()) {
0074         const QString line = s.readLine();
0075         QRegularExpressionMatch match = rx.match(line);
0076         if (!match.hasMatch()) {
0077             continue;
0078         }
0079 
0080         Q_ASSERT(!match.capturedView(4).endsWith(QLatin1Char('\n')));
0081         const File file = {
0082             match.capturedView(1) == QLatin1Char('\\') ? decode(match.captured(4)) : match.captured(4),
0083             match.capturedView(2).toLatin1(),
0084             match.capturedView(3) == QLatin1Char('*'),
0085         };
0086         files.push_back(file);
0087     }
0088 
0089     return files;
0090 }
0091 
0092 std::shared_ptr<Kleo::ChecksumDefinition> ChecksumsUtils::filename2definition(const QString &fileName,
0093                                                                               const std::vector<std::shared_ptr<Kleo::ChecksumDefinition>> &checksumDefinitions)
0094 {
0095     auto matchFileName = [&fileName](const std::shared_ptr<Kleo::ChecksumDefinition> &cd) {
0096         if (!cd) {
0097             return false;
0098         }
0099 
0100         const QStringList &patterns = cd->patterns();
0101         return std::any_of(patterns.cbegin(), patterns.cend(), [&fileName](const QString &pattern) {
0102             const QRegularExpression re(QRegularExpression::anchoredPattern(pattern), s_regex_cs);
0103             return re.match(fileName).hasMatch();
0104         });
0105     };
0106 
0107     auto it = std::find_if(checksumDefinitions.cbegin(), checksumDefinitions.cend(), matchFileName);
0108 
0109     return it != checksumDefinitions.cend() ? *it : std::shared_ptr<Kleo::ChecksumDefinition>{};
0110 }