Project

General

Profile

Download (9.6 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / test / haketilo_test / world_wide_library.py @ 57ce414c

1 5b2a7a61 Wojtek Kosior
# SPDX-License-Identifier: AGPL-3.0-or-later
2
3
"""
4
Our helpful little stand-in for the Internet
5
"""
6
7
# This file is part of Haketilo.
8
#
9
# Copyright (C) 2021 jahoti <jahoti@tilde.team>
10
# Copyright (C) 2021 Wojtek Kosior <koszko@koszko.org>
11
#
12
# This program is free software: you can redistribute it and/or modify
13
# it under the terms of the GNU Affero General Public License as
14
# published by the Free Software Foundation, either version 3 of the
15
# License, or (at your option) any later version.
16
#
17
# This program is distributed in the hope that it will be useful,
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
# GNU Affero General Public License for more details.
21
#
22
# You should have received a copy of the GNU Affero General Public License
23
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
24
#
25
#
26
# I, Wojtek Kosior, thereby promise not to sue for violation of this
27 372d24ea Wojtek Kosior
# file's license. Although I request that you do not make use of this code
28 5b2a7a61 Wojtek Kosior
# in a proprietary program, I am not going to enforce this in court.
29
30 702eefd2 Wojtek Kosior
from hashlib import sha256
31
from pathlib import Path
32
from shutil import rmtree
33
from threading import Lock
34 7218849a Wojtek Kosior
from uuid import uuid4
35 046b8a7b Wojtek Kosior
import json
36 702eefd2 Wojtek Kosior
37 5b2a7a61 Wojtek Kosior
from .misc_constants import here
38 7218849a Wojtek Kosior
from .unit.utils import * # sample repo data
39
40
# TODO: instead of having the entire catalog defined here, make it possible to
41
# add catalog items from within individual test files.
42 5b2a7a61 Wojtek Kosior
43 702eefd2 Wojtek Kosior
served_scripts = {}
44
served_scripts_lock = Lock()
45
46
def start_serving_script(script_text):
47
    """
48
    Register given script so that it is served at
49
    https://serve.scrip.ts/?sha256=<script's_sha256_sum>
50
51
    Returns the URL at which script will be served.
52
53
    This function lacks thread safety. Might moght consider fixing this if it
54
    turns
55
    """
56
    sha256sum = sha256(script_text.encode()).digest().hex()
57
    served_scripts_lock.acquire()
58
    served_scripts[sha256sum] = script_text
59
    served_scripts_lock.release()
60
61
    return f'https://serve.scrip.ts/?sha256={sha256sum}'
62
63
def serve_script(command, get_params, post_params):
64
    """
65
    info() callback to pass to request-handling code in server.py. Facilitates
66
    serving scripts that have been registered with start_serving_script().
67
    """
68
    served_scripts_lock.acquire()
69
    try:
70
        script = served_scripts.get(get_params['sha256'][0])
71
    finally:
72
        served_scripts_lock.release()
73
    if script is None:
74
        return 404, {}, b''
75
76
    return 200, {'Content-Type': 'application/javascript'}, script
77
78 fd9f2fc4 Wojtek Kosior
def dump_scripts(directory=(Path.cwd() / 'injected_scripts')):
79 702eefd2 Wojtek Kosior
    """
80
    Write all scripts that have been registered with start_serving_script()
81
    under the provided directory. If the directory already exists, it is wiped
82
    beforehand. If it doesn't exist, it is created.
83
    """
84
    directory = Path(directory)
85
    rmtree(directory, ignore_errors=True)
86
    directory.mkdir(parents=True)
87
88
    served_scripts_lock.acquire()
89
    for sha256, script in served_scripts.items():
90
        with open(directory / sha256, 'wt') as file:
91
            file.write(script)
92
    served_scripts_lock.release()
93
94 17614206 Wojtek Kosior
some_data = '{"some": "data"}'
95
96 046b8a7b Wojtek Kosior
# used by handler function of https://counterdoma.in
97
request_counter = 0
98
99
def serve_counter(command, get_params, post_params):
100
    global request_counter
101
    request_counter += 1
102
    return (
103
        200,
104
        {'Cache-Control': 'private, max-age=0, no-store'},
105
        json.dumps({'counter': request_counter})
106
    )
107
108 7218849a Wojtek Kosior
# Mock a Hydrilla repository.
109
110 b75a5717 Wojtek Kosior
make_handler = lambda txt: lambda c, g, p: (200, {}, txt)
111
112 7218849a Wojtek Kosior
# Mock files in the repository.
113
sample_contents = [f'Mi povas manĝi vitron, ĝi ne damaĝas min {i}'
114
                   for i in range(9)]
115 b75a5717 Wojtek Kosior
sample_hashes = [sha256(c.encode()).digest().hex() for c in sample_contents]
116 7218849a Wojtek Kosior
117 1c65dd5c Wojtek Kosior
file_url = lambda hashed: f'https://hydril.la/file/sha256/{hashed}'
118 7218849a Wojtek Kosior
119 b75a5717 Wojtek Kosior
sample_files_catalog = dict([(file_url(h), make_handler(c))
120 7218849a Wojtek Kosior
                             for h, c in zip(sample_hashes, sample_contents)])
121
122
# Mock resources and mappings in the repository.
123
sample_resource_templates = []
124
125
for deps in [(0, 1, 2, 3), (3, 4, 5, 6), (6, 7, 8, 9)]:
126
    letters = [chr(ord('a') + i) for i in deps]
127
    sample_resource_templates.append({
128
        'id_suffix':    ''.join(letters),
129
        'files_count':  deps[0],
130 57ce414c Wojtek Kosior
        'dependencies': [{'identifier': f'resource-{l}'} for l in letters]
131 7218849a Wojtek Kosior
    })
132
133
suffixes = [srt['id_suffix'] for srt in sample_resource_templates]
134
sample_resource_templates.append({
135
    'id_suffix':    '-'.join(suffixes),
136
    'files_count':  2,
137 57ce414c Wojtek Kosior
    'dependencies': [{'identifier': f'resource-{suf}'} for suf in suffixes]
138 7218849a Wojtek Kosior
})
139
140
for i in range(10):
141
    sample_resource_templates.append({
142
        'id_suffix':    chr(ord('a') + i),
143
        'files_count':  i,
144
        'dependencies': []
145
    })
146
147
sample_resources_catalog = {}
148
sample_mappings_catalog = {}
149 b75a5717 Wojtek Kosior
sample_queries = {}
150 7218849a Wojtek Kosior
151
for srt in sample_resource_templates:
152
    resource = make_sample_resource()
153 57ce414c Wojtek Kosior
    resource['identifier']          = f'resource-{srt["id_suffix"]}'
154 7218849a Wojtek Kosior
    resource['long_name']           = resource['identifier'].upper()
155
    resource['uuid']                = str(uuid4())
156
    resource['dependencies']        = srt['dependencies']
157
    resource['source_copyright']    = []
158
    resource['scripts']             = []
159
    for i in range(srt['files_count']):
160
        file_ref = {'file': f'file_{i}', 'sha256': sample_hashes[i]}
161
        resource[('source_copyright', 'scripts')[i & 1]].append(file_ref)
162
163 b75a5717 Wojtek Kosior
    resource_versions = [resource['version'], resource['version'].copy()]
164
    resource_versions[1][-1] += 1
165 7218849a Wojtek Kosior
166
    mapping = make_sample_mapping()
167 57ce414c Wojtek Kosior
    mapping['identifier']          = f'mapping-{srt["id_suffix"]}'
168 7218849a Wojtek Kosior
    mapping['long_name']           = mapping['identifier'].upper()
169
    mapping['uuid']                = str(uuid4())
170
    mapping['source_copyright']    = resource['source_copyright']
171
172 b75a5717 Wojtek Kosior
    mapping_versions = [mapping['version'], mapping['version'].copy()]
173
    mapping_versions[1][-1] += 1
174
175
    sufs = [srt["id_suffix"], *[l for l in srt["id_suffix"] if l.isalpha()]]
176
    patterns = [f'https://example_{suf}.com/*' for suf in set(sufs)]
177
    payloads = {}
178
179
    for pat in patterns:
180
        payloads[pat] = {'identifier': resource['identifier']}
181
182
        queryable_url = pat.replace('*', 'something')
183
        if queryable_url not in sample_queries:
184
            sample_queries[queryable_url] = []
185
186
        sample_queries[queryable_url].append({
187
            'identifier': mapping['identifier'],
188
            'long_name':  mapping['long_name'],
189
            'version':    mapping_versions[1]
190
        })
191 7218849a Wojtek Kosior
192 b75a5717 Wojtek Kosior
    mapping['payloads'] = payloads
193
194
    for item, versions, catalog in [
195
        (resource, resource_versions, sample_resources_catalog),
196
        (mapping,  mapping_versions,  sample_mappings_catalog)
197 7218849a Wojtek Kosior
    ]:
198 8477d0cf Wojtek Kosior
        fmt = f'https://hydril.la/{item["type"]}/{item["identifier"]}%s'
199 7218849a Wojtek Kosior
        # Make 2 versions of each item so that we can test updates.
200 b75a5717 Wojtek Kosior
        for ver in versions:
201
            item['version'] = ver
202 8477d0cf Wojtek Kosior
            for fmt_arg in ('.json', '/' + item_version_string(item)):
203 7218849a Wojtek Kosior
                catalog[fmt % fmt_arg] = make_handler(json.dumps(item))
204 b75a5717 Wojtek Kosior
205
def serve_query(command, get_params, post_params):
206
    response = {
207 72553a2d Wojtek Kosior
        '$schema': 'https://hydrilla.koszko.org/schemas/api_query_result-1.schema.json',
208
        'generated_by': {
209
            'name': 'human',
210
            'version': 'sapiens-0.8.15'
211
        },
212
        'mappings': sample_queries[get_params['url'][0]]
213 b75a5717 Wojtek Kosior
    }
214
215
    return (200, {}, json.dumps(response))
216
217
sample_queries_catalog = dict([(f'https://hydril.la/{suf}query', serve_query)
218
                               for suf in ('', '1/', '2/', '3/', '4/')])
219 7218849a Wojtek Kosior
220 5b2a7a61 Wojtek Kosior
catalog = {
221 702eefd2 Wojtek Kosior
    'http://gotmyowndoma.in':
222
    (302, {'location': 'http://gotmyowndoma.in/index.html'}, None),
223
    'http://gotmyowndoma.in/':
224
    (302, {'location': 'http://gotmyowndoma.in/index.html'}, None),
225
    'http://gotmyowndoma.in/index.html':
226
    (200, {}, here / 'data' / 'pages' / 'gotmyowndomain.html'),
227
228
    'https://gotmyowndoma.in':
229
    (302, {'location': 'https://gotmyowndoma.in/index.html'}, None),
230
    'https://gotmyowndoma.in/':
231
    (302, {'location': 'https://gotmyowndoma.in/index.html'}, None),
232
    'https://gotmyowndoma.in/index.html':
233
    (200, {}, here / 'data' / 'pages' / 'gotmyowndomain_https.html'),
234
235 7bedbcbd Wojtek Kosior
    'https://gotmyowndoma.in/scripts_to_block_1.html':
236
    (200, {}, here / 'data' / 'pages' / 'scripts_to_block_1.html'),
237
238 17614206 Wojtek Kosior
    'https://anotherdoma.in/resource/blocked/by/CORS.json':
239
    lambda command, get_params, post_params: (200, {}, some_data),
240
241 046b8a7b Wojtek Kosior
    'https://counterdoma.in/': serve_counter,
242
243 702eefd2 Wojtek Kosior
    'https://serve.scrip.ts/': serve_script,
244
245
    'https://site.with.scripts.block.ed':
246
    (302, {'location': 'https://site.with.scripts.block.ed/index.html'}, None),
247
    'https://site.with.scripts.block.ed/':
248
    (302, {'location': 'https://site.with.scripts.block.ed/index.html'}, None),
249
    'https://site.with.scripts.block.ed/index.html':
250
    (200, {}, here / 'data' / 'pages' / 'gotmyowndomain_https.html'),
251
252
    'https://site.with.scripts.allow.ed':
253
    (302, {'location': 'https://site.with.scripts.allow.ed/index.html'}, None),
254
    'https://site.with.scripts.allow.ed/':
255
    (302, {'location': 'https://site.with.scripts.allow.ed/index.html'}, None),
256
    'https://site.with.scripts.allow.ed/index.html':
257
    (200, {}, here / 'data' / 'pages' / 'gotmyowndomain_https.html'),
258
259
    'https://site.with.paylo.ad':
260
    (302, {'location': 'https://site.with.paylo.ad/index.html'}, None),
261
    'https://site.with.paylo.ad/':
262
    (302, {'location': 'https://site.with.paylo.ad/index.html'}, None),
263
    'https://site.with.paylo.ad/index.html':
264 7218849a Wojtek Kosior
    (200, {}, here / 'data' / 'pages' / 'gotmyowndomain_https.html'),
265
266
    **sample_files_catalog,
267
    **sample_resources_catalog,
268 b75a5717 Wojtek Kosior
    **sample_mappings_catalog,
269
    **sample_queries_catalog
270 5b2a7a61 Wojtek Kosior
}