1#!/usr/bin/env python3
2from sys import exit
3from test.http_test import HTTPTest
4from misc.wget_file import WgetFile
5import hashlib
6from base64 import b64encode
7
8"""
9    This is to test Metalink/HTTP with Content-Type Metalink/XML.
10
11    With --trust-server-names, trust the metalink:file names.
12
13    Without --trust-server-names, don't trust the metalink:file names:
14    use the basename of --input-metalink, and add a sequential number
15    (e.g. .#1, .#2, etc.).
16
17    Strip the directory from unsafe paths.
18"""
19
20############# File Definitions ###############################################
21bad = "Ouch!"
22
23File1 = "Would you like some Tea?"
24File1_lowPref = "Do not take this"
25File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest ()
26
27File2 = "This is gonna be good"
28File2_lowPref = "Not this one too"
29File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest ()
30
31File3 = "A little more, please"
32File3_lowPref = "That's just too much"
33File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest ()
34
35File4 = "Maybe a biscuit?"
36File4_lowPref = "No, thanks"
37File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest ()
38
39File5 = "More Tea...?"
40File5_lowPref = "I have to go..."
41File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest ()
42
43MetaXml = \
44"""<?xml version="1.0" encoding="utf-8"?>
45<metalink version="3.0" xmlns="http://www.metalinker.org/">
46  <publisher>
47    <name>GNU Wget</name>
48  </publisher>
49  <license>
50    <name>GNU GPL</name>
51    <url>http://www.gnu.org/licenses/gpl.html</url>
52  </license>
53  <identity>Wget Test Files</identity>
54  <version>1.2.3</version>
55  <description>Wget Test Files description</description>
56  <files>
57    <file name="dir/File1">
58      <verification>
59        <hash type="sha256">{{FILE1_HASH}}</hash>
60      </verification>
61      <resources>
62        <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url>
63        <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url>
64        <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url>
65        <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url>
66      </resources>
67    </file>
68    <file name="dir/File2">
69      <verification>
70        <hash type="sha256">{{FILE2_HASH}}</hash>
71      </verification>
72      <resources>
73        <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url>
74        <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url>
75        <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url>
76        <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url>
77      </resources>
78    </file>
79    <file name="/dir/File3"> <!-- rejected by libmetalink -->
80      <verification>
81        <hash type="sha256">{{FILE3_HASH}}</hash>
82      </verification>
83      <resources>
84        <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url>
85        <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url>
86        <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url>
87        <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url>
88      </resources>
89    </file>
90    <file name="dir/File4">
91      <verification>
92        <hash type="sha256">{{FILE4_HASH}}</hash>
93      </verification>
94      <resources>
95        <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url>
96        <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url>
97        <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url>
98        <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url>
99      </resources>
100    </file>
101    <file name="dir/File5">
102      <verification>
103        <hash type="sha256">{{FILE5_HASH}}</hash>
104      </verification>
105      <resources>
106        <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url>
107        <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url>
108        <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url>
109        <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url>
110      </resources>
111    </file>
112  </files>
113</metalink>
114"""
115
116# This will be filled as soon as we know server hostname and port
117MetaHTTPRules = {'SendHeader' : {}}
118
119MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules)
120MetaHTTP_down = WgetFile ("main.metalink.meta#1", MetaXml)
121
122wrong_file = WgetFile ("wrong_file", bad)
123
124File1_orig = WgetFile ("File1", File1)
125File1_down = WgetFile ("main.metalink.meta#1.#1", File1)
126File1_nono = WgetFile ("File1_lowPref", File1_lowPref)
127
128File2_orig = WgetFile ("File2", File2)
129File2_down = WgetFile ("main.metalink.meta#1.#2", File2)
130File2_nono = WgetFile ("File2_lowPref", File2_lowPref)
131
132# rejected by libmetalink
133File3_orig = WgetFile ("File3", File3)
134File3_nono = WgetFile ("File3_lowPref", File3_lowPref)
135
136File4_orig = WgetFile ("File4", File4)
137File4_down = WgetFile ("main.metalink.meta#1.#3", File4)
138File4_nono = WgetFile ("File4_lowPref", File4_lowPref)
139
140File5_orig = WgetFile ("File5", File5)
141File5_down = WgetFile ("main.metalink.meta#1.#4", File5)
142File5_nono = WgetFile ("File5_lowPref", File5_lowPref)
143
144WGET_OPTIONS = "--metalink-over-http --metalink-index=0"
145WGET_URLS = [["main.metalink"]]
146
147RequestList = [[
148    "HEAD /main.metalink",
149    "GET /main.metalink",
150    "GET /404",
151    "GET /wrong_file",
152    "GET /File1",
153    "GET /File2",
154    "GET /File4",
155    "GET /File5"
156]]
157
158Files = [[
159    MetaHTTP,
160    wrong_file,
161    File1_orig, File1_nono,
162    File2_orig, File2_nono,
163    File3_orig, File3_nono,
164    File4_orig, File4_nono,
165    File5_orig, File5_nono
166]]
167Existing_Files = []
168
169ExpectedReturnCode = 0
170ExpectedDownloadedFiles = [
171    MetaHTTP_down,
172    File1_down,
173    File2_down,
174    File4_down,
175    File5_down
176]
177
178################ Pre and Post Test Hooks #####################################
179pre_test = {
180    "ServerFiles"       : Files,
181    "LocalFiles"        : Existing_Files
182}
183test_options = {
184    "WgetCommands"      : WGET_OPTIONS,
185    "Urls"              : WGET_URLS
186}
187post_test = {
188    "ExpectedFiles"     : ExpectedDownloadedFiles,
189    "ExpectedRetcode"   : ExpectedReturnCode,
190    "FilesCrawled"      : RequestList
191}
192
193http_test = HTTPTest (
194                pre_hook=pre_test,
195                test_params=test_options,
196                post_hook=post_test
197)
198
199http_test.server_setup()
200### Get and use dynamic server sockname
201srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname ()
202
203MetaXml = MetaXml.replace('{{FILE1_HASH}}', File1_sha256)
204MetaXml = MetaXml.replace('{{FILE2_HASH}}', File2_sha256)
205MetaXml = MetaXml.replace('{{FILE3_HASH}}', File3_sha256)
206MetaXml = MetaXml.replace('{{FILE4_HASH}}', File4_sha256)
207MetaXml = MetaXml.replace('{{FILE5_HASH}}', File5_sha256)
208MetaXml = MetaXml.replace('{{SRV_HOST}}', srv_host)
209MetaXml = MetaXml.replace('{{SRV_PORT}}', str (srv_port))
210MetaHTTP_down.content = MetaXml
211
212MetaHTTP.content = MetaXml
213
214MetaHTTPRules["SendHeader"] = {
215    'Content-Type': 'application/metalink4+xml',
216    'Content-Disposition': 'filename="newname.metalink"'
217}
218
219err = http_test.begin ()
220
221exit (err)
222