summaryrefslogtreecommitdiff
path: root/src/leap/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/util')
-rw-r--r--src/leap/util/__init__.py50
-rw-r--r--src/leap/util/config.py172
-rw-r--r--src/leap/util/exceptions.py23
-rw-r--r--src/leap/util/log.py154
-rw-r--r--src/leap/util/net.py126
-rw-r--r--src/leap/util/version.py101
6 files changed, 0 insertions, 626 deletions
diff --git a/src/leap/util/__init__.py b/src/leap/util/__init__.py
deleted file mode 100644
index 35e1297..0000000
--- a/src/leap/util/__init__.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- encoding: utf-8 -*-
-"""
- mx/util/__init__.py
- -------------------
- Initialization file for leap_mx utilities. Some miscellaneous things are
- stored here also.
-"""
-
-
-class Storage(dict):
- """
- A Storage object is like a dictionary except `obj.foo` can be used
- in addition to `obj['foo']`.
-
- >>> o = Storage(a=1)
- >>> o.a
- 1
- >>> o['a']
- 1
- >>> o.a = 2
- >>> o['a']
- 2
- >>> del o.a
- >>> o.a
- None
- """
- def __getattr__(self, key):
- try:
- return self[key]
- except KeyError, k:
- return None
-
- def __setattr__(self, key, value):
- self[key] = value
-
- def __delattr__(self, key):
- try:
- del self[key]
- except KeyError, k:
- raise AttributeError, k
-
- def __repr__(self):
- return '<Storage ' + dict.__repr__(self) + '>'
-
- def __getstate__(self):
- return dict(self)
-
- def __setstate__(self, value):
- for (k, v) in value.items():
- self[k] = v
diff --git a/src/leap/util/config.py b/src/leap/util/config.py
deleted file mode 100644
index 5bc5231..0000000
--- a/src/leap/util/config.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#! -*- encoding: utf-8 -*-
-"""
-Config file utilities.
-
-This module has an :attr:`config_filename`, which can be used to set the
-filename outside of function calls:
-
- >>> from leap.mx.util import config
- >>> config.config_filename = "blahblah.yaml"
-
-If not set anywhere, it will default to using the top level repository
-directory, i.e. "/.../leap_mx/leap_mx.conf", and will create that file with
-the default settings if it does not exist.
-
-The config file can be loaded/created with :func:`config.loadConfig`:
-
- >>> config.loadConfig()
-
-Once the config file is loaded, this module presents a highly object-oriented
-interface, so that sections taken from the config file become attribute of
-this module, and the name of their respective settings become attributes of
-the section names. Like this:
-
- >>> print config.basic.postfix_port
- 465
-
-@authors: Isis Lovecruft, <isis@leap.se> 0x2cdb8b35
-@version: 0.0.1
-@license: see included LICENSE file
-"""
-
-import os
-import yaml
-
-## xxx only install/import this in *nix
-from xdg import BaseDirectory
-
-from leap.util import log, version, Storage
-from leap.util.exceptions import MissingConfig, UnsupportedOS
-
-
-def _create_config_file(file):
- """
- xxx fill me in
- """
- with open(file, 'w+') as conf:
- conf.write("""
-#
-# mx.conf
-# =======
-# Configurable options for the leap_mx encrypting mail exchange.
-#
-# This file follows YAML markup format: http://yaml.org/spec/1.2/spec.html
-# Keep in mind that indentation matters.
-#
-
-basic:
- # Where is the spoolfile of messages to encrypt?:
- spoolfile: /var/mail/encrypt_me
-advanced:
- # Which port on localhost should postfix send check_recipient queries to?:
- check_recipient_access_port: 1347
- # Which port on localhost should postfix ask for UUIDs?:
- virtual_alias_map_port: 1348
- # Enable debugging output in the logger:
- debug: true
- # Print enough things really fast to make you look super 1337:
- noisy: false
-
-""")
- conf.flush()
- try:
- assert os.path.isfile(file), "Config file %s not created!" % file
- except AssertionError, ae:
- raise SystemExit(ae.message)
- else:
- return file
-
-def _get_config_filename(filename=None, use_dot_config_directory=False):
- """
- Get the full path and filename of the config file.
- """
- platform = version.getClientPlatform()[0]
- resource = version.name
-
- ## Oh hell, it could be said only to beguile:
- ## That windoze users are capable of editing a .conf file.
- ## Also, what maddened wingnut would be so fool
- ## To run a mail exchange on a windoze nodule?
- ## I'm ignoring these loons for now. And pardon if I seem jaded,
- ## But srsly, this and that solaris sh*t should be deprecated.
- if not platform.endswith('LINUX') and not platform.endswith('BSD'):
- raise UnsupportedOS("Sorry, your operating system isn't supported.")
-
- ## If not given, default to the application's name + '.conf'
- if not filename:
- filename = resource + ".conf"
-
- where = None
- if not use_dot_config_directory:
- repo_dir = version.getRepoDir()
- where = os.path.abspath(repo_dir)
- ## Use ~/.config/ instead:
- else:
- dot_config_dirs = BaseDirectory.xdg_config_dirs
- for dir in dot_config_dirs:
- our_dir = os.path.join(dir, resource)
- if os.path.isdir(our_dir):
- if filename in os.listdir(our_dir):
- where = os.path.abspath(our_dir)
- if not where:
- where = BaseDirectory.save_config_path(resource)
-
- conffile = os.path.join(where, filename)
- try:
- with open(conffile) as cf: pass
- except IOError:
- conffile = _create_config_file(conffile)
- finally:
- return conffile
-
-def loadConfig(filename=config_filename):
- """
- Some of this is taken from OONI config code for now, and so this should be
- refacotored, along with the leap_client config code, so that we have
- similarly structured config files. It is perhaps desirable to also use
- soledad as a backend for remote setup and maintainance, and thus this code
- will need to hook into u1db (and potentially "pysqlcipher").
-
- Excuse the yaml for now, I just wanted something that works.
-
- @param filename: (optional) If provided, use this filename.
- """
- if not filename:
- filename = _get_config_filename()
-
- if os.path.isfile(filename):
- with open(filename, 'a+') as conf:
- config_contents = '\n'.join(conf.readlines())
- configuration = yaml.safe_load(config_contents)
-
- ## These become objects with their keys loaded as attributes:
- ##
- ## from leap.util import config
- ## config.basic.foo = bar
- ##
- basic = Storage()
- try:
- for k, v in configuration['basic'].items():
- basic[k] = v
- except AttributeError:
- pass
-
- advanced = Storage()
- try:
- for k, v in configuration['advanced'].items():
- advanced[k] = v
- except AttributeError:
- pass
-
- return basic, advanced
- else:
- raise MissingConfig("Could not load config file.")
-
-
-## This is the name of the config file to use:
-## If not set, it defaults to 'leap_mx/leap_mx.conf'
-if not config_filename:
- config_filename = _get_config_filename()
-else:
- config_filename = _get_config_filename(filename=config_filename)
-
diff --git a/src/leap/util/exceptions.py b/src/leap/util/exceptions.py
deleted file mode 100644
index 63b946c..0000000
--- a/src/leap/util/exceptions.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#! -*- encoding: utf-8 -*-
-"""
-Custom exceptions for leap_mx.
-
-@authors: Isis Lovecruft, <isis@leap.se> 0x2cdb8b35
-@version: 0.0.1
-@license: see included LICENSE file
-"""
-
-
-class MissingConfig(Exception):
- """Raised when the config file cannot be found."""
- def __init__(self, message=None, config_file=None):
- if message:
- return
- else:
- self.message = "Cannot locate config file"
- if config_file:
- self.message += " %s" % config_file
- self.message += "."
-
-class UnsupportedOS(Exception):
- """Raised when we're not *nix or *BSD."""
diff --git a/src/leap/util/log.py b/src/leap/util/log.py
deleted file mode 100644
index ef54605..0000000
--- a/src/leap/util/log.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding: utf-8 -*-
-'''
-log.py
-------
-Logging for leap_mx.
-
-@authors: Isis Agora Lovecruft, <isis@leap.se> 0x2cdb8b35
-@licence: see included LICENSE file
-@copyright: 2013 Isis Agora Lovecruft
-'''
-
-from datetime import datetime
-from functools import wraps
-
-import logging
-import os
-import sys
-import time
-import traceback
-
-from twisted.python import log as txlog
-from twisted.python import util as txutil
-from twisted.python.logfile import DailyLogFile
-from twisted.python.failure import Failure
-
-from leap.util import version, config
-
-
-class InvalidTimestampFormat(Exception):
- pass
-
-class UnprefixedLogfile(txlog.FileLogObserver):
- """Logfile with plain messages, without timestamp prefixes."""
- def emit(self, eventDict):
- text = txlog.textFromEventDict(eventDict)
- if text is None:
- return
-
- txutil.untilConcludes(self.write, "%s\n" % text)
- txutil.untilConcludes(self.flush)
-
-
-def utcDateNow():
- """The current date for UTC time."""
- return datetime.utcnow()
-
-def utcTimeNow():
- """Seconds since epoch in UTC time, as type float."""
- return time.mktime(time.gmtime())
-
-def dateToTime(date):
- """Convert datetime to seconds since epoch."""
- return time.mktime(date.timetuple())
-
-def prettyDateNow():
- """Pretty string for the local time."""
- return datetime.now().ctime()
-
-def utcPrettyDateNow():
- """Pretty string for UTC."""
- return datetime.utcnow().ctime()
-
-def timeToPrettyDate(time_val):
- """Convert seconds since epoch to date."""
- return time.ctime(time_val)
-
-def start(logfile=None, application_name=None):
- """
- Start logging to stdout, and optionally to a logfile as well.
-
- @param logfile: The filename to store logs in, which is placed in
- /leap_mx/logs/.
- @param application_name: The name of the running application.
- """
- if not application_name:
- application_name = version.name
- print "application name: %s" % application_name
-
- daily_logfile = None
-
- if not logfile:
- logfile = config.basic.logfile
-
- repo_dir = version.getRepoDir()
- logfile_dir = os.path.join(repo_dir, 'log')
- logfile_name = logfile
-
- daily_logfile = DailyLogFile(logfile_name, logfile_dir)
-
- txlog.startLoggingWithObserver(UnprefixedLogfile(sys.stdout).emit)
- txlog.addObserver(txlog.FileLogObserver(daily_logfile).emit)
- txlog.msg("Starting %s on %s (%s UTC)" % (application_name,
- prettyDateNow(),
- utcPrettyDateNow()))
-
-def msg(msg, *arg, **kwarg):
- """Log a message at the INFO level."""
- print "[*] %s" % msg
-
-def debug(msg, *arg, **kwarg):
- """Log a message at the DEBUG level."""
- if config.basic.debug:
- print "[d] %s" % msg
-
-def warn(msg, *arg, **kwarg):
- """Log a message at the WARN level."""
- if config.basic.show_warnings:
- txlog.logging.captureWarnings('true')
- print "[#] %s" % msg
-
-def err(msg, *arg, **kwarg):
- """Log a message at the ERROR level."""
- print "[!] %s" % msg
-
-def fail(*failure):
- """Log a message at the CRITICAL level."""
- logging.critical(failure)
- ## xxx should we take steps to exit here?
-
-def exception(error):
- """
- Catch an exception and print only the error message, then continue normal
- program execution.
-
- @param error: Can be error messages printed to stdout and to the
- logfile, or can be a twisted.python.failure.Failure instance.
- """
- if isinstance(error, Failure):
- error.printTraceback()
- else:
- exc_type, exc_value, exc_traceback = sys.exc_info()
- traceback.print_exception(exc_type, exc_value, exc_traceback)
-
-def catch(func):
- """
- Quick wrapper to add around test methods for debugging purposes,
- catches the given Exception. Use like so:
-
- >>> @log.catch
- def foo(bar):
- if bar == 'baz':
- raise Exception("catch me no matter what I am")
- >>> foo("baz")
- [!] catch me no matter what I am
-
- """
- @wraps(func)
- def _catch(*args, **kwargs):
- try:
- func(*args, **kwargs)
- except Exception, exc:
- exception(exc)
- return _catch
diff --git a/src/leap/util/net.py b/src/leap/util/net.py
deleted file mode 100644
index a4104d0..0000000
--- a/src/leap/util/net.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding: utf-8 -*-
-'''
-net.py
--------
-Utilities for networking.
-
-@authors: Isis Agora Lovecruft, <isis@leap.se> 0x2cdb8b35
-@license: see included LICENSE file
-@copyright: 2013 Isis Agora Lovecruft
-'''
-
-import ipaddr
-import sys
-import socket
-
-from random import randint
-
-from leap.mx.utils import log
-
-
-PLATFORMS = {'LINUX': sys.platform.startswith("linux"),
- 'OPENBSD': sys.platform.startswith("openbsd"),
- 'FREEBSD': sys.platform.startswith("freebsd"),
- 'NETBSD': sys.platform.startswith("netbsd"),
- 'DARWIN': sys.platform.startswith("darwin"),
- 'SOLARIS': sys.platform.startswith("sunos"),
- 'WINDOWS': sys.platform.startswith("win32")}
-
-
-class UnsupportedPlatform(Exception):
- """Support for this platform is not currently available."""
-
-class IfaceError(Exception):
- """Could not find default network interface."""
-
-class PermissionsError(SystemExit):
- """This test requires admin or root privileges to run. Exiting..."""
-
-
-def checkIPaddress(addr):
- """
- Check that a given string is a valid IPv4 or IPv6 address.
-
- @param addr: Any string defining an IP address, i.e. '1.2.3.4' or '::1'.
- @returns: True if :param:`addr` defines a valid IPAddress, else False.
- """
- import ipaddr
-
- try:
- check = ipaddr.IPAddress(addr)
- except ValueError, ve:
- log.warn(ve.message)
- return False
- else:
- return True
-
-def getClientPlatform(platform_name=None):
- for name, test in PLATFORMS.items():
- if not platform_name or platform_name.upper() == name:
- if test:
- return name, test
-
-def getPosixIfaces():
- from twisted.internet.test import _posixifaces
- log.msg("Attempting to discover network interfaces...")
- ifaces = _posixifaces._interfaces()
- return ifaces
-
-def getWindowsIfaces():
- from twisted.internet.test import _win32ifaces
- log.msg("Attempting to discover network interfaces...")
- ifaces = _win32ifaces._interfaces()
- return ifaces
-
-def getIfaces(platform_name=None):
- client, test = getClientPlatform(platform_name)
- if client:
- if client == ('LINUX' or 'DARWIN') or client[-3:] == 'BSD':
- return getPosixIfaces()
- elif client == 'WINDOWS':
- return getWindowsIfaces()
- ## XXX fixme figure out how to get iface for Solaris
- else:
- raise UnsupportedPlatform
- else:
- raise UnsupportedPlatform
-
-def getRandomUnusedPort(addr=None):
- free = False
- while not free:
- port = randint(1024, 65535)
- s = socket.socket()
- try:
- s.bind((addr, port))
- free = True
- except:
- pass
- s.close()
- return port
-
-def getNonLoopbackIfaces(platform_name=None):
- try:
- ifaces = getIfaces(platform_name)
- except UnsupportedPlatform, up:
- log.err(up)
-
- if not ifaces:
- log.msg("Unable to discover network interfaces...")
- return None
- else:
- found = [{i[0]: i[2]} for i in ifaces if i[0] != 'lo']
- log.debug("Found non-loopback interfaces: %s" % found)
- for iface in ifaces:
- try:
- interface = checkInterfaces(found)
- except IfaceError, ie:
- log.err(ie)
- return None
- else:
- return interfaces
-
-
-def getLocalAddress():
- default_iface = getDefaultIface()
- return default_iface.ipaddr
diff --git a/src/leap/util/version.py b/src/leap/util/version.py
deleted file mode 100644
index 215876c..0000000
--- a/src/leap/util/version.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding: utf-8 -*-
-'''
-version.py
-----------
-Version information for leap_mx.
-
-@authors: Isis Agora Lovecruft, <isis@leap.se> 0x2cdb8b35
-@licence: see included LICENSE file
-@copyright: 2013 Isis Agora Lovecruft
-'''
-
-import os
-import sys
-
-from twisted.python import versions
-
-name = 'leap_mx'
-version = versions.Version(name, 0, 0, 1, None)
-authors = [('Isis Agora Lovecruft', '<isis@leap.se>', '0x2cdb8b35'),]
-git_url = 'https://github.com/isislovecruft/leap_mx/'
-website = 'https://leap.se'
-
-PLATFORMS = {'LINUX': sys.platform.startswith("linux"),
- 'OPENBSD': sys.platform.startswith("openbsd"),
- 'FREEBSD': sys.platform.startswith("freebsd"),
- 'NETBSD': sys.platform.startswith("netbsd"),
- 'DARWIN': sys.platform.startswith("darwin"),
- 'SOLARIS': sys.platform.startswith("sunos"),
- 'WINDOWS': sys.platform.startswith("win32")}
-
-def getClientPlatform(platform_name=None):
- """
- Determine the client's operating system platform. Optionally, if
- :param:`platform_name` is given, check that this is indeed the platform
- we're operating on.
-
- @param platform_name: A string, upper-, lower-, or mixed case, of one of
- the keys in the :attr:`leap.util.version.PLATFORMS` dictionary. E.g.
- 'Linux' or 'OPENBSD', etc.
- @returns: A string specifying the platform name, and the boolean test used
- to determine it.
- """
- for name, test in PLATFORMS.items():
- if not platform_name or platform_name.upper() == name:
- if test:
- return name, test
-
-def getVersion():
- """
- Returns a version object, with attributes authors, git_url, and website.
- """
- version.authors = authors
- version.git_url = git_url
- version.website = website
- return version
-
-def getRepoDir():
- """
- Get the top-level repository directory.
- """
- here = os.getcwd()
- base = here.rsplit(name, 1)[0]
- repo = os.path.join(base, name)
- return repo
-
-def __make_text__(extra_text=None):
- splitter = "-" * len(version.__str__())
- header = ["\n%s\n" % version.__str__(), "%s\n" % splitter]
- footer = ["Website: \t%s\n" % website, "Github: \t%s\n" % git_url, "\n"]
- contacts = ["\t%s, %s %s\n" % (a[0], a[1], a[2]) for a in authors]
- contacts.insert(0, "Authors: ")
-
- with_contacts = header + contacts
-
- if extra_text is not None:
- if isinstance(extra_text, iter):
- with_contacts.extend((e for e in extra_text))
- elif isinstance(extra_text, str):
- with_contacts.append(extra_text)
- else:
- print "Couldn't add extra text..."
-
- text = with_contacts + footer
- return text
-
-def __update_version__():
- repo = getRepoDir()
- version_file = os.path.join(repo, 'VERSION')
- version_text = __make_text__()
-
- with open(version_file, 'w+') as fh:
- fh.writelines((line for line in version_text))
- fh.flush()
- fh.truncate()
-
-
-if __name__ == "__main__":
- print "Generating new VERSION file..."
- __update_version__()
- print "Done."