uploadserver 5.2.2__tar.gz → 6.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {uploadserver-5.2.2/uploadserver.egg-info → uploadserver-6.0.0}/PKG-INFO +49 -4
- {uploadserver-5.2.2 → uploadserver-6.0.0}/README.md +47 -2
- {uploadserver-5.2.2 → uploadserver-6.0.0}/setup.py +2 -2
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver/__init__.py +21 -13
- {uploadserver-5.2.2 → uploadserver-6.0.0/uploadserver.egg-info}/PKG-INFO +49 -4
- {uploadserver-5.2.2 → uploadserver-6.0.0}/LICENSE +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/setup.cfg +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver/__main__.py +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver/cgi.py +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver.egg-info/SOURCES.txt +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver.egg-info/dependency_links.txt +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver.egg-info/entry_points.txt +0 -0
- {uploadserver-5.2.2 → uploadserver-6.0.0}/uploadserver.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: uploadserver
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
4
4
|
Summary: Python's http.server extended to include a file upload page
|
|
5
5
|
Home-page: https://github.com/Densaugeo/uploadserver
|
|
6
6
|
Author: Densaugeo
|
|
@@ -8,7 +8,7 @@ Author-email: author@example.com
|
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
|
|
@@ -23,8 +23,8 @@ Python's http.server extended to include a file upload page
|
|
|
23
23
|
|
|
24
24
|
| Platform | Supported? | Notes |
|
|
25
25
|
|-|-|-|
|
|
26
|
-
| Python 3.
|
|
27
|
-
| Python 3.6-3.
|
|
26
|
+
| Python 3.9+ | Yes | Tested on 3.9 through 3.14 every release. |
|
|
27
|
+
| Python 3.6-3.8 | No | Was supported by previous versions. |
|
|
28
28
|
| Python 3.5- | No | |
|
|
29
29
|
| Linux | Yes | Tested on Fedora and Ubuntu every release. |
|
|
30
30
|
| Windows | Yes | Occasional manual testing. Haven't noticed any obvious problems. |
|
|
@@ -123,6 +123,51 @@ curl -X POST https://localhost:8000/upload --insecure --cert client.pem -F files
|
|
|
123
123
|
|
|
124
124
|
Note: This uses a self-signed server certificate which clients such as web browser and cURL will warn about. Most browsers will allow you to proceed after adding an exception, and cURL will work if given the -k/--insecure option. Using your own certificate from a certificate authority will avoid these warnings.
|
|
125
125
|
|
|
126
|
+
## Available Options
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
usage: __main__.py [-h] [--cgi] [--allow-replace] [--bind ADDRESS]
|
|
130
|
+
[--directory DIRECTORY] [--theme {light,auto,dark}]
|
|
131
|
+
[--server-certificate SERVER_CERTIFICATE]
|
|
132
|
+
[--client-certificate CLIENT_CERTIFICATE]
|
|
133
|
+
[--basic-auth BASIC_AUTH]
|
|
134
|
+
[--basic-auth-upload BASIC_AUTH_UPLOAD]
|
|
135
|
+
[port]
|
|
136
|
+
|
|
137
|
+
positional arguments:
|
|
138
|
+
port Specify alternate port [default: 8000]
|
|
139
|
+
|
|
140
|
+
options:
|
|
141
|
+
-h, --help show this help message and exit
|
|
142
|
+
--cgi Run as CGI Server
|
|
143
|
+
--allow-replace Replace existing file if uploaded file has the same
|
|
144
|
+
name. Auto rename by default.
|
|
145
|
+
--bind, -b ADDRESS Specify alternate bind address [default: all
|
|
146
|
+
interfaces]
|
|
147
|
+
--directory, -d DIRECTORY
|
|
148
|
+
Specify alternative directory [default:current
|
|
149
|
+
directory]
|
|
150
|
+
--theme {light,auto,dark}
|
|
151
|
+
Specify a light or dark theme for the upload page
|
|
152
|
+
[default: auto]
|
|
153
|
+
--server-certificate, --certificate, -c SERVER_CERTIFICATE
|
|
154
|
+
Specify HTTPS server certificate to use [default:
|
|
155
|
+
none]
|
|
156
|
+
--client-certificate CLIENT_CERTIFICATE
|
|
157
|
+
Specify HTTPS client certificate to accept for mutual
|
|
158
|
+
TLS [default: none]
|
|
159
|
+
--basic-auth BASIC_AUTH
|
|
160
|
+
Specify user:pass for basic authentication (downloads
|
|
161
|
+
and uploads)
|
|
162
|
+
--basic-auth-upload BASIC_AUTH_UPLOAD
|
|
163
|
+
Specify user:pass for basic authentication (uploads
|
|
164
|
+
only)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Breaking Changes in 6.0.0
|
|
168
|
+
|
|
169
|
+
- Support for Python 3.8 dropped.
|
|
170
|
+
|
|
126
171
|
## Breaking Changes in 5.0.0
|
|
127
172
|
|
|
128
173
|
- Support for Python 3.6-7 dropped.
|
|
@@ -9,8 +9,8 @@ Python's http.server extended to include a file upload page
|
|
|
9
9
|
|
|
10
10
|
| Platform | Supported? | Notes |
|
|
11
11
|
|-|-|-|
|
|
12
|
-
| Python 3.
|
|
13
|
-
| Python 3.6-3.
|
|
12
|
+
| Python 3.9+ | Yes | Tested on 3.9 through 3.14 every release. |
|
|
13
|
+
| Python 3.6-3.8 | No | Was supported by previous versions. |
|
|
14
14
|
| Python 3.5- | No | |
|
|
15
15
|
| Linux | Yes | Tested on Fedora and Ubuntu every release. |
|
|
16
16
|
| Windows | Yes | Occasional manual testing. Haven't noticed any obvious problems. |
|
|
@@ -109,6 +109,51 @@ curl -X POST https://localhost:8000/upload --insecure --cert client.pem -F files
|
|
|
109
109
|
|
|
110
110
|
Note: This uses a self-signed server certificate which clients such as web browser and cURL will warn about. Most browsers will allow you to proceed after adding an exception, and cURL will work if given the -k/--insecure option. Using your own certificate from a certificate authority will avoid these warnings.
|
|
111
111
|
|
|
112
|
+
## Available Options
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
usage: __main__.py [-h] [--cgi] [--allow-replace] [--bind ADDRESS]
|
|
116
|
+
[--directory DIRECTORY] [--theme {light,auto,dark}]
|
|
117
|
+
[--server-certificate SERVER_CERTIFICATE]
|
|
118
|
+
[--client-certificate CLIENT_CERTIFICATE]
|
|
119
|
+
[--basic-auth BASIC_AUTH]
|
|
120
|
+
[--basic-auth-upload BASIC_AUTH_UPLOAD]
|
|
121
|
+
[port]
|
|
122
|
+
|
|
123
|
+
positional arguments:
|
|
124
|
+
port Specify alternate port [default: 8000]
|
|
125
|
+
|
|
126
|
+
options:
|
|
127
|
+
-h, --help show this help message and exit
|
|
128
|
+
--cgi Run as CGI Server
|
|
129
|
+
--allow-replace Replace existing file if uploaded file has the same
|
|
130
|
+
name. Auto rename by default.
|
|
131
|
+
--bind, -b ADDRESS Specify alternate bind address [default: all
|
|
132
|
+
interfaces]
|
|
133
|
+
--directory, -d DIRECTORY
|
|
134
|
+
Specify alternative directory [default:current
|
|
135
|
+
directory]
|
|
136
|
+
--theme {light,auto,dark}
|
|
137
|
+
Specify a light or dark theme for the upload page
|
|
138
|
+
[default: auto]
|
|
139
|
+
--server-certificate, --certificate, -c SERVER_CERTIFICATE
|
|
140
|
+
Specify HTTPS server certificate to use [default:
|
|
141
|
+
none]
|
|
142
|
+
--client-certificate CLIENT_CERTIFICATE
|
|
143
|
+
Specify HTTPS client certificate to accept for mutual
|
|
144
|
+
TLS [default: none]
|
|
145
|
+
--basic-auth BASIC_AUTH
|
|
146
|
+
Specify user:pass for basic authentication (downloads
|
|
147
|
+
and uploads)
|
|
148
|
+
--basic-auth-upload BASIC_AUTH_UPLOAD
|
|
149
|
+
Specify user:pass for basic authentication (uploads
|
|
150
|
+
only)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Breaking Changes in 6.0.0
|
|
154
|
+
|
|
155
|
+
- Support for Python 3.8 dropped.
|
|
156
|
+
|
|
112
157
|
## Breaking Changes in 5.0.0
|
|
113
158
|
|
|
114
159
|
- Support for Python 3.6-7 dropped.
|
|
@@ -5,7 +5,7 @@ with open('README.md', 'r') as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name='uploadserver',
|
|
8
|
-
version='
|
|
8
|
+
version='6.0.0',
|
|
9
9
|
author='Densaugeo',
|
|
10
10
|
author_email='author@example.com',
|
|
11
11
|
description='Python\'s http.server extended to include a file upload page',
|
|
@@ -18,7 +18,7 @@ setuptools.setup(
|
|
|
18
18
|
'License :: OSI Approved :: MIT License',
|
|
19
19
|
'Operating System :: OS Independent',
|
|
20
20
|
],
|
|
21
|
-
python_requires='>=3.
|
|
21
|
+
python_requires='>=3.9',
|
|
22
22
|
entry_points = {
|
|
23
23
|
'console_scripts': ['uploadserver=uploadserver:main'],
|
|
24
24
|
}
|
|
@@ -18,7 +18,7 @@ COLOR_SCHEME = {
|
|
|
18
18
|
'dark': 'dark',
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
def get_upload_page(theme):
|
|
21
|
+
def get_upload_page(theme: str) -> bytes:
|
|
22
22
|
return bytes('''<!DOCTYPE html>
|
|
23
23
|
<html>
|
|
24
24
|
<head>
|
|
@@ -74,7 +74,7 @@ document.getElementsByTagName('form')[0].addEventListener('submit', async e => {
|
|
|
74
74
|
</script>
|
|
75
75
|
</html>''', 'utf-8')
|
|
76
76
|
|
|
77
|
-
def get_directory_head_injection(theme):
|
|
77
|
+
def get_directory_head_injection(theme: str) -> bytes:
|
|
78
78
|
return bytes('''<!-- Injected by uploadserver -->
|
|
79
79
|
<meta name="viewport" content="width=device-width" />
|
|
80
80
|
<meta name="color-scheme" content="''' + COLOR_SCHEME.get(theme) + '''">
|
|
@@ -88,7 +88,7 @@ DIRECTORY_BODY_INJECTION = b'''<!-- Injected by uploadserver -->
|
|
|
88
88
|
<!-- End injection by uploadserver -->
|
|
89
89
|
'''
|
|
90
90
|
|
|
91
|
-
def send_upload_page(handler):
|
|
91
|
+
def send_upload_page(handler: http.server.BaseHTTPRequestHandler):
|
|
92
92
|
handler.send_response(http.HTTPStatus.OK)
|
|
93
93
|
handler.send_header('Content-Type', 'text/html; charset=utf-8')
|
|
94
94
|
handler.send_header('Content-Length', len(get_upload_page(args.theme)))
|
|
@@ -99,7 +99,7 @@ class PersistentFieldStorage(cgi.FieldStorage):
|
|
|
99
99
|
# Override cgi.FieldStorage.make_file() method. Valid for Python 3.1 ~ 3.10.
|
|
100
100
|
# Modified version of the original .make_file() method (base copied from
|
|
101
101
|
# Python 3.10)
|
|
102
|
-
def make_file(self):
|
|
102
|
+
def make_file(self) -> object:
|
|
103
103
|
if self._binary_file:
|
|
104
104
|
return tempfile.NamedTemporaryFile(mode = 'wb+',
|
|
105
105
|
dir = args.directory, delete = False)
|
|
@@ -107,7 +107,9 @@ class PersistentFieldStorage(cgi.FieldStorage):
|
|
|
107
107
|
return tempfile.NamedTemporaryFile("w+", dir = args.directory,
|
|
108
108
|
delete = False, encoding = self.encoding, newline = '\n')
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
# True argument/return type is str | pathlib.Path, but Python 3.9 doesn't
|
|
111
|
+
# support |
|
|
112
|
+
def auto_rename(path: pathlib.Path) -> pathlib.Path:
|
|
111
113
|
if not os.path.exists(path):
|
|
112
114
|
return path
|
|
113
115
|
(base, ext) = os.path.splitext(path)
|
|
@@ -117,7 +119,8 @@ def auto_rename(path):
|
|
|
117
119
|
return renamed_path
|
|
118
120
|
raise FileExistsError(f'File {path} already exists.')
|
|
119
121
|
|
|
120
|
-
def receive_upload(handler
|
|
122
|
+
def receive_upload(handler: http.server.BaseHTTPRequestHandler,
|
|
123
|
+
) -> tuple[http.HTTPStatus, str]:
|
|
121
124
|
result = (http.HTTPStatus.INTERNAL_SERVER_ERROR, 'Server error')
|
|
122
125
|
name_conflict = False
|
|
123
126
|
|
|
@@ -153,16 +156,19 @@ def receive_upload(handler):
|
|
|
153
156
|
os.rename(source, destination)
|
|
154
157
|
# class '_io.BytesIO', small file (< 1000B, in cgi.py), in-memory
|
|
155
158
|
# buffer
|
|
156
|
-
else:
|
|
159
|
+
else:
|
|
157
160
|
with open(destination, 'wb') as f:
|
|
158
161
|
f.write(field.file.read())
|
|
159
|
-
handler.log_message(
|
|
162
|
+
handler.log_message('[Uploaded] "%s" --> %s', filename, destination)
|
|
160
163
|
result = (http.HTTPStatus.NO_CONTENT, 'Some filename(s) changed '
|
|
161
164
|
'due to name conflict' if name_conflict else 'Files accepted')
|
|
162
165
|
|
|
163
166
|
return result
|
|
164
167
|
|
|
165
|
-
|
|
168
|
+
# True return type is tuple[bool, str | None], but Python 3.9 doesn't support |
|
|
169
|
+
def check_http_authentication_header(
|
|
170
|
+
handler: http.server.BaseHTTPRequestHandler, auth: str,
|
|
171
|
+
) -> tuple[bool, str]:
|
|
166
172
|
auth_header = handler.headers.get('Authorization')
|
|
167
173
|
if auth_header is None:
|
|
168
174
|
return (False, 'No credentials given')
|
|
@@ -186,7 +192,8 @@ def check_http_authentication_header(handler, auth):
|
|
|
186
192
|
|
|
187
193
|
return (True, None)
|
|
188
194
|
|
|
189
|
-
def check_http_authentication(handler
|
|
195
|
+
def check_http_authentication(handler: http.server.BaseHTTPRequestHandler
|
|
196
|
+
) -> bool:
|
|
190
197
|
"""
|
|
191
198
|
This function should be called in at the beginning of HTTP method handler.
|
|
192
199
|
It validates Authorization header and sends back 401 response on failure.
|
|
@@ -219,7 +226,7 @@ def check_http_authentication(handler):
|
|
|
219
226
|
valid, message = check_http_authentication_header(handler, args.basic_auth_upload)
|
|
220
227
|
|
|
221
228
|
if not valid:
|
|
222
|
-
handler.log_message(
|
|
229
|
+
handler.log_message('Request rejected (%s)', message)
|
|
223
230
|
handler.send_response(http.HTTPStatus.UNAUTHORIZED, message)
|
|
224
231
|
handler.send_header('WWW-Authenticate', 'Basic realm="uploadserver"')
|
|
225
232
|
handler.end_headers()
|
|
@@ -251,7 +258,8 @@ class ListDirectoryInterception:
|
|
|
251
258
|
content = content.replace(b'<ul>', DIRECTORY_BODY_INJECTION + b'<ul>')
|
|
252
259
|
outputfile.write(content)
|
|
253
260
|
|
|
254
|
-
|
|
261
|
+
# True argument type is str | pathlib.Path, but Python 3.9 doesn't support |
|
|
262
|
+
def list_directory(self, path: pathlib.Path) -> object:
|
|
255
263
|
setattr(self, 'flush_headers', self.flush_headers_interceptor)
|
|
256
264
|
setattr(self, 'copyfile', self.copyfile_interceptor)
|
|
257
265
|
|
|
@@ -323,7 +331,7 @@ def intercept_first_print():
|
|
|
323
331
|
builtins.print = old_print
|
|
324
332
|
builtins.print = new_print
|
|
325
333
|
|
|
326
|
-
def ssl_wrap(socket):
|
|
334
|
+
def ssl_wrap(socket: socket.socket) -> ssl.SSLSocket:
|
|
327
335
|
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
328
336
|
server_root = pathlib.Path(args.directory).resolve()
|
|
329
337
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: uploadserver
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
4
4
|
Summary: Python's http.server extended to include a file upload page
|
|
5
5
|
Home-page: https://github.com/Densaugeo/uploadserver
|
|
6
6
|
Author: Densaugeo
|
|
@@ -8,7 +8,7 @@ Author-email: author@example.com
|
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
|
|
@@ -23,8 +23,8 @@ Python's http.server extended to include a file upload page
|
|
|
23
23
|
|
|
24
24
|
| Platform | Supported? | Notes |
|
|
25
25
|
|-|-|-|
|
|
26
|
-
| Python 3.
|
|
27
|
-
| Python 3.6-3.
|
|
26
|
+
| Python 3.9+ | Yes | Tested on 3.9 through 3.14 every release. |
|
|
27
|
+
| Python 3.6-3.8 | No | Was supported by previous versions. |
|
|
28
28
|
| Python 3.5- | No | |
|
|
29
29
|
| Linux | Yes | Tested on Fedora and Ubuntu every release. |
|
|
30
30
|
| Windows | Yes | Occasional manual testing. Haven't noticed any obvious problems. |
|
|
@@ -123,6 +123,51 @@ curl -X POST https://localhost:8000/upload --insecure --cert client.pem -F files
|
|
|
123
123
|
|
|
124
124
|
Note: This uses a self-signed server certificate which clients such as web browser and cURL will warn about. Most browsers will allow you to proceed after adding an exception, and cURL will work if given the -k/--insecure option. Using your own certificate from a certificate authority will avoid these warnings.
|
|
125
125
|
|
|
126
|
+
## Available Options
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
usage: __main__.py [-h] [--cgi] [--allow-replace] [--bind ADDRESS]
|
|
130
|
+
[--directory DIRECTORY] [--theme {light,auto,dark}]
|
|
131
|
+
[--server-certificate SERVER_CERTIFICATE]
|
|
132
|
+
[--client-certificate CLIENT_CERTIFICATE]
|
|
133
|
+
[--basic-auth BASIC_AUTH]
|
|
134
|
+
[--basic-auth-upload BASIC_AUTH_UPLOAD]
|
|
135
|
+
[port]
|
|
136
|
+
|
|
137
|
+
positional arguments:
|
|
138
|
+
port Specify alternate port [default: 8000]
|
|
139
|
+
|
|
140
|
+
options:
|
|
141
|
+
-h, --help show this help message and exit
|
|
142
|
+
--cgi Run as CGI Server
|
|
143
|
+
--allow-replace Replace existing file if uploaded file has the same
|
|
144
|
+
name. Auto rename by default.
|
|
145
|
+
--bind, -b ADDRESS Specify alternate bind address [default: all
|
|
146
|
+
interfaces]
|
|
147
|
+
--directory, -d DIRECTORY
|
|
148
|
+
Specify alternative directory [default:current
|
|
149
|
+
directory]
|
|
150
|
+
--theme {light,auto,dark}
|
|
151
|
+
Specify a light or dark theme for the upload page
|
|
152
|
+
[default: auto]
|
|
153
|
+
--server-certificate, --certificate, -c SERVER_CERTIFICATE
|
|
154
|
+
Specify HTTPS server certificate to use [default:
|
|
155
|
+
none]
|
|
156
|
+
--client-certificate CLIENT_CERTIFICATE
|
|
157
|
+
Specify HTTPS client certificate to accept for mutual
|
|
158
|
+
TLS [default: none]
|
|
159
|
+
--basic-auth BASIC_AUTH
|
|
160
|
+
Specify user:pass for basic authentication (downloads
|
|
161
|
+
and uploads)
|
|
162
|
+
--basic-auth-upload BASIC_AUTH_UPLOAD
|
|
163
|
+
Specify user:pass for basic authentication (uploads
|
|
164
|
+
only)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Breaking Changes in 6.0.0
|
|
168
|
+
|
|
169
|
+
- Support for Python 3.8 dropped.
|
|
170
|
+
|
|
126
171
|
## Breaking Changes in 5.0.0
|
|
127
172
|
|
|
128
173
|
- Support for Python 3.6-7 dropped.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|