change identation from tabs to spaces
This commit is contained in:
parent
c8e28f5241
commit
3224d59dfe
62 changed files with 6614 additions and 6614 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()])
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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(":"))
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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">')
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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()])
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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(":")
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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":{} }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||