[BACK]Return to acopm-dronebl-submit.py.in CVS log [TXT][DIR] Up to [local] / acopm / dist

File: [local] / acopm / dist / acopm-dronebl-submit.py.in (download)

Revision 1.1, Sat May 8 15:42:29 2021 UTC (3 years ago) by bountyht
Branch point for: MAIN

Initial revision

#!/usr/bin/env python
#
# Copyright (C) 2008 DroneBL Contributors
# Copyright (C) 2008 William Pitcock <nenolod@dereferenced.org>
# Copyright (C) 2017 Aaron M. D. Jones <aaronmdjones@gmail.com>
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
#    copyright notice, this list of conditions and the following
#    disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following
#    disclaimer in the documentation and/or other materials
#    provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of
#    its contributors may be used to endorse or promote products
#    derived from this software without specific prior written
#    permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED.
#
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

__version__ = '@PACKAGE_VERSION@'


import os
import sys
import urllib
import httplib
import xml.etree.ElementTree as ElementTree


class ACOPMNoVersionException(Exception):

	def __str__(self):
		return 'Version number missing -- are you using the INSTALLED copy of this script?'


class ACOPMMissingEnvironmentException(Exception):

	def __init__(self, value):
		self.value = value

	def __str__(self):
		return 'The environment variable "{}" is missing'.format(self.value)


class ACOPMMalformedEnvironmentException(ACOPMMissingEnvironmentException):

	def __str__(self):
		return 'The environment variable "{}" is missing or malformed'.format(self.value)


def acopm_is_number(s):
	try:
		float(s)
		return True
	except ValueError:
		return False


def acopm_get_env(name, required=True, length=0):

	val = os.getenv(name, default='')

	if required and not val:
		raise ACOPMMissingEnvironmentException(name)

	if not val:
		return None

	if length and len(val) != length:
		raise ACOPMMalformedEnvironmentException(name)

	return val


def acopm_proto_to_dbl_type(proto):

	if proto == 'SOCKS4' or proto == 'SOCKS5':
		return '8'

	if proto == 'HTTP' or proto == 'HTTPS':
		return '9'

	sys.exit(0)


def acopm_build_dbl_add_request(addr, port, proto, rpckey):

	type_id  = acopm_proto_to_dbl_type(proto)
	request  = '<?xml version="1.0"?>\n'
	request += '<request key="{}" staging="1">\n'.format(rpckey)
	request += '    <add ip="{}" port="{}" type="{}" />\n'.format(addr, port, type_id)
	request += '</request>\n'

	return request


if __name__ == "__main__":

	if not acopm_is_number(__version__):
		raise ACOPMNoVersionException

	addr = acopm_get_env('ADDRESS')
	port = acopm_get_env('PORT')
	proto = acopm_get_env('TYPE')
	rpckey = acopm_get_env('CONFIG1', length=32)

	stype, srest = urllib.splittype('https://dronebl.org/rpc2')
	shost, spath = urllib.splithost(srest)

	request = acopm_build_dbl_add_request(addr, port, proto, rpckey)

	connection = httplib.HTTPSConnection(shost)
	connection.putrequest('POST', spath)
	connection.putheader('Content-Type', 'text/xml')
	connection.putheader('Content-Length', len(request))
	connection.putheader('User-Agent', 'ACOPM/v{} DroneBL submission script'.format(__version__))

	net_name = acopm_get_env('CONFIG2', required=False)
	if net_name:
		connection.putheader('From', net_name)

	connection.endheaders()
	connection.send(request)

	response = connection.getresponse()
	response_data = response.read()

	root = ElementTree.fromstring(response_data)

	if root.tag != 'response':
		sys.stderr.write('Unexpected: root tag is "{}"\n'.format(root.tag))
		sys.exit(1)

	if not 'type' in root.attrib:
		sys.stderr.write('Unexpected: no "type" attribute in response tag\n')
		sys.exit(2)

	if root.attrib['type'] == 'error':
		for child in root:
			if child.tag == 'data':
				sys.stderr.write('Error: {}\n'.format(child.text))
				sys.exit(3)

		sys.stderr.write('Error: error type without data tag\n')
		sys.exit(4)

	elif root.attrib['type'] != 'success':
		sys.stderr.write('Unexpected: not an error, but not success: "{}"\n'.format(root.attrib['type']))
		sys.exit(5)

	for child in root:
		if child.tag == 'warning':
			if not 'data' in child.attrib:
				sys.stderr.write('Warning: "{}"\n'.format(child.attrib))

			sys.stderr.write('Warning: {}\n'.format(child.attrib['data']))

		elif child.tag != 'success':
			sys.stderr.write('Unexpected: not a warning, but not success: "{}"\n'.format(child.attrib))
			sys.exit(6)

		elif 'data' in child.attrib:
			sys.stdout.write('{}\n'.format(child.attrib['data']))