Port to python 3

master
Ferry Boender 4 years ago
parent 84e9084be2
commit 077ecf696c
  1. 18
      src/scriptform.py
  2. 27
      src/webapp.py
  3. 19
      src/webserver.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
@ -10,7 +10,7 @@ import optparse
import os import os
import json import json
import logging import logging
import thread import threading
import hashlib import hashlib
import socket import socket
@ -51,7 +51,8 @@ class ScriptForm(object):
if self.cache and self.form_config_singleton is not None: if self.cache and self.form_config_singleton is not None:
return self.form_config_singleton return self.form_config_singleton
file_contents = file(self.config_file, 'r').read() with open(self.config_file, "r") as fh:
file_contents = fh.read()
try: try:
config = json.loads(file_contents) config = json.loads(file_contents)
except ValueError as err: except ValueError as err:
@ -138,7 +139,7 @@ class ScriptForm(object):
# We need to spawn a new thread in which the server is shut down, # We need to spawn a new thread in which the server is shut down,
# because doing it from the main thread blocks, since the server is # because doing it from the main thread blocks, since the server is
# waiting for connections.. # waiting for connections..
thread.start_new_thread(t_shutdown, (self, )) threading.Thread(target=t_shutdown, args=(1,))
def main(): # pragma: no cover def main(): # pragma: no cover
@ -181,7 +182,7 @@ def main(): # pragma: no cover
if plain_pw != getpass.getpass('Repeat password: '): if plain_pw != getpass.getpass('Repeat password: '):
sys.stderr.write("Passwords do not match.\n") sys.stderr.write("Passwords do not match.\n")
sys.exit(1) sys.exit(1)
sys.stdout.write(hashlib.sha256(plain_pw).hexdigest() + '\n') sys.stdout.write(hashlib.sha256(plain_pw.encode('utf8')).hexdigest() + '\n')
sys.exit(0) sys.exit(0)
else: else:
if not options.action_stop and len(args) < 1: if not options.action_stop and len(args) < 1:
@ -210,13 +211,6 @@ def main(): # pragma: no cover
elif options.action_stop: elif options.action_stop:
daemon.stop() daemon.stop()
sys.exit(0) sys.exit(0)
except socket.error as err:
log.exception(err)
sys.stderr.write("Cannot bind to port {0}: {1}\n".format(
options.port,
str(err)
))
sys.exit(2)
except Exception as err: except Exception as err:
log.exception(err) log.exception(err)
raise raise

@ -209,14 +209,12 @@ class ScriptFormWebApp(RequestHandler):
# If a 'users' element was present in the form configuration file, the # If a 'users' element was present in the form configuration file, the
# user must be authenticated. # user must be authenticated.
if form_config.users: if form_config.users:
auth_header = self.headers.getheader("Authorization") auth_header = self.headers.get("Authorization")
if auth_header is not None: if auth_header is not None:
# Validate the username and password # Validate the username and password
auth_unpw = auth_header.split(' ', 1)[1] auth_unpw = auth_header.split(' ', 1)[1].encode('utf-8')
username, password = base64.decodestring(auth_unpw).split(":", username, password = base64.b64decode(auth_unpw).decode('utf-8').split(":", 1)
1) pw_hash = hashlib.sha256(password.encode('utf-8')).hexdigest()
pw_hash = hashlib.sha256(password).hexdigest()
if username in form_config.users and \ if username in form_config.users and \
pw_hash == form_config.users[username]: pw_hash == form_config.users[username]:
# Valid username and password. Return the username. # Valid username and password. Return the username.
@ -414,13 +412,12 @@ class ScriptFormWebApp(RequestHandler):
if field.filename == '': if field.filename == '':
continue continue
tmp_fname = tempfile.mktemp(prefix="scriptform_") tmp_fname = tempfile.mktemp(prefix="scriptform_")
tmp_file = file(tmp_fname, 'w') with open(tmp_fname, "wb") as tmp_file:
while True: while True:
buf = field.file.read(1024 * 16) buf = field.file.read(1024 * 16)
if not buf: if not buf:
break break
tmp_file.write(buf) tmp_file.write(buf)
tmp_file.close()
field.file.close() field.file.close()
tmp_files.append(tmp_fname) # For later cleanup tmp_files.append(tmp_fname) # For later cleanup
@ -509,7 +506,7 @@ class ScriptFormWebApp(RequestHandler):
if not os.path.exists(path): if not os.path.exists(path):
raise HTTPError(404, "Not found") raise HTTPError(404, "Not found")
static_file = file(path, 'r')
self.send_response(200) self.send_response(200)
self.end_headers() self.end_headers()
self.wfile.write(static_file.read()) with open(path, "r") as static_file:
self.wfile.write(static_file.read())

@ -2,9 +2,9 @@
Basic web server / framework. Basic web server / framework.
""" """
from SocketServer import ThreadingMixIn from socketserver import ThreadingMixIn
import BaseHTTPServer from http.server import HTTPServer, BaseHTTPRequestHandler
import urlparse import urllib.parse
import cgi import cgi
@ -14,6 +14,9 @@ class HTTPError(Exception):
etc. They are caught by the 'framework' and sent to the client's browser. etc. They are caught by the 'framework' and sent to the client's browser.
""" """
def __init__(self, status_code, msg, headers=None): def __init__(self, status_code, msg, headers=None):
assert isinstance(status_code, int)
assert isinstance(msg, str)
if headers is None: if headers is None:
headers = {} headers = {}
self.status_code = status_code self.status_code = status_code
@ -22,14 +25,14 @@ class HTTPError(Exception):
Exception.__init__(self, status_code, msg, headers) Exception.__init__(self, status_code, msg, headers)
class ThreadedHTTPServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
""" """
Base class for multithreaded HTTP servers. Base class for multithreaded HTTP servers.
""" """
pass pass
class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): class RequestHandler(BaseHTTPRequestHandler):
""" """
Basic web server request handler. Handles GET and POST requests. You should Basic web server request handler. Handles GET and POST requests. You should
inherit from this class and implement h_ methods for handling requests. inherit from this class and implement h_ methods for handling requests.
@ -61,9 +64,9 @@ class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
""" """
Parse information from a request. Parse information from a request.
""" """
url_comp = urlparse.urlsplit(reqinfo) url_comp = urllib.parse.urlsplit(reqinfo)
path = url_comp.path path = url_comp.path
query_vars = urlparse.parse_qs(url_comp.query) query_vars = urllib.parse.parse_qs(url_comp.query)
# Only return the first value of each query var. E.g. for # Only return the first value of each query var. E.g. for
# "?foo=1&foo=2" return '1'. # "?foo=1&foo=2" return '1'.
var_values = dict([(k, v[0]) for k, v in query_vars.items()]) var_values = dict([(k, v[0]) for k, v in query_vars.items()])
@ -104,7 +107,7 @@ class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.send_header(header_k, header_v) self.send_header(header_k, header_v)
self.end_headers() self.end_headers()
self.wfile.write("Error {0}: {1}".format(err.status_code, self.wfile.write("Error {0}: {1}".format(err.status_code,
err.msg)) err.msg).encode('utf-8'))
self.wfile.flush() self.wfile.flush()
return False return False
except Exception as err: except Exception as err:

Loading…
Cancel
Save