File indexing completed on 2025-01-05 04:37:25

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003     SPDX-FileCopyrightText: 2005 Ivan Vasic <ivasic@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 #ifndef BTTORRENT_H
0008 #define BTTORRENT_H
0009 
0010 #include "torrentfile.h"
0011 #include <QList>
0012 #include <QUrl>
0013 #include <QVector>
0014 #include <interfaces/torrentinterface.h>
0015 #include <ktorrent_export.h>
0016 #include <peer/peerid.h>
0017 #include <util/constants.h>
0018 #include <util/sha1hash.h>
0019 
0020 class QTextCodec;
0021 
0022 namespace bt
0023 {
0024 class BNode;
0025 class BDictNode;
0026 class BListNode;
0027 
0028 struct TrackerTier {
0029     QList<QUrl> urls;
0030     TrackerTier *next;
0031 
0032     TrackerTier()
0033         : next(nullptr)
0034     {
0035     }
0036 
0037     ~TrackerTier()
0038     {
0039         delete next;
0040     }
0041 };
0042 
0043 /**
0044  * @author Joris Guisson
0045  *
0046  * Listener base class, to get notified when the priority of a file changes.
0047  */
0048 class KTORRENT_EXPORT FilePriorityListener
0049 {
0050 public:
0051     virtual ~FilePriorityListener()
0052     {
0053     }
0054 
0055     virtual void downloadPriorityChanged(TorrentFile *tf, Priority newpriority, Priority oldpriority) = 0;
0056 };
0057 
0058 /**
0059  * @author Joris Guisson
0060  * @brief Loads a .torrent file
0061  *
0062  * Loads a torrent file and calculates some miscelanious other data,
0063  * like the info_hash and the peer_id.
0064  */
0065 class KTORRENT_EXPORT Torrent
0066 {
0067 public:
0068     Torrent();
0069     Torrent(const bt::SHA1Hash &hash);
0070     virtual ~Torrent();
0071 
0072     /**
0073      * Set the FilePriorityListener
0074      * @param l THe listener
0075      */
0076     void setFilePriorityListener(FilePriorityListener *l)
0077     {
0078         file_prio_listener = l;
0079     }
0080 
0081     /**
0082      * Called by TorrentFile when the priority changes
0083      * @param tf The file
0084      * @param newpriority The old priority
0085      * @param oldpriority The new priority
0086      */
0087     void downloadPriorityChanged(TorrentFile *tf, Priority newpriority, Priority oldpriority);
0088 
0089     /**
0090      * Called by TorrentFile when the percentage changes
0091      * @param tf The file
0092      * @param perc The percentage
0093      */
0094     void filePercentageChanged(TorrentFile *tf, float perc);
0095 
0096     /**
0097      * Called by TorrentFile when the preview state changes
0098      * @param tf The file
0099      * @param preview Whether preview is possible or not
0100      */
0101     void filePreviewChanged(TorrentFile *tf, bool preview);
0102 
0103     /**
0104      * Load a .torrent file.
0105      * @param data The data
0106      * @param verbose Whether to print information to the log
0107      * @throw Error if something goes wrong
0108      */
0109     void load(const QByteArray &data, bool verbose);
0110 
0111     void debugPrintInfo();
0112 
0113     /// Return the comments in the torrent
0114     QString getComments() const
0115     {
0116         return comments;
0117     }
0118 
0119     /// Get the number of chunks.
0120     Uint32 getNumChunks() const
0121     {
0122         return hash_pieces.size();
0123     }
0124 
0125     /// Get the size of a chunk.
0126     Uint64 getChunkSize() const
0127     {
0128         return chunk_size;
0129     }
0130 
0131     /// Get the size of the last chunk
0132     Uint64 getLastChunkSize() const
0133     {
0134         return last_chunk_size;
0135     }
0136 
0137     /// Get the info_hash.
0138     const SHA1Hash &getInfoHash() const
0139     {
0140         return info_hash;
0141     }
0142 
0143     /// Get our peer_id.
0144     const PeerID &getPeerID() const
0145     {
0146         return peer_id;
0147     }
0148 
0149     /// Get the file size in number of bytes.
0150     Uint64 getTotalSize() const
0151     {
0152         return total_size;
0153     }
0154 
0155     /// Get the suggested name.
0156     QString getNameSuggestion() const
0157     {
0158         return name_suggestion;
0159     }
0160 
0161     /**
0162      * Verify whether a hash matches the hash
0163      * of a Chunk
0164      * @param h The hash
0165      * @param index The index of the chunk
0166      * @return true if they match
0167      */
0168     bool verifyHash(const SHA1Hash &h, Uint32 index);
0169 
0170     /// Get the number of tracker URL's
0171     unsigned int getNumTrackerURLs() const;
0172 
0173     /**
0174      * Get the hash of a Chunk. Throws an Error
0175      * if idx is out of bounds.
0176      * @param idx Index of Chunk
0177      * @return The SHA1 hash of the chunk
0178      */
0179     const SHA1Hash &getHash(Uint32 idx) const;
0180 
0181     /// See if we have a multi file torrent.
0182     bool isMultiFile() const
0183     {
0184         return files.count() > 0;
0185     }
0186 
0187     /// Get the number of files in a multi file torrent.
0188     /// If we have a single file torrent, this will return 0.
0189     Uint32 getNumFiles() const
0190     {
0191         return files.count();
0192     }
0193 
0194     /**
0195      * Get a TorrentFile. If the index is out of range, or
0196      * we have a single file torrent we return a null TorrentFile.
0197      * @param idx Index of the file
0198      * @param A reference to the file
0199      */
0200     TorrentFile &getFile(Uint32 idx);
0201 
0202     /**
0203      * Get a TorrentFile. If the index is out of range, or
0204      * we have a single file torrent we return a null TorrentFile.
0205      * @param idx Index of the file
0206      * @param A reference to the file
0207      */
0208     const TorrentFile &getFile(Uint32 idx) const;
0209 
0210     /**
0211      * Calculate in which file(s) a Chunk lies. A list will
0212      * get filled with the indices of all the files. The list gets cleared at
0213      * the beginning. If something is wrong only the list will
0214      * get cleared.
0215      * @param chunk The index of the chunk
0216      * @param file_list This list will be filled with all the indices
0217      */
0218     void calcChunkPos(Uint32 chunk, QList<Uint32> &file_list) const;
0219 
0220     /**
0221      * Checks if torrent file is audio or video.
0222      **/
0223     bool isMultimedia() const;
0224 
0225     /// See if the torrent is private
0226     bool isPrivate() const
0227     {
0228         return priv_torrent;
0229     }
0230 
0231     /// Is the torrent loaded
0232     bool isLoaded() const
0233     {
0234         return loaded;
0235     }
0236 
0237     /// Gets a pointer to AnnounceList
0238     const TrackerTier *getTrackerList() const
0239     {
0240         return trackers;
0241     }
0242 
0243     /// Get the number of initial DHT nodes
0244     Uint32 getNumDHTNodes() const
0245     {
0246         return nodes.count();
0247     }
0248 
0249     /// Get a DHT node
0250     const DHTNode &getDHTNode(Uint32 i)
0251     {
0252         return nodes[i];
0253     }
0254 
0255     /**
0256      * Update the percentage of all files.
0257      * @param cman The ChunkManager
0258      */
0259     void updateFilePercentage(ChunkManager &cman);
0260 
0261     /**
0262      * Update the percentage of a all files which have a particular chunk.
0263      * @param cman The ChunkManager
0264      */
0265     void updateFilePercentage(Uint32 chunk, ChunkManager &cman);
0266 
0267     /**
0268      * Get the list with web seed URL's
0269      */
0270     const QList<QUrl> &getWebSeeds() const
0271     {
0272         return web_seeds;
0273     }
0274 
0275     /// Change the text codec
0276     void changeTextCodec(QTextCodec *codec);
0277 
0278     /// Get the text codec
0279     const QTextCodec *getTextCodec()
0280     {
0281         return text_codec;
0282     }
0283 
0284     /// Set the monitor
0285     void setMonitor(MonitorInterface *m)
0286     {
0287         tmon = m;
0288     }
0289 
0290     /// Get the metadata
0291     const QByteArray &getMetaData() const
0292     {
0293         return metadata;
0294     }
0295 
0296 private:
0297     void loadInfo(BDictNode *node);
0298     void loadTrackerURL(const QString &s);
0299     void loadHash(BDictNode *dict);
0300     void loadFiles(BListNode *node);
0301     void loadNodes(BListNode *node);
0302     void loadAnnounceList(BNode *node);
0303     void loadWebSeeds(BListNode *node);
0304     bool checkPathForDirectoryTraversal(const QString &p);
0305 
0306 private:
0307     QString name_suggestion;
0308     QByteArray unencoded_name;
0309     QString comments;
0310     QByteArray metadata;
0311 
0312     SHA1Hash info_hash;
0313     QVector<SHA1Hash> hash_pieces;
0314     QVector<TorrentFile> files;
0315     QVector<DHTNode> nodes;
0316     QList<QUrl> web_seeds;
0317     PeerID peer_id;
0318 
0319     TrackerTier *trackers;
0320     Uint64 chunk_size;
0321     Uint64 last_chunk_size;
0322     Uint64 total_size;
0323     QTextCodec *text_codec;
0324     FilePriorityListener *file_prio_listener;
0325     mutable Uint32 pos_cache_chunk;
0326     mutable Uint32 pos_cache_file;
0327     MonitorInterface *tmon;
0328     bool priv_torrent;
0329     bool loaded;
0330 };
0331 
0332 }
0333 
0334 #endif