# This file is part of FreedomBox. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # import os import re import augeas I2P_CONF_DIR = '/var/lib/i2p/i2p-config' FILE_TUNNEL_CONF = os.path.join(I2P_CONF_DIR, 'i2ptunnel.config') TUNNEL_IDX_REGEX = re.compile(r'tunnel.(\d+).name$') class TunnelEditor(object): """ :type aug: augeas.Augeas """ def __init__(self, conf_filename=None, idx=None): self.conf_filename = conf_filename or FILE_TUNNEL_CONF self.idx = idx self.aug = None @property def lines(self): if self.aug: return self.aug.match('/files{}/*'.format(self.conf_filename)) else: return [] def read_conf(self): """Return an instance of Augeaus for processing APT configuration.""" self.aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD) self.aug.set('/augeas/load/Properties/lens', 'Properties.lns') self.aug.set('/augeas/load/Properties/incl[last() + 1]', self.conf_filename) self.aug.load() return self def write_conf(self): self.aug.save() return self def set_tunnel_idx(self, name): """ Finds the index of the tunnel with the given name. Chainable method. :type name: basestring """ for prop in self.aug.match('/files{}/*'.format(self.conf_filename)): match = TUNNEL_IDX_REGEX.search(prop) if match and self.aug.get(prop) == name: self.idx = int(match.group(1)) return self raise ValueError('No tunnel with that name') def calc_prop_path(self, tunnel_prop): """ Calculates the property name as found in the properties files :type tunnel_prop: str :rtype: basestring """ calced_prop_path = '/files{filepath}/tunnel.{idx}.{tunnel_prop}'.format( idx=self.idx, tunnel_prop=tunnel_prop, filepath=self.conf_filename ) return calced_prop_path def set_tunnel_prop(self, tunnel_prop, value): """ Updates a tunnel's property. The idx has to be set and the property has to exist in the config file and belong to the tunnel's properties. see calc_prop_path Chainable method. :param tunnel_prop: :type tunnel_prop: str :param value: :type value: basestring | int :return: :rtype: """ if self.idx is None: raise ValueError('Please init the tunnel index before calling this method') calc_prop_path = self.calc_prop_path(tunnel_prop) self.aug.set(calc_prop_path, value) return self def __getitem__(self, tunnel_prop): ret = self.aug.get(self.calc_prop_path(tunnel_prop)) if ret is None: raise KeyError('Unknown property {}'.format(tunnel_prop)) return ret def __setitem__(self, tunnel_prop, value): self.aug.set(self.calc_prop_path(tunnel_prop), value)