1 # The software in this package is distributed under the GNU General
2 # Public License version 2 (with a special exception described below).
4 # A copy of GNU General Public License (GPL) is included in this distribution,
5 # in the file COPYING.GPL.
7 # As a special exception, if other files instantiate templates or use macros
8 # or inline functions from this file, or you compile this file and link it
9 # with other works to produce a work based on this file, this file
10 # does not by itself cause the resulting work to be covered
11 # by the GNU General Public License.
13 # However the source code for this file must still be made available
14 # in accordance with section (3) of the GNU General Public License.
16 # This exception does not invalidate any other reasons why a work based
17 # on this file might be covered by the GNU General Public License.
19 # Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
24 ------------------------------------------------------
25 Utility for HTTP based interaction with the arnied web page.
27 Copyright: Intra2net AG
31 ------------------------------------------------------
37 import http.client as client
38 import urllib.parse as parse
41 from .arnied_wrapper import accept_licence
43 log = logging.getLogger('pyi2ncommon.web_interface')
46 #: FQDN of local machine
47 LOCALHOST = socket.gethostname()
50 def find_in_form(regex, form="status", escape=False, check_certs=True):
52 Find a regex in given I2N web page form.
54 :param str regex: regular expression to find
55 :param str form: form name to open
56 :param bool escape: whether to escape the regex
57 :param check_certs: forwarded to :py:func:`web_page_request`, see doc there
58 :returns: whether the regex was found
62 data = web_page_request(method="GET", url="/arnie?form=" + form,
63 check_certs=check_certs)
65 regex = re.escape(regex)
66 if re.search(regex, data):
69 log.debug("'%s' could not be found in:\n%s", regex, data)
73 def web_page_request(method="GET", url="/", body=None, check_certs=True):
75 Send an HTTPS request and return any response data.
77 SSL certificates are checked against a default set of certificates
78 installed on you system. This can be disabled (not recommended, security
79 implications!) by setting `check_certs` to `False`. To allow a secure
80 connection to host with e.g. a self-signed certificate, the caller can
81 load this certificate by specifying `check_certs=/path/to/cert.pem`.
82 (see also: :py:meth:`ssl.SSLContext.load_verify_locations`). Note that the
83 certificate has to be issued for the same server name that we try to
84 access, i.e. :py:data:`LOCALHOST`.
86 :param str method: GET or POST method for the request
87 :param str url: url location within the remote host
88 :param body: dictionary to be parsed and added to the url
89 :type body: {str, str} or None
90 :param check_certs: Whether or not to check ssl certificates for connection
91 or file name to a certificate file
92 :type check_certs: bool or str
93 :returns: data from the response if any
96 body = parse.urlencode(body) if body is not None else ""
97 headers = {"Content-Type": "application/x-www-form-urlencoded",
98 "Accept": "text/plain"}
100 if isinstance(check_certs, str):
101 context = ssl.create_default_context(cafile=check_certs)
103 context = ssl.create_default_context()
105 # disable certificate checks
106 context = ssl._create_unverified_context()
107 conn = client.HTTPSConnection(LOCALHOST, context=context)
108 conn.request(method, url, body, headers)
109 resp = conn.getresponse()
110 logging.info("Request status %s and response %s",
111 resp.status, resp.reason)
112 if resp.status != 200:
113 raise client.HTTPException("POST request failed.")
114 data = resp.read().decode()