diff options
| author | Simeon Simeonov | 2023-07-03 00:02:02 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2023-07-03 00:02:02 +0200 |
| commit | e98d4a056f51f831f39c75ba0971fe766a77808c (patch) | |
| tree | a44e29fb4cdd0dc8d2b6c2d529a253697b6be145 | |
| parent | 884e8a3562801aac86e31950ab1974513161d48b (diff) | |
Reimplement the relevant POST-functionality of the deprecated cgi.FieldStorage
| -rwxr-xr-x | beinc_server.py | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/beinc_server.py b/beinc_server.py index a105801..0098fba 100755 --- a/beinc_server.py +++ b/beinc_server.py | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- |
| 3 | 3 | ||
| 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.3 | 4 | # Blackmore's Enhanced IRC-Notification Collection (BEINC) v4.3 |
| 5 | # Copyright (C) 2013-2022 Simeon Simeonov | 5 | # Copyright (C) 2013-2023 Simeon Simeonov |
| 6 | 6 | ||
| 7 | # This program is free software: you can redistribute it and/or modify | 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -19,7 +19,6 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | import argparse | 21 | import argparse |
| 22 | import cgi | ||
| 23 | import errno | 22 | import errno |
| 24 | import io | 23 | import io |
| 25 | import json | 24 | import json |
| @@ -27,6 +26,7 @@ import logging | |||
| 27 | import os | 26 | import os |
| 28 | import ssl | 27 | import ssl |
| 29 | import sys | 28 | import sys |
| 29 | import urllib.parse | ||
| 30 | from functools import wraps | 30 | from functools import wraps |
| 31 | from http.server import BaseHTTPRequestHandler, HTTPServer | 31 | from http.server import BaseHTTPRequestHandler, HTTPServer |
| 32 | from logging.config import fileConfig | 32 | from logging.config import fileConfig |
| @@ -48,6 +48,10 @@ BEINC_OSD_TYPE_PYNOTIFY = 1 | |||
| 48 | BEINC_CURRENT_CONFIG_VERSION = 3 | 48 | BEINC_CURRENT_CONFIG_VERSION = 3 |
| 49 | 49 | ||
| 50 | 50 | ||
| 51 | class BEINCError400(Exception): | ||
| 52 | """BEINCError400""" | ||
| 53 | |||
| 54 | |||
| 51 | class BEINCError401(Exception): | 55 | class BEINCError401(Exception): |
| 52 | """BEINCError401""" | 56 | """BEINCError401""" |
| 53 | 57 | ||
| @@ -203,33 +207,46 @@ class BEINCInstance: | |||
| 203 | class BEINCCustomHandler(BaseHTTPRequestHandler): | 207 | class BEINCCustomHandler(BaseHTTPRequestHandler): |
| 204 | """Custom handler""" | 208 | """Custom handler""" |
| 205 | 209 | ||
| 210 | @staticmethod | ||
| 211 | def parse_raw_POST_data(fp, headers): | ||
| 212 | """ | ||
| 213 | Parses the POST data the way the deprecated cgi.FieldStorage used to | ||
| 214 | """ | ||
| 215 | try: | ||
| 216 | clen = -1 | ||
| 217 | if headers is None: | ||
| 218 | headers = {} | ||
| 219 | if 'content-length' in headers: | ||
| 220 | try: | ||
| 221 | clen = int(headers['content-length']) | ||
| 222 | except ValueError: | ||
| 223 | pass | ||
| 224 | return dict(urllib.parse.parse_qsl(fp.read(clen).decode('utf-8'))) | ||
| 225 | except Exception as e: | ||
| 226 | raise BEINCError400('Invalid POST request') from e | ||
| 227 | |||
| 206 | def do_POST(self): | 228 | def do_POST(self): |
| 207 | """Handle POST requests""" | 229 | """Handle POST requests""" |
| 208 | if self.path.strip('/') not in ('beinc/push', 'beinc/pull'): | 230 | if self.path.strip('/') not in ('beinc/push', 'beinc/pull'): |
| 209 | self._generate_json_error(404, 'Invalid resource path') | 231 | self._generate_json_error(404, 'Invalid resource path') |
| 210 | return | 232 | return |
| 211 | form = cgi.FieldStorage( | ||
| 212 | fp=self.rfile, | ||
| 213 | headers=self.headers, | ||
| 214 | environ={ | ||
| 215 | 'REQUEST_METHOD': 'POST', | ||
| 216 | 'CONTENT_TYPE': self.headers['Content-Type'], | ||
| 217 | }, | ||
| 218 | ) | ||
| 219 | # extract all known fields | ||
| 220 | POST_data = dict( | ||
| 221 | resource_name=form.getvalue('resource_name'), | ||
| 222 | password=form.getvalue('password'), | ||
| 223 | title=form.getvalue('title', ''), | ||
| 224 | message=form.getvalue('message', ''), | ||
| 225 | ) | ||
| 226 | try: | 233 | try: |
| 234 | form = self.parse_raw_POST_data(self.rfile, self.headers) | ||
| 235 | # extract all known fields | ||
| 236 | POST_data = { | ||
| 237 | 'resource_name': form.get('resource_name'), | ||
| 238 | 'password': form.get('password'), | ||
| 239 | 'title': form.get('title', ''), | ||
| 240 | 'message': form.get('message', ''), | ||
| 241 | } | ||
| 227 | result = {} | 242 | result = {} |
| 228 | if self.path.strip('/') == 'beinc/push': | 243 | if self.path.strip('/') == 'beinc/push': |
| 229 | result = self._handle_push(POST_data) | 244 | result = self._handle_push(POST_data) |
| 230 | elif self.path.strip('/') == 'beinc/pull': | 245 | elif self.path.strip('/') == 'beinc/pull': |
| 231 | result = self._handle_pull(POST_data) | 246 | result = self._handle_pull(POST_data) |
| 232 | self._render_to_JSON_response(result) | 247 | self._render_to_JSON_response(result) |
| 248 | except BEINCError400 as e: | ||
| 249 | self._generate_json_error(400, str(e)) | ||
| 233 | except BEINCError401 as e: | 250 | except BEINCError401 as e: |
| 234 | self._generate_json_error(401, str(e)) | 251 | self._generate_json_error(401, str(e)) |
| 235 | except BEINCError403 as e: | 252 | except BEINCError403 as e: |
