1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the examples of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "bencodeparser.h" |
52 | #include "metainfo.h" |
53 | |
54 | #include <QDateTime> |
55 | #include <QMetaType> |
56 | #include <QString> |
57 | |
58 | MetaInfo::MetaInfo() |
59 | { |
60 | clear(); |
61 | } |
62 | |
63 | void MetaInfo::clear() |
64 | { |
65 | errString = "Unknown error" ; |
66 | content.clear(); |
67 | infoData.clear(); |
68 | metaInfoMultiFiles.clear(); |
69 | metaInfoAnnounce.clear(); |
70 | metaInfoAnnounceList.clear(); |
71 | metaInfoCreationDate = QDateTime(); |
72 | metaInfoComment.clear(); |
73 | metaInfoCreatedBy.clear(); |
74 | metaInfoName.clear(); |
75 | metaInfoPieceLength = 0; |
76 | metaInfoSha1Sums.clear(); |
77 | } |
78 | |
79 | bool MetaInfo::parse(const QByteArray &data) |
80 | { |
81 | clear(); |
82 | content = data; |
83 | |
84 | BencodeParser parser; |
85 | if (!parser.parse(content)) { |
86 | errString = parser.errorString(); |
87 | return false; |
88 | } |
89 | |
90 | infoData = parser.infoSection(); |
91 | |
92 | QMap<QByteArray, QVariant> dict = parser.dictionary(); |
93 | if (!dict.contains(akey: "info" )) |
94 | return false; |
95 | |
96 | QMap<QByteArray, QVariant> info = qvariant_cast<Dictionary>(v: dict.value(akey: "info" )); |
97 | |
98 | if (info.contains(akey: "files" )) { |
99 | metaInfoFileForm = MultiFileForm; |
100 | |
101 | QList<QVariant> files = info.value(akey: "files" ).toList(); |
102 | |
103 | for (int i = 0; i < files.size(); ++i) { |
104 | const QMap<QByteArray, QVariant> file = qvariant_cast<Dictionary>(v: files.at(i)); |
105 | const QList<QVariant> pathElements = file.value(akey: "path" ).toList(); |
106 | QByteArray path; |
107 | for (const QVariant &p : pathElements) { |
108 | if (!path.isEmpty()) |
109 | path += '/'; |
110 | path += p.toByteArray(); |
111 | } |
112 | |
113 | MetaInfoMultiFile multiFile; |
114 | multiFile.length = file.value(akey: "length" ).toLongLong(); |
115 | multiFile.path = QString::fromUtf8(str: path); |
116 | multiFile.md5sum = file.value(akey: "md5sum" ).toByteArray(); |
117 | metaInfoMultiFiles << multiFile; |
118 | } |
119 | |
120 | metaInfoName = QString::fromUtf8(str: info.value(akey: "name" ).toByteArray()); |
121 | metaInfoPieceLength = info.value(akey: "piece length" ).toInt(); |
122 | QByteArray pieces = info.value(akey: "pieces" ).toByteArray(); |
123 | for (int i = 0; i < pieces.size(); i += 20) |
124 | metaInfoSha1Sums << pieces.mid(index: i, len: 20); |
125 | } else if (info.contains(akey: "length" )) { |
126 | metaInfoFileForm = SingleFileForm; |
127 | metaInfoSingleFile.length = info.value(akey: "length" ).toLongLong(); |
128 | metaInfoSingleFile.md5sum = info.value(akey: "md5sum" ).toByteArray(); |
129 | metaInfoSingleFile.name = QString::fromUtf8(str: info.value(akey: "name" ).toByteArray()); |
130 | metaInfoSingleFile.pieceLength = info.value(akey: "piece length" ).toInt(); |
131 | |
132 | QByteArray pieces = info.value(akey: "pieces" ).toByteArray(); |
133 | for (int i = 0; i < pieces.size(); i += 20) |
134 | metaInfoSingleFile.sha1Sums << pieces.mid(index: i, len: 20); |
135 | } |
136 | |
137 | metaInfoAnnounce = QString::fromUtf8(str: dict.value(akey: "announce" ).toByteArray()); |
138 | |
139 | if (dict.contains(akey: "announce-list" )) { |
140 | // ### unimplemented |
141 | } |
142 | |
143 | if (dict.contains(akey: "creation date" )) |
144 | metaInfoCreationDate.setSecsSinceEpoch(dict.value(akey: "creation date" ).toInt()); |
145 | if (dict.contains(akey: "comment" )) |
146 | metaInfoComment = QString::fromUtf8(str: dict.value(akey: "comment" ).toByteArray()); |
147 | if (dict.contains(akey: "created by" )) |
148 | metaInfoCreatedBy = QString::fromUtf8(str: dict.value(akey: "created by" ).toByteArray()); |
149 | |
150 | return true; |
151 | } |
152 | |
153 | QByteArray MetaInfo::infoValue() const |
154 | { |
155 | return infoData; |
156 | } |
157 | |
158 | QString MetaInfo::errorString() const |
159 | { |
160 | return errString; |
161 | } |
162 | |
163 | MetaInfo::FileForm MetaInfo::fileForm() const |
164 | { |
165 | return metaInfoFileForm; |
166 | } |
167 | |
168 | QString MetaInfo::announceUrl() const |
169 | { |
170 | return metaInfoAnnounce; |
171 | } |
172 | |
173 | QStringList MetaInfo::announceList() const |
174 | { |
175 | return metaInfoAnnounceList; |
176 | } |
177 | |
178 | QDateTime MetaInfo::creationDate() const |
179 | { |
180 | return metaInfoCreationDate; |
181 | } |
182 | |
183 | QString MetaInfo::() const |
184 | { |
185 | return metaInfoComment; |
186 | } |
187 | |
188 | QString MetaInfo::createdBy() const |
189 | { |
190 | return metaInfoCreatedBy; |
191 | } |
192 | |
193 | MetaInfoSingleFile MetaInfo::singleFile() const |
194 | { |
195 | return metaInfoSingleFile; |
196 | } |
197 | |
198 | QList<MetaInfoMultiFile> MetaInfo::multiFiles() const |
199 | { |
200 | return metaInfoMultiFiles; |
201 | } |
202 | |
203 | QString MetaInfo::name() const |
204 | { |
205 | return metaInfoName; |
206 | } |
207 | |
208 | int MetaInfo::pieceLength() const |
209 | { |
210 | return metaInfoPieceLength; |
211 | } |
212 | |
213 | QList<QByteArray> MetaInfo::sha1Sums() const |
214 | { |
215 | return metaInfoSha1Sums; |
216 | } |
217 | |
218 | qint64 MetaInfo::totalSize() const |
219 | { |
220 | if (fileForm() == SingleFileForm) |
221 | return singleFile().length; |
222 | |
223 | qint64 size = 0; |
224 | for (const MetaInfoMultiFile &file : metaInfoMultiFiles) |
225 | size += file.length; |
226 | return size; |
227 | } |
228 | |