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 log = logging.getLogger('pyi2ncommon.web_interface')
43 from .arnied_wrapper import accept_licence
45 #: FQDN of local machine
46 LOCALHOST = socket.gethostname()
49 def find_in_form(regex, form="status", escape=False, check_certs=True):
51 Find a regex in I2N web page's status frame.
53 :param str regex: regular expression to find
54 :param bool escape: whether to escape the regex
55 :param check_certs: forwarded to :py:func:`web_page_request`, see doc there
56 :returns: whether the regex was found
60 data = web_page_request(method="GET", url="/arnie?form=" + form,
61 check_certs=check_certs)
63 regex = re.escape(regex)
64 if re.search(regex, data):
67 log.debug("'%s' could not be found in:\n%s", regex, data)
71 def web_page_request(method="GET", url="/", body=None, check_certs=True):
73 Send an HTTPS request and return any response data.
75 SSL certificates are checked against a default set of certificates
76 installed on you system. This can be disabled (not recommended, security
77 implications!) by setting `check_certs` to `False`. To allow a secure
78 connection to host with e.g. a self-signed certificate, the caller can
79 load this certificate by specifying `check_certs=/path/to/cert.pem`.
80 (see also: :py:meth:`ssl.SSLContext.load_verify_locations`). Note that the
81 certificate has to be issued for the same server name that we try to
82 access, i.e. :py:data:`LOCALHOST`.
84 :param str method: GET or POST method for the request
85 :param str url: url location within the remote host
86 :param body: dictionary to be parsed and added to the url
87 :type body: {str, str} or None
88 :param check_certs: Whether or not to check ssl certificates for connection
89 or file name to a certificate file
90 :type check_certs: bool or str
91 :returns: data from the response if any
94 body = parse.urlencode(body) if body is not None else ""
95 headers = {"Content-Type": "application/x-www-form-urlencoded",
96 "Accept": "text/plain"}
98 if isinstance(check_certs, str):
99 context = ssl.create_default_context(cafile=check_certs)
101 context = ssl.create_default_context()
103 # disable certificate checks
104 context = ssl._create_unverified_context()
105 conn = client.HTTPSConnection(LOCALHOST, context=context)
106 conn.request(method, url, body, headers)
107 resp = conn.getresponse()
108 logging.info("Request status %s and response %s",
109 resp.status, resp.reason)
110 if resp.status != 200:
111 raise client.HTTPException("POST request failed.")
112 data = resp.read().decode()