change identation from tabs to spaces

This commit is contained in:
lars 2007-08-18 00:45:12 +00:00
parent c8e28f5241
commit 3224d59dfe
62 changed files with 6614 additions and 6614 deletions

View file

@ -31,86 +31,86 @@ import cryptobox.plugins.base
class date(cryptobox.plugins.base.CryptoBoxPlugin):
"""The date feature of the CryptoBox.
"""
"""The date feature of the CryptoBox.
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = False
rank = 10
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = False
rank = 10
def do_action(self, store=None, year=0, month=0, day=0, hour=0, minute=0):
"""The action handler.
"""
import datetime
if store:
try:
year, month, day = int(year), int(month), int(day)
hour, minute = int(hour), int(minute)
## check if the values are valid
datetime.datetime(year, month, day, hour, minute)
except ValueError:
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
else:
new_date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
if self.__set_date(new_date):
self.cbox.log.info("changed date to: %s" % new_date)
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
else:
## a failure should usually be an invalid date (we do not check it really)
self.cbox.log.info("failed to set date: %s" % new_date)
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
self.__prepare_form_data()
return "form_date"
def do_action(self, store=None, year=0, month=0, day=0, hour=0, minute=0):
"""The action handler.
"""
import datetime
if store:
try:
year, month, day = int(year), int(month), int(day)
hour, minute = int(hour), int(minute)
## check if the values are valid
datetime.datetime(year, month, day, hour, minute)
except ValueError:
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
else:
new_date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
if self.__set_date(new_date):
self.cbox.log.info("changed date to: %s" % new_date)
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
else:
## a failure should usually be an invalid date (we do not check it really)
self.cbox.log.info("failed to set date: %s" % new_date)
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
self.__prepare_form_data()
return "form_date"
def get_status(self):
"""Retrieve the status of the feature.
"""
now = self.__get_current_date()
return "%d/%d/%d/%d/%d/%d" % \
(now.year, now.month, now.day, now.hour, now.minute, now.second)
def get_status(self):
"""Retrieve the status of the feature.
"""
now = self.__get_current_date()
return "%d/%d/%d/%d/%d/%d" % \
(now.year, now.month, now.day, now.hour, now.minute, now.second)
def get_warnings(self):
import os
warnings = []
if not os.path.isfile(self.root_action.DATE_BIN):
warnings.append((48, "Plugins.%s.MissingProgramDate" % self.get_name()))
return warnings
def get_warnings(self):
import os
warnings = []
if not os.path.isfile(self.root_action.DATE_BIN):
warnings.append((48, "Plugins.%s.MissingProgramDate" % self.get_name()))
return warnings
def __prepare_form_data(self):
"""Set some hdf values.
"""
cur_date = self.__get_current_date()
self.hdf[self.hdf_prefix + "year"] = cur_date.year
self.hdf[self.hdf_prefix + "month"] = cur_date.month
self.hdf[self.hdf_prefix + "day"] = cur_date.day
self.hdf[self.hdf_prefix + "hour"] = cur_date.hour
self.hdf[self.hdf_prefix + "minute"] = cur_date.minute
def __prepare_form_data(self):
"""Set some hdf values.
"""
cur_date = self.__get_current_date()
self.hdf[self.hdf_prefix + "year"] = cur_date.year
self.hdf[self.hdf_prefix + "month"] = cur_date.month
self.hdf[self.hdf_prefix + "day"] = cur_date.day
self.hdf[self.hdf_prefix + "hour"] = cur_date.hour
self.hdf[self.hdf_prefix + "minute"] = cur_date.minute
def __get_current_date(self):
"""Retrieve the current date and time.
"""
import datetime
return datetime.datetime(2000, 1, 1).now()
def __get_current_date(self):
"""Retrieve the current date and time.
"""
import datetime
return datetime.datetime(2000, 1, 1).now()
def __set_date(self, new_date):
"""Set a new date and time.
"""
import subprocess
import os
proc = subprocess.Popen(
shell = False,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
new_date])
proc.wait()
return proc.returncode == 0
def __set_date(self, new_date):
"""Set a new date and time.
"""
import subprocess
import os
proc = subprocess.Popen(
shell = False,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
new_date])
proc.wait()
return proc.returncode == 0

View file

@ -33,26 +33,26 @@ import sys
import os
if __name__ == "__main__":
args = sys.argv[1:]
args = sys.argv[1:]
self_bin = sys.argv[0]
if len(args) > 1:
sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args))
sys.exit(1)
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
if re.search(r'\D', args[0]):
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
sys.exit(1)
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
args = [DATE_BIN, args[0]])
proc.wait()
sys.exit(proc.returncode)
self_bin = sys.argv[0]
if len(args) > 1:
sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args))
sys.exit(1)
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
if re.search(r'\D', args[0]):
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
sys.exit(1)
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
args = [DATE_BIN, args[0]])
proc.wait()
sys.exit(proc.returncode)

View file

@ -23,75 +23,75 @@ __revision__ = "$Id$"
from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_get_date(self):
"""retrieve the current date"""
date = self._get_current_date()
def test_get_date(self):
"""retrieve the current date"""
date = self._get_current_date()
def test_change_date(self):
"""set the date back and forth"""
now = self._get_current_date()
## copy current time
new_date = dict(now)
## move three minutes forward (more is not nice because of screensavers)
new_date["minute"] = (now["minute"] + 3) % 60
## in case of minute-overflow we also have to move the hour a little bit forward
new_date["hour"] = now["hour"] + ((now["minute"] + 3) / 60)
## move forward ...
self._setDate(new_date)
self.assertEquals(new_date, self._get_current_date())
## ... and backward
self._setDate(now)
self.assertEquals(now, self._get_current_date())
def test_change_date(self):
"""set the date back and forth"""
now = self._get_current_date()
## copy current time
new_date = dict(now)
## move three minutes forward (more is not nice because of screensavers)
new_date["minute"] = (now["minute"] + 3) % 60
## in case of minute-overflow we also have to move the hour a little bit forward
new_date["hour"] = now["hour"] + ((now["minute"] + 3) / 60)
## move forward ...
self._setDate(new_date)
self.assertEquals(new_date, self._get_current_date())
## ... and backward
self._setDate(now)
self.assertEquals(now, self._get_current_date())
def test_try_broken_date(self):
"""expect error messages for invalid dates"""
self._setDate({"hour":12, "minute":40, "year":2004, "month":7, "day":0})
self.cmd.find("invalid value for date")
self._setDate({"hour":12, "minute":40, "year":"x", "month":7, "day":2})
self.cmd.find("invalid value for date")
self._setDate({"hour":12, "minute":40, "year":2004, "month":2, "day":31})
self.cmd.find("invalid value for date")
def test_try_broken_date(self):
"""expect error messages for invalid dates"""
self._setDate({"hour":12, "minute":40, "year":2004, "month":7, "day":0})
self.cmd.find("invalid value for date")
self._setDate({"hour":12, "minute":40, "year":"x", "month":7, "day":2})
self.cmd.find("invalid value for date")
self._setDate({"hour":12, "minute":40, "year":2004, "month":2, "day":31})
self.cmd.find("invalid value for date")
def _get_current_date(self):
date_url = self.url + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.find("Data.Status.Plugins.date=([0-9]+/[0-9]+/[0-9]+/[0-9]+/[0-9]+/[0-9]+)$", "m")
dateNumbers = self.locals["__match__"].split("/")
self.assertEquals(len(dateNumbers), 6)
## we ignore seconds
dateField = {
"year" : int(dateNumbers[0]),
"month" : int(dateNumbers[1]),
"day" : int(dateNumbers[2]),
"hour" : int(dateNumbers[3]),
"minute" : int(dateNumbers[4])}
return dateField
def _get_current_date(self):
date_url = self.url + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.find("Data.Status.Plugins.date=([0-9]+/[0-9]+/[0-9]+/[0-9]+/[0-9]+/[0-9]+)$", "m")
dateNumbers = self.locals["__match__"].split("/")
self.assertEquals(len(dateNumbers), 6)
## we ignore seconds
dateField = {
"year" : int(dateNumbers[0]),
"month" : int(dateNumbers[1]),
"day" : int(dateNumbers[2]),
"hour" : int(dateNumbers[3]),
"minute" : int(dateNumbers[4])}
return dateField
def _setDate(self, date):
"""for now we have to use this function instead of the one below"""
date_url = self.url + "date?weblang=en&store=1&year=%s&month=%s&day=%s&hour=%s&minute=%s"\
% (str(date["year"]), str(date["month"]), str(date["day"]),
str(date["hour"]), str(date["minute"]))
self.register_auth(date_url)
self.cmd.go(date_url)
def _setDate(self, date):
"""for now we have to use this function instead of the one below"""
date_url = self.url + "date?weblang=en&store=1&year=%s&month=%s&day=%s&hour=%s&minute=%s"\
% (str(date["year"]), str(date["month"]), str(date["day"]),
str(date["hour"]), str(date["minute"]))
self.register_auth(date_url)
self.cmd.go(date_url)
def _setDateBroken(self, date):
"""this should work, but the parsing of twill seems to be broken
as soon as the twill bug is fixed, we should use this function"""
date_url = self.url + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.formvalue("set_date", "year", str(date["year"]))
self.cmd.formvalue("set_date", "month", str(date["month"]))
self.cmd.formvalue("set_date", "day", str(date["day"]))
self.cmd.formvalue("set_date", "hour", str(date["hour"]))
self.cmd.formvalue("set_date", "minute", str(date["minute"]))
self.cmd.submit()
def _setDateBroken(self, date):
"""this should work, but the parsing of twill seems to be broken
as soon as the twill bug is fixed, we should use this function"""
date_url = self.url + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.formvalue("set_date", "year", str(date["year"]))
self.cmd.formvalue("set_date", "month", str(date["month"]))
self.cmd.formvalue("set_date", "day", str(date["day"]))
self.cmd.formvalue("set_date", "hour", str(date["hour"]))
self.cmd.formvalue("set_date", "minute", str(date["minute"]))
self.cmd.submit()

View file

@ -26,23 +26,23 @@ __revision__ = "$Id$"
import cryptobox.plugins.base
class disks(cryptobox.plugins.base.CryptoBoxPlugin):
"""The disk feature of the CryptoBox.
"""
"""The disk feature of the CryptoBox.
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 10
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 10
def do_action(self):
"""The action handler.
"""
self.cbox.reread_container_list()
return "disks"
def do_action(self):
"""The action handler.
"""
self.cbox.reread_container_list()
return "disks"
def get_status(self):
"""Retrieve the current status of the feature.
"""
return ":".join([e.get_device() for e in self.cbox.get_container_list()])
def get_status(self):
"""Retrieve the current status of the feature.
"""
return ":".join([e.get_device() for e in self.cbox.get_container_list()])

View file

@ -24,20 +24,20 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
'''display all devices'''
self.register_auth(self.url)
self.cmd.go(self.url + "disks?weblang=en")
self.cmd.find("Available disks")
def test_read_form(self):
'''display all devices'''
self.register_auth(self.url)
self.cmd.go(self.url + "disks?weblang=en")
self.cmd.find("Available disks")
def test_is_device_in_list(self):
"""check if the device-under-test is in the device list"""
self.register_auth(self.url)
self.cmd.go(self.url + "disks?weblang=en")
self.cmd.find("Available disks")
self.cmd.find(r'Data.Status.Plugins.disks=(.*)$', "m")
devices = self.locals["__match__"].split(":")
self.assertTrue(len(devices)>0)
self.assertTrue(self.device in devices)
def test_is_device_in_list(self):
"""check if the device-under-test is in the device list"""
self.register_auth(self.url)
self.cmd.go(self.url + "disks?weblang=en")
self.cmd.find("Available disks")
self.cmd.find(r'Data.Status.Plugins.disks=(.*)$', "m")
devices = self.locals["__match__"].split(":")
self.assertTrue(len(devices)>0)
self.assertTrue(self.device in devices)

View file

@ -35,232 +35,232 @@ import cherrypy
CERT_FILENAME = 'cryptobox-ssl-certificate.pem'
KEY_BITS = 1024
ISSUER_INFOS = {
"ST": "SomeIssuerState",
"L": "SomeIssuerLocality",
"O": "SomeIssuerOrganization",
"OU": "CryptoBox-ServerIssuer",
"CN": "cryptoboxIssuer",
"emailAddress": "infoIssuer@cryptobox.org"}
"ST": "SomeIssuerState",
"L": "SomeIssuerLocality",
"O": "SomeIssuerOrganization",
"OU": "CryptoBox-ServerIssuer",
"CN": "cryptoboxIssuer",
"emailAddress": "infoIssuer@cryptobox.org"}
CERT_INFOS = {
"ST": "SomeState",
"L": "SomeLocality",
"O": "SomeOrganization",
"OU": "CryptoBox-Server",
"CN": "*",
"emailAddress": "info@cryptobox.org"}
"ST": "SomeState",
"L": "SomeLocality",
"O": "SomeOrganization",
"OU": "CryptoBox-Server",
"CN": "*",
"emailAddress": "info@cryptobox.org"}
EXPIRE_TIME = 60*60*24*365*20 # 20 years forward and backward
SIGN_DIGEST = "md5"
PID_FILE = os.path.join("/tmp/cryptobox-stunnel.pid")
class encrypted_webinterface(cryptobox.plugins.base.CryptoBoxPlugin):
"""Provide an encrypted webinterface connection via stunnel
"""
"""Provide an encrypted webinterface connection via stunnel
"""
plugin_capabilities = [ "system" ]
plugin_visibility = []
request_auth = True
rank = 80
plugin_capabilities = [ "system" ]
plugin_visibility = []
request_auth = True
rank = 80
def do_action(self):
"""The action handler.
"""
return None
def do_action(self):
"""The action handler.
"""
return None
def get_status(self):
"""Retrieve the current state of the webinterface connection
"""
if self.__is_encrypted():
return "1"
else:
return "0"
def get_status(self):
"""Retrieve the current state of the webinterface connection
"""
if self.__is_encrypted():
return "1"
else:
return "0"
def get_warnings(self):
"""check if the connection is encrypted
"""
warnings = []
## check if m2crypto is available
try:
import M2Crypto
except ImportError:
warnings.append((45, "Plugins.%s.MissingModuleM2Crypto" % self.get_name()))
if not os.path.isfile(self.root_action.STUNNEL_BIN):
warnings.append((44, "Plugins.%s.MissingProgramStunnel" % self.get_name()))
if not self.__is_encrypted():
## plaintext connection -> "heavy security risk" (priority=20..39)
warnings.append((25, "Plugins.%s.NoSSL" % self.get_name()))
return warnings
def get_warnings(self):
"""check if the connection is encrypted
"""
warnings = []
## check if m2crypto is available
try:
import M2Crypto
except ImportError:
warnings.append((45, "Plugins.%s.MissingModuleM2Crypto" % self.get_name()))
if not os.path.isfile(self.root_action.STUNNEL_BIN):
warnings.append((44, "Plugins.%s.MissingProgramStunnel" % self.get_name()))
if not self.__is_encrypted():
## plaintext connection -> "heavy security risk" (priority=20..39)
warnings.append((25, "Plugins.%s.NoSSL" % self.get_name()))
return warnings
def __is_encrypted(self):
"""perform some checks for encrypted connections
"""
if cherrypy.request.scheme == "https":
return True
## check an environment setting - this is quite common behind proxies
if os.environ.has_key("HTTPS"):
return True
## check if it is a local connection (or via stunnel)
if cherrypy.request.headers.has_key("Remote-Host") \
and (cherrypy.request.headers["Remote-Host"] == "127.0.0.1"):
return True
## the arbitrarily chosen header is documented in README.proxy
if cherrypy.request.headers.has_key("X-SSL-Request") \
and (cherrypy.request.headers["X-SSL-Request"] == "1"):
return True
## it looks like a plain connection
return False
def __is_encrypted(self):
"""perform some checks for encrypted connections
"""
if cherrypy.request.scheme == "https":
return True
## check an environment setting - this is quite common behind proxies
if os.environ.has_key("HTTPS"):
return True
## check if it is a local connection (or via stunnel)
if cherrypy.request.headers.has_key("Remote-Host") \
and (cherrypy.request.headers["Remote-Host"] == "127.0.0.1"):
return True
## the arbitrarily chosen header is documented in README.proxy
if cherrypy.request.headers.has_key("X-SSL-Request") \
and (cherrypy.request.headers["X-SSL-Request"] == "1"):
return True
## it looks like a plain connection
return False
def handle_event(self, event, event_info=None):
"""Create a certificate during startup (if it does not exist) and run stunnel
"""
if event == "bootup":
cert_abs_name = self.cbox.prefs.get_misc_config_filename(CERT_FILENAME)
if not os.path.isfile(cert_abs_name):
cert = self.__get_certificate()
if cert is None:
## failed to create a certificate?
self.cbox.log.warn("Failed to import M2Crypto python module" \
+ " required for SSL certificate generation")
return
try:
self.cbox.prefs.create_misc_config_file(CERT_FILENAME, cert)
self.cbox.log.info("Created new SSL certificate: %s" % \
cert_abs_name)
## make it non-readable for other users
try:
os.chmod(cert_abs_name, 0600)
except OSError, err_msg:
self.cbox.log.warn("Failed to change permissions of secret " \
+ "certificate file (%s): %s" % \
(cert_abs_name, err_msg))
except IOError, err_msg:
## do not run stunnel without a certificate
self.cbox.log.warn("Failed to create new SSL certificate (%s): %s" \
% (cert_abs_name, err_msg))
return
self.__run_stunnel(cert_abs_name)
elif event == "shutdown":
self.__kill_stunnel()
def handle_event(self, event, event_info=None):
"""Create a certificate during startup (if it does not exist) and run stunnel
"""
if event == "bootup":
cert_abs_name = self.cbox.prefs.get_misc_config_filename(CERT_FILENAME)
if not os.path.isfile(cert_abs_name):
cert = self.__get_certificate()
if cert is None:
## failed to create a certificate?
self.cbox.log.warn("Failed to import M2Crypto python module" \
+ " required for SSL certificate generation")
return
try:
self.cbox.prefs.create_misc_config_file(CERT_FILENAME, cert)
self.cbox.log.info("Created new SSL certificate: %s" % \
cert_abs_name)
## make it non-readable for other users
try:
os.chmod(cert_abs_name, 0600)
except OSError, err_msg:
self.cbox.log.warn("Failed to change permissions of secret " \
+ "certificate file (%s): %s" % \
(cert_abs_name, err_msg))
except IOError, err_msg:
## do not run stunnel without a certificate
self.cbox.log.warn("Failed to create new SSL certificate (%s): %s" \
% (cert_abs_name, err_msg))
return
self.__run_stunnel(cert_abs_name)
elif event == "shutdown":
self.__kill_stunnel()
def __kill_stunnel(self):
"""try to kill a running stunnel daemon
"""
if not os.path.isfile(PID_FILE):
self.cbox.log.warn("Could not find the pid file of a running stunnel " \
+ "daemon: %s" % PID_FILE)
return
try:
pfile = open(PID_FILE, "r")
try:
pid = pfile.read().strip()
except IOError, err_msg:
self.cbox.log.warn("Failed to read the pid file (%s): %s" % (PID_FILE, err_msg))
pfile.close()
return
pfile.close()
except IOError, err_msg:
self.cbox.log.warn("Failed to open the pid file (%s): %s" % (PID_FILE, err_msg))
return
if pid.isdigit():
pid = int(pid)
else:
return
try:
## SIGTERM = 15
os.kill(pid, 15)
self.cbox.log.info("Successfully stopped stunnel")
try:
os.remove(PID_FILE)
except OSError, err_msg:
self.cbox.log.warn("Failed to remove the pid file (%s) of stunnel: %s" \
% (PID_FILE, err_msg))
except OSError, err_msg:
self.cbox.log.warn("Failed to kill stunnel process (PID: %d): %s" % \
(pid, err_msg))
def __kill_stunnel(self):
"""try to kill a running stunnel daemon
"""
if not os.path.isfile(PID_FILE):
self.cbox.log.warn("Could not find the pid file of a running stunnel " \
+ "daemon: %s" % PID_FILE)
return
try:
pfile = open(PID_FILE, "r")
try:
pid = pfile.read().strip()
except IOError, err_msg:
self.cbox.log.warn("Failed to read the pid file (%s): %s" % (PID_FILE, err_msg))
pfile.close()
return
pfile.close()
except IOError, err_msg:
self.cbox.log.warn("Failed to open the pid file (%s): %s" % (PID_FILE, err_msg))
return
if pid.isdigit():
pid = int(pid)
else:
return
try:
## SIGTERM = 15
os.kill(pid, 15)
self.cbox.log.info("Successfully stopped stunnel")
try:
os.remove(PID_FILE)
except OSError, err_msg:
self.cbox.log.warn("Failed to remove the pid file (%s) of stunnel: %s" \
% (PID_FILE, err_msg))
except OSError, err_msg:
self.cbox.log.warn("Failed to kill stunnel process (PID: %d): %s" % \
(pid, err_msg))
def __run_stunnel(self, cert_name, dest_port=443):
## retrieve currently requested port (not necessarily the port served
## by cherrypy - e.g. in a proxy setup)
request_port = cherrypy.config.get("server.socket_port", 80)
self.cbox.log.debug("[encrypted_webinterface] starting " \
+ "%s on port %s for %s" % \
(self.root_action.STUNNEL_BIN, dest_port, request_port))
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin", os.path.join(self.plugin_dir, "root_action.py"),
cert_name,
str(request_port),
str(dest_port),
PID_FILE ])
(output, error) = proc.communicate()
if proc.returncode == 0:
self.cbox.log.info("Successfully started 'stunnel'")
return True
else:
self.cbox.log.warn("Failed to run 'stunnel': %s" % error)
return False
def __run_stunnel(self, cert_name, dest_port=443):
## retrieve currently requested port (not necessarily the port served
## by cherrypy - e.g. in a proxy setup)
request_port = cherrypy.config.get("server.socket_port", 80)
self.cbox.log.debug("[encrypted_webinterface] starting " \
+ "%s on port %s for %s" % \
(self.root_action.STUNNEL_BIN, dest_port, request_port))
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin", os.path.join(self.plugin_dir, "root_action.py"),
cert_name,
str(request_port),
str(dest_port),
PID_FILE ])
(output, error) = proc.communicate()
if proc.returncode == 0:
self.cbox.log.info("Successfully started 'stunnel'")
return True
else:
self.cbox.log.warn("Failed to run 'stunnel': %s" % error)
return False
def __get_certificate(self):
"""Create a self-signed certificate and return its pem content
The code is mainly inspired by:
https://dev.tribler.org/browser/m2crypto/trunk/contrib/SimpleX509create.py
"""
## check if m2crypto is available
try:
import M2Crypto
except ImportError:
## failed to import the module
return None
import time
string_type = 0x1000 | 1 # see http://www.koders.com/python/..
# ../fid07A99E089F55187896A06CD4E0B6F21B9B8F5B0B.aspx?s=bavaria
key_gen_number = 0x10001 # commonly used for key generation: 65537
rsa_key = M2Crypto.RSA.gen_key(KEY_BITS, key_gen_number, callback=lambda: None)
rsa_key2 = M2Crypto.RSA.gen_key(KEY_BITS, key_gen_number, callback=lambda: None)
pkey = M2Crypto.EVP.PKey(md=SIGN_DIGEST)
pkey.assign_rsa(rsa_key)
sign_key = M2Crypto.EVP.PKey(md=SIGN_DIGEST)
sign_key.assign_rsa(rsa_key2)
subject = M2Crypto.X509.X509_Name()
for (key, value) in CERT_INFOS.items():
subject.add_entry_by_txt(key, string_type, value, -1, -1, 0)
issuer = M2Crypto.X509.X509_Name(M2Crypto.m2.x509_name_new())
for (key, value) in ISSUER_INFOS.items():
issuer.add_entry_by_txt(key, string_type, value, -1, -1, 0)
## time object
asn_time1 = M2Crypto.ASN1.ASN1_UTCTIME()
asn_time1.set_time(long(time.time()) - EXPIRE_TIME)
asn_time2 = M2Crypto.ASN1.ASN1_UTCTIME()
asn_time2.set_time(long(time.time()) + EXPIRE_TIME)
request = M2Crypto.X509.Request()
request.set_subject_name(subject)
request.set_pubkey(pkey)
request.sign(pkey=pkey, md=SIGN_DIGEST)
cert = M2Crypto.X509.X509()
## always create a unique version number
cert.set_version(0)
cert.set_serial_number(long(time.time()))
cert.set_pubkey(pkey)
cert.set_not_before(asn_time1)
cert.set_not_after(asn_time2)
cert.set_subject_name(request.get_subject())
cert.set_issuer_name(issuer)
cert.sign(pkey, SIGN_DIGEST)
result = ""
result += cert.as_pem()
result += pkey.as_pem(cipher=None)
return result
def __get_certificate(self):
"""Create a self-signed certificate and return its pem content
The code is mainly inspired by:
https://dev.tribler.org/browser/m2crypto/trunk/contrib/SimpleX509create.py
"""
## check if m2crypto is available
try:
import M2Crypto
except ImportError:
## failed to import the module
return None
import time
string_type = 0x1000 | 1 # see http://www.koders.com/python/..
# ../fid07A99E089F55187896A06CD4E0B6F21B9B8F5B0B.aspx?s=bavaria
key_gen_number = 0x10001 # commonly used for key generation: 65537
rsa_key = M2Crypto.RSA.gen_key(KEY_BITS, key_gen_number, callback=lambda: None)
rsa_key2 = M2Crypto.RSA.gen_key(KEY_BITS, key_gen_number, callback=lambda: None)
pkey = M2Crypto.EVP.PKey(md=SIGN_DIGEST)
pkey.assign_rsa(rsa_key)
sign_key = M2Crypto.EVP.PKey(md=SIGN_DIGEST)
sign_key.assign_rsa(rsa_key2)
subject = M2Crypto.X509.X509_Name()
for (key, value) in CERT_INFOS.items():
subject.add_entry_by_txt(key, string_type, value, -1, -1, 0)
issuer = M2Crypto.X509.X509_Name(M2Crypto.m2.x509_name_new())
for (key, value) in ISSUER_INFOS.items():
issuer.add_entry_by_txt(key, string_type, value, -1, -1, 0)
## time object
asn_time1 = M2Crypto.ASN1.ASN1_UTCTIME()
asn_time1.set_time(long(time.time()) - EXPIRE_TIME)
asn_time2 = M2Crypto.ASN1.ASN1_UTCTIME()
asn_time2.set_time(long(time.time()) + EXPIRE_TIME)
request = M2Crypto.X509.Request()
request.set_subject_name(subject)
request.set_pubkey(pkey)
request.sign(pkey=pkey, md=SIGN_DIGEST)
cert = M2Crypto.X509.X509()
## always create a unique version number
cert.set_version(0)
cert.set_serial_number(long(time.time()))
cert.set_pubkey(pkey)
cert.set_not_before(asn_time1)
cert.set_not_after(asn_time2)
cert.set_subject_name(request.get_subject())
cert.set_issuer_name(issuer)
cert.sign(pkey, SIGN_DIGEST)
result = ""
result += cert.as_pem()
result += pkey.as_pem(cipher=None)
return result

View file

@ -32,61 +32,61 @@ import os
def _get_username():
if ("SUPERCMD" in os.environ) and ("ORIG_USER" in os.environ):
return os.environ["ORIG_USER"]
elif "USER" in os.environ:
return os.environ["USER"]
else:
return "cryptobox"
if ("SUPERCMD" in os.environ) and ("ORIG_USER" in os.environ):
return os.environ["ORIG_USER"]
elif "USER" in os.environ:
return os.environ["USER"]
else:
return "cryptobox"
def run_stunnel(cert_file, src_port, dst_port, pid_file):
import subprocess
if not src_port.isdigit():
sys.stderr.write("Source port is not a number: %s" % src_port)
return False
if not dst_port.isdigit():
sys.stderr.write("Destination port is not a number: %s" % dst_port)
return False
if not os.path.isfile(cert_file):
sys.stderr.write("The certificate file (%s) does not exist!" % cert_file)
return False
username = _get_username()
if not username:
sys.stderr.write("Could not retrieve the username with uid=%d." % os.getuid())
return False
## the environment (especially PATH) should be clean, as 'stunnel' cares about
## this in a setuid situation
proc = subprocess.Popen(
shell = False,
env = {},
stdin = subprocess.PIPE,
args = [ STUNNEL_BIN,
"-fd",
"0"])
proc.stdin.write("setuid = %s\n" % username)
proc.stdin.write("pid = %s\n" % pid_file)
proc.stdin.write("[cryptobox-server]\n")
proc.stdin.write("connect = %s\n" % src_port)
proc.stdin.write("accept = %s\n" % dst_port)
proc.stdin.write("cert = %s\n" % cert_file)
(output, error) = proc.communicate()
return proc.returncode == 0
import subprocess
if not src_port.isdigit():
sys.stderr.write("Source port is not a number: %s" % src_port)
return False
if not dst_port.isdigit():
sys.stderr.write("Destination port is not a number: %s" % dst_port)
return False
if not os.path.isfile(cert_file):
sys.stderr.write("The certificate file (%s) does not exist!" % cert_file)
return False
username = _get_username()
if not username:
sys.stderr.write("Could not retrieve the username with uid=%d." % os.getuid())
return False
## the environment (especially PATH) should be clean, as 'stunnel' cares about
## this in a setuid situation
proc = subprocess.Popen(
shell = False,
env = {},
stdin = subprocess.PIPE,
args = [ STUNNEL_BIN,
"-fd",
"0"])
proc.stdin.write("setuid = %s\n" % username)
proc.stdin.write("pid = %s\n" % pid_file)
proc.stdin.write("[cryptobox-server]\n")
proc.stdin.write("connect = %s\n" % src_port)
proc.stdin.write("accept = %s\n" % dst_port)
proc.stdin.write("cert = %s\n" % cert_file)
(output, error) = proc.communicate()
return proc.returncode == 0
if __name__ == "__main__":
args = sys.argv[1:]
args = sys.argv[1:]
self_bin = sys.argv[0]
if len(args) != 4:
sys.stderr.write("%s: invalid number of arguments (%d instead of %d))\n" % \
(self_bin, len(args), 4))
sys.exit(1)
if not run_stunnel(args[0], args[1], args[2], args[3]):
sys.stderr.write("%s: failed to run 'stunnel'!" % self_bin)
sys.exit(100)
sys.exit(0)
self_bin = sys.argv[0]
if len(args) != 4:
sys.stderr.write("%s: invalid number of arguments (%d instead of %d))\n" % \
(self_bin, len(args), 4))
sys.exit(1)
if not run_stunnel(args[0], args[1], args[2], args[3]):
sys.stderr.write("%s: failed to run 'stunnel'!" % self_bin)
sys.exit(100)
sys.exit(0)

View file

@ -23,12 +23,12 @@ __revision__ = "$Id$"
from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_get_cert_form(self):
"""retrieve the default form of the certificate manager"""
url = self.url + "encrypted_webinterface"
self.register_auth(url)
self.cmd.go(url)
## TODO: enable it, as soon as the plugin is enabled by default
#self.cmd.find("Data.Status.Plugins.encrypted_webinterface")
def test_get_cert_form(self):
"""retrieve the default form of the certificate manager"""
url = self.url + "encrypted_webinterface"
self.register_auth(url)
self.cmd.go(url)
## TODO: enable it, as soon as the plugin is enabled by default
#self.cmd.find("Data.Status.Plugins.encrypted_webinterface")

View file

@ -26,56 +26,56 @@ __revision__ = "$Id$"
import cryptobox.plugins.base
class help(cryptobox.plugins.base.CryptoBoxPlugin):
"""The help feature of the CryptoBox.
"""
"""The help feature of the CryptoBox.
"""
#plugin_capabilities = [ "system" ]
#TODO: enable this plugin as soon as the user documentation is ready again
plugin_capabilities = [ ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 80
#plugin_capabilities = [ "system" ]
#TODO: enable this plugin as soon as the user documentation is ready again
plugin_capabilities = [ ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 80
default_lang = 'en'
default_page = "CryptoBoxUser"
default_lang = 'en'
default_page = "CryptoBoxUser"
def do_action(self, page=""):
'''prints the offline wikipage
'''
import re, os
## check for invalid characters and if the page exists in the default language
if page and \
not re.search(r'\W', page) and \
os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
self.default_lang, page + '.html')):
## everything is ok
pass
else:
## display this page as default help page
page = self.default_page
if page:
## issue warning
self.cbox.log.info("could not find the selected documentation page: %s" % str(page))
## store the name of the page
self.hdf[self.hdf_prefix + "Page"] = page
## choose the right language
for lang in self.site.lang_order:
if os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
lang, page + '.html')):
doc_lang = lang
break
else:
doc_lang = self.default_lang
self.hdf[self.hdf_prefix + "Language"] = doc_lang
## store the current setting for a later "getStatus" call
self.current_lang = doc_lang
self.current_page = page
return "doc"
def do_action(self, page=""):
'''prints the offline wikipage
'''
import re, os
## check for invalid characters and if the page exists in the default language
if page and \
not re.search(r'\W', page) and \
os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
self.default_lang, page + '.html')):
## everything is ok
pass
else:
## display this page as default help page
page = self.default_page
if page:
## issue warning
self.cbox.log.info("could not find the selected documentation page: %s" % str(page))
## store the name of the page
self.hdf[self.hdf_prefix + "Page"] = page
## choose the right language
for lang in self.site.lang_order:
if os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
lang, page + '.html')):
doc_lang = lang
break
else:
doc_lang = self.default_lang
self.hdf[self.hdf_prefix + "Language"] = doc_lang
## store the current setting for a later "getStatus" call
self.current_lang = doc_lang
self.current_page = page
return "doc"
def get_status(self):
"""Retrieve the current status of the feature.
"""
return "%s:%s" % (self.current_lang, self.current_page)
def get_status(self):
"""Retrieve the current status of the feature.
"""
return "%s:%s" % (self.current_lang, self.current_page)

View file

@ -25,70 +25,70 @@ from twill.errors import *
class unittests(WebInterfaceTestClass):
def test_help_language_texts(self):
'''help pages should be available in different languages'''
def test_help_language_texts(self):
'''help pages should be available in different languages'''
## check english help pages
self.cmd.go(self.url + "help?weblang=en")
self.cmd.find("Table of Contents")
self.cmd.find("Getting started")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## check english help pages
self.cmd.go(self.url + "help?weblang=en")
self.cmd.find("Table of Contents")
self.cmd.find("Getting started")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## check german help pages
self.cmd.go(self.url + "help?weblang=de")
self.cmd.find("Table of Contents")
self.cmd.find("Wie geht es los")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "de")
self.assertTrue(page == "CryptoBoxUser")
## check german help pages
self.cmd.go(self.url + "help?weblang=de")
self.cmd.find("Table of Contents")
self.cmd.find("Wie geht es los")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "de")
self.assertTrue(page == "CryptoBoxUser")
## check slovene help pages
self.cmd.go(self.url + "help?weblang=sl")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
## add a slovene text here, as soon as the help is translated
(lang,page) = self._getHelpStatus()
## change this to "sl" as soon as the help is translated
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## check slovene help pages
self.cmd.go(self.url + "help?weblang=sl")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
## add a slovene text here, as soon as the help is translated
(lang,page) = self._getHelpStatus()
## change this to "sl" as soon as the help is translated
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## check french help pages
self.cmd.go(self.url + "help?weblang=fr")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
## add a french text here, as soon as the help is translated
(lang,page) = self._getHelpStatus()
## change this to "fr" as soon as the help is translated
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## check french help pages
self.cmd.go(self.url + "help?weblang=fr")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
## add a french text here, as soon as the help is translated
(lang,page) = self._getHelpStatus()
## change this to "fr" as soon as the help is translated
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## test a random language - it should fall back to english
self.cmd.go(self.url + "help?weblang=foobar")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
## test a random language - it should fall back to english
self.cmd.go(self.url + "help?weblang=foobar")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
self.assertTrue(page == "CryptoBoxUser")
def test_help_pages(self):
"""check invalid page requests"""
self.cmd.go(self.url + "help?page=foobar")
(lang,page) = self._getHelpStatus()
self.assertTrue(page == "CryptoBoxUser")
def test_help_pages(self):
"""check invalid page requests"""
self.cmd.go(self.url + "help?page=foobar")
(lang,page) = self._getHelpStatus()
self.assertTrue(page == "CryptoBoxUser")
self.cmd.go(self.url + "help?page=CryptoBoxUser")
(lang,page) = self._getHelpStatus()
self.assertTrue(page == "CryptoBoxUser")
self.cmd.go(self.url + "help?page=CryptoBoxUser")
(lang,page) = self._getHelpStatus()
self.assertTrue(page == "CryptoBoxUser")
def test_help_default_languages(self):
"""check invalid page requests"""
self.cmd.go(self.url + "help?weblang=foobar")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
def test_help_default_languages(self):
"""check invalid page requests"""
self.cmd.go(self.url + "help?weblang=foobar")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
def _getHelpStatus(self):
self.cmd.find(r'Data.Status.Plugins.help=(.*)$', "m")
return tuple(self.locals["__match__"].split(":"))
def _getHelpStatus(self):
self.cmd.find(r'Data.Status.Plugins.help=(.*)$', "m")
return tuple(self.locals["__match__"].split(":"))

View file

@ -27,22 +27,22 @@ import cryptobox.plugins.base
class language_selection(cryptobox.plugins.base.CryptoBoxPlugin):
"""The language_selection feature of the CryptoBox.
"""
"""The language_selection feature of the CryptoBox.
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu", "preferences" ]
request_auth = False
rank = 60
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu", "preferences" ]
request_auth = False
rank = 60
def do_action(self):
"""Show all available languages.
"""
return "language_selection"
def do_action(self):
"""Show all available languages.
"""
return "language_selection"
def get_status(self):
"""The current status of the feature is defined as the current language.
"""
return ":".join(self.site.lang_order)
def get_status(self):
"""The current status of the feature is defined as the current language.
"""
return ":".join(self.site.lang_order)

View file

@ -24,23 +24,23 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""Check if the 'language_selection' plugin works.
"""
url = self.url + "language_selection?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Choose your tongue')
def test_read_form(self):
"""Check if the 'language_selection' plugin works.
"""
url = self.url + "language_selection?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Choose your tongue')
def test_check_language_list(self):
"""Check the list of available languages.
"""
url = self.url + "language_selection?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find(r'Data.Status.Plugins.language_selection=(.*)$', "m")
langs = self.locals["__match__"].split(":")
self.assertTrue(len(langs)>1)
self.assertTrue(langs[0] == "en")
def test_check_language_list(self):
"""Check the list of available languages.
"""
url = self.url + "language_selection?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find(r'Data.Status.Plugins.language_selection=(.*)$', "m")
langs = self.locals["__match__"].split(":")
self.assertTrue(len(langs)>1)
self.assertTrue(langs[0] == "en")

View file

@ -32,215 +32,215 @@ import cherrypy
LOG_LEVELS = [ 'DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR' ]
LINE_REGEX = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}) " \
+ r"(?P<hour>\d{2}):(?P<minute>\d{2}):\d{2},\d{3} (?P<level>" \
+ "|".join([ "(?:%s)" % e for e in LOG_LEVELS]) + r"): (?P<text>.*)$")
+ r"(?P<hour>\d{2}):(?P<minute>\d{2}):\d{2},\d{3} (?P<level>" \
+ "|".join([ "(?:%s)" % e for e in LOG_LEVELS]) + r"): (?P<text>.*)$")
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
"""The logs feature of the CryptoBox.
"""
"""The logs feature of the CryptoBox.
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = False
rank = 90
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = False
rank = 90
def do_action(self, lines=50, size=3000, level=None):
"""Show the latest part of the log file.
"""
## filter input
try:
lines = int(lines)
if lines <= 0:
raise(ValueError)
except ValueError:
self.cbox.log.info("[logs] invalid line number: %s" % str(lines))
lines = 50
try:
size = int(size)
if size <= 0:
raise(ValueError)
except ValueError:
self.cbox.log.info("[logs] invalid log size: %s" % str(size))
size = 3000
if not level is None:
level = str(level)
if not level in LOG_LEVELS:
self.cbox.log.info("[logs] invalid log level: %s" % str(level))
level = None
for (index, line) in enumerate(self.__filter_log_content(lines, size, level)):
self.__set_line_hdf_data(self.hdf_prefix + "Content.%d" % index, line)
self.hdf[self.hdf_prefix + "Destination"] = \
self.cbox.prefs["Log"]["Destination"].lower()
def do_action(self, lines=50, size=3000, level=None):
"""Show the latest part of the log file.
"""
## filter input
try:
lines = int(lines)
if lines <= 0:
raise(ValueError)
except ValueError:
self.cbox.log.info("[logs] invalid line number: %s" % str(lines))
lines = 50
try:
size = int(size)
if size <= 0:
raise(ValueError)
except ValueError:
self.cbox.log.info("[logs] invalid log size: %s" % str(size))
size = 3000
if not level is None:
level = str(level)
if not level in LOG_LEVELS:
self.cbox.log.info("[logs] invalid log level: %s" % str(level))
level = None
for (index, line) in enumerate(self.__filter_log_content(lines, size, level)):
self.__set_line_hdf_data(self.hdf_prefix + "Content.%d" % index, line)
self.hdf[self.hdf_prefix + "Destination"] = \
self.cbox.prefs["Log"]["Destination"].lower()
## this generates more download buttons if the files are available
if "syslogfile" in self.defaults:
try:
syslogfile = self.defaults["syslogfile"]
except KeyError:
self.cbox.log.error("could not evaluate the config setting: "
+ "[logs]->syslogfile")
if syslogfile and os.access(syslogfile, os.R_OK):
self.cbox.log.info("[logs]->syslogfile: '%s' will be exported" % syslogfile)
self.hdf[self.hdf_prefix + "syslogfile"] = "readable"
self.cbox.prefs["Log"]["syslogfile"] = syslogfile
else:
self.cbox.log.warn("[logs]->syslogfile: '%s' is not readable for cryptobox user" % syslogfile)
self.hdf[self.hdf_prefix + "syslogfile"] = "not readable"
return "show_log"
## this generates more download buttons if the files are available
if "syslogfile" in self.defaults:
try:
syslogfile = self.defaults["syslogfile"]
except KeyError:
self.cbox.log.error("could not evaluate the config setting: "
+ "[logs]->syslogfile")
if syslogfile and os.access(syslogfile, os.R_OK):
self.cbox.log.info("[logs]->syslogfile: '%s' will be exported" % syslogfile)
self.hdf[self.hdf_prefix + "syslogfile"] = "readable"
self.cbox.prefs["Log"]["syslogfile"] = syslogfile
else:
self.cbox.log.warn("[logs]->syslogfile: '%s' is not readable for cryptobox user" % syslogfile)
self.hdf[self.hdf_prefix + "syslogfile"] = "not readable"
return "show_log"
@cherrypy.expose
def download(self, **kargs):
"""Download the complete log file
@cherrypy.expose
def download(self, **kargs):
"""Download the complete log file
**kargs are necessary - we have to ignore 'weblang' and so on ...
"""
##TODO: check the download url to know which file is wanted
if self.cbox.prefs["Log"]["syslogfile"]:
try:
syslogfile = self.cbox.prefs["Log"]["syslogfile"]
except KeyError:
self.cbox.log.error("could not evaluate the config setting: "
+ "[logs]->syslogfile %s")
if syslogfile and os.access(syslogfile, os.R_OK):
return cherrypy.lib.cptools.serveFile(syslogfile,
disposition="attachment", name="syslog.txt")
else:
self.cbox.log.error("'%s' could not be exposed" % syslogfile)
**kargs are necessary - we have to ignore 'weblang' and so on ...
"""
##TODO: check the download url to know which file is wanted
if self.cbox.prefs["Log"]["syslogfile"]:
try:
syslogfile = self.cbox.prefs["Log"]["syslogfile"]
except KeyError:
self.cbox.log.error("could not evaluate the config setting: "
+ "[logs]->syslogfile %s")
if syslogfile and os.access(syslogfile, os.R_OK):
return cherrypy.lib.cptools.serveFile(syslogfile,
disposition="attachment", name="syslog.txt")
else:
self.cbox.log.error("'%s' could not be exposed" % syslogfile)
log_file = self.__get_log_destination_file()
if log_file is None:
return ""
else:
return cherrypy.lib.cptools.serveFile(log_file,
disposition="attachment", name="cryptobox_logfile.txt")
log_file = self.__get_log_destination_file()
if log_file is None:
return ""
else:
return cherrypy.lib.cptools.serveFile(log_file,
disposition="attachment", name="cryptobox_logfile.txt")
def get_status(self):
"""The current status includes the log configuration details.
"""
return "%s:%s:%s" % (
self.cbox.prefs["Log"]["Level"],
self.cbox.prefs["Log"]["Destination"],
self.cbox.prefs["Log"]["Details"])
def get_status(self):
"""The current status includes the log configuration details.
"""
return "%s:%s:%s" % (
self.cbox.prefs["Log"]["Level"],
self.cbox.prefs["Log"]["Destination"],
self.cbox.prefs["Log"]["Details"])
def __filter_log_content(self, lines, max_size, level):
"""Filter, sort and shorten the log content.
"""
if level and level in LOG_LEVELS:
filtered_levels = LOG_LEVELS[:]
## only the given and higher levels are accepted
while filtered_levels[0] != level:
del filtered_levels[0]
content = []
current_length = 0
for line in self.__get_log_data():
## search for matching lines for the given log level
for one_level in filtered_levels:
if line.find(" %s: " % one_level) != -1:
break
else:
## the line does not contain an appropriate level name
continue
## we found a line that fits
content.append(line)
current_length += len(line)
if lines and len(content) >= lines:
break
if max_size and current_length >= max_size:
break
else:
content = self.__get_log_data(lines, max_size)
return content
def __filter_log_content(self, lines, max_size, level):
"""Filter, sort and shorten the log content.
"""
if level and level in LOG_LEVELS:
filtered_levels = LOG_LEVELS[:]
## only the given and higher levels are accepted
while filtered_levels[0] != level:
del filtered_levels[0]
content = []
current_length = 0
for line in self.__get_log_data():
## search for matching lines for the given log level
for one_level in filtered_levels:
if line.find(" %s: " % one_level) != -1:
break
else:
## the line does not contain an appropriate level name
continue
## we found a line that fits
content.append(line)
current_length += len(line)
if lines and len(content) >= lines:
break
if max_size and current_length >= max_size:
break
else:
content = self.__get_log_data(lines, max_size)
return content
def __set_line_hdf_data(self, hdf_prefix, line):
"""Parse the log line for time and log level.
def __set_line_hdf_data(self, hdf_prefix, line):
"""Parse the log line for time and log level.
If parsing fails, then the output line is simply displayed without
meta information.
"""
self.hdf[hdf_prefix + ".Text"] = line.strip()
match = LINE_REGEX.match(line)
if not match:
## we could not parse the line - just return the text without meta info
return
## matching was successful - we can parse the line for details
## calculate time difference of log line (aka: age of event)
try:
(year, month, day, hour, minute) = match.group(
'year', 'month', 'day', 'hour', 'minute')
(year, month, day, hour, minute) = \
(int(year), int(month), int(day), int(hour), int(minute))
## timediff is a timedelta object
timediff = datetime.datetime.today() - \
datetime.datetime(year, month, day, hour, minute)
## the time units (see below) correspond to the names within the language
## file: Text.TimeUnits.Days ...
if timediff.days >= 1:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Days'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.days
elif timediff.seconds >= 3600:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Hours'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds / 3600
elif timediff.seconds >= 60:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Minutes'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds / 60
else:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Seconds'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds
except (OverflowError, TypeError, ValueError, IndexError), err_msg:
pass
## retrieve the level
try:
self.hdf[hdf_prefix + ".Level"] = match.group('level')
except IndexError:
pass
try:
self.hdf[hdf_prefix + ".Text"] = match.group('text').strip()
except IndexError:
pass
If parsing fails, then the output line is simply displayed without
meta information.
"""
self.hdf[hdf_prefix + ".Text"] = line.strip()
match = LINE_REGEX.match(line)
if not match:
## we could not parse the line - just return the text without meta info
return
## matching was successful - we can parse the line for details
## calculate time difference of log line (aka: age of event)
try:
(year, month, day, hour, minute) = match.group(
'year', 'month', 'day', 'hour', 'minute')
(year, month, day, hour, minute) = \
(int(year), int(month), int(day), int(hour), int(minute))
## timediff is a timedelta object
timediff = datetime.datetime.today() - \
datetime.datetime(year, month, day, hour, minute)
## the time units (see below) correspond to the names within the language
## file: Text.TimeUnits.Days ...
if timediff.days >= 1:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Days'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.days
elif timediff.seconds >= 3600:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Hours'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds / 3600
elif timediff.seconds >= 60:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Minutes'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds / 60
else:
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Seconds'
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds
except (OverflowError, TypeError, ValueError, IndexError), err_msg:
pass
## retrieve the level
try:
self.hdf[hdf_prefix + ".Level"] = match.group('level')
except IndexError:
pass
try:
self.hdf[hdf_prefix + ".Text"] = match.group('text').strip()
except IndexError:
pass
def __get_log_destination_file(self):
"""For non-file log destinations return 'None' and output a warning
"""
try:
if self.cbox.prefs["Log"]["Destination"].upper() == "FILE":
import os
return os.path.abspath(self.cbox.prefs["Log"]["Details"])
else:
return None
except KeyError:
self.cbox.log.error(
"could not evaluate one of the following config settings: "
+ "[Log]->Destination or [Log]->Details")
return None
def __get_log_destination_file(self):
"""For non-file log destinations return 'None' and output a warning
"""
try:
if self.cbox.prefs["Log"]["Destination"].upper() == "FILE":
import os
return os.path.abspath(self.cbox.prefs["Log"]["Details"])
else:
return None
except KeyError:
self.cbox.log.error(
"could not evaluate one of the following config settings: "
+ "[Log]->Destination or [Log]->Details")
return None
def __get_log_data(self, lines=None, max_size=None):
"""get the most recent log entries of the log file
def __get_log_data(self, lines=None, max_size=None):
"""get the most recent log entries of the log file
the maximum number and size of these entries can be limited by
'lines' and 'max_size'
"""
log_file = self.__get_log_destination_file()
## return nothing if the currently selected log output is not a file
if log_file is None:
return []
try:
fdesc = open(log_file, "r")
if max_size:
fdesc.seek(-max_size, 2) # seek relative to the end of the file
content = fdesc.readlines()
fdesc.close()
except IOError:
self.cbox.log.warn("failed to read the log file (%s)" % log_file)
return []
if lines:
content = content[-lines:]
content.reverse()
return content
the maximum number and size of these entries can be limited by
'lines' and 'max_size'
"""
log_file = self.__get_log_destination_file()
## return nothing if the currently selected log output is not a file
if log_file is None:
return []
try:
fdesc = open(log_file, "r")
if max_size:
fdesc.seek(-max_size, 2) # seek relative to the end of the file
content = fdesc.readlines()
fdesc.close()
except IOError:
self.cbox.log.warn("failed to read the log file (%s)" % log_file)
return []
if lines:
content = content[-lines:]
content.reverse()
return content

View file

@ -24,42 +24,42 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_logs(self):
"""Read the log files.
"""
log_url = self.url + "logs"
self.register_auth(log_url)
self.cmd.go(log_url)
self.cmd.find('<table class="log">')
def test_read_logs(self):
"""Read the log files.
"""
log_url = self.url + "logs"
self.register_auth(log_url)
self.cmd.go(log_url)
self.cmd.find('<table class="log">')
def test_write_logs(self):
"""Send a log message and read it again.
"""
log_text = "unittest - just a marker - please ignore"
self.cbox.log.error(log_text)
log_url = self.url + "logs"
self.register_auth(log_url)
self.cmd.go(log_url + "?level=ERROR")
self.cmd.find(log_text)
def test_write_logs(self):
"""Send a log message and read it again.
"""
log_text = "unittest - just a marker - please ignore"
self.cbox.log.error(log_text)
log_url = self.url + "logs"
self.register_auth(log_url)
self.cmd.go(log_url + "?level=ERROR")
self.cmd.find(log_text)
def test_invalid_args(self):
"""Send various invalid input combinations to the 'log' plugin.
"""
log_url = self.url + "logs"
self.cmd.go(log_url + "?lines=10")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?lines=0")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?lines=x")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?size=1000")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?size=0")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?size=x")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?level=foobar")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + r"?level=kfj!^(]")
self.cmd.find('<table class="log">')
def test_invalid_args(self):
"""Send various invalid input combinations to the 'log' plugin.
"""
log_url = self.url + "logs"
self.cmd.go(log_url + "?lines=10")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?lines=0")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?lines=x")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?size=1000")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?size=0")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?size=x")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + "?level=foobar")
self.cmd.find('<table class="log">')
self.cmd.go(log_url + r"?level=kfj!^(]")
self.cmd.find('<table class="log">')

View file

@ -39,371 +39,371 @@ CHANGE_IP_DELAY = 5
DEFAULT_INTERFACE = "eth0"
class network(cryptobox.plugins.base.CryptoBoxPlugin):
"""The network feature of the CryptoBox.
"""
"""The network feature of the CryptoBox.
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 30
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 30
def do_action(self, store=None, redirected="", ip1="", ip2="", ip3="", ip4="",
nm1="", nm2="", nm3="", nm4="", confirm_dhcp=""):
"""Show a form containing the current IP - change it if requested.
"""
## if we were redirected, then we should display the default page
self.cbox.log.debug("executing network plugin")
if redirected == "1":
self.cbox.log.debug("network plugin: redirected")
return "form_network"
## check possible actions
if store is None:
## no action was requested -> just show the form
self.cbox.log.debug("network plugin: show form (interface %s)" \
% self.__get_interface())
self.__prepare_form_data()
return "form_network"
## change of ip address and/or netmask requested
elif store == "set_ip":
self.cbox.log.debug("network plugin: changing server IP")
if self.__IP_is_valid(ip1, ip2, ip3, ip4):
new_ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4))
else:
self.hdf["Data.Warning"] = "Plugins.network.InvalidServerIP"
self.__prepare_form_data()
return "form_network"
if self.__IP_is_valid(nm1, nm2, nm3, nm4):
new_nm = "%d.%d.%d.%d" % (int(nm1), int(nm2), int(nm3), int(nm4))
else:
self.hdf["Data.Warning"] = "Plugins.network.InvalidNetmask"
self.__prepare_form_data()
return "form_network"
if self.__set_ip(new_ip, new_nm):
self.cbox.log.info("[network] the IP was successfully changed: %s" % new_ip)
self.hdf["Data.Success"] = "Plugins.network.IPChanged"
self.hdf["Data.Redirect.URL"] = self.__get_redirect_destination(new_ip)
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
self.prefs["_address"] = new_ip
self.prefs["_netmask"] = new_nm
## if an ip is set manually, don't use dhcp any longer
if self.prefs.has_key("_dhcp"):
del self.prefs["_dhcp"]
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Could not write plugin configuration")
self.__prepare_form_data()
return "empty"
else:
self.cbox.log.warn("[network] failed to change IP address to: %s" % \
new_ip)
self.hdf["Data.Warning"] = "Plugins.network.AddressChangeFailed"
self.__prepare_form_data()
return "form_network"
## request for default gateway change
elif store == "set_gateway":
old_gw = self.__get_current_gw()
old_gw_str = ".".join([str(e) for e in old_gw])
if self.__IP_is_valid(ip1, ip2, ip3, ip4):
new_gw = (int(ip1), int(ip2), int(ip3), int(ip4))
new_gw_str = ".".join([str(e) for e in new_gw])
else:
self.hdf["Data.Warning"] = "Plugins.network.InvalidGatewayIP"
self.__prepare_form_data()
return "form_network"
if self.__set_gw(old_gw_str, new_gw_str):
self.cbox.log.info( "[network] successfully changed gateway address:" \
+ new_gw_str)
self.hdf["Data.Success"] = "Plugins.network.GWChanged"
self.prefs["_gateway"] = new_gw_str
## if an gw is set manually, don't use dhcp any longer
if self.prefs.has_key("_dhcp"):
del self.prefs["_dhcp"]
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Could not write plugin configuration")
else:
self.cbox.log.warn("[network] failed to change gateway address to: %s" \
% new_gw_str)
self.hdf["Data.Warning"] = "Plugins.network.GatewayChangeFailed"
self.__prepare_form_data()
return "form_network"
## request for dhcp usage
elif store == "use_dhcp":
if confirm_dhcp != "1":
## do nothing as the action was not confirmed with the checkbox
self.hdf["Data.Warning"] = "Plugins.network.DHCPNotConfirmed"
self.__prepare_form_data()
return "form_network"
else:
self.cbox.log.info( "[network] recieve network settings via DHCP")
if not os.path.isfile(self.root_action.DHCLIENT_BIN):
self.hdf["Data.Warning"] = "Plugins.network.DHCPNotFound"
elif self.__use_dhcp():
self.hdf["Data.Success"] = "Plugins.network.DHCPRunning"
self.prefs["_dhcp"] = "use"
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Could not write plugin configuration")
else:
self.hdf["Data.Warning"] = "Plugins.network.DHCPNotRunning"
self.__prepare_form_data()
return "form_network"
else:
## invalid action was requested -> show default form
self.cbox.log.debug("network plugin: invalid request (%s)" % str(store))
self.__prepare_form_data()
return "form_network"
def do_action(self, store=None, redirected="", ip1="", ip2="", ip3="", ip4="",
nm1="", nm2="", nm3="", nm4="", confirm_dhcp=""):
"""Show a form containing the current IP - change it if requested.
"""
## if we were redirected, then we should display the default page
self.cbox.log.debug("executing network plugin")
if redirected == "1":
self.cbox.log.debug("network plugin: redirected")
return "form_network"
## check possible actions
if store is None:
## no action was requested -> just show the form
self.cbox.log.debug("network plugin: show form (interface %s)" \
% self.__get_interface())
self.__prepare_form_data()
return "form_network"
## change of ip address and/or netmask requested
elif store == "set_ip":
self.cbox.log.debug("network plugin: changing server IP")
if self.__IP_is_valid(ip1, ip2, ip3, ip4):
new_ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4))
else:
self.hdf["Data.Warning"] = "Plugins.network.InvalidServerIP"
self.__prepare_form_data()
return "form_network"
if self.__IP_is_valid(nm1, nm2, nm3, nm4):
new_nm = "%d.%d.%d.%d" % (int(nm1), int(nm2), int(nm3), int(nm4))
else:
self.hdf["Data.Warning"] = "Plugins.network.InvalidNetmask"
self.__prepare_form_data()
return "form_network"
if self.__set_ip(new_ip, new_nm):
self.cbox.log.info("[network] the IP was successfully changed: %s" % new_ip)
self.hdf["Data.Success"] = "Plugins.network.IPChanged"
self.hdf["Data.Redirect.URL"] = self.__get_redirect_destination(new_ip)
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
self.prefs["_address"] = new_ip
self.prefs["_netmask"] = new_nm
## if an ip is set manually, don't use dhcp any longer
if self.prefs.has_key("_dhcp"):
del self.prefs["_dhcp"]
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Could not write plugin configuration")
self.__prepare_form_data()
return "empty"
else:
self.cbox.log.warn("[network] failed to change IP address to: %s" % \
new_ip)
self.hdf["Data.Warning"] = "Plugins.network.AddressChangeFailed"
self.__prepare_form_data()
return "form_network"
## request for default gateway change
elif store == "set_gateway":
old_gw = self.__get_current_gw()
old_gw_str = ".".join([str(e) for e in old_gw])
if self.__IP_is_valid(ip1, ip2, ip3, ip4):
new_gw = (int(ip1), int(ip2), int(ip3), int(ip4))
new_gw_str = ".".join([str(e) for e in new_gw])
else:
self.hdf["Data.Warning"] = "Plugins.network.InvalidGatewayIP"
self.__prepare_form_data()
return "form_network"
if self.__set_gw(old_gw_str, new_gw_str):
self.cbox.log.info( "[network] successfully changed gateway address:" \
+ new_gw_str)
self.hdf["Data.Success"] = "Plugins.network.GWChanged"
self.prefs["_gateway"] = new_gw_str
## if an gw is set manually, don't use dhcp any longer
if self.prefs.has_key("_dhcp"):
del self.prefs["_dhcp"]
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Could not write plugin configuration")
else:
self.cbox.log.warn("[network] failed to change gateway address to: %s" \
% new_gw_str)
self.hdf["Data.Warning"] = "Plugins.network.GatewayChangeFailed"
self.__prepare_form_data()
return "form_network"
## request for dhcp usage
elif store == "use_dhcp":
if confirm_dhcp != "1":
## do nothing as the action was not confirmed with the checkbox
self.hdf["Data.Warning"] = "Plugins.network.DHCPNotConfirmed"
self.__prepare_form_data()
return "form_network"
else:
self.cbox.log.info( "[network] recieve network settings via DHCP")
if not os.path.isfile(self.root_action.DHCLIENT_BIN):
self.hdf["Data.Warning"] = "Plugins.network.DHCPNotFound"
elif self.__use_dhcp():
self.hdf["Data.Success"] = "Plugins.network.DHCPRunning"
self.prefs["_dhcp"] = "use"
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Could not write plugin configuration")
else:
self.hdf["Data.Warning"] = "Plugins.network.DHCPNotRunning"
self.__prepare_form_data()
return "form_network"
else:
## invalid action was requested -> show default form
self.cbox.log.debug("network plugin: invalid request (%s)" % str(store))
self.__prepare_form_data()
return "form_network"
def get_status(self):
"""The current IP is the status of this feature.
"""
return "%d.%d.%d.%d" % self.__get_current_ip()
def get_status(self):
"""The current IP is the status of this feature.
"""
return "%d.%d.%d.%d" % self.__get_current_ip()
def handle_event(self, event, event_info=None):
"""Override bootup behaviour
def handle_event(self, event, event_info=None):
"""Override bootup behaviour
Apply the configured network settings
"""
if event == "bootup":
if "_address" in self.prefs:
if "_netmask" in self.prefs:
## change the ip without any delay - otherwise the following
## gateway setting will fail, if the network range changes
self.__set_ip(self.prefs["_address"], self.prefs["_netmask"],
change_delay=0)
else:
## no netmask setting stored
self.__set_ip(self.prefs["_address"])
if "_gateway" in self.prefs:
self.__set_gw(".".join([str(e) for e in self.__get_current_gw()]),
self.prefs["_gateway"])
Apply the configured network settings
"""
if event == "bootup":
if "_address" in self.prefs:
if "_netmask" in self.prefs:
## change the ip without any delay - otherwise the following
## gateway setting will fail, if the network range changes
self.__set_ip(self.prefs["_address"], self.prefs["_netmask"],
change_delay=0)
else:
## no netmask setting stored
self.__set_ip(self.prefs["_address"])
if "_gateway" in self.prefs:
self.__set_gw(".".join([str(e) for e in self.__get_current_gw()]),
self.prefs["_gateway"])
def get_warnings(self):
"""Check for missing programs
"""
warnings = []
if not os.path.isfile(self.root_action.IFCONFIG_BIN):
warnings.append((55, "Plugins.%s.MissingProgramIfconfig" % self.get_name()))
if not os.path.isfile(self.root_action.ROUTE_BIN):
warnings.append((52, "Plugins.%s.MissingProgramRoute" % self.get_name()))
return warnings
def get_warnings(self):
"""Check for missing programs
"""
warnings = []
if not os.path.isfile(self.root_action.IFCONFIG_BIN):
warnings.append((55, "Plugins.%s.MissingProgramIfconfig" % self.get_name()))
if not os.path.isfile(self.root_action.ROUTE_BIN):
warnings.append((52, "Plugins.%s.MissingProgramRoute" % self.get_name()))
return warnings
def __get_redirect_destination(self, ip):
"""Put the new URL together.
"""
import cherrypy
req = cherrypy.request
base_parts = req.base.split(":")
dest = "%s://%s" % (base_parts[0], ip)
if len(base_parts) == 3:
dest += ":%s" % base_parts[2]
dest += "/network"
return dest
def __get_redirect_destination(self, ip):
"""Put the new URL together.
"""
import cherrypy
req = cherrypy.request
base_parts = req.base.split(":")
dest = "%s://%s" % (base_parts[0], ip)
if len(base_parts) == 3:
dest += ":%s" % base_parts[2]
dest += "/network"
return dest
def __prepare_form_data(self):
"""Set some hdf values.
"""
#TODO: the following looks nicer in a loop
(oc1, oc2, oc3, oc4) = self.__get_current_ip("ip")
self.hdf[self.hdf_prefix + "ip.oc1"] = oc1
self.hdf[self.hdf_prefix + "ip.oc2"] = oc2
self.hdf[self.hdf_prefix + "ip.oc3"] = oc3
self.hdf[self.hdf_prefix + "ip.oc4"] = oc4
(oc1, oc2, oc3, oc4) = self.__get_current_ip("nm")
self.hdf[self.hdf_prefix + "nm.oc1"] = oc1
self.hdf[self.hdf_prefix + "nm.oc2"] = oc2
self.hdf[self.hdf_prefix + "nm.oc3"] = oc3
self.hdf[self.hdf_prefix + "nm.oc4"] = oc4
(oc1, oc2, oc3, oc4) = self.__get_current_gw()
self.hdf[self.hdf_prefix + "gw.oc1"] = oc1
self.hdf[self.hdf_prefix + "gw.oc2"] = oc2
self.hdf[self.hdf_prefix + "gw.oc3"] = oc3
self.hdf[self.hdf_prefix + "gw.oc4"] = oc4
if self.prefs.has_key("_dhcp"):
self.hdf[self.hdf_prefix + "dhcp"] = str(self.prefs["_dhcp"])
def __prepare_form_data(self):
"""Set some hdf values.
"""
#TODO: the following looks nicer in a loop
(oc1, oc2, oc3, oc4) = self.__get_current_ip("ip")
self.hdf[self.hdf_prefix + "ip.oc1"] = oc1
self.hdf[self.hdf_prefix + "ip.oc2"] = oc2
self.hdf[self.hdf_prefix + "ip.oc3"] = oc3
self.hdf[self.hdf_prefix + "ip.oc4"] = oc4
(oc1, oc2, oc3, oc4) = self.__get_current_ip("nm")
self.hdf[self.hdf_prefix + "nm.oc1"] = oc1
self.hdf[self.hdf_prefix + "nm.oc2"] = oc2
self.hdf[self.hdf_prefix + "nm.oc3"] = oc3
self.hdf[self.hdf_prefix + "nm.oc4"] = oc4
(oc1, oc2, oc3, oc4) = self.__get_current_gw()
self.hdf[self.hdf_prefix + "gw.oc1"] = oc1
self.hdf[self.hdf_prefix + "gw.oc2"] = oc2
self.hdf[self.hdf_prefix + "gw.oc3"] = oc3
self.hdf[self.hdf_prefix + "gw.oc4"] = oc4
if self.prefs.has_key("_dhcp"):
self.hdf[self.hdf_prefix + "dhcp"] = str(self.prefs["_dhcp"])
def __get_current_ip(self, address_type="ip"):
"""Retrieve the current IP.
def __get_current_ip(self, address_type="ip"):
"""Retrieve the current IP.
TODO: do not use "address_type" for ip and netmask, but return both in
two tuples
"""
import re
## get the current IP of the network interface
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
args = [
self.root_action.IFCONFIG_BIN,
self.__get_interface()])
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
return (0, 0, 0, 0)
if address_type == "ip":
## this regex matches the four numbers of the IP
match = re.search(r'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s', stdout)
if match:
## use the previously matched numbers
return tuple([int(e) for e in match.groups()])
else:
return (0, 0, 0, 0)
elif address_type == "nm":
## this greps the netmask
match = re.search(
r'inet [\w]+:.*Mask:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s',
stdout)
if match:
## use the previously matched numbers
return tuple([int(e) for e in match.groups()])
else:
return (0, 0, 0, 0)
TODO: do not use "address_type" for ip and netmask, but return both in
two tuples
"""
import re
## get the current IP of the network interface
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
args = [
self.root_action.IFCONFIG_BIN,
self.__get_interface()])
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
return (0, 0, 0, 0)
if address_type == "ip":
## this regex matches the four numbers of the IP
match = re.search(r'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s', stdout)
if match:
## use the previously matched numbers
return tuple([int(e) for e in match.groups()])
else:
return (0, 0, 0, 0)
elif address_type == "nm":
## this greps the netmask
match = re.search(
r'inet [\w]+:.*Mask:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s',
stdout)
if match:
## use the previously matched numbers
return tuple([int(e) for e in match.groups()])
else:
return (0, 0, 0, 0)
def __get_current_gw(self):
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.root_action.ROUTE_BIN,
"-n"])
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.warn(
"[network] failed to retrieve gateway address: %s" % stdout)
return (0, 0, 0, 0)
current_interface = self.__get_interface()
## skip the first two heading lines
for line in stdout.splitlines()[2:]:
attrs = line.split()
if len(attrs) != 8:
self.cbox.log.info("[network] misformed route entry: %s" % line)
continue
interface = attrs[7]
netmask = attrs[2]
gateway = attrs[1]
destination = attrs[0]
if (destination == "0.0.0.0") and (netmask == "0.0.0.0") and \
(interface == current_interface):
gw_octet = tuple(gateway.split("."))
if len(gw_octet) != 4:
self.cbox.log.info(
"[network] ignored invalid gateway setting: %s" % gateway)
else:
return gw_octet
return (0, 0, 0, 0)
def __get_current_gw(self):
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.root_action.ROUTE_BIN,
"-n"])
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.warn(
"[network] failed to retrieve gateway address: %s" % stdout)
return (0, 0, 0, 0)
current_interface = self.__get_interface()
## skip the first two heading lines
for line in stdout.splitlines()[2:]:
attrs = line.split()
if len(attrs) != 8:
self.cbox.log.info("[network] misformed route entry: %s" % line)
continue
interface = attrs[7]
netmask = attrs[2]
gateway = attrs[1]
destination = attrs[0]
if (destination == "0.0.0.0") and (netmask == "0.0.0.0") and \
(interface == current_interface):
gw_octet = tuple(gateway.split("."))
if len(gw_octet) != 4:
self.cbox.log.info(
"[network] ignored invalid gateway setting: %s" % gateway)
else:
return gw_octet
return (0, 0, 0, 0)
def __set_ip(self, new_ip, new_nm="255.255.255.0", change_delay=None):
"""Change the IP, additionally a netmask can be applied
"""
import threading
if change_delay is None:
change_delay = CHANGE_IP_DELAY
## call the root_action script after some seconds - so we can deliver the page before
def delayed_ip_change():
"""A threaded function to change the IP.
"""
import time
if change_delay > 0:
time.sleep(change_delay)
proc = subprocess.Popen(
shell = False,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"change_ip",
self.__get_interface(),
new_ip,
new_nm])
proc.wait()
if proc.returncode != 0:
self.cbox.log.warn("failed to change IP address: %s" % new_ip)
self.cbox.log.warn("error output: %s" % str(proc.stderr.read()))
return
thread = threading.Thread()
thread.run = delayed_ip_change
thread.setDaemon(True)
thread.start()
# TODO: how could we guess, if it failed?
return True
def __set_ip(self, new_ip, new_nm="255.255.255.0", change_delay=None):
"""Change the IP, additionally a netmask can be applied
"""
import threading
if change_delay is None:
change_delay = CHANGE_IP_DELAY
## call the root_action script after some seconds - so we can deliver the page before
def delayed_ip_change():
"""A threaded function to change the IP.
"""
import time
if change_delay > 0:
time.sleep(change_delay)
proc = subprocess.Popen(
shell = False,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"change_ip",
self.__get_interface(),
new_ip,
new_nm])
proc.wait()
if proc.returncode != 0:
self.cbox.log.warn("failed to change IP address: %s" % new_ip)
self.cbox.log.warn("error output: %s" % str(proc.stderr.read()))
return
thread = threading.Thread()
thread.run = delayed_ip_change
thread.setDaemon(True)
thread.start()
# TODO: how could we guess, if it failed?
return True
def __set_gw(self, old_ip, new_ip):
"""Change the gateway IP adress
"""
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"change_gw",
old_ip,
new_ip])
(output, error) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.warn("[network] gateway setting failed: %s" % str(error))
return False
else:
return True
def __set_gw(self, old_ip, new_ip):
"""Change the gateway IP adress
"""
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"change_gw",
old_ip,
new_ip])
(output, error) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.warn("[network] gateway setting failed: %s" % str(error))
return False
else:
return True
def __get_interface(self):
"""Return the name of the configured network interface
"""
if "interface" in self.defaults:
return self.defaults["interface"]
else:
return DEFAULT_INTERFACE
def __get_interface(self):
"""Return the name of the configured network interface
"""
if "interface" in self.defaults:
return self.defaults["interface"]
else:
return DEFAULT_INTERFACE
def __IP_is_valid(self, ip1, ip2, ip3, ip4):
try:
for ip_in in (ip1, ip2, ip3, ip4):
if (int(ip_in) < 0) or (int(ip_in) > 255):
## we give an info only and a webwarning
## further reaction depends on the case
self.cbox.log.info("IP number is invalid: %s" % \
str((ip1, ip2, ip3, ip4)))
raise ValueError
except ValueError:
## handled by individual caller
#self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
return False
return True
def __IP_is_valid(self, ip1, ip2, ip3, ip4):
try:
for ip_in in (ip1, ip2, ip3, ip4):
if (int(ip_in) < 0) or (int(ip_in) > 255):
## we give an info only and a webwarning
## further reaction depends on the case
self.cbox.log.info("IP number is invalid: %s" % \
str((ip1, ip2, ip3, ip4)))
raise ValueError
except ValueError:
## handled by individual caller
#self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
return False
return True
def __use_dhcp(self):
"""Try to recieve network settings via dhcp
"""
proc = subprocess.Popen(
shell = False,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"use_dhcp",
self.__get_interface() ])
proc.wait()
if proc.returncode != 0:
self.cbox.log.warn("failed to recieve IP address via DHCP")
self.cbox.log.warn("error output: %s" % str(proc.stderr.read()))
return True
def __use_dhcp(self):
"""Try to recieve network settings via dhcp
"""
proc = subprocess.Popen(
shell = False,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"use_dhcp",
self.__get_interface() ])
proc.wait()
if proc.returncode != 0:
self.cbox.log.warn("failed to recieve IP address via DHCP")
self.cbox.log.warn("error output: %s" % str(proc.stderr.read()))
return True

View file

@ -34,88 +34,88 @@ import re
import sys
def __changeIP(interface, ipaddress, netmask="0"):
__check_address(ipaddress)
if netmask == "0":
## change the IP only
proc = subprocess.Popen(
shell = False,
args = [IFCONFIG_BIN, interface, ipaddress])
proc.wait()
else:
## someone wants to change the netmask too
__check_address(netmask)
proc = subprocess.Popen(
shell = False,
args = [IFCONFIG_BIN, interface, ipaddress, "netmask", netmask])
proc.wait()
return proc.returncode == 0
__check_address(ipaddress)
if netmask == "0":
## change the IP only
proc = subprocess.Popen(
shell = False,
args = [IFCONFIG_BIN, interface, ipaddress])
proc.wait()
else:
## someone wants to change the netmask too
__check_address(netmask)
proc = subprocess.Popen(
shell = False,
args = [IFCONFIG_BIN, interface, ipaddress, "netmask", netmask])
proc.wait()
return proc.returncode == 0
def __changeGW(old_gw, new_gw):
__check_address(old_gw)
__check_address(new_gw)
if old_gw != "0.0.0.0":
## assume that a default route exists and delete it
proc = subprocess.Popen(
shell = False,
args = [ROUTE_BIN, "del", "default", "gw", old_gw])
proc.wait()
## ignore errors
proc = subprocess.Popen(
shell = False,
args = [ROUTE_BIN, "add", "default", "gw", new_gw])
proc.wait()
return proc.returncode == 0
__check_address(old_gw)
__check_address(new_gw)
if old_gw != "0.0.0.0":
## assume that a default route exists and delete it
proc = subprocess.Popen(
shell = False,
args = [ROUTE_BIN, "del", "default", "gw", old_gw])
proc.wait()
## ignore errors
proc = subprocess.Popen(
shell = False,
args = [ROUTE_BIN, "add", "default", "gw", new_gw])
proc.wait()
return proc.returncode == 0
def __check_address(address):
"""Check for correct numbers in given address
"""
match = re.search(r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$', address)
## did we match? If yes, then: are there wrong values inside?
if not match or [e for e in match.groups() if int(e) > 255]:
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, address))
sys.exit(1)
return
"""Check for correct numbers in given address
"""
match = re.search(r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$', address)
## did we match? If yes, then: are there wrong values inside?
if not match or [e for e in match.groups() if int(e) > 255]:
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, address))
sys.exit(1)
return
def __use_DHCP(interface):
"""Recieve network settings via dhcp
"""
proc = subprocess.Popen(
shell = False,
args = [DHCLIENT_BIN, interface])
proc.wait()
"""Recieve network settings via dhcp
"""
proc = subprocess.Popen(
shell = False,
args = [DHCLIENT_BIN, interface])
proc.wait()
if __name__ == "__main__":
args = sys.argv[1:]
args = sys.argv[1:]
self_bin = sys.argv[0]
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
try:
if args[0] == "change_ip":
if len(args) != 4: raise "InvalidArgNum"
result = __changeIP(args[1], args[2], args[3])
elif args[0] == "change_gw":
if len(args) != 3: raise "InvalidArgNum"
result = __changeGW(args[1], args[2])
elif args[0] == "use_dhcp":
if len(args) != 2: raise "InvalidArgNum"
result = __use_DHCP(args[1])
else:
sys.stderr.write("%s: invalid action (%s)\n" % (self_bin, args[0]))
sys.exit(1)
if result:
sys.exit(0)
else:
sys.exit(1)
except "InvalidArgNum":
sys.stderr.write("%s: invalid number of arguments (%s)\n" % (self_bin, args))
sys.exit(1)
self_bin = sys.argv[0]
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
try:
if args[0] == "change_ip":
if len(args) != 4: raise "InvalidArgNum"
result = __changeIP(args[1], args[2], args[3])
elif args[0] == "change_gw":
if len(args) != 3: raise "InvalidArgNum"
result = __changeGW(args[1], args[2])
elif args[0] == "use_dhcp":
if len(args) != 2: raise "InvalidArgNum"
result = __use_DHCP(args[1])
else:
sys.stderr.write("%s: invalid action (%s)\n" % (self_bin, args[0]))
sys.exit(1)
if result:
sys.exit(0)
else:
sys.exit(1)
except "InvalidArgNum":
sys.stderr.write("%s: invalid number of arguments (%s)\n" % (self_bin, args))
sys.exit(1)

View file

@ -26,53 +26,53 @@ from network import CHANGE_IP_DELAY
class unittests(WebInterfaceTestClass):
def test_ip_change(self):
'''Change network address.'''
## the time module is necessary for the CHANGE_IP_DELAY
import time
self.register_auth(self.url + "network")
## do not follow redirects - they would break the test otherwise
self.cmd.config("acknowledge_equiv_refresh", 0)
self.cmd.go(self.url + "network")
## extract the current IP from the network plugin output
def get_current_ip():
self.register_auth(self.url + "network")
self.cmd.go(self.url + "network")
self.cmd.find(r'Data.Status.Plugins.network=([0-9\.]*)$', "m")
return self.locals["__match__"]
orig_ip_text = get_current_ip()
orig_ip_octs = orig_ip_text.split(".")
## check, if the original IP is valid (contains four octets)
self.assertEquals(4, len(orig_ip_octs))
def set_ip((ip1, ip2, ip3, ip4)):
self.cmd.go(self.url + "network")
self.cmd.formvalue("network_address", "ip1", str(ip1))
self.cmd.formvalue("network_address", "ip2", str(ip2))
self.cmd.formvalue("network_address", "ip3", str(ip3))
self.cmd.formvalue("network_address", "ip4", str(ip4))
self.cmd.submit()
## sleep a little bit longer than the delay necessary for ip-change
time.sleep(CHANGE_IP_DELAY + 3)
set_ip([1,-2,0,1])
self.assertEquals(orig_ip_text, get_current_ip())
set_ip([1,0,0,256])
self.assertEquals(orig_ip_text, get_current_ip())
set_ip([1,"foo",0,1])
self.assertEquals(orig_ip_text, get_current_ip())
new_ip = orig_ip_octs[:]
new_ip[3] = str((int(orig_ip_octs[3]) + 128) % 256)
set_ip(new_ip)
self.assertEquals(".".join(new_ip), get_current_ip())
set_ip(orig_ip_octs)
self.assertEquals(orig_ip_text, get_current_ip())
def test_ip_change(self):
'''Change network address.'''
## the time module is necessary for the CHANGE_IP_DELAY
import time
self.register_auth(self.url + "network")
## do not follow redirects - they would break the test otherwise
self.cmd.config("acknowledge_equiv_refresh", 0)
self.cmd.go(self.url + "network")
## extract the current IP from the network plugin output
def get_current_ip():
self.register_auth(self.url + "network")
self.cmd.go(self.url + "network")
self.cmd.find(r'Data.Status.Plugins.network=([0-9\.]*)$', "m")
return self.locals["__match__"]
orig_ip_text = get_current_ip()
orig_ip_octs = orig_ip_text.split(".")
## check, if the original IP is valid (contains four octets)
self.assertEquals(4, len(orig_ip_octs))
def set_ip((ip1, ip2, ip3, ip4)):
self.cmd.go(self.url + "network")
self.cmd.formvalue("network_address", "ip1", str(ip1))
self.cmd.formvalue("network_address", "ip2", str(ip2))
self.cmd.formvalue("network_address", "ip3", str(ip3))
self.cmd.formvalue("network_address", "ip4", str(ip4))
self.cmd.submit()
## sleep a little bit longer than the delay necessary for ip-change
time.sleep(CHANGE_IP_DELAY + 3)
set_ip([1,-2,0,1])
self.assertEquals(orig_ip_text, get_current_ip())
set_ip([1,0,0,256])
self.assertEquals(orig_ip_text, get_current_ip())
set_ip([1,"foo",0,1])
self.assertEquals(orig_ip_text, get_current_ip())
new_ip = orig_ip_octs[:]
new_ip[3] = str((int(orig_ip_octs[3]) + 128) % 256)
set_ip(new_ip)
self.assertEquals(".".join(new_ip), get_current_ip())
set_ip(orig_ip_octs)
self.assertEquals(orig_ip_text, get_current_ip())
def test_inputs(self):
"""Check various input patterns for 'network' plugin.
"""
self.register_auth(self.url + "network")
self.cmd.go(self.url + "network" + "?redirected=1")
self.cmd.notfind("problem")
self.cmd.go(self.url + "network" + "?store=set_ip")
self.cmd.find("server address is not valid")
def test_inputs(self):
"""Check various input patterns for 'network' plugin.
"""
self.register_auth(self.url + "network")
self.cmd.go(self.url + "network" + "?redirected=1")
self.cmd.notfind("problem")
self.cmd.go(self.url + "network" + "?store=set_ip")
self.cmd.find("server address is not valid")

View file

@ -33,505 +33,505 @@ from cryptobox.core.exceptions import *
PARTTYPES = {
"windows" : ["0xC", "vfat"],
"linux" : ["L", "ext3"]}
"windows" : ["0xC", "vfat"],
"linux" : ["L", "ext3"]}
CONFIGPARTITION = {
"size" : 5, # size of configuration partition (if necessary) in MB
"type" : "L",
"fs" : "ext2"}
"size" : 5, # size of configuration partition (if necessary) in MB
"type" : "L",
"fs" : "ext2"}
class partition(cryptobox.plugins.base.CryptoBoxPlugin):
"""The partition feature of the CryptoBox.
"""
"""The partition feature of the CryptoBox.
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 80
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 80
def do_action(self, **args):
"""Show the partitioning form and execute the requested action.
"""
## load default hdf values
self.__prepare_dataset()
## retrieve some values from 'args' - defaults are empty
self.blockdevice = self.__get_selected_device(args)
self.with_config_partition = self.__is_with_config_partition()
self.cbox.log.debug(
"partition plugin: selected device=%s" % str(self.blockdevice))
self.blockdevice_size = self.__get_available_device_size(self.blockdevice)
## no (or invalid) device was supplied
if not self.blockdevice:
return self.__action_select_device()
## exit if the blockdevice is not writeable
if not os.access(self.blockdevice, os.W_OK):
self.hdf["Data.Warning"] = "DeviceNotWriteable"
return self.__action_select_device()
## no confirm setting?
if not args.has_key("confirm") or (args["confirm"] != "1"):
self.hdf["Data.Warning"] = "Plugins.partition.FormatNotConfirmed"
return self.__action_select_device()
elif args.has_key("easy"):
return self.__action_easy_setup()
elif args.has_key("add_part"):
return self.__action_add_partition(args)
elif args.has_key("finish"):
return self.__action_finish(args)
elif args.has_key("cancel"):
return self.__action_select_device()
## check if we should remove a partition
del_args = [ e for e in args.keys() if re.match(r"del_part_[\d]+$", e) ]
if len(del_args) == 1:
try:
num_part = int(del_args[0][9:])
except ValueError:
self.cbox.log.warn(
"partition: invalid partition number to delete (%s)" % del_args[0])
return self.__action_select_device()
return self.__action_del_partition(args, num_part)
else: # for "select_device" and for invalid targets
return self.__action_select_device()
def do_action(self, **args):
"""Show the partitioning form and execute the requested action.
"""
## load default hdf values
self.__prepare_dataset()
## retrieve some values from 'args' - defaults are empty
self.blockdevice = self.__get_selected_device(args)
self.with_config_partition = self.__is_with_config_partition()
self.cbox.log.debug(
"partition plugin: selected device=%s" % str(self.blockdevice))
self.blockdevice_size = self.__get_available_device_size(self.blockdevice)
## no (or invalid) device was supplied
if not self.blockdevice:
return self.__action_select_device()
## exit if the blockdevice is not writeable
if not os.access(self.blockdevice, os.W_OK):
self.hdf["Data.Warning"] = "DeviceNotWriteable"
return self.__action_select_device()
## no confirm setting?
if not args.has_key("confirm") or (args["confirm"] != "1"):
self.hdf["Data.Warning"] = "Plugins.partition.FormatNotConfirmed"
return self.__action_select_device()
elif args.has_key("easy"):
return self.__action_easy_setup()
elif args.has_key("add_part"):
return self.__action_add_partition(args)
elif args.has_key("finish"):
return self.__action_finish(args)
elif args.has_key("cancel"):
return self.__action_select_device()
## check if we should remove a partition
del_args = [ e for e in args.keys() if re.match(r"del_part_[\d]+$", e) ]
if len(del_args) == 1:
try:
num_part = int(del_args[0][9:])
except ValueError:
self.cbox.log.warn(
"partition: invalid partition number to delete (%s)" % del_args[0])
return self.__action_select_device()
return self.__action_del_partition(args, num_part)
else: # for "select_device" and for invalid targets
return self.__action_select_device()
def get_status(self):
"""The status of this plugin is the selected device and some information.
"""
return "%s / %s / %s" % (self.blockdevice, self.blockdevice_size,
self.with_config_partition)
def get_status(self):
"""The status of this plugin is the selected device and some information.
"""
return "%s / %s / %s" % (self.blockdevice, self.blockdevice_size,
self.with_config_partition)
def get_warnings(self):
warnings = []
## this check is done _after_ "reset_dataset" -> if there is
## a config partition, then it was loaded before
if self.cbox.prefs.requires_partition() \
and not self.cbox.prefs.get_active_partition():
warnings.append((50, "Plugins.%s.ReadOnlyConfig" % self.get_name()))
## check required programs
if not os.path.isfile(self.root_action.SFDISK_BIN):
warnings.append((53, "Plugins.%s.MissingProgramSfdisk" % self.get_name()))
if not os.path.isfile(self.root_action.MKFS_BIN):
warnings.append((56, "Plugins.%s.MissingProgramMkfs" % self.get_name()))
if not os.path.isfile(self.root_action.LABEL_BIN):
warnings.append((40, "Plugins.%s.MissingProgramE2label" % self.get_name()))
return warnings
def get_warnings(self):
warnings = []
## this check is done _after_ "reset_dataset" -> if there is
## a config partition, then it was loaded before
if self.cbox.prefs.requires_partition() \
and not self.cbox.prefs.get_active_partition():
warnings.append((50, "Plugins.%s.ReadOnlyConfig" % self.get_name()))
## check required programs
if not os.path.isfile(self.root_action.SFDISK_BIN):
warnings.append((53, "Plugins.%s.MissingProgramSfdisk" % self.get_name()))
if not os.path.isfile(self.root_action.MKFS_BIN):
warnings.append((56, "Plugins.%s.MissingProgramMkfs" % self.get_name()))
if not os.path.isfile(self.root_action.LABEL_BIN):
warnings.append((40, "Plugins.%s.MissingProgramE2label" % self.get_name()))
return warnings
def __prepare_dataset(self):
"""Set some hdf values.
"""
self.hdf["Data.AdditionalStylesheets.%s" % self.get_name()] = \
os.path.join(self.plugin_dir, "partition.css")
self.hdf[self.hdf_prefix + "PluginDir"] = self.plugin_dir
def __prepare_dataset(self):
"""Set some hdf values.
"""
self.hdf["Data.AdditionalStylesheets.%s" % self.get_name()] = \
os.path.join(self.plugin_dir, "partition.css")
self.hdf[self.hdf_prefix + "PluginDir"] = self.plugin_dir
def __get_selected_device(self, args):
"""Check the selected device (valid, not busy, ...).
"""
try:
blockdevice = args["block_device"]
except KeyError:
return None
if not self.__is_device_valid(blockdevice):
return None
if self.__is_device_busy(blockdevice):
self.hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
return None
return blockdevice
def __get_selected_device(self, args):
"""Check the selected device (valid, not busy, ...).
"""
try:
blockdevice = args["block_device"]
except KeyError:
return None
if not self.__is_device_valid(blockdevice):
return None
if self.__is_device_busy(blockdevice):
self.hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
return None
return blockdevice
def __is_device_valid(self, blockdevice):
"""Check if the device is valid and allowed.
"""
if not blockdevice:
return False
if not self.cbox.is_device_allowed(blockdevice):
return False
if not blockdevice in cbox_tools.get_parent_blockdevices():
return False
return True
def __is_device_valid(self, blockdevice):
"""Check if the device is valid and allowed.
"""
if not blockdevice:
return False
if not self.cbox.is_device_allowed(blockdevice):
return False
if not blockdevice in cbox_tools.get_parent_blockdevices():
return False
return True
def __is_device_busy(self, blockdevice):
"""check if the device (or one of its partitions) is mounted
"""
## the config partition is ignored, as it will get unmounted if necessary
for cont in self.cbox.get_container_list():
if cbox_tools.is_part_of_blockdevice(blockdevice, cont.get_device()) \
and cont.is_mounted():
return True
return False
def __is_device_busy(self, blockdevice):
"""check if the device (or one of its partitions) is mounted
"""
## the config partition is ignored, as it will get unmounted if necessary
for cont in self.cbox.get_container_list():
if cbox_tools.is_part_of_blockdevice(blockdevice, cont.get_device()) \
and cont.is_mounted():
return True
return False
def __action_select_device(self):
"""Show a form to select the device for partitioning.
"""
block_devices = [e
for e in cbox_tools.get_parent_blockdevices()
if self.cbox.is_device_allowed(e)]
counter = 0
for dev in block_devices:
self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = dev
self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = \
cbox_tools.get_blockdevice_size_humanly(dev)
self.cbox.log.debug("found a suitable block device: %s" % dev)
counter += 1
if self.with_config_partition:
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
## there is no disk available
if not block_devices:
self.hdf["Data.Warning"] = "Plugins.partition.NoDisksAvailable"
return "select_device"
def __action_select_device(self):
"""Show a form to select the device for partitioning.
"""
block_devices = [e
for e in cbox_tools.get_parent_blockdevices()
if self.cbox.is_device_allowed(e)]
counter = 0
for dev in block_devices:
self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = dev
self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = \
cbox_tools.get_blockdevice_size_humanly(dev)
self.cbox.log.debug("found a suitable block device: %s" % dev)
counter += 1
if self.with_config_partition:
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
## there is no disk available
if not block_devices:
self.hdf["Data.Warning"] = "Plugins.partition.NoDisksAvailable"
return "select_device"
def __action_add_partition(self, args):
"""Add a selected partition to the currently proposed partition table.
"""
self.hdf[self.hdf_prefix + "Device"] = self.blockdevice
self.hdf[self.hdf_prefix + "Device.Size"] = self.blockdevice_size
parts = self.__get_partitions_from_args(args)
self.__set_partition_data(parts)
return "set_partitions"
def __action_add_partition(self, args):
"""Add a selected partition to the currently proposed partition table.
"""
self.hdf[self.hdf_prefix + "Device"] = self.blockdevice
self.hdf[self.hdf_prefix + "Device.Size"] = self.blockdevice_size
parts = self.__get_partitions_from_args(args)
self.__set_partition_data(parts)
return "set_partitions"
def __action_del_partition(self, args, part_num):
"""Remove a partition from the proposed partition table.
"""
self.hdf[self.hdf_prefix + "Device"] = self.blockdevice
self.hdf[self.hdf_prefix + "Device.Size"] = self.blockdevice_size
parts = self.__get_partitions_from_args(args)
## valid partition number to be deleted?
if part_num < len(parts):
del parts[part_num]
self.__set_partition_data(parts)
return "set_partitions"
def __action_del_partition(self, args, part_num):
"""Remove a partition from the proposed partition table.
"""
self.hdf[self.hdf_prefix + "Device"] = self.blockdevice
self.hdf[self.hdf_prefix + "Device.Size"] = self.blockdevice_size
parts = self.__get_partitions_from_args(args)
## valid partition number to be deleted?
if part_num < len(parts):
del parts[part_num]
self.__set_partition_data(parts)
return "set_partitions"
def __action_finish(self, args):
"""Write the partition table.
"""
parts = self.__get_partitions_from_args(args)
if parts:
self.__set_partition_data(parts)
if cbox_tools.is_part_of_blockdevice(self.blockdevice,
self.cbox.prefs.get_active_partition()):
self.cbox.prefs.umount_partition()
if not self.__run_fdisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
self.cbox.log.warn(
"partition: failed to partition device: %s" % self.blockdevice)
return self.__action_add_partition(args)
else:
## tricky problem: if the device was partitioned, then a created config
## partition is still part of the containerlist, as the label is not
## checked again - very ugly!!! So we will call reReadContainerList
## after formatting the last partition - see below
#self.cbox.reread_container_list()
format_ok = True
counter = 0
## initialize the generator
format_part_gen = self.__format_partitions(parts)
while counter < len(parts):
## first part: get the device name
counter += 1
## second part: do the real formatting of a partition
result = format_part_gen.next()
## after the first partiton, we can reRead the containerList
## (as the possible config partition was already created)
if self.with_config_partition and (counter == 1):
## important: reRead the containerList - but somehow it
## breaks the flow (hanging process)
#self.cbox.reReadContainerList()
## write config data
self.cbox.prefs.mount_partition()
try:
self.cbox.prefs.write()
self.cbox.log.info("settings stored on config partition")
except IOError:
self.cbox.log.warn(
"Failed to store settings on new config partition")
## return the result
if not result:
format_ok = False
if format_ok:
self.hdf["Data.Success"] = "Plugins.partition.Partitioned"
else:
self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
return "empty"
else:
return self.__action_add_partition(args)
def __action_finish(self, args):
"""Write the partition table.
"""
parts = self.__get_partitions_from_args(args)
if parts:
self.__set_partition_data(parts)
if cbox_tools.is_part_of_blockdevice(self.blockdevice,
self.cbox.prefs.get_active_partition()):
self.cbox.prefs.umount_partition()
if not self.__run_fdisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
self.cbox.log.warn(
"partition: failed to partition device: %s" % self.blockdevice)
return self.__action_add_partition(args)
else:
## tricky problem: if the device was partitioned, then a created config
## partition is still part of the containerlist, as the label is not
## checked again - very ugly!!! So we will call reReadContainerList
## after formatting the last partition - see below
#self.cbox.reread_container_list()
format_ok = True
counter = 0
## initialize the generator
format_part_gen = self.__format_partitions(parts)
while counter < len(parts):
## first part: get the device name
counter += 1
## second part: do the real formatting of a partition
result = format_part_gen.next()
## after the first partiton, we can reRead the containerList
## (as the possible config partition was already created)
if self.with_config_partition and (counter == 1):
## important: reRead the containerList - but somehow it
## breaks the flow (hanging process)
#self.cbox.reReadContainerList()
## write config data
self.cbox.prefs.mount_partition()
try:
self.cbox.prefs.write()
self.cbox.log.info("settings stored on config partition")
except IOError:
self.cbox.log.warn(
"Failed to store settings on new config partition")
## return the result
if not result:
format_ok = False
if format_ok:
self.hdf["Data.Success"] = "Plugins.partition.Partitioned"
else:
self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
return "empty"
else:
return self.__action_add_partition(args)
def __action_easy_setup(self):
"""Do automatic partitioning (create only one big partition).
"""
import types
## we do not have to take special care for a possible config partition
parts = [ { "size": self.blockdevice_size, "type": "windows" } ]
## umount partition if necessary
if cbox_tools.is_part_of_blockdevice(self.blockdevice,
self.cbox.prefs.get_active_partition()):
self.cbox.prefs.umount_partition()
## partition it
if not self.__run_fdisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
return None
## "formatPartitions" is a generator, returning device names and bolean values
result = [e for e in self.__format_partitions(parts)
if type(e) == types.BooleanType]
if self.with_config_partition:
self.cbox.prefs.mount_partition()
if not self.cbox.prefs.write():
self.cbox.log.warn("Failed to store settings on new config partition")
## check if there is a "False" return value
if False in result:
## operation failed
self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
self.cbox.log.info("easy partitioning failed")
return "select_partitions"
else:
## operation was successful
self.hdf["Data.Success"] = "Plugins.partition.EasySetup"
self.cbox.log.info("easy partitioning succeeded")
## do not show the disk overview immediately
## it does not get updated that fast
return { "plugin":"system_preferences", "values":[] }
def __action_easy_setup(self):
"""Do automatic partitioning (create only one big partition).
"""
import types
## we do not have to take special care for a possible config partition
parts = [ { "size": self.blockdevice_size, "type": "windows" } ]
## umount partition if necessary
if cbox_tools.is_part_of_blockdevice(self.blockdevice,
self.cbox.prefs.get_active_partition()):
self.cbox.prefs.umount_partition()
## partition it
if not self.__run_fdisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
return None
## "formatPartitions" is a generator, returning device names and bolean values
result = [e for e in self.__format_partitions(parts)
if type(e) == types.BooleanType]
if self.with_config_partition:
self.cbox.prefs.mount_partition()
if not self.cbox.prefs.write():
self.cbox.log.warn("Failed to store settings on new config partition")
## check if there is a "False" return value
if False in result:
## operation failed
self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
self.cbox.log.info("easy partitioning failed")
return "select_partitions"
else:
## operation was successful
self.hdf["Data.Success"] = "Plugins.partition.EasySetup"
self.cbox.log.info("easy partitioning succeeded")
## do not show the disk overview immediately
## it does not get updated that fast
return { "plugin":"system_preferences", "values":[] }
def __set_partition_data(self, parts):
"""Set some hdf values for the currently proposed partition table.
"""
avail_size = self.blockdevice_size
i = 0
for part in parts:
self.cbox.log.debug(part)
self.hdf[self.hdf_prefix + "Parts.%d.Size" % i] = part["size"]
self.hdf[self.hdf_prefix + "Parts.%d.Type" % i] = part["type"]
avail_size -= part["size"]
i += 1
self.hdf[self.hdf_prefix + "availSize"] = avail_size
if self.with_config_partition:
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
for ptype in PARTTYPES.keys():
self.hdf[self.hdf_prefix + "Types.%s" % ptype] = ptype
## store the currently existing partitions of the choosen block device
current_containers = [ e for e in self.cbox.get_container_list()
if cbox_tools.is_part_of_blockdevice(self.blockdevice, e.get_device()) ]
for (index, cont) in enumerate(current_containers):
self.hdf[self.hdf_prefix + "ExistingContainers.%d" % index] = \
cont.get_device()
def __set_partition_data(self, parts):
"""Set some hdf values for the currently proposed partition table.
"""
avail_size = self.blockdevice_size
i = 0
for part in parts:
self.cbox.log.debug(part)
self.hdf[self.hdf_prefix + "Parts.%d.Size" % i] = part["size"]
self.hdf[self.hdf_prefix + "Parts.%d.Type" % i] = part["type"]
avail_size -= part["size"]
i += 1
self.hdf[self.hdf_prefix + "availSize"] = avail_size
if self.with_config_partition:
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
for ptype in PARTTYPES.keys():
self.hdf[self.hdf_prefix + "Types.%s" % ptype] = ptype
## store the currently existing partitions of the choosen block device
current_containers = [ e for e in self.cbox.get_container_list()
if cbox_tools.is_part_of_blockdevice(self.blockdevice, e.get_device()) ]
for (index, cont) in enumerate(current_containers):
self.hdf[self.hdf_prefix + "ExistingContainers.%d" % index] = \
cont.get_device()
def __get_partitions_from_args(self, args):
"""Filter the given arguments and construct a partition table.
"""
parts = []
done = False
avail_size = self.blockdevice_size
i = -1
while not done:
i += 1
try:
## skip every unconfirmed (probably the last) partition if we should not add it
if args.has_key("part%d_unconfirmed" % i) and \
not args.has_key("add_part"):
continue
size = int(args["part%d_size" % i])
part_type = args["part%d_type" % i]
if int(size) > avail_size:
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
continue
if int(size) < 10:
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
continue
if not part_type in PARTTYPES.keys():
continue
parts.append({"size":size, "type":part_type})
avail_size -= size
except TypeError:
pass
except KeyError:
done = True
return parts
def __get_partitions_from_args(self, args):
"""Filter the given arguments and construct a partition table.
"""
parts = []
done = False
avail_size = self.blockdevice_size
i = -1
while not done:
i += 1
try:
## skip every unconfirmed (probably the last) partition if we should not add it
if args.has_key("part%d_unconfirmed" % i) and \
not args.has_key("add_part"):
continue
size = int(args["part%d_size" % i])
part_type = args["part%d_type" % i]
if int(size) > avail_size:
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
continue
if int(size) < 10:
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
continue
if not part_type in PARTTYPES.keys():
continue
parts.append({"size":size, "type":part_type})
avail_size -= size
except TypeError:
pass
except KeyError:
done = True
return parts
def __get_available_device_size(self, device):
"""calculate the available size (MB) of the device
also consider a (possible) configuration partition
"""
device_size = cbox_tools.get_blockdevice_size(device)
if device_size < 0:
return 0
if self.with_config_partition:
device_size -= CONFIGPARTITION["size"]
return device_size
def __get_available_device_size(self, device):
"""calculate the available size (MB) of the device
also consider a (possible) configuration partition
"""
device_size = cbox_tools.get_blockdevice_size(device)
if device_size < 0:
return 0
if self.with_config_partition:
device_size -= CONFIGPARTITION["size"]
return device_size
def __is_with_config_partition(self):
"""check if we have to create a configuration partition
"""
if self.cbox.prefs.requires_partition():
active = self.cbox.prefs.get_active_partition()
## we need a partition, if there is no active one
if not active:
return True
## check if the active one is part of the current device
return cbox_tools.is_part_of_blockdevice(self.blockdevice, active)
return False
def __is_with_config_partition(self):
"""check if we have to create a configuration partition
"""
if self.cbox.prefs.requires_partition():
active = self.cbox.prefs.get_active_partition()
## we need a partition, if there is no active one
if not active:
return True
## check if the active one is part of the current device
return cbox_tools.is_part_of_blockdevice(self.blockdevice, active)
return False
def __run_fdisk(self, parts):
"""Call fdisk to partition the device.
"""
## check if the device is completely filled (to avoid some empty last blocks)
avail_size = self.blockdevice_size
for one_part in parts:
avail_size -= one_part["size"]
self.cbox.log.debug("remaining size: %d" % avail_size)
is_filled = avail_size == 0
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"partition",
self.blockdevice])
for line in self.__get_sfdisk_layout(parts, is_filled):
proc.stdin.write(line + "\n")
#TODO: if running inside of an uml, then sfdisk hangs at "nanosleep({3,0})"
# very ugly - maybe a uml bug?
# it seems, like this can be avoided by running uml with the param "aio=2.4"
(output, error) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.debug("partitioning failed: %s" % error)
return proc.returncode == 0
def __run_fdisk(self, parts):
"""Call fdisk to partition the device.
"""
## check if the device is completely filled (to avoid some empty last blocks)
avail_size = self.blockdevice_size
for one_part in parts:
avail_size -= one_part["size"]
self.cbox.log.debug("remaining size: %d" % avail_size)
is_filled = avail_size == 0
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"partition",
self.blockdevice])
for line in self.__get_sfdisk_layout(parts, is_filled):
proc.stdin.write(line + "\n")
#TODO: if running inside of an uml, then sfdisk hangs at "nanosleep({3,0})"
# very ugly - maybe a uml bug?
# it seems, like this can be avoided by running uml with the param "aio=2.4"
(output, error) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.debug("partitioning failed: %s" % error)
return proc.returncode == 0
def __get_sfdisk_layout(self, param_parts, is_filled):
"""this generator returns the input lines for sfdisk
"""
parts = param_parts[:]
## first a (possible) configuration partition - so it will be reusable
if self.with_config_partition:
## fill the main table (including a config partition)
yield ",%d,%s" % (CONFIGPARTITION["size"], CONFIGPARTITION["type"])
## one primary partition
if is_filled and (len(parts) == 1):
## fill the rest of the device
yield ",,%s,*" % PARTTYPES[parts[0]["type"]][0]
else:
## only use the specified size
yield ",%d,%s,*" % (parts[0]["size"], PARTTYPES[parts[0]["type"]][0])
del parts[0]
## no extended partition, if there is only one disk
if not parts:
return
## an extended container for the rest
yield ",,E"
## an empty partition in main table
yield ";"
## maybe another empty partition if there is no config partition
if not self.with_config_partition:
yield ";"
while parts:
if is_filled and (len(parts) == 1):
yield ",,%s" % (PARTTYPES[parts[0]["type"]][0],)
else:
yield ",%d,%s" % (parts[0]["size"], PARTTYPES[parts[0]["type"]][0])
del parts[0]
def __get_sfdisk_layout(self, param_parts, is_filled):
"""this generator returns the input lines for sfdisk
"""
parts = param_parts[:]
## first a (possible) configuration partition - so it will be reusable
if self.with_config_partition:
## fill the main table (including a config partition)
yield ",%d,%s" % (CONFIGPARTITION["size"], CONFIGPARTITION["type"])
## one primary partition
if is_filled and (len(parts) == 1):
## fill the rest of the device
yield ",,%s,*" % PARTTYPES[parts[0]["type"]][0]
else:
## only use the specified size
yield ",%d,%s,*" % (parts[0]["size"], PARTTYPES[parts[0]["type"]][0])
del parts[0]
## no extended partition, if there is only one disk
if not parts:
return
## an extended container for the rest
yield ",,E"
## an empty partition in main table
yield ";"
## maybe another empty partition if there is no config partition
if not self.with_config_partition:
yield ";"
while parts:
if is_filled and (len(parts) == 1):
yield ",,%s" % (PARTTYPES[parts[0]["type"]][0],)
else:
yield ",%d,%s" % (parts[0]["size"], PARTTYPES[parts[0]["type"]][0])
del parts[0]
def __format_partitions(self, param_parts):
"""Format all partitions of the device.
"""
parts = param_parts[:]
part_num = 1
## maybe a config partition?
if self.with_config_partition:
dev_name = self.__get_partition_name(self.blockdevice, part_num)
self.cbox.log.info("formatting config partition (%s)" % dev_name)
if self.__format_one_partition(dev_name, CONFIGPARTITION["fs"]):
self.__set_label_of_partition(dev_name,
self.cbox.prefs["Main"]["ConfigVolumeLabel"])
part_num += 1
## the first data partition
dev_name = self.__get_partition_name(self.blockdevice, part_num)
part_type = PARTTYPES[parts[0]["type"]][1]
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
yield self.__format_one_partition(dev_name, part_type)
del parts[0]
## other data partitions
part_num = 5
while parts:
dev_name = self.__get_partition_name(self.blockdevice, part_num)
part_type = PARTTYPES[parts[0]["type"]][1]
self.cbox.log.info("formatting partition (%s) as '%s'" % \
(dev_name, part_type))
yield self.__format_one_partition(dev_name, part_type)
part_num += 1
del parts[0]
return
def __format_partitions(self, param_parts):
"""Format all partitions of the device.
"""
parts = param_parts[:]
part_num = 1
## maybe a config partition?
if self.with_config_partition:
dev_name = self.__get_partition_name(self.blockdevice, part_num)
self.cbox.log.info("formatting config partition (%s)" % dev_name)
if self.__format_one_partition(dev_name, CONFIGPARTITION["fs"]):
self.__set_label_of_partition(dev_name,
self.cbox.prefs["Main"]["ConfigVolumeLabel"])
part_num += 1
## the first data partition
dev_name = self.__get_partition_name(self.blockdevice, part_num)
part_type = PARTTYPES[parts[0]["type"]][1]
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
yield self.__format_one_partition(dev_name, part_type)
del parts[0]
## other data partitions
part_num = 5
while parts:
dev_name = self.__get_partition_name(self.blockdevice, part_num)
part_type = PARTTYPES[parts[0]["type"]][1]
self.cbox.log.info("formatting partition (%s) as '%s'" % \
(dev_name, part_type))
yield self.__format_one_partition(dev_name, part_type)
part_num += 1
del parts[0]
return
def __get_partition_name(self, blockdev, number):
"""Return the devicename of a specific partition of a device
No tests are performed, whether the partition exists or
not.
"""
if re.search("[0-9]$", blockdev):
## blockdev ends with a digit, so it is a partition, we insert a 'p'
return "%sp%d" % (blockdev, number)
else:
## whole disk, no 'p' necessary
return "%s%d" % (blockdev, number)
def __get_partition_name(self, blockdev, number):
"""Return the devicename of a specific partition of a device
No tests are performed, whether the partition exists or
not.
"""
if re.search("[0-9]$", blockdev):
## blockdev ends with a digit, so it is a partition, we insert a 'p'
return "%sp%d" % (blockdev, number)
else:
## whole disk, no 'p' necessary
return "%s%d" % (blockdev, number)
def __format_one_partition(self, dev_name, fs_type):
"""Format a single partition
"""
import cryptobox.core.container
## first: retrieve UUID - it can be removed from the database afterwards
prev_name = [e.get_name() for e in self.cbox.get_container_list()
if e.get_device() == dev_name]
## call "mkfs"
try:
cont = cryptobox.core.container.CryptoBoxContainer(dev_name, self.cbox)
cont.create(cryptobox.core.container.CONTAINERTYPES["plain"], fs_type=fs_type)
except (CBInvalidType, CBCreateError, CBVolumeIsActive), err_msg:
self.cbox.log.warn(err_msg)
return False
## remove unused volume entry
if prev_name:
del self.cbox.prefs.volumes_db[prev_name[0]]
return True
def __format_one_partition(self, dev_name, fs_type):
"""Format a single partition
"""
import cryptobox.core.container
## first: retrieve UUID - it can be removed from the database afterwards
prev_name = [e.get_name() for e in self.cbox.get_container_list()
if e.get_device() == dev_name]
## call "mkfs"
try:
cont = cryptobox.core.container.CryptoBoxContainer(dev_name, self.cbox)
cont.create(cryptobox.core.container.CONTAINERTYPES["plain"], fs_type=fs_type)
except (CBInvalidType, CBCreateError, CBVolumeIsActive), err_msg:
self.cbox.log.warn(err_msg)
return False
## remove unused volume entry
if prev_name:
del self.cbox.prefs.volumes_db[prev_name[0]]
return True
def __set_label_of_partition(self, dev_name, label):
"""Set the label of a partition - useful for the config partition.
"""
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"label",
dev_name,
label])
(output, error) = proc.communicate()
if proc.returncode == 0:
return True
else:
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
return False
def __set_label_of_partition(self, dev_name, label):
"""Set the label of a partition - useful for the config partition.
"""
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
"label",
dev_name,
label])
(output, error) = proc.communicate()
if proc.returncode == 0:
return True
else:
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
return False

View file

@ -36,83 +36,83 @@ import os
def __partitionDevice(device):
## do not use the "-q" flag, as this spoils the exit code of sfdisk (seems to be a bug)
proc = subprocess.Popen(
shell = False,
args = [
SFDISK_BIN,
"-uM",
device])
proc.wait()
return proc.returncode == 0
## do not use the "-q" flag, as this spoils the exit code of sfdisk (seems to be a bug)
proc = subprocess.Popen(
shell = False,
args = [
SFDISK_BIN,
"-uM",
device])
proc.wait()
return proc.returncode == 0
def __formatPartition(device, type):
import time, threading
result = True
def formatting():
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
MKFS_BIN,
"-t", type,
device])
proc.wait()
## TODO: very ugly way of communication: it assumes, that failures are fast - success is slow
if proc.returncode == 0:
time.sleep(1)
return True
else:
return False
thread = threading.Thread()
thread.setDaemon(True)
thread.run = formatting
thread.start()
time.sleep(0.5)
return thread.isAlive()
import time, threading
result = True
def formatting():
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
MKFS_BIN,
"-t", type,
device])
proc.wait()
## TODO: very ugly way of communication: it assumes, that failures are fast - success is slow
if proc.returncode == 0:
time.sleep(1)
return True
else:
return False
thread = threading.Thread()
thread.setDaemon(True)
thread.run = formatting
thread.start()
time.sleep(0.5)
return thread.isAlive()
def __labelPartition(device, label):
proc = subprocess.Popen(
shell = False,
args = [
LABEL_BIN,
device,
label])
proc.wait()
return proc.returncode == 0
proc = subprocess.Popen(
shell = False,
args = [
LABEL_BIN,
device,
label])
proc.wait()
return proc.returncode == 0
if __name__ == "__main__":
args = sys.argv[1:]
args = sys.argv[1:]
self_bin =sys.argv[0]
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
self_bin =sys.argv[0]
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
try:
if args[0] == "partition":
if len(args) != 2: raise "InvalidArgNum"
result = __partitionDevice(args[1])
elif args[0] == "format":
if len(args) != 3: raise "InvalidArgNum"
result = __formatPartition(args[1], args[2])
elif args[0] == "label":
if len(args) != 3: raise "InvalidArgNum"
result = __labelPartition(args[1], args[2])
else:
sys.stderr.write("%s: invalid action (%s)\n" % (self_bin, args[0]))
sys.exit(1)
if result:
sys.exit(0)
else:
sys.exit(1)
except "InvalidArgNum":
sys.stderr.write("%s: invalid number of arguments (%s)\n" % (self_bin, args))
sys.exit(1)
try:
if args[0] == "partition":
if len(args) != 2: raise "InvalidArgNum"
result = __partitionDevice(args[1])
elif args[0] == "format":
if len(args) != 3: raise "InvalidArgNum"
result = __formatPartition(args[1], args[2])
elif args[0] == "label":
if len(args) != 3: raise "InvalidArgNum"
result = __labelPartition(args[1], args[2])
else:
sys.stderr.write("%s: invalid action (%s)\n" % (self_bin, args[0]))
sys.exit(1)
if result:
sys.exit(0)
else:
sys.exit(1)
except "InvalidArgNum":
sys.stderr.write("%s: invalid number of arguments (%s)\n" % (self_bin, args))
sys.exit(1)

View file

@ -24,9 +24,9 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
url = self.url + "partition?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('VERY careful')
def test_read_form(self):
url = self.url + "partition?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('VERY careful')

View file

@ -26,124 +26,124 @@ import cryptobox.plugins.manage
class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 90
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 90
def do_action(self, store=None, action=None, plugin_name=None, **args):
import re
if plugin_name:
## check for invalid characters
if re.search(r'\W', plugin_name): return "plugin_list"
plugin_manager = cryptobox.plugins.manage.PluginManager(
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
plugin = plugin_manager.get_plugin(plugin_name)
if not plugin: return "plugin_list"
## take only plugins, that are of the same type as the choosen one
self.plugins = [e for e in plugin_manager.get_plugins()
if e.plugin_capabilities == plugin.plugin_capabilities and \
e != "volume_props" ]
if action == "up":
self.__move_up(plugin)
elif action == "down":
self.__move_down(plugin)
return "plugin_list"
elif store:
for key in args.keys():
if key.endswith("_listed"):
if not re.search(r'\W',key):
self.__set_config(key[:-7], args)
else:
self.cbox.log.info("plugin_manager: invalid plugin name (%s)" % \
str(key[:-7]))
try:
self.cbox.prefs.plugin_conf.write()
self.cbox.log.info("Successfully stored plugin configuration")
except IOError, err_msg:
self.cbox.log.warn("Failed to write plugin configuration: %s" % err_msg)
return "plugin_list"
def do_action(self, store=None, action=None, plugin_name=None, **args):
import re
if plugin_name:
## check for invalid characters
if re.search(r'\W', plugin_name): return "plugin_list"
plugin_manager = cryptobox.plugins.manage.PluginManager(
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
plugin = plugin_manager.get_plugin(plugin_name)
if not plugin: return "plugin_list"
## take only plugins, that are of the same type as the choosen one
self.plugins = [e for e in plugin_manager.get_plugins()
if e.plugin_capabilities == plugin.plugin_capabilities and \
e != "volume_props" ]
if action == "up":
self.__move_up(plugin)
elif action == "down":
self.__move_down(plugin)
return "plugin_list"
elif store:
for key in args.keys():
if key.endswith("_listed"):
if not re.search(r'\W',key):
self.__set_config(key[:-7], args)
else:
self.cbox.log.info("plugin_manager: invalid plugin name (%s)" % \
str(key[:-7]))
try:
self.cbox.prefs.plugin_conf.write()
self.cbox.log.info("Successfully stored plugin configuration")
except IOError, err_msg:
self.cbox.log.warn("Failed to write plugin configuration: %s" % err_msg)
return "plugin_list"
def get_status(self):
plugin_manager = cryptobox.plugins.manage.PluginManager(
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
return ":".join([e.get_name() for e in plugin_manager.get_plugins()])
def get_status(self):
plugin_manager = cryptobox.plugins.manage.PluginManager(
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
return ":".join([e.get_name() for e in plugin_manager.get_plugins()])
def __sort_plugins(self):
"""sort all plugins in the list according to their rank"""
def cmp_func(x,y):
x_rank = x.get_rank()
y_rank = y.get_rank()
if x_rank < y_rank:
return -1
elif x_rank == y_rank:
return 0
else:
return 1
self.plugins.sort(cmp = cmp_func)
def __distribute_ranks(self):
"""evenly distribute the 'rank' values according to the current order of
the list"""
dist = 100 / (len(self.plugins) - 1)
for (index, pl) in enumerate(self.plugins):
pl.set_rank(dist*index)
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("failed to write plugin configuration")
def __sort_plugins(self):
"""sort all plugins in the list according to their rank"""
def cmp_func(x,y):
x_rank = x.get_rank()
y_rank = y.get_rank()
if x_rank < y_rank:
return -1
elif x_rank == y_rank:
return 0
else:
return 1
self.plugins.sort(cmp = cmp_func)
def __distribute_ranks(self):
"""evenly distribute the 'rank' values according to the current order of
the list"""
dist = 100 / (len(self.plugins) - 1)
for (index, pl) in enumerate(self.plugins):
pl.set_rank(dist*index)
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("failed to write plugin configuration")
def __move_up(self, plugin):
self.__sort_plugins()
try:
index = self.plugins.index(plugin)
## first elements may not move up
if index == 0:
return
except ValueError:
return
self.plugins.remove(plugin)
self.plugins.insert(index-1, plugin)
self.__distribute_ranks()
def __move_up(self, plugin):
self.__sort_plugins()
try:
index = self.plugins.index(plugin)
## first elements may not move up
if index == 0:
return
except ValueError:
return
self.plugins.remove(plugin)
self.plugins.insert(index-1, plugin)
self.__distribute_ranks()
def __move_down(self, plugin):
self.__sort_plugins()
try:
index = self.plugins.index(plugin)
## last elements may not move down
if index == len(self.plugins) - 1:
return
except ValueError:
return
self.plugins.remove(plugin)
self.plugins.insert(index+1, plugin)
self.__distribute_ranks()
def __move_down(self, plugin):
self.__sort_plugins()
try:
index = self.plugins.index(plugin)
## last elements may not move down
if index == len(self.plugins) - 1:
return
except ValueError:
return
self.plugins.remove(plugin)
self.plugins.insert(index+1, plugin)
self.__distribute_ranks()
def __set_config(self, name, args):
import re
if not self.cbox.prefs.plugin_conf.has_key(name):
self.cbox.prefs.plugin_conf[name] = {}
setting = self.cbox.prefs.plugin_conf[name]
setting["visibility"] = []
## look for "_visible_" values and apply them
pattern = re.compile(r'%s_visible_([\w]+)$' % name)
for key in args.keys():
if key.startswith(name + "_visible_"):
(vis_type, ) = pattern.match(key).groups()
if vis_type:
setting["visibility"].append(vis_type)
## the plugin_manager _must_ always be visible
if (self.get_name() == name) and (not setting["visibility"]):
## reset to default
setting["visibility"] = self.plugin_visibility[:]
if args.has_key("%s_auth" % name):
setting["requestAuth"] = True
else:
setting["requestAuth"] = False
def __set_config(self, name, args):
import re
if not self.cbox.prefs.plugin_conf.has_key(name):
self.cbox.prefs.plugin_conf[name] = {}
setting = self.cbox.prefs.plugin_conf[name]
setting["visibility"] = []
## look for "_visible_" values and apply them
pattern = re.compile(r'%s_visible_([\w]+)$' % name)
for key in args.keys():
if key.startswith(name + "_visible_"):
(vis_type, ) = pattern.match(key).groups()
if vis_type:
setting["visibility"].append(vis_type)
## the plugin_manager _must_ always be visible
if (self.get_name() == name) and (not setting["visibility"]):
## reset to default
setting["visibility"] = self.plugin_visibility[:]
if args.has_key("%s_auth" % name):
setting["requestAuth"] = True
else:
setting["requestAuth"] = False

View file

@ -26,67 +26,67 @@ COMMON_STRING = 'Volume plugins'
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""Check if the 'plugin_manager' works.
"""
url = self.url + "plugin_manager?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find(COMMON_STRING)
def test_read_form(self):
"""Check if the 'plugin_manager' works.
"""
url = self.url + "plugin_manager?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find(COMMON_STRING)
def test_set_options(self):
"""Do some various stuff.
"""
#TODO: these 'tests' are really a bit stupid - someone should fix this
url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + r"?plugin_name=t/-!")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=foobar")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=up")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=down")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&dis/ks_listed")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=x")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_auth=1")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50&disks_auth=1")
self.cmd.find(COMMON_STRING)
def test_move_up(self):
"""Move some plugins up.
"""
#TODO: if we want to be perfect, then we should check the change of the rank
url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + r"?plugin_name=disks&action=up")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=0")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=up")
self.cmd.find(COMMON_STRING)
def test_set_options(self):
"""Do some various stuff.
"""
#TODO: these 'tests' are really a bit stupid - someone should fix this
url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + r"?plugin_name=t/-!")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=foobar")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=up")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=down")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&dis/ks_listed")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=x")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_auth=1")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50&disks_auth=1")
self.cmd.find(COMMON_STRING)
def test_move_up(self):
"""Move some plugins up.
"""
#TODO: if we want to be perfect, then we should check the change of the rank
url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + r"?plugin_name=disks&action=up")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=0")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=up")
self.cmd.find(COMMON_STRING)
def test_move_down(self):
"""Move some plugins down.
"""
## TODO: if we want to be perfect, then we should check the change of the rank
url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + r"?plugin_name=disks&action=down")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=100")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=down")
self.cmd.find(COMMON_STRING)
def test_move_down(self):
"""Move some plugins down.
"""
## TODO: if we want to be perfect, then we should check the change of the rank
url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + r"?plugin_name=disks&action=down")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=100")
self.cmd.find(COMMON_STRING)
self.cmd.go(url + r"?plugin_name=disks&action=down")
self.cmd.find(COMMON_STRING)

View file

@ -30,41 +30,41 @@ import cryptobox.plugins.base
class plugin_template(cryptobox.plugins.base.CryptoBoxPlugin):
"""a template for CryptoBox plugins
"""
"""a template for CryptoBox plugins
"""
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = False
rank = 99
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = False
rank = 99
def do_action(self):
"""The action handler.
"""
self.cbox.log.info("This is a log entry generated by the plugin_template.")
if True:
self.hdf["Data.Success"] = "Plugins.plugin_template.TemplateLaunched"
else:
self.hdf["Data.Warning"] = "Plugins.plugin_template.SomeError"
self.__prepare_form_data()
return "form_plugin_template"
def do_action(self):
"""The action handler.
"""
self.cbox.log.info("This is a log entry generated by the plugin_template.")
if True:
self.hdf["Data.Success"] = "Plugins.plugin_template.TemplateLaunched"
else:
self.hdf["Data.Warning"] = "Plugins.plugin_template.SomeError"
self.__prepare_form_data()
return "form_plugin_template"
def get_status(self):
"""Retrieve the status of the feature.
"""
return
def get_status(self):
"""Retrieve the status of the feature.
"""
return
def get_warnings(self):
warnings = []
## uncomment this to see the environment warning message
#warnings.append((48, "Plugins.%s.MissingFoo" % self.get_name()))
return warnings
def get_warnings(self):
warnings = []
## uncomment this to see the environment warning message
#warnings.append((48, "Plugins.%s.MissingFoo" % self.get_name()))
return warnings
def __prepare_form_data(self):
"""Set some hdf values.
"""
def __prepare_form_data(self):
"""Set some hdf values.
"""

View file

@ -35,36 +35,36 @@ import sys
def call_prog(progy):
proc = subprocess.Popen(
shell = False,
args = progy)
proc.communicate()
return proc.returncode == 0
proc = subprocess.Popen(
shell = False,
args = progy)
proc.communicate()
return proc.returncode == 0
if __name__ == "__main__":
args = sys.argv[1:]
args = sys.argv[1:]
self_bin = sys.argv[0]
if len(args) > 1:
sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args))
sys.exit(1)
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
if args[0] == "reboot":
result = call_prog([SHUTDOWN_BIN, "-t", str(SHUTDOWN_DELAY), "-r", "now"])
elif args[0] == "shutdown":
result = call_prog([SHUTDOWN_BIN, "-t", str(SHUTDOWN_DELAY), "-h", "now"])
else:
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
sys.exit(1)
if result:
sys.exit(0)
else:
sys.exit(1)
self_bin = sys.argv[0]
if len(args) > 1:
sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args))
sys.exit(1)
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
if args[0] == "reboot":
result = call_prog([SHUTDOWN_BIN, "-t", str(SHUTDOWN_DELAY), "-r", "now"])
elif args[0] == "shutdown":
result = call_prog([SHUTDOWN_BIN, "-t", str(SHUTDOWN_DELAY), "-h", "now"])
else:
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
sys.exit(1)
if result:
sys.exit(0)
else:
sys.exit(1)

View file

@ -26,49 +26,49 @@ REDIRECT_DELAY = 120
class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 90
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 90
def do_action(self, type=None):
if not type:
return "form_shutdown"
elif type == "shutdown":
if self.__do_shutdown("shutdown"):
self.hdf["Data.Success"] = "Plugins.shutdown.Shutdown"
return "progress_shutdown"
else:
self.hdf["Data.Warning"] = "Plugins.shutdown.ShutdownFailed"
return "form_shutdown"
elif type == "reboot":
if self.__do_shutdown("reboot"):
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
self.hdf["Data.Redirect.URL"] = "/"
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
return "progress_reboot"
else:
self.hdf["Data.Warning"] = "Plugins.shutdown.RebootFailed"
return "form_shutdown"
else:
return "form_shutdown"
def do_action(self, type=None):
if not type:
return "form_shutdown"
elif type == "shutdown":
if self.__do_shutdown("shutdown"):
self.hdf["Data.Success"] = "Plugins.shutdown.Shutdown"
return "progress_shutdown"
else:
self.hdf["Data.Warning"] = "Plugins.shutdown.ShutdownFailed"
return "form_shutdown"
elif type == "reboot":
if self.__do_shutdown("reboot"):
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
self.hdf["Data.Redirect.URL"] = "/"
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
return "progress_reboot"
else:
self.hdf["Data.Warning"] = "Plugins.shutdown.RebootFailed"
return "form_shutdown"
else:
return "form_shutdown"
def get_status(self):
return "the box is up'n'running"
def get_status(self):
return "the box is up'n'running"
def __do_shutdown(self, action):
import subprocess
import os
proc = subprocess.Popen(
shell = False,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
action])
proc.wait()
return proc.returncode == 0
def __do_shutdown(self, action):
import subprocess
import os
proc = subprocess.Popen(
shell = False,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
os.path.join(self.plugin_dir, "root_action.py"),
action])
proc.wait()
return proc.returncode == 0

View file

@ -24,12 +24,12 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""just read the form - I do not know of a way how to check success"""
url = self.url + "shutdown"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('shutdown')
self.cmd.find('type=reboot')
self.cmd.find('type=shutdown')
def test_read_form(self):
"""just read the form - I do not know of a way how to check success"""
url = self.url + "shutdown"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('shutdown')
self.cmd.find('type=reboot')
self.cmd.find('type=shutdown')

View file

@ -24,17 +24,17 @@ import cryptobox.plugins.base
class system_preferences(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 25
plugin_capabilities = [ "system" ]
plugin_visibility = [ "menu" ]
request_auth = False
rank = 25
def do_action(self):
return "show_plugins"
def do_action(self):
return "show_plugins"
def get_status(self):
plugin_manager = cryptobox.plugins.manage.PluginManager(
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
return ":".join([p.get_name() for p in plugin_manager.get_plugins()])
def get_status(self):
plugin_manager = cryptobox.plugins.manage.PluginManager(
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
return ":".join([p.get_name() for p in plugin_manager.get_plugins()])

View file

@ -24,15 +24,15 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
self.cmd.go(self.url + "system_preferences")
self.cmd.find("Preferences")
def test_read_form(self):
self.cmd.go(self.url + "system_preferences")
self.cmd.find("Preferences")
def test_check_plugins(self):
self.cmd.go(self.url + "system_preferences")
self.cmd.find(r'Data.Status.Plugins.system_preferences=(.*)$', "m")
plugins = self.locals["__match__"].split(":")
self.assertTrue(len(plugins) > 1)
self.assertTrue("disks" in plugins)
def test_check_plugins(self):
self.cmd.go(self.url + "system_preferences")
self.cmd.find(r'Data.Status.Plugins.system_preferences=(.*)$', "m")
plugins = self.locals["__match__"].split(":")
self.assertTrue(len(plugins) > 1)
self.assertTrue("disks" in plugins)

View file

@ -26,171 +26,171 @@ from cryptobox.tests.base import WebInterfaceTestClass
from user_manager import RESERVED_USERS
class unittests(WebInterfaceTestClass):
def test_read_users(self):
"""does the 'admin' user exist?"""
cur_users = self._getUsers()
self.cmd.find("Add new user")
self.assertTrue("admin" in cur_users)
def test_read_users(self):
"""does the 'admin' user exist?"""
cur_users = self._getUsers()
self.cmd.find("Add new user")
self.assertTrue("admin" in cur_users)
def test_test_wrong_credentials(self):
"""check if the user_manager is protected"""
url = self.url + "user_manager"
self.register_auth(url,"foo","bar")
self.cmd.go(url)
self.cmd.notfind("Manage users")
def test_test_wrong_credentials(self):
"""check if the user_manager is protected"""
url = self.url + "user_manager"
self.register_auth(url,"foo","bar")
self.cmd.go(url)
self.cmd.notfind("Manage users")
def test_add_existing_user(self):
"""adding an existing user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self._add_user("admin","foo","foo")
self.cmd.find("The choosen username does already exist")
def test_add_existing_user(self):
"""adding an existing user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self._add_user("admin","foo","foo")
self.cmd.find("The choosen username does already exist")
def test_add_invalid_username(self):
"""adding an invalid username should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self._add_user("foo/bar","foo","foo")
self.cmd.find("Invalid username")
self.assertFalse("foo/bar" in self._getUsers())
def test_add_invalid_username(self):
"""adding an invalid username should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self._add_user("foo/bar","foo","foo")
self.cmd.find("Invalid username")
self.assertFalse("foo/bar" in self._getUsers())
def test_add_without_password(self):
"""adding a user without password should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","","foo")
self.cmd.find("Missing new password")
self.assertFalse("foo" in self._getUsers())
def test_add_without_password(self):
"""adding a user without password should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","","foo")
self.cmd.find("Missing new password")
self.assertFalse("foo" in self._getUsers())
def test_add_with_different_passwords(self):
"""adding a user with different passwords should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","foo")
self.cmd.find("Different passwords")
self.assertFalse("foo" in self._getUsers())
def test_add_with_different_passwords(self):
"""adding a user with different passwords should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","foo")
self.cmd.find("Different passwords")
self.assertFalse("foo" in self._getUsers())
def test_change_pw_for_invalid_user(self):
"""changing a password of a non existing user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("barfoo" in self._getUsers())
self.cmd.go(url + "?store=change_password&user=foobar&new_pw=foo&new_pw2=foo")
self.cmd.notfind("Password changed")
def test_change_pw_for_invalid_user(self):
"""changing a password of a non existing user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("barfoo" in self._getUsers())
self.cmd.go(url + "?store=change_password&user=foobar&new_pw=foo&new_pw2=foo")
self.cmd.notfind("Password changed")
def test_change_pw_without_password(self):
"""changing a password without a new password should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","bar")
self.assertTrue("foo" in self._getUsers())
self._change_password("foo","","foo")
self.cmd.find("Missing new password")
self._del_user("foo")
self.assertFalse("foo" in self._getUsers())
def test_change_pw_without_password(self):
"""changing a password without a new password should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","bar")
self.assertTrue("foo" in self._getUsers())
self._change_password("foo","","foo")
self.cmd.find("Missing new password")
self._del_user("foo")
self.assertFalse("foo" in self._getUsers())
def test_change_pw_wit_different_passwords(self):
"""changing a password while supplying different passwords should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","bar")
self.assertTrue("foo" in self._getUsers())
self._change_password("foo","bar","foo")
self.cmd.find("Different passwords")
self._del_user("foo")
self.assertFalse("foo" in self._getUsers())
def test_change_pw_wit_different_passwords(self):
"""changing a password while supplying different passwords should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","bar")
self.assertTrue("foo" in self._getUsers())
self._change_password("foo","bar","foo")
self.cmd.find("Different passwords")
self._del_user("foo")
self.assertFalse("foo" in self._getUsers())
def _remove_reserved_user(self):
"""removing a reserved user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertTrue("admin" in self._getUsers())
self._del_user("admin")
self.cmd.find("may not remove a reserved user")
self.assertTrue("admin" in self._getUsers())
def _remove_reserved_user(self):
"""removing a reserved user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertTrue("admin" in self._getUsers())
self._del_user("admin")
self.cmd.find("may not remove a reserved user")
self.assertTrue("admin" in self._getUsers())
def _remove_non_existing_user(self):
"""removing a non-existing user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("barfoo" in self._getUsers())
self._del_user("barfoo")
self.cmd.notfind("User removed")
def _remove_non_existing_user(self):
"""removing a non-existing user should fail"""
url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("barfoo" in self._getUsers())
self._del_user("barfoo")
self.cmd.notfind("User removed")
def test_manage_users(self):
"""add a new user, change its password and remove the user afterwards"""
url = self.url + "user_manager"
self.register_auth(url)
## remove the user that should be added - just in case a previous run was unclean
## check its existence before
if "foobar" in self._getUsers(): self._del_user("foobar")
## add a new user
self._add_user("foobar","foo","foo")
self.cmd.find("User added")
users = self._getUsers()
self.assertTrue("foobar" in users)
## change the password of the new user
self.register_auth(url,"foobar","foo")
self._change_password("foobar","bar","bar")
self.cmd.find("Password changed")
## remove the new user
self.register_auth(url,"foobar","bar")
self._del_user("foobar")
self.cmd.find("User removed")
users = self._getUsers()
self.assertFalse("foobar" in users)
def test_manage_users(self):
"""add a new user, change its password and remove the user afterwards"""
url = self.url + "user_manager"
self.register_auth(url)
## remove the user that should be added - just in case a previous run was unclean
## check its existence before
if "foobar" in self._getUsers(): self._del_user("foobar")
## add a new user
self._add_user("foobar","foo","foo")
self.cmd.find("User added")
users = self._getUsers()
self.assertTrue("foobar" in users)
## change the password of the new user
self.register_auth(url,"foobar","foo")
self._change_password("foobar","bar","bar")
self.cmd.find("Password changed")
## remove the new user
self.register_auth(url,"foobar","bar")
self._del_user("foobar")
self.cmd.find("User removed")
users = self._getUsers()
self.assertFalse("foobar" in users)
def test_invalid_input(self):
"""check all combinations of invalid input"""
url = self.url + "user_manager"
self.register_auth(url)
self.cmd.go(url + "?store=foobar")
def test_invalid_input(self):
"""check all combinations of invalid input"""
url = self.url + "user_manager"
self.register_auth(url)
self.cmd.go(url + "?store=foobar")
def _add_user(self, username, pw, pw2):
self.cmd.go(self.url + "user_manager")
self.cmd.formvalue("add_user","user",username)
self.cmd.formvalue("add_user","new_pw",pw)
self.cmd.formvalue("add_user","new_pw2",pw2)
self.cmd.submit()
def _add_user(self, username, pw, pw2):
self.cmd.go(self.url + "user_manager")
self.cmd.formvalue("add_user","user",username)
self.cmd.formvalue("add_user","new_pw",pw)
self.cmd.formvalue("add_user","new_pw2",pw2)
self.cmd.submit()
def _del_user(self, username):
self.cmd.go(self.url + "user_manager")
self.cmd.formvalue("del_user","user",username)
self.cmd.submit()
def _del_user(self, username):
self.cmd.go(self.url + "user_manager")
self.cmd.formvalue("del_user","user",username)
self.cmd.submit()
def _change_password(self, username, pw, pw2):
self.cmd.go(self.url + "user_manager")
self.cmd.formvalue("change_password","user",username)
self.cmd.formvalue("change_password","new_pw",pw)
self.cmd.formvalue("change_password","new_pw2",pw2)
self.cmd.submit()
def _change_password(self, username, pw, pw2):
self.cmd.go(self.url + "user_manager")
self.cmd.formvalue("change_password","user",username)
self.cmd.formvalue("change_password","new_pw",pw)
self.cmd.formvalue("change_password","new_pw2",pw2)
self.cmd.submit()
def _getUsers(self):
url = self.url + "user_manager"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find("Data.Status.Plugins.user_manager=([\w:]+)")
return self.locals["__match__"].split(":")
def _getUsers(self):
url = self.url + "user_manager"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find("Data.Status.Plugins.user_manager=([\w:]+)")
return self.locals["__match__"].split(":")

View file

@ -26,81 +26,81 @@ RESERVED_USERS = [ "admin" ]
class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 45
plugin_capabilities = [ "system" ]
plugin_visibility = [ "preferences" ]
request_auth = True
rank = 45
def do_action(self, store=None, user=None, new_pw=None, new_pw2=None):
import re
admin_dict = self.cbox.prefs.user_db["admins"]
self.__clean_hdf()
if store is None:
pass
elif store == "add_user":
if (user is None) or (re.search(r'\W', user)):
self.hdf["Data.Warning"] = "Plugins.user_manager.InvalidUserName"
elif not new_pw:
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
elif user in admin_dict.keys():
self.hdf["Data.Warning"] = "Plugins.user_manager.UserAlreadyExists"
else:
admin_dict[user] = self.cbox.prefs.user_db.get_digest(new_pw)
self.hdf["Data.Success"] = "Plugins.user_manager.UserAdded"
try:
self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
elif store == "change_password":
if not new_pw:
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
elif user in admin_dict.keys():
admin_dict[user] = self.cbox.prefs.user_db.get_digest(new_pw)
self.hdf["Data.Success"] = "Plugins.user_manager.PasswordChanged"
try:
self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
else:
self.cbox.log.info("user_manager: invalid user choosen (%s)" % str(user))
elif store == "del_user":
if user in RESERVED_USERS:
self.cbox.log.info("user_manager: tried to remove reserved user (%s)" % user)
self.hdf["Data.Warning"] = "NeverRemoveReservedUser"
elif user in admin_dict.keys():
del admin_dict[user]
self.hdf["Data.Success"] = "Plugins.user_manager.UserRemoved"
try:
self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
else:
self.cbox.log.info("user_manager: tried to remove non-existing user (%s)" \
% str(user))
else:
self.cbox.log.info("user_manager: invalid value of 'store' (%s)" % store)
self.__prepare_hdf(admin_dict)
return "user_list"
def do_action(self, store=None, user=None, new_pw=None, new_pw2=None):
import re
admin_dict = self.cbox.prefs.user_db["admins"]
self.__clean_hdf()
if store is None:
pass
elif store == "add_user":
if (user is None) or (re.search(r'\W', user)):
self.hdf["Data.Warning"] = "Plugins.user_manager.InvalidUserName"
elif not new_pw:
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
elif user in admin_dict.keys():
self.hdf["Data.Warning"] = "Plugins.user_manager.UserAlreadyExists"
else:
admin_dict[user] = self.cbox.prefs.user_db.get_digest(new_pw)
self.hdf["Data.Success"] = "Plugins.user_manager.UserAdded"
try:
self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
elif store == "change_password":
if not new_pw:
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
elif user in admin_dict.keys():
admin_dict[user] = self.cbox.prefs.user_db.get_digest(new_pw)
self.hdf["Data.Success"] = "Plugins.user_manager.PasswordChanged"
try:
self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
else:
self.cbox.log.info("user_manager: invalid user choosen (%s)" % str(user))
elif store == "del_user":
if user in RESERVED_USERS:
self.cbox.log.info("user_manager: tried to remove reserved user (%s)" % user)
self.hdf["Data.Warning"] = "NeverRemoveReservedUser"
elif user in admin_dict.keys():
del admin_dict[user]
self.hdf["Data.Success"] = "Plugins.user_manager.UserRemoved"
try:
self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
else:
self.cbox.log.info("user_manager: tried to remove non-existing user (%s)" \
% str(user))
else:
self.cbox.log.info("user_manager: invalid value of 'store' (%s)" % store)
self.__prepare_hdf(admin_dict)
return "user_list"
def get_status(self):
return ":".join(self.cbox.prefs.user_db["admins"].keys())
def get_status(self):
return ":".join(self.cbox.prefs.user_db["admins"].keys())
def __clean_hdf(self):
for key in self.hdf.keys():
del self.hdf[key]
def __clean_hdf(self):
for key in self.hdf.keys():
del self.hdf[key]
def __prepare_hdf(self, dataset):
## sort by name
users = dataset.keys()
users.sort()
## export all users
for name in users:
self.hdf[self.hdf_prefix + "Users." + name] = name
def __prepare_hdf(self, dataset):
## sort by name
users = dataset.keys()
users.sort()
## export all users
for name in users:
self.hdf[self.hdf_prefix + "Users." + name] = name

View file

@ -24,33 +24,33 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""try to read automount form"""
url = self.url + "volume_automount?weblang=en&device=" + self.device_html
self.register_auth(url)
## first: turn it off
self.cmd.go(url + "&action=disable")
self.cmd.go(url)
self.cmd.find('is disabled')
def test_read_form(self):
"""try to read automount form"""
url = self.url + "volume_automount?weblang=en&device=" + self.device_html
self.register_auth(url)
## first: turn it off
self.cmd.go(url + "&action=disable")
self.cmd.go(url)
self.cmd.find('is disabled')
def test_toggle(self):
"""try to toggle automount property"""
url = self.url + "volume_automount"
self.register_auth(url)
self.cmd.go(url + "?device=%s&action=disable" % self.device_html)
self.cmd.find("Automatic activation disabled")
self.cmd.find("is disabled")
self.cmd.go(url + "?device=%s&action=enable" % self.device_html)
self.cmd.find("Automatic activation enabled")
self.cmd.find("is enabled")
def test_toggle(self):
"""try to toggle automount property"""
url = self.url + "volume_automount"
self.register_auth(url)
self.cmd.go(url + "?device=%s&action=disable" % self.device_html)
self.cmd.find("Automatic activation disabled")
self.cmd.find("is disabled")
self.cmd.go(url + "?device=%s&action=enable" % self.device_html)
self.cmd.find("Automatic activation enabled")
self.cmd.find("is enabled")
def test_invalid_input(self):
"""check invalid inputs"""
url = self.url + "volume_automount"
self.register_auth(url)
self.cmd.go(url + "?device=%s&action=foobar" % self.device_html)
self.cmd.notfind("Automatic activation disabled")
self.cmd.notfind("Automatic activation enabled")
def test_invalid_input(self):
"""check invalid inputs"""
url = self.url + "volume_automount"
self.register_auth(url)
self.cmd.go(url + "?device=%s&action=foobar" % self.device_html)
self.cmd.notfind("Automatic activation disabled")
self.cmd.notfind("Automatic activation enabled")

View file

@ -27,94 +27,94 @@ from cryptobox.core.exceptions import *
class volume_automount(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "properties" ]
request_auth = False
rank = 80
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "properties" ]
request_auth = False
rank = 80
true_string = "yes"
false_string = "no"
true_string = "yes"
false_string = "no"
def do_action(self, action=None):
container = self.cbox.get_container(self.device)
if action is None:
pass
elif action == "enable":
self.__set_auto_mount(container, True)
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountEnabled"
self.cbox.log.info("volume_automount: enabled for device '%s'" % self.device)
elif action == "disable":
self.__set_auto_mount(container, False)
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountDisabled"
self.cbox.log.info("volume_automount: disabled for device '%s'" % self.device)
else:
self.cbox.log.info("volume_automount: invalid action (%s)" % str(action))
self.__prepare_hdf()
return "volume_automount"
def do_action(self, action=None):
container = self.cbox.get_container(self.device)
if action is None:
pass
elif action == "enable":
self.__set_auto_mount(container, True)
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountEnabled"
self.cbox.log.info("volume_automount: enabled for device '%s'" % self.device)
elif action == "disable":
self.__set_auto_mount(container, False)
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountDisabled"
self.cbox.log.info("volume_automount: disabled for device '%s'" % self.device)
else:
self.cbox.log.info("volume_automount: invalid action (%s)" % str(action))
self.__prepare_hdf()
return "volume_automount"
def handle_event(self, event, event_info=None):
"""Override bootup behaviour.
Mount all volumes marked as 'automount'.
"""
cryptobox.plugins.base.CryptoBoxPlugin.handle_event(self, event, event_info)
if event == "bootup":
for cont in self.cbox.get_container_list():
if self.__is_auto_mount(cont) and not cont.is_mounted():
cont.mount()
def handle_event(self, event, event_info=None):
"""Override bootup behaviour.
Mount all volumes marked as 'automount'.
"""
cryptobox.plugins.base.CryptoBoxPlugin.handle_event(self, event, event_info)
if event == "bootup":
for cont in self.cbox.get_container_list():
if self.__is_auto_mount(cont) and not cont.is_mounted():
cont.mount()
def is_useful(self, device):
"""Automount does not work for encrypted volumes.
"""
cont = self.cbox.get_container(device)
if not cont:
return False
if cont.get_type() != cryptobox.core.container.CONTAINERTYPES["luks"]:
return True
return False
def is_useful(self, device):
"""Automount does not work for encrypted volumes.
"""
cont = self.cbox.get_container(device)
if not cont:
return False
if cont.get_type() != cryptobox.core.container.CONTAINERTYPES["luks"]:
return True
return False
def get_status(self):
return str(self.__is_auto_mount(self.cbox.get_container(self.device)))
def get_status(self):
return str(self.__is_auto_mount(self.cbox.get_container(self.device)))
def __prepare_hdf(self):
if self.__is_auto_mount(self.cbox.get_container(self.device)):
self.hdf[self.hdf_prefix + "automount_setting"] = "1"
else:
self.hdf[self.hdf_prefix + "automount_setting"] = "0"
def __prepare_hdf(self):
if self.__is_auto_mount(self.cbox.get_container(self.device)):
self.hdf[self.hdf_prefix + "automount_setting"] = "1"
else:
self.hdf[self.hdf_prefix + "automount_setting"] = "0"
def __is_auto_mount(self, container):
if not container:
return False
## only valid for plain volumes
if container.get_type() != cryptobox.core.container.CONTAINERTYPES["plain"]:
return False
if "_automount_names" in self.prefs:
if container.get_name() in self.prefs["_automount_names"]:
return True
else:
return False
else:
return False
def __is_auto_mount(self, container):
if not container:
return False
## only valid for plain volumes
if container.get_type() != cryptobox.core.container.CONTAINERTYPES["plain"]:
return False
if "_automount_names" in self.prefs:
if container.get_name() in self.prefs["_automount_names"]:
return True
else:
return False
else:
return False
def __set_auto_mount(self, container, state):
if state == self.__is_auto_mount(container):
return
name = container.get_name()
if not "_automount_names" in self.prefs:
self.prefs["_automount_names"] = []
if state:
self.prefs["_automount_names"].append(name)
else:
self.prefs["_automount_names"].remove(name)
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Failed to store plugin configuration")
def __set_auto_mount(self, container, state):
if state == self.__is_auto_mount(container):
return
name = container.get_name()
if not "_automount_names" in self.prefs:
self.prefs["_automount_names"] = []
if state:
self.prefs["_automount_names"].append(name)
else:
self.prefs["_automount_names"].remove(name)
try:
self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("Failed to store plugin configuration")

View file

@ -24,10 +24,10 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
url = self.url + "volume_chpasswd?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('hange')
self.cmd.find('password')
def test_read_form(self):
url = self.url + "volume_chpasswd?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('hange')
self.cmd.find('password')

View file

@ -26,66 +26,66 @@ from cryptobox.core.exceptions import *
class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "properties" ]
request_auth = False
rank = 70
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "properties" ]
request_auth = False
rank = 70
def do_action(self, store=None, old_pw=None, new_pw=None, new_pw2=None):
self.container = self.cbox.get_container(self.device)
if not self.container:
return None
elif store == "change_pw":
return self.__change_password(old_pw, new_pw, new_pw2)
elif not store:
return "volume_chpasswd"
else:
self.cbox.log.info("plugin 'volume_chpasswd' - unknown action: %s" % store)
return "volume_chpasswd"
def do_action(self, store=None, old_pw=None, new_pw=None, new_pw2=None):
self.container = self.cbox.get_container(self.device)
if not self.container:
return None
elif store == "change_pw":
return self.__change_password(old_pw, new_pw, new_pw2)
elif not store:
return "volume_chpasswd"
else:
self.cbox.log.info("plugin 'volume_chpasswd' - unknown action: %s" % store)
return "volume_chpasswd"
def get_status(self):
"""chpasswd doesn't give any useful status information, other
than True
"""
return True
def get_status(self):
"""chpasswd doesn't give any useful status information, other
than True
"""
return True
def is_useful(self, device):
from cryptobox.core.container import CONTAINERTYPES as cont_types
cont = self.cbox.get_container(device)
if not cont:
return False
if cont.get_type() == cont_types["luks"]:
return True
return False
def is_useful(self, device):
from cryptobox.core.container import CONTAINERTYPES as cont_types
cont = self.cbox.get_container(device)
if not cont:
return False
if cont.get_type() == cont_types["luks"]:
return True
return False
def __change_password(self, old_pw, new_pw, new_pw2):
if not old_pw:
self.hdf["Data.Warning"] = "EmptyPassword"
elif not new_pw:
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
elif old_pw == new_pw:
## do nothing
pass
else:
try:
self.container.change_password(old_pw, new_pw)
except CBInvalidType, err_msg:
self.cbox.log.info("plugin 'volume_chpasswd' - cannot change " \
+ "passphrase for non-encrypted container (%s): %s" \
% (self.device, err_msg))
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
except CBChangePasswordError, err_msg:
self.cbox.log.warn("plugin 'volume_chpasswd' - cannot change " \
+ "password for device (%s): %s" % (self.device, err_msg))
self.hdf["Data.Warning"] = "Plugins.volume_chpasswd.PasswordChange"
else:
self.hdf["Data.Success"] = "Plugins.volume_chpasswd.PasswordChange"
return "volume_chpasswd"
def __change_password(self, old_pw, new_pw, new_pw2):
if not old_pw:
self.hdf["Data.Warning"] = "EmptyPassword"
elif not new_pw:
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
elif old_pw == new_pw:
## do nothing
pass
else:
try:
self.container.change_password(old_pw, new_pw)
except CBInvalidType, err_msg:
self.cbox.log.info("plugin 'volume_chpasswd' - cannot change " \
+ "passphrase for non-encrypted container (%s): %s" \
% (self.device, err_msg))
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
except CBChangePasswordError, err_msg:
self.cbox.log.warn("plugin 'volume_chpasswd' - cannot change " \
+ "password for device (%s): %s" % (self.device, err_msg))
self.hdf["Data.Warning"] = "Plugins.volume_chpasswd.PasswordChange"
else:
self.hdf["Data.Success"] = "Plugins.volume_chpasswd.PasswordChange"
return "volume_chpasswd"

View file

@ -24,9 +24,9 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
url = self.url + "volume_details?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Technical details')
def test_read_form(self):
url = self.url + "volume_details?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Technical details')

View file

@ -25,17 +25,17 @@ import cryptobox.plugins.base
class volume_details(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = False
rank = 100
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = False
rank = 100
def do_action(self):
## all variables are already set somewhere else
return "volume_details"
def do_action(self):
## all variables are already set somewhere else
return "volume_details"
def get_status(self):
return "no status"
def get_status(self):
return "no status"

View file

@ -26,76 +26,76 @@ import cryptobox.tests.tools as cbox_tools
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""Simply check if the plugin works.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Initializing filesystem')
def test_read_form(self):
"""Simply check if the plugin works.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Initializing filesystem')
def test_invalid_actions(self):
"""Try to issue some invalid orders.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
## make sure, it is not mounted
cbox_tools.umount(self.device)
## try invalid filesystem type
self.cmd.go(url + "&fs_type=foo")
self.cmd.find('Initializing filesystem')
## try invalid container type
self.cmd.go(url + "&container_type=foo")
self.cmd.find('Initializing filesystem')
## missing confirmation
self.cmd.go(url + "&store=step1")
self.cmd.find('Confirmation missing')
## call luks form
self.cmd.go(url + "&store=step1&confirm=1&container_type=luks")
self.cmd.find('name="crypto_password2"')
## try 'step2' with plain container type
self.cmd.go(url + "&store=step2&confirm=1&container_type=plain")
self.cmd.find('Initializing filesystem')
## try invalid 'store'
self.cmd.go(url + "&store=foo")
self.cmd.find('Initializing filesystem')
## try without password
self.cmd.go(url + "&store=step2&container_type=luks&fs_type=windows" \
+ "&crypto_password=&crypto_password2=foo")
self.cmd.find('Missing password')
## try with different passwords
self.cmd.go(url + "&store=step2&container_type=luks&fs_type=windows" \
+ "&crypto_password=bar&crypto_password2=foo")
self.cmd.find('Different passwords')
def test_invalid_actions(self):
"""Try to issue some invalid orders.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
## make sure, it is not mounted
cbox_tools.umount(self.device)
## try invalid filesystem type
self.cmd.go(url + "&fs_type=foo")
self.cmd.find('Initializing filesystem')
## try invalid container type
self.cmd.go(url + "&container_type=foo")
self.cmd.find('Initializing filesystem')
## missing confirmation
self.cmd.go(url + "&store=step1")
self.cmd.find('Confirmation missing')
## call luks form
self.cmd.go(url + "&store=step1&confirm=1&container_type=luks")
self.cmd.find('name="crypto_password2"')
## try 'step2' with plain container type
self.cmd.go(url + "&store=step2&confirm=1&container_type=plain")
self.cmd.find('Initializing filesystem')
## try invalid 'store'
self.cmd.go(url + "&store=foo")
self.cmd.find('Initializing filesystem')
## try without password
self.cmd.go(url + "&store=step2&container_type=luks&fs_type=windows" \
+ "&crypto_password=&crypto_password2=foo")
self.cmd.find('Missing password')
## try with different passwords
self.cmd.go(url + "&store=step2&container_type=luks&fs_type=windows" \
+ "&crypto_password=bar&crypto_password2=foo")
self.cmd.find('Different passwords')
def test_format_open_device(self):
"""Try to format an open device.
"""
url_format = self.url + "volume_format_fs?weblang=en&device=" \
+ self.device_html
self.register_auth(url_format)
url_mount = self.url + "volume_mount?weblang=en&device=" \
+ self.device_html
self.register_auth(url_mount)
## mount device - do not care, if it was mounted before
self.cmd.go(url_mount + "&action=mount_plain")
self.cmd.find('Data.Status.Plugins.volume_mount=active')
## try plain device
self.cmd.go(url_format + "&store=step1&confirm=1&container_type=plain&" \
+ "fs_type=linux")
self.cmd.find('This action is not available while the volume is active.')
## try luks device
self.cmd.go(url_format + "&store=step2&container_type=luks&fs_type=" \
+ "windows&crypto_password=foo&crypto_password2=foo")
self.cmd.find('This action is not available while the volume is active.')
## umount
cbox_tools.umount(self.device)
def test_format_open_device(self):
"""Try to format an open device.
"""
url_format = self.url + "volume_format_fs?weblang=en&device=" \
+ self.device_html
self.register_auth(url_format)
url_mount = self.url + "volume_mount?weblang=en&device=" \
+ self.device_html
self.register_auth(url_mount)
## mount device - do not care, if it was mounted before
self.cmd.go(url_mount + "&action=mount_plain")
self.cmd.find('Data.Status.Plugins.volume_mount=active')
## try plain device
self.cmd.go(url_format + "&store=step1&confirm=1&container_type=plain&" \
+ "fs_type=linux")
self.cmd.find('This action is not available while the volume is active.')
## try luks device
self.cmd.go(url_format + "&store=step2&container_type=luks&fs_type=" \
+ "windows&crypto_password=foo&crypto_password2=foo")
self.cmd.find('This action is not available while the volume is active.')
## umount
cbox_tools.umount(self.device)
def test_format_device(self):
"""Formatting of a device was done in 'volume_mount' plugin tests.
"""
pass
def test_format_device(self):
"""Formatting of a device was done in 'volume_mount' plugin tests.
"""
pass

View file

@ -26,112 +26,112 @@ import cryptobox.core.container as cbx_container
## map filesystem types to the appropriate arguments for 'mkfs'
FSTYPES = {
"windows": "vfat",
"linux": "ext3" }
"windows": "vfat",
"linux": "ext3" }
class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = True
rank = 60
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = True
rank = 60
def do_action(self, store=None, fs_type="windows", container_type="luks",
crypto_password=None, crypto_password2=None, confirm=None):
container = self.cbox.get_container(self.device)
## exit immediately if the device is not writeable
if not container.is_writeable():
self.hdf["Data.Warning"] = "DeviceNotWriteable"
return "empty"
if not fs_type in FSTYPES.keys():
self.cbox.log.info("Invalid filesystem type choosen: %s" % str(fs_type))
return "volume_format"
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
if not container_type in ['plain', 'luks']:
self.cbox.log.info("Invalid container type type choosen: %s" % \
str(container_type))
return "volume_format"
self.hdf[self.hdf_prefix + "container_type"] = container_type
for t in FSTYPES.keys():
self.hdf[self.hdf_prefix + "fs_types." + t] = t
if store == "step1":
if not confirm:
self.cbox.log.info("Missing confirmation for formatting of " + \
"filesystem: %s" % self.device)
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatNotConfirmed"
return "volume_format"
if container_type == "luks":
return "volume_format_luks"
elif container_type == "plain":
return self.__format_plain(FSTYPES[fs_type])
elif store == "step2":
if container_type == "luks":
return self.__format_luks(FSTYPES[fs_type],
crypto_password, crypto_password2)
else:
self.cbox.log.info("Invalid input value for 'container_type': %s" \
% container_type)
return "volume_format"
elif store:
self.cbox.log.info("Invalid input value for 'store': %s" % store)
return "volume_format"
else:
return "volume_format"
def do_action(self, store=None, fs_type="windows", container_type="luks",
crypto_password=None, crypto_password2=None, confirm=None):
container = self.cbox.get_container(self.device)
## exit immediately if the device is not writeable
if not container.is_writeable():
self.hdf["Data.Warning"] = "DeviceNotWriteable"
return "empty"
if not fs_type in FSTYPES.keys():
self.cbox.log.info("Invalid filesystem type choosen: %s" % str(fs_type))
return "volume_format"
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
if not container_type in ['plain', 'luks']:
self.cbox.log.info("Invalid container type type choosen: %s" % \
str(container_type))
return "volume_format"
self.hdf[self.hdf_prefix + "container_type"] = container_type
for t in FSTYPES.keys():
self.hdf[self.hdf_prefix + "fs_types." + t] = t
if store == "step1":
if not confirm:
self.cbox.log.info("Missing confirmation for formatting of " + \
"filesystem: %s" % self.device)
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatNotConfirmed"
return "volume_format"
if container_type == "luks":
return "volume_format_luks"
elif container_type == "plain":
return self.__format_plain(FSTYPES[fs_type])
elif store == "step2":
if container_type == "luks":
return self.__format_luks(FSTYPES[fs_type],
crypto_password, crypto_password2)
else:
self.cbox.log.info("Invalid input value for 'container_type': %s" \
% container_type)
return "volume_format"
elif store:
self.cbox.log.info("Invalid input value for 'store': %s" % store)
return "volume_format"
else:
return "volume_format"
def get_status(self):
return "no status"
def get_status(self):
return "no status"
def __format_plain(self, fs_type):
try:
container = self.cbox.get_container(self.device)
container.create(cbx_container.CONTAINERTYPES["plain"], fs_type=fs_type)
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
self.cbox.log.info("Initialization is not possible as long as the device " \
+ "(%s) is mounted" % self.device)
return "volume_format"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatFailed"
self.cbox.log.error("Initialization of the device (%s) failed: %s" % \
(self.device, err_msg))
return "volume_format"
else:
self.hdf["Data.Success"] = "Plugins.volume_format_fs.FormatSuccess"
self.cbox.log.info("Successfully initialized device '%s'" % self.device)
return { "plugin":"disks", "values":{} }
def __format_plain(self, fs_type):
try:
container = self.cbox.get_container(self.device)
container.create(cbx_container.CONTAINERTYPES["plain"], fs_type=fs_type)
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
self.cbox.log.info("Initialization is not possible as long as the device " \
+ "(%s) is mounted" % self.device)
return "volume_format"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatFailed"
self.cbox.log.error("Initialization of the device (%s) failed: %s" % \
(self.device, err_msg))
return "volume_format"
else:
self.hdf["Data.Success"] = "Plugins.volume_format_fs.FormatSuccess"
self.cbox.log.info("Successfully initialized device '%s'" % self.device)
return { "plugin":"disks", "values":{} }
def __format_luks(self, fs_type, pw, pw2):
if not pw:
self.hdf["Data.Warning"] = "EmptyPassword"
self.cbox.log.info("No crypto password was supplied for initialization " \
+ "of device '%s'" % self.device)
return "volume_format"
if pw != pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
self.cbox.log.info("The crypto password was not repeated correctly for " \
+ "initialization of device '%s'" % self.device)
return "volume_format"
container = self.cbox.get_container(self.device)
try:
container.create(cbx_container.CONTAINERTYPES["luks"],
fs_type=fs_type, password=pw)
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
self.cbox.log.info("Initialization is not possible as long as the device " \
+ "(%s) is mounted" % self.device)
return "volume_format"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatFailed"
self.cbox.log.error("Initialization of the device (%s) failed: %s" % \
(self.device, err_msg))
return "volume_format"
else:
self.hdf["Data.Success"] = "Plugins.volume_format_fs.FormatSuccess"
self.cbox.log.info("Successfully initialized device '%s'" % self.device)
return { "plugin":"disks", "values":{} }
def __format_luks(self, fs_type, pw, pw2):
if not pw:
self.hdf["Data.Warning"] = "EmptyPassword"
self.cbox.log.info("No crypto password was supplied for initialization " \
+ "of device '%s'" % self.device)
return "volume_format"
if pw != pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
self.cbox.log.info("The crypto password was not repeated correctly for " \
+ "initialization of device '%s'" % self.device)
return "volume_format"
container = self.cbox.get_container(self.device)
try:
container.create(cbx_container.CONTAINERTYPES["luks"],
fs_type=fs_type, password=pw)
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
self.cbox.log.info("Initialization is not possible as long as the device " \
+ "(%s) is mounted" % self.device)
return "volume_format"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatFailed"
self.cbox.log.error("Initialization of the device (%s) failed: %s" % \
(self.device, err_msg))
return "volume_format"
else:
self.hdf["Data.Success"] = "Plugins.volume_format_fs.FormatSuccess"
self.cbox.log.info("Successfully initialized device '%s'" % self.device)
return { "plugin":"disks", "values":{} }

View file

@ -26,164 +26,164 @@ import twill
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""Simply check if the plugin works
"""
## umount, if necessary
cbox_tools.umount(self.device)
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Open this volume')
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
def test_read_form(self):
"""Simply check if the plugin works
"""
## umount, if necessary
cbox_tools.umount(self.device)
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Open this volume')
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
def test_mount(self):
"""Do all variations of mount/umount actions.
"""
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.register_auth(url)
## umount, if necessary
cbox_tools.umount(self.device)
## we may not split these tests into two functions, as the order
## is important (we must leave a clean plain volume behind)
self.__do_tests_with_luks()
self.__do_tests_with_plain()
def test_mount(self):
"""Do all variations of mount/umount actions.
"""
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.register_auth(url)
## umount, if necessary
cbox_tools.umount(self.device)
## we may not split these tests into two functions, as the order
## is important (we must leave a clean plain volume behind)
self.__do_tests_with_luks()
self.__do_tests_with_plain()
def __do_tests_with_luks(self):
"""Some tests with a luks partition.
"""
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.__format_luks()
## mount the volume
self.cmd.go(url)
self.cmd.find('Open this volume')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("mount", "pw", "foo")
#self.cmd.submit()
self.cmd.go(url + "&action=mount_luks&pw=foo")
self.cmd.find('Volume opened')
self.cmd.find('Data.Status.Plugins.volume_mount=active')
## try to mount active volume
self.cmd.go(url + "&action=mount_luks&pw=foo")
self.cmd.find('The volume is already open.')
## close the volume
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.submit()
self.cmd.go(url + "&action=umount")
self.cmd.find('Volume closed')
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
## try plain instead of luks
self.cmd.go(url + "&action=mount_plain")
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
self.cmd.find('Unknown format')
## no password supplied
self.cmd.go(url + "&action=mount_luks")
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
self.cmd.find('Missing password')
## wrong password supplied
self.cmd.go(url + "&action=mount_luks&pw=bar")
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
self.cmd.find('Maybe you entered a wrong password?')
def __do_tests_with_luks(self):
"""Some tests with a luks partition.
"""
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.__format_luks()
## mount the volume
self.cmd.go(url)
self.cmd.find('Open this volume')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("mount", "pw", "foo")
#self.cmd.submit()
self.cmd.go(url + "&action=mount_luks&pw=foo")
self.cmd.find('Volume opened')
self.cmd.find('Data.Status.Plugins.volume_mount=active')
## try to mount active volume
self.cmd.go(url + "&action=mount_luks&pw=foo")
self.cmd.find('The volume is already open.')
## close the volume
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.submit()
self.cmd.go(url + "&action=umount")
self.cmd.find('Volume closed')
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
## try plain instead of luks
self.cmd.go(url + "&action=mount_plain")
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
self.cmd.find('Unknown format')
## no password supplied
self.cmd.go(url + "&action=mount_luks")
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
self.cmd.find('Missing password')
## wrong password supplied
self.cmd.go(url + "&action=mount_luks&pw=bar")
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
self.cmd.find('Maybe you entered a wrong password?')
def __do_tests_with_plain(self):
"""Some tests with a plain partition.
"""
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.__format_plain()
## open plain volume
self.cmd.go(url)
self.cmd.find('Open this volume')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.submit()
self.cmd.go(url + "&action=mount_plain")
self.cmd.find('Volume opened')
self.cmd.find('Data.Status.Plugins.volume_mount=active')
## try to mount active volume
self.cmd.go(url + "&action=mount_plain")
self.cmd.find('The volume is already open.')
## umount
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.submit()
self.cmd.go(url + "&action=umount")
self.cmd.find('Volume closed')
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
## try to umount closed volume
self.cmd.go(url + "&action=umount")
self.cmd.find('The volume is already closed.')
def __do_tests_with_plain(self):
"""Some tests with a plain partition.
"""
url = self.url + "volume_mount?weblang=en&device=" + self.device_html
self.__format_plain()
## open plain volume
self.cmd.go(url)
self.cmd.find('Open this volume')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.submit()
self.cmd.go(url + "&action=mount_plain")
self.cmd.find('Volume opened')
self.cmd.find('Data.Status.Plugins.volume_mount=active')
## try to mount active volume
self.cmd.go(url + "&action=mount_plain")
self.cmd.find('The volume is already open.')
## umount
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.submit()
self.cmd.go(url + "&action=umount")
self.cmd.find('Volume closed')
self.cmd.find('Data.Status.Plugins.volume_mount=passive')
## try to umount closed volume
self.cmd.go(url + "&action=umount")
self.cmd.find('The volume is already closed.')
def __format_luks(self):
"""Format a luks partition.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('select name="fs_type"')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("set_type", "fs_type", "linux")
#self.cmd.formvalue("set_type", "container_type", "luks")
#self.cmd.formvalue("set_type", "confirm", "1")
#self.cmd.submit()
self.cmd.go(url + "&fs_type=linux&container_type=luks&confirm=1&store=step1")
self.cmd.find('name="crypto_password"')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("set_luks", "crypto_password", "foo")
#self.cmd.formvalue("set_luks", "crypto_password2", "foo")
#self.cmd.submit()
self.cmd.go(url + "&store=step2&container_type=luks&fs_type=windows&" \
+ "crypto_password=foo&crypto_password2=foo")
self.cmd.find('Formatting is running')
self.__wait_until_ready()
def __format_luks(self):
"""Format a luks partition.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('select name="fs_type"')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("set_type", "fs_type", "linux")
#self.cmd.formvalue("set_type", "container_type", "luks")
#self.cmd.formvalue("set_type", "confirm", "1")
#self.cmd.submit()
self.cmd.go(url + "&fs_type=linux&container_type=luks&confirm=1&store=step1")
self.cmd.find('name="crypto_password"')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("set_luks", "crypto_password", "foo")
#self.cmd.formvalue("set_luks", "crypto_password2", "foo")
#self.cmd.submit()
self.cmd.go(url + "&store=step2&container_type=luks&fs_type=windows&" \
+ "crypto_password=foo&crypto_password2=foo")
self.cmd.find('Formatting is running')
self.__wait_until_ready()
def __format_plain(self):
"""Format a plaintext partition.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('select name="fs_type"')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("set_type", "fs_type", "windows")
#self.cmd.formvalue("set_type", "container_type", "plain")
#self.cmd.formvalue("set_type", "confirm", "1")
#self.cmd.submit()
self.cmd.go(url + "&store=step1&confirm=1&container_type=plain&fs_type=windows")
self.cmd.find('Formatting is running')
self.__wait_until_ready()
def __format_plain(self):
"""Format a plaintext partition.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('select name="fs_type"')
# the following _should_ work, but it does not - probably a parsing problem
# of twill - for now we use the direct link instead
#self.cmd.formvalue("set_type", "fs_type", "windows")
#self.cmd.formvalue("set_type", "container_type", "plain")
#self.cmd.formvalue("set_type", "confirm", "1")
#self.cmd.submit()
self.cmd.go(url + "&store=step1&confirm=1&container_type=plain&fs_type=windows")
self.cmd.find('Formatting is running')
self.__wait_until_ready()
def __wait_until_ready(self):
"""Wait until the device is ready again.
"""
import time
finish_time = time.time() + 120
while self.__is_device_busy():
if (time.time() > finish_time):
self.fail("timeout for plain formatting expired")
time.sleep(5)
def __is_device_busy(self):
"""Check if the device is busy.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
try:
self.cmd.find("Disk is busy")
return True
except twill.errors.TwillAssertionError:
return False
def __wait_until_ready(self):
"""Wait until the device is ready again.
"""
import time
finish_time = time.time() + 120
while self.__is_device_busy():
if (time.time() > finish_time):
self.fail("timeout for plain formatting expired")
time.sleep(5)
def __is_device_busy(self):
"""Check if the device is busy.
"""
url = self.url + "volume_format_fs?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
try:
self.cmd.find("Disk is busy")
return True
except twill.errors.TwillAssertionError:
return False

View file

@ -27,109 +27,109 @@ import cryptobox.core.container as cbxContainer
class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = False
rank = 0
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = False
rank = 0
def do_action(self, action=None, pw=None):
self.hdf[self.hdf_prefix + "PluginDir"] = self.plugin_dir
self.container = self.cbox.get_container(self.device)
if action == "mount_plain":
return self.__do_mount_plain()
elif action == "mount_luks":
return self.__do_mount_luks(pw)
elif action == "umount":
return self.__do_umount()
elif not action:
return "volume_status"
else:
self.cbox.log.info("plugin 'volume_mount' - unknown action: %s" % action)
return "volume_status"
def do_action(self, action=None, pw=None):
self.hdf[self.hdf_prefix + "PluginDir"] = self.plugin_dir
self.container = self.cbox.get_container(self.device)
if action == "mount_plain":
return self.__do_mount_plain()
elif action == "mount_luks":
return self.__do_mount_luks(pw)
elif action == "umount":
return self.__do_umount()
elif not action:
return "volume_status"
else:
self.cbox.log.info("plugin 'volume_mount' - unknown action: %s" % action)
return "volume_status"
def get_status(self):
container = self.cbox.get_container(self.device)
if not self.container:
return "invalid device"
if container.is_mounted():
return "active"
else:
return "passive"
def get_status(self):
container = self.cbox.get_container(self.device)
if not self.container:
return "invalid device"
if container.is_mounted():
return "active"
else:
return "passive"
def __do_mount_plain(self):
if self.container.is_mounted():
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
self.cbox.log.info("the device (%s) is already mounted" % self.device)
return "volume_status"
if self.container.get_type() != cbxContainer.CONTAINERTYPES["plain"]:
## not a plain container
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
self.hdf["Data.Warning"] = "Plugins.volume_mount.InvalidContainerType"
return "volume_status"
try:
self.container.mount()
except CBMountError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
return "volume_status"
def __do_mount_plain(self):
if self.container.is_mounted():
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
self.cbox.log.info("the device (%s) is already mounted" % self.device)
return "volume_status"
if self.container.get_type() != cbxContainer.CONTAINERTYPES["plain"]:
## not a plain container
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
self.hdf["Data.Warning"] = "Plugins.volume_mount.InvalidContainerType"
return "volume_status"
try:
self.container.mount()
except CBMountError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
return "volume_status"
def __do_mount_luks(self, pw):
if self.container.get_type() != cbxContainer.CONTAINERTYPES["luks"]:
## not a luks container - fail silently
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
return "volume_status"
if self.container.is_mounted():
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
self.cbox.log.info("the device (%s) is already mounted" % self.device)
return "volume_status"
if not pw:
self.hdf["Data.Warning"] = "EmptyPassword"
self.cbox.log.info("no password was supplied for mounting of device: '%s'" \
% self.device)
return "volume_status"
try:
self.container.mount(pw)
except CBMountError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
return "volume_status"
def __do_mount_luks(self, pw):
if self.container.get_type() != cbxContainer.CONTAINERTYPES["luks"]:
## not a luks container - fail silently
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
return "volume_status"
if self.container.is_mounted():
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
self.cbox.log.info("the device (%s) is already mounted" % self.device)
return "volume_status"
if not pw:
self.hdf["Data.Warning"] = "EmptyPassword"
self.cbox.log.info("no password was supplied for mounting of device: '%s'" \
% self.device)
return "volume_status"
try:
self.container.mount(pw)
except CBMountError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
except CBContainerError, err_msg:
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
self.cbox.log.warn("failed to mount the device (%s): %s" \
% (self.device, err_msg))
return "volume_status"
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
return "volume_status"
def __do_umount(self):
if not self.container.is_mounted():
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsNotMounted"
self.cbox.log.info("the device (%s) is currently not mounted" % self.device)
return "volume_status"
try:
self.container.umount()
except CBUmountError, err_msg:
self.hdf["Data.Warning"] = "UmountFailed"
self.cbox.log.warn("could not umount the volume (%s): %s" \
% (self.device, err_msg))
return "volume_status"
self.cbox.log.info("successfully unmounted the container: %s" % self.device)
self.hdf["Data.Success"] = "Plugins.volume_mount.UmountDone"
return "volume_status"
def __do_umount(self):
if not self.container.is_mounted():
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsNotMounted"
self.cbox.log.info("the device (%s) is currently not mounted" % self.device)
return "volume_status"
try:
self.container.umount()
except CBUmountError, err_msg:
self.hdf["Data.Warning"] = "UmountFailed"
self.cbox.log.warn("could not umount the volume (%s): %s" \
% (self.device, err_msg))
return "volume_status"
self.cbox.log.info("successfully unmounted the container: %s" % self.device)
self.hdf["Data.Success"] = "Plugins.volume_mount.UmountDone"
return "volume_status"

View file

@ -24,9 +24,9 @@ from cryptobox.tests.base import WebInterfaceTestClass
class unittests(WebInterfaceTestClass):
def test_read_form(self):
url = self.url + "volume_props?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Properties')
def test_read_form(self):
url = self.url + "volume_props?weblang=en&device=" + self.device_html
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Properties')

View file

@ -27,64 +27,64 @@ from cryptobox.core.exceptions import *
class volume_props(cryptobox.plugins.base.CryptoBoxPlugin):
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = False
rank = 30
plugin_capabilities = [ "volume" ]
plugin_visibility = [ "volume" ]
request_auth = False
rank = 30
def do_action(self, **args):
import os
## include all plugins marked as "properties"
## skip ourselves to prevent recursion
self.props_plugins = [e for e in cryptobox.plugins.manage.PluginManager(self.cbox,
self.cbox.prefs["Locations"]["PluginDir"]).get_plugins()
if ("properties") in (e.get_visibility()) \
and (e.get_name() != self.get_name())]
## sort plugins by rank
self.props_plugins.sort(cmp = self.__cmp_plugins_rank)
## set the name of the templates for every plugin
load_string = ""
for p in self.props_plugins:
## skip all volume plugins that are not suitable
## (e.g. chpasswd for plain containers)
if not p.is_useful(self.device):
continue
p.device = self.device
plfname = os.path.join(p.plugin_dir, str(p.do_action(**args)) + ".cs")
load_string += "<?cs include:'%s' ?>" % plfname
## this is a little bit ugly: as it is not possible, to load cs files via
## 'linclude' (see clearsilver doc) if they use previously defined macros
## (see clearsilver mailing list thread
## 'linclude file which calls a macro' - 27th December 02005)
## our workaround: define the appropriate "include" (not 'linclude')
## command as a hdf variable - then we can include it via 'evar'
self.hdf[self.hdf_prefix + 'includePlugins'] = load_string
return "volume_properties"
def do_action(self, **args):
import os
## include all plugins marked as "properties"
## skip ourselves to prevent recursion
self.props_plugins = [e for e in cryptobox.plugins.manage.PluginManager(self.cbox,
self.cbox.prefs["Locations"]["PluginDir"]).get_plugins()
if ("properties") in (e.get_visibility()) \
and (e.get_name() != self.get_name())]
## sort plugins by rank
self.props_plugins.sort(cmp = self.__cmp_plugins_rank)
## set the name of the templates for every plugin
load_string = ""
for p in self.props_plugins:
## skip all volume plugins that are not suitable
## (e.g. chpasswd for plain containers)
if not p.is_useful(self.device):
continue
p.device = self.device
plfname = os.path.join(p.plugin_dir, str(p.do_action(**args)) + ".cs")
load_string += "<?cs include:'%s' ?>" % plfname
## this is a little bit ugly: as it is not possible, to load cs files via
## 'linclude' (see clearsilver doc) if they use previously defined macros
## (see clearsilver mailing list thread
## 'linclude file which calls a macro' - 27th December 02005)
## our workaround: define the appropriate "include" (not 'linclude')
## command as a hdf variable - then we can include it via 'evar'
self.hdf[self.hdf_prefix + 'includePlugins'] = load_string
return "volume_properties"
def get_status(self):
return ":".join([ e.get_name() for e in self.props_plugins ])
def get_status(self):
return ":".join([ e.get_name() for e in self.props_plugins ])
def load_dataset(self, hdf):
"""Override the parent's function
def load_dataset(self, hdf):
"""Override the parent's function
we have to get the data from all included plugins
"""
for plugin in self.props_plugins:
## retrieve the results of an included plugin
plugin.load_dataset(hdf)
## call our parent's method
cryptobox.plugins.base.CryptoBoxPlugin.load_dataset(self, hdf)
we have to get the data from all included plugins
"""
for plugin in self.props_plugins:
## retrieve the results of an included plugin
plugin.load_dataset(hdf)
## call our parent's method
cryptobox.plugins.base.CryptoBoxPlugin.load_dataset(self, hdf)
def __cmp_plugins_rank(self, p1, p2):
order = p1.get_rank() - p2.get_rank()
if order < 0:
return -1
elif order == 0:
return 0
else:
return 1
def __cmp_plugins_rank(self, p1, p2):
order = p1.get_rank() - p2.get_rank()
if order < 0:
return -1
elif order == 0:
return 0
else:
return 1

View file

@ -25,137 +25,137 @@ import cryptobox.tests.tools as cbox_tools
class unittests(WebInterfaceTestClass):
def test_read_form(self):
"""Check if the 'volume_rename' plugin works.
"""
url = self.url + "volume_rename?weblang=en&device=" + self.device_html
self.register_auth(url)
## umount, if necessary
cbox_tools.umount(self.device)
## check a language string
self.cmd.go(url)
self.cmd.find('Change name')
def test_read_form(self):
"""Check if the 'volume_rename' plugin works.
"""
url = self.url + "volume_rename?weblang=en&device=" + self.device_html
self.register_auth(url)
## umount, if necessary
cbox_tools.umount(self.device)
## check a language string
self.cmd.go(url)
self.cmd.find('Change name')
def test_rename(self):
"""Try to rename the volume.
"""
## umount, if necessary
cbox_tools.umount(self.device)
save_name = self.__get_name()
## rename if the name is already "foo"
if save_name == "foo":
self.__set_name("bar")
## set 'foo'
self.__set_name("foo")
self.cmd.find('The name of this volume was changed successfully.')
self.assertEquals("foo", self.__get_name())
## set 'bar'
self.__set_name("bar")
self.cmd.find('The name of this volume was changed successfully.')
self.assertEquals("bar", self.__get_name())
## set the same name twice to catch all lines of code
self.__set_name("bar")
self.cmd.notfind('The name of this volume was changed successfully.')
self.assertEquals("bar", self.__get_name())
self.__set_name(save_name)
self.assertEquals(save_name, self.__get_name())
def test_rename(self):
"""Try to rename the volume.
"""
## umount, if necessary
cbox_tools.umount(self.device)
save_name = self.__get_name()
## rename if the name is already "foo"
if save_name == "foo":
self.__set_name("bar")
## set 'foo'
self.__set_name("foo")
self.cmd.find('The name of this volume was changed successfully.')
self.assertEquals("foo", self.__get_name())
## set 'bar'
self.__set_name("bar")
self.cmd.find('The name of this volume was changed successfully.')
self.assertEquals("bar", self.__get_name())
## set the same name twice to catch all lines of code
self.__set_name("bar")
self.cmd.notfind('The name of this volume was changed successfully.')
self.assertEquals("bar", self.__get_name())
self.__set_name(save_name)
self.assertEquals(save_name, self.__get_name())
def test_invalid_names(self):
"""Setting of invalid names should fail.
"""
## umount, if necessary
cbox_tools.umount(self.device)
save_name = self.__get_name()
## we want to avoid, that if the previous name is (by accident) 'foo'
## then the later search for "changed successfully" would fail
if save_name == "foo":
self.__set_name("bar")
self.__set_name("foo")
self.cmd.find('The name of this volume was changed successfully.')
self.assertEquals("foo", self.__get_name())
self.__set_name("foo:")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo/")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo/")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo*")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo(")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("")
self.cmd.notfind("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name(save_name)
self.assertEquals(save_name, self.__get_name())
def test_invalid_names(self):
"""Setting of invalid names should fail.
"""
## umount, if necessary
cbox_tools.umount(self.device)
save_name = self.__get_name()
## we want to avoid, that if the previous name is (by accident) 'foo'
## then the later search for "changed successfully" would fail
if save_name == "foo":
self.__set_name("bar")
self.__set_name("foo")
self.cmd.find('The name of this volume was changed successfully.')
self.assertEquals("foo", self.__get_name())
self.__set_name("foo:")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo/")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo/")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo*")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("foo(")
self.cmd.find("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name("")
self.cmd.notfind("Changing of volume's name failed")
self.assertEquals("foo", self.__get_name())
self.__set_name(save_name)