File indexing completed on 2024-04-14 04:52:02

0001 /**************************************************************************
0002  *   Copyright (C) 2009-2011 Matthias Fuchs <mat69@gmx.net>                *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0018  ***************************************************************************/
0019 
0020 #ifndef VERIFIER_H
0021 #define VERIFIER_H
0022 
0023 #include <QUrl>
0024 #include <kio/global.h>
0025 
0026 #include <QHash>
0027 #include <QModelIndex>
0028 #include <QStringList>
0029 
0030 #include "kget_export.h"
0031 
0032 class QDomElement;
0033 class VerificationModel;
0034 class VerifierPrivate;
0035 typedef QPair<QString, QString> Checksum;
0036 
0037 class KGET_EXPORT PartialChecksums
0038 {
0039 public:
0040     PartialChecksums()
0041         : m_length(0)
0042     {
0043     }
0044 
0045     PartialChecksums(KIO::filesize_t len, const QStringList &sums)
0046         : m_length(len)
0047         , m_checksums(sums)
0048     {
0049     }
0050 
0051     bool isValid() const
0052     {
0053         return (length() && m_checksums.count());
0054     }
0055 
0056     KIO::filesize_t length() const
0057     {
0058         return m_length;
0059     }
0060     void setLength(KIO::filesize_t length)
0061     {
0062         m_length = length;
0063     }
0064 
0065     QStringList checksums() const
0066     {
0067         return m_checksums;
0068     }
0069     void setChecksums(const QStringList &checksums)
0070     {
0071         m_checksums = checksums;
0072     }
0073 
0074 private:
0075     KIO::filesize_t m_length;
0076     QStringList m_checksums;
0077 };
0078 
0079 Q_DECLARE_METATYPE(PartialChecksums)
0080 
0081 class KGET_EXPORT Verifier : public QObject
0082 {
0083     Q_OBJECT
0084 
0085 public:
0086     explicit Verifier(const QUrl &dest, QObject *parent = nullptr);
0087     ~Verifier() override;
0088 
0089     enum VerificationStatus {
0090         NoResult, // either not tried, or not enough information
0091         NotVerified,
0092         Verified
0093     };
0094 
0095     enum ChecksumStrength { Weak, Strong, Strongest };
0096 
0097     /**
0098      * @returns the object path that will be shown in the DBUS interface
0099      */
0100     QString dBusObjectPath() const;
0101 
0102     QUrl destination() const;
0103     void setDestination(const QUrl &destination); // TODO handle the case when m_thread is working, while the file gets moved
0104 
0105     VerificationStatus status() const;
0106 
0107     /**
0108      * Returns the supported verification types
0109      * @return the supported verification types (e.g. MD5, SHA1 ...)
0110      */
0111     static QStringList supportedVerficationTypes();
0112 
0113     /**
0114      * Returns the diggest length of type
0115      * @param type the checksum type for which to get the diggest length
0116      * @return the length the diggest should have
0117      */
0118     static int diggestLength(const QString &type);
0119 
0120     /**
0121      * Tries to check if the checksum is a checksum and if it is supported
0122      * it compares the diggestLength and checks if there are only alphanumerics in checksum
0123      * @param type of the checksum
0124      * @param checksum the checksum you want to check
0125      */
0126     static bool isChecksum(const QString &type, const QString &checksum);
0127 
0128     /**
0129      * Cleans the checksum type, that it should match the official name, i.e. upper case
0130      * e.g. SHA-1 instead of sha1
0131      */
0132     static QString cleanChecksumType(const QString &type);
0133 
0134     /**
0135      * Creates the checksum type of the file @p dest
0136      * @param dest the destination
0137      * @param type the type of the checksum
0138      * @param abortPtr makes it possible to abort the calculation of the checksum from another thread
0139      */
0140     static QString checksum(const QUrl &dest, const QString &type, bool *abortPtr);
0141 
0142     /**
0143      * Create partial checksums of type for file @p dest
0144      * @param dest the destination
0145      * @param type the type of the checksum
0146      * @param length the file length
0147      * @param abortPtr makes it possible to abort the calculation of the checksums from another thread
0148      * @note the length of the partial checksum (if not defined = 0) is not less than 512 kb
0149      * and there won't be more partial checksums than 101
0150      */
0151     static PartialChecksums partialChecksums(const QUrl &dest, const QString &type, KIO::filesize_t length = 0, bool *abortPtr = nullptr);
0152 
0153     /**
0154      * @note only call verify() when this function returns true
0155      * @return true if the downloaded file exists and a supported checksum is set
0156      */
0157     bool isVerifyable() const;
0158 
0159     /**
0160      * Convenience function if only a row of the model should be checked
0161      * @note only call verify() when this function returns true
0162      * @param index the row in the model of the checksum
0163      * @return true if the downloaded file exists and a supported checksum is set
0164      */
0165     bool isVerifyable(const QModelIndex &index) const;
0166 
0167     /**
0168      * Call this method if you want to verify() in its own thread, then signals with
0169      * the result are emitted
0170      * @param index row of the model should be checked, if not defined the a checkum defined by
0171      * Verifier::ChecksumStrength will be used
0172      */
0173     void verify(const QModelIndex &index = QModelIndex());
0174 
0175     /**
0176      * Call this method after calling verify() with a negative result, it will
0177      * Q_EMIT a list of the broken pieces, if PartialChecksums were defined,
0178      * otherwise and in case of any error an empty list will be emitted
0179      */
0180     void brokenPieces() const;
0181 
0182     /**
0183      * Add a checksum that is later used in the verification process
0184      * @note only one checksum per type can be added (one MD5, one SHA1 etc.),
0185      * the newer overwrites the older and a checksum can only be added if it is
0186      * supported by the verifier
0187      * @param type the type of the checksum
0188      * @param checksum the checksum
0189      * @param verified if the file has been verified using this checksum
0190      * @note uses VerificationModel internally
0191      * @see VerificationModel
0192      */
0193     void addChecksum(const QString &type, const QString &checksum, int verified = 0);
0194 
0195     /**
0196      * Add multiple checksums that will later be used in the verification process
0197      * @note only one checksum per type can be added (one MD5, one SHA1 etc.),
0198      * the newer overwrites the older and a checksum can only be added if it is
0199      * supported by the verifier
0200      * @param checksums <type, checksum>
0201      * @note uses VerificationModel internally
0202      * @see VerificationModel
0203      */
0204     void addChecksums(const QMultiHash<QString, QString> &checksums);
0205 
0206     /**
0207      * Add partial checksums that can be used as repairinformation
0208      * @note only one checksum per type can be added (one MD5, one SHA1 etc.),
0209      * the newer overwrites the older and a checksum can only be added if it is
0210      * supported by the verifier
0211      * @param type the type of the checksums
0212      * @param length the length of each piece
0213      * @param checksums the checksums, first entry is piece number 0
0214      */
0215     void addPartialChecksums(const QString &type, KIO::filesize_t length, const QStringList &checksums);
0216 
0217     /**
0218      * Returns the length of the "best" partialChecksums
0219      */
0220     KIO::filesize_t partialChunkLength() const;
0221 
0222     /**
0223      * Returns a checksum and a type
0224      * @param strength the strength the checksum-type should have;
0225      * weak is md5 > md4 (md5 preferred), strong is sha1 > ripmed160 >
0226      * sha256 > sha384 > sha512 (sha1 preferred), strongest is sha512 >
0227      * sha384 > sha256 .... < (sha512 preferred)
0228      * If the category does not match then any checksum is taken
0229      */
0230     Checksum availableChecksum(ChecksumStrength strength) const;
0231 
0232     /**
0233      * Returns all set checksums
0234      */
0235     QList<Checksum> availableChecksums() const;
0236 
0237     /**
0238      * Returns a PartialChecksum and a type
0239      * @param strength the strength the checksum-type should have;
0240      * weak is md5 > md4 > ... (md5 preferred), strong is sha1 > ripmed160 >
0241      * sha256 > sha384 > sha512 > ... (sha1 preferred), strongest is sha512 >
0242      * sha384 > sha256 ... (sha512 preferred)
0243      * If the category does not match then any checksum is taken
0244      */
0245     QPair<QString, PartialChecksums *> availablePartialChecksum(Verifier::ChecksumStrength strength) const;
0246 
0247     /**
0248      * @return the model that stores the hash-types and checksums
0249      */
0250     VerificationModel *model();
0251 
0252     void save(const QDomElement &element);
0253     void load(const QDomElement &e);
0254 
0255 Q_SIGNALS:
0256     /**
0257      * Emitted when the verification of a file finishes
0258      */
0259     void verified(bool verified);
0260 
0261     /**
0262      * Emitted when brokenPiecesThreaded finishes, the list can be empty, while length will be always set
0263      */
0264     void brokenPieces(const QList<KIO::fileoffset_t> &offsets, KIO::filesize_t length);
0265 
0266 private Q_SLOTS:
0267     void changeStatus(const QString &type, bool verified);
0268 
0269 private:
0270     VerifierPrivate *const d;
0271 
0272     friend class VerifierPrivate;
0273 };
0274 
0275 #endif // VERIFIER_H