diff --git a/bin/CryptoBoxRootActions b/bin/CryptoBoxRootActions
index 08683a8..e668f3b 100755
--- a/bin/CryptoBoxRootActions
+++ b/bin/CryptoBoxRootActions
@@ -31,6 +31,8 @@ Syntax:
this script will always return with an exitcode 0 (true), if "check" is the only argument
"""
+__revision__ = "$Id"
+
import os
import sys
import subprocess
diff --git a/bin/CryptoBoxWebserver b/bin/CryptoBoxWebserver
index 5160253..e01559e 100755
--- a/bin/CryptoBoxWebserver
+++ b/bin/CryptoBoxWebserver
@@ -24,16 +24,42 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
import os, sys
import cryptobox.web.sites
from cryptobox.core.exceptions import *
from optparse import OptionParser
+## check python version
+(ver_major, ver_minor, ver_sub, ver_desc, ver_subsub) = sys.version_info
+if (ver_major < 2) or ((ver_major == 2) and (ver_minor < 4)):
+ sys.stderr.write("You need a python version >= 2.4\n")
+ sys.stderr.write("Current version is: %s\n" % sys.version)
+ sys.exit(1)
+
+## check cherrypy dependency
try:
import cherrypy
except:
- print "Could not import the cherrypy module! Try 'apt-get install python-cherrypy'."
+ sys.stderr.write("Could not import the cherrypy module!\n")
+ sys.stderr.write("Try 'apt-get install python-cherrypy'.\n")
+ sys.exit(1)
+
+## check clearsilver dependency
+try:
+ import neo_cgi, neo_util
+except:
+ sys.stderr.write("Could not import the clearsilver module!\n")
+ sys.stderr.write("Try 'apt-get install python-clearsilver'.\n")
+ sys.exit(1)
+
+## check configobj dependency
+try:
+ import configobj, validate
+except:
+ sys.stderr.write("Could not import the configobj or validate module!\n")
+ sys.stderr.write("Try 'apt-get install python-configobj'.\n")
sys.exit(1)
@@ -129,17 +155,22 @@ def close_open_files():
def write_pid_file(pid_file):
+ if os.path.exists(pid_file):
+ sys.stderr.write(
+ "Warning: pid file (%s) already exists - overwriting ...\n" % pid_file)
try:
pidf = open(pid_file,"w")
pidf.write(str(os.getpid()))
pidf.close()
except (IOError, OSError), errMsg:
- sys.stderr.write("Warning: failed to write pid file (%s): %s\n" % (pid_file, errMsg))
+ sys.stderr.write(
+ "Warning: failed to write pid file (%s): %s\n" % (pid_file, errMsg))
## it is just a warning - no need to break
def parseOptions():
- version = "%prog" + cryptobox.core.main.VERSION
+ import cryptobox
+ version = "%prog" + cryptobox.__version__
parser = OptionParser(version=version)
parser.set_defaults(conffile="/etc/cryptobox-server/cryptobox.conf",
pidfile="/var/run/cryptobox-server/webserver.pid",
diff --git a/bin/do_pylint.sh b/bin/do_pylint.sh
new file mode 100755
index 0000000..b53f984
--- /dev/null
+++ b/bin/do_pylint.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# set some environmental variables for pylint
+#
+
+PROJ_DIR=$(dirname "$0")/..
+PROJ_DIR=$(cd "$PROJ_DIR"; pwd)
+
+PYLINTRC=$PROJ_DIR/src/pylintrc
+PYTHONPATH=$PROJ_DIR/src
+
+function check_for_filename()
+{
+ # maybe the argument is a file instead of a module name
+ if echo "$1" | grep -q "\.py$" && test -e "$1"
+ then local FILE_DIR=$(dirname "$1")
+ local MODULE=$(basename "${1%.py}")
+ ARGS="${ARGS} ${MODULE}"
+ PYTHONPATH="${PYTHONPATH}:${FILE_DIR}"
+ else ARGS="${ARGS} ${1}"
+ fi
+}
+
+while test $# -gt 0
+ do check_for_filename "$1"
+ shift
+ done
+
+export PYTHONPATH
+export PYLINTRC
+
+pylint $ARGS
+
diff --git a/debian/cryptobox-server.init b/debian/cryptobox-server.init
index 2b2aead..ddd10bf 100644
--- a/debian/cryptobox-server.init
+++ b/debian/cryptobox-server.init
@@ -16,7 +16,6 @@
# Short-Description: start CryptoBox webserver
### END INIT INFO
-
# read the default setting file, if it exists
[ -r /etc/default/cryptobox-server ] && source /etc/default/cryptobox-server
@@ -33,6 +32,7 @@ CONF_FILE=/etc/cryptobox-server/cryptobox.conf
[ "$NO_START" = "1" ] && exit 0
DAEMON=/usr/sbin/CryptoBoxWebserver
+PYTHON_EXEC=/usr/bin/python
PIDFILE=/var/run/cryptobox-server/webserver.pid
DESC="CryptoBox Daemon (webinterface)"
OPTIONS="-B --pidfile=$PIDFILE --config=$CONF_FILE --logfile=$LOGFILE --host=$HOST --port=$PORT $SERVER_OPTS"
@@ -45,11 +45,7 @@ test -e "$DAEMON" || exit 0
case "$1" in
start )
- # TODO: mount config dir
- # TODO: create certificate
- # TODO: run stunnel
- # the lines above should go into the live-cd scripts
- ## create the directory of the pid file if necessary
+ # create the directory of the pid file if necessary
PIDDIR=$(dirname "$PIDFILE")
if [ -d "$PIDDIR" ]
then mkdir -p "$PIDDIR"
@@ -60,14 +56,21 @@ case "$1" in
if start-stop-daemon \
--chuid $RUNAS: --quiet --start \
--user $RUNAS --pidfile "$PIDFILE" \
- --exec /usr/bin/python --startas "$DAEMON" -- $OPTIONS
+ --startas "$PYTHON_EXEC" -- "$DAEMON" $OPTIONS
then log_end_msg 0
else log_end_msg 1
fi
;;
stop )
log_daemon_msg "Stopping cryptobox webserver" "$DESC"
- if start-stop-daemon --quiet --stop \
+ # if there is no pid file for some reason, then we try to find the process
+ if test ! -e "$PIDFILE"
+ then if start-stop-daemon --quiet --stop --user "$RUNAS" --exec "$PYTHON_EXEC"
+ then log_end_msg 0
+ else log_end_msg 1
+ fi
+ # there is a pid file - great!
+ elif start-stop-daemon --quiet --stop \
--pidfile "$PIDFILE" \
--user "$RUNAS"
then test -e "$PIDFILE" && rm "$PIDFILE"
diff --git a/plugins/date/date.py b/plugins/date/date.py
index 17d895a..6206551 100644
--- a/plugins/date/date.py
+++ b/plugins/date/date.py
@@ -18,29 +18,39 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Change date and time.
+"""
+
+__revision__ = "$Id"
+
import cryptobox.plugins.base
class date(cryptobox.plugins.base.CryptoBoxPlugin):
+ """The date feature of the CryptoBox.
+ """
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences" ]
+ request_auth = False
rank = 10
- def doAction(self, store=None, year=0, month=0, day=0, hour=0, minute=0):
+ 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)
- new_date = datetime.datetime(year, month, day, hour, minute)
+ ## check if the values are valid
+ datetime.datetime(year, month, day, hour, minute)
except ValueError:
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
- self.__prepareFormData()
+ self.__prepare_form_data()
return "form_date"
date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
- if self.__setDate(date):
+ if self.__set_date(date):
self.cbox.log.info("changed date to: %s" % date)
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
return None
@@ -48,33 +58,42 @@ class date(cryptobox.plugins.base.CryptoBoxPlugin):
## a failure should usually be an invalid date (we do not check it really)
self.cbox.log.info("failed to set date: %s" % date)
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
- self.__prepareFormData()
+ self.__prepare_form_data()
return "form_date"
else:
- self.__prepareFormData()
+ self.__prepare_form_data()
return "form_date"
- def getStatus(self):
- now = self.__getCurrentDate()
- 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 __prepareFormData(self):
- date = self.__getCurrentDate()
- self.hdf[self.hdf_prefix + "year"] = date.year
- self.hdf[self.hdf_prefix + "month"] = date.month
- self.hdf[self.hdf_prefix + "day"] = date.day
- self.hdf[self.hdf_prefix + "hour"] = date.hour
- self.hdf[self.hdf_prefix + "minute"] = 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 __getCurrentDate(self):
+ def __get_current_date(self):
+ """Retrieve the current date and time.
+ """
import datetime
- return datetime.datetime(2000,1,1).now()
+ return datetime.datetime(2000, 1, 1).now()
- def __setDate(self, date):
+ def __set_date(self, date):
+ """Set a new date and time.
+ """
import subprocess
import os
proc = subprocess.Popen(
@@ -83,7 +102,7 @@ class date(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
- os.path.join(self.pluginDir, "root_action.py"),
+ os.path.join(self.plugin_dir, "root_action.py"),
date])
proc.wait()
return proc.returncode == 0
diff --git a/plugins/date/root_action.py b/plugins/date/root_action.py
index d83d27f..a0c2846 100755
--- a/plugins/date/root_action.py
+++ b/plugins/date/root_action.py
@@ -19,6 +19,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
PLUGIN_TYPE = "cryptobox"
diff --git a/plugins/date/unittests.py b/plugins/date/unittests.py
index ac9ea57..a09fa1a 100644
--- a/plugins/date/unittests.py
+++ b/plugins/date/unittests.py
@@ -18,18 +18,20 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_get_date(self):
"""retrieve the current date"""
- date = self._getCurrentDate()
+ date = self._get_current_date()
def test_change_date(self):
"""set the date back and forth"""
- now = self._getCurrentDate()
+ now = self._get_current_date()
## copy current time
new_date = dict(now)
## move three minutes forward (more is not nice because of screensavers)
@@ -38,10 +40,10 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
new_date["hour"] = now["hour"] + ((now["minute"] + 3) / 60)
## move forward ...
self._setDate(new_date)
- self.assertEquals(new_date, self._getCurrentDate())
+ self.assertEquals(new_date, self._get_current_date())
## ... and backward
self._setDate(now)
- self.assertEquals(now, self._getCurrentDate())
+ self.assertEquals(now, self._get_current_date())
def test_try_broken_date(self):
@@ -54,8 +56,8 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
self.cmd.find("invalid value for date")
- def _getCurrentDate(self):
- date_url = self.URL + "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")
@@ -73,7 +75,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
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"\
+ 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)
@@ -83,7 +85,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
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"
+ date_url = self.url + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.formvalue("set_date", "year", str(date["year"]))
diff --git a/plugins/disks/disks.py b/plugins/disks/disks.py
index a9f5c92..f7e4b06 100644
--- a/plugins/disks/disks.py
+++ b/plugins/disks/disks.py
@@ -18,21 +18,31 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""The disks feature of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import cryptobox.plugins.base
class disks(cryptobox.plugins.base.CryptoBoxPlugin):
+ """The disk feature of the CryptoBox.
+ """
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "menu" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "menu" ]
+ request_auth = False
rank = 10
- def doAction(self):
- self.cbox.reReadContainerList()
+ def do_action(self):
+ """The action handler.
+ """
+ self.cbox.reread_container_list()
return "disks"
- def getStatus(self):
- return ":".join([e.getDevice() for e in self.cbox.getContainerList()])
-
+ def get_status(self):
+ """Retrieve the current status of the feature.
+ """
+ return ":".join([e.get_device() for e in self.cbox.get_container_list()])
diff --git a/plugins/disks/unittests.py b/plugins/disks/unittests.py
index 56316a1..d8aa0d9 100644
--- a/plugins/disks/unittests.py
+++ b/plugins/disks/unittests.py
@@ -18,24 +18,26 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
'''display all devices'''
- self.register_auth(self.URL)
- self.cmd.go(self.URL + "disks?weblang=en")
+ 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.register_auth(self.url)
+ self.cmd.go(self.url + "disks?weblang=en")
self.cmd.find("Available disks")
self.cmd.find(u'Data.Status.Plugins.disks=(.*)$', "m")
devices = self.locals["__match__"].split(":")
self.assertTrue(len(devices)>0)
- self.assertTrue(("/dev/%s1" % self.device in devices) or ("/dev/%s2" % self.device in devices))
+ self.assertTrue("/dev/%s" % self.device in devices)
diff --git a/plugins/help/help.py b/plugins/help/help.py
index 19e1e68..6b4ce9b 100644
--- a/plugins/help/help.py
+++ b/plugins/help/help.py
@@ -18,26 +18,34 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""The help feature of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import cryptobox.plugins.base
class help(cryptobox.plugins.base.CryptoBoxPlugin):
+ """The help feature of the CryptoBox.
+ """
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "menu" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "menu" ]
+ request_auth = False
rank = 80
default_lang = 'en'
default_page = "CryptoBoxUser"
- def doAction(self, page=""):
+ def do_action(self, page=""):
'''prints the offline wikipage
'''
- import re,os
+ import re, os
## check for invalid characters and if the page exists in the default language
if page and \
not re.search(u'\W', page) and \
- os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"], self.default_lang, page + '.html')):
+ os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
+ self.default_lang, page + '.html')):
## everything is ok
pass
else:
@@ -49,20 +57,23 @@ class help(cryptobox.plugins.base.CryptoBoxPlugin):
## store the name of the page
self.hdf[self.hdf_prefix + "Page"] = page
## choose the right language
- for l in self.site.langOrder:
- if os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"], l, page + '.html')):
- lang = l
+ 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:
- lang = self.default_lang
- self.hdf[self.hdf_prefix + "Language"] = lang
+ 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 = lang
+ self.current_lang = doc_lang
self.current_page = page
return "doc"
- def getStatus(self):
+ def get_status(self):
+ """Retrieve the current status of the feature.
+ """
return "%s:%s" % (self.current_lang, self.current_page)
diff --git a/plugins/help/unittests.py b/plugins/help/unittests.py
index 94fa4cc..0d9b46c 100644
--- a/plugins/help/unittests.py
+++ b/plugins/help/unittests.py
@@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
from twill.errors import *
@@ -27,7 +29,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
'''help pages should be available in different languages'''
## check english help pages
- self.cmd.go(self.URL + "help?weblang=en")
+ self.cmd.go(self.url + "help?weblang=en")
self.cmd.find("Table of Contents")
self.cmd.find("Getting started")
(lang,page) = self._getHelpStatus()
@@ -35,7 +37,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
self.assertTrue(page == "CryptoBoxUser")
## check german help pages
- self.cmd.go(self.URL + "help?weblang=de")
+ 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()
@@ -43,7 +45,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
self.assertTrue(page == "CryptoBoxUser")
## check slovene help pages
- self.cmd.go(self.URL + "help?weblang=sl")
+ 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()
@@ -52,7 +54,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
self.assertTrue(page == "CryptoBoxUser")
## check french help pages
- self.cmd.go(self.URL + "help?weblang=fr")
+ 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()
@@ -61,7 +63,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
self.assertTrue(page == "CryptoBoxUser")
## test a random language - it should fall back to english
- self.cmd.go(self.URL + "help?weblang=foobar")
+ 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")
@@ -70,18 +72,18 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_help_pages(self):
"""check invalid page requests"""
- self.cmd.go(self.URL + "help?page=foobar")
+ self.cmd.go(self.url + "help?page=foobar")
(lang,page) = self._getHelpStatus()
self.assertTrue(page == "CryptoBoxUser")
- self.cmd.go(self.URL + "help?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")
+ self.cmd.go(self.url + "help?weblang=foobar")
(lang,page) = self._getHelpStatus()
self.assertTrue(lang == "en")
diff --git a/plugins/language_selection/language_selection.py b/plugins/language_selection/language_selection.py
index 9d2bfcd..6436bba 100644
--- a/plugins/language_selection/language_selection.py
+++ b/plugins/language_selection/language_selection.py
@@ -18,20 +18,31 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""The language_selection feature of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import cryptobox.plugins.base
class language_selection(cryptobox.plugins.base.CryptoBoxPlugin):
+ """The language_selection feature of the CryptoBox.
+ """
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "menu", "preferences" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "menu", "preferences" ]
+ request_auth = False
rank = 60
- def doAction(self):
+ def do_action(self):
+ """Show all available languages.
+ """
return "language_selection"
- def getStatus(self):
- return ":".join(self.site.langOrder)
+ def get_status(self):
+ """The current status of the feature is defined as the current language.
+ """
+ return ":".join(self.site.lang_order)
diff --git a/plugins/language_selection/unittests.py b/plugins/language_selection/unittests.py
index 2f0eb6f..1f06609 100644
--- a/plugins/language_selection/unittests.py
+++ b/plugins/language_selection/unittests.py
@@ -18,19 +18,21 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "language_selection?weblang=en"
+ url = self.url + "language_selection?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('hoose an interface language')
def test_check_language_list(self):
- url = self.URL + "language_selection"
+ url = self.url + "language_selection"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find(u'Data.Status.Plugins.language_selection=(.*)$', "m")
diff --git a/plugins/logs/logs.py b/plugins/logs/logs.py
index 5187ce8..e4ddd18 100644
--- a/plugins/logs/logs.py
+++ b/plugins/logs/logs.py
@@ -18,56 +18,76 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+
+"""The logs feature of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import cryptobox.plugins.base
import os
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
+ """The logs feature of the CryptoBox.
+ """
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences" ]
+ request_auth = False
rank = 90
- def doAction(self, lines=50, size=3000, pattern=None):
+ def do_action(self, lines=50, size=3000, pattern=None):
+ """Show the latest part of the log file.
+ """
import re
## filter input
try:
lines = int(lines)
- if lines <= 0: raise(ValueError)
+ if lines <= 0:
+ raise(ValueError)
except ValueError:
lines = 50
try:
size = int(size)
- if size <= 0: raise(ValueError)
+ if size <= 0:
+ raise(ValueError)
except ValueError:
size = 3000
if not pattern is None:
pattern = str(pattern)
- if re.search(u'\W', pattern): pattern = None
- self.hdf[self.hdf_prefix + "Content"] = self.__getLogContent(lines, size, pattern)
- self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.abspath(os.path.join(self.pluginDir, "logs.css"))
+ if re.search(u'\W', pattern):
+ pattern = None
+ self.hdf[self.hdf_prefix + "Content"] = self.__get_log_content(
+ lines, size, pattern)
+ self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.abspath(os.path.join(
+ self.plugin_dir, "logs.css"))
return "show_log"
- def getStatus(self):
+ 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 __getLogContent(self, lines, maxSize, pattern):
- import re
+ def __get_log_content(self, lines, max_size, pattern):
+ """Filter, sort and shorten the log content.
+ """
if pattern:
content = []
current_length = 0
- for line in self.cbox.getLogData():
+ for line in self.cbox.get_log_data():
if line.find(pattern) != -1:
content.append(line)
current_length += len(line)
- if lines and len(content) >=lines: break
- if maxSize and current_length >=maxSize: break
+ if lines and len(content) >= lines:
+ break
+ if max_size and current_length >= max_size:
+ break
else:
- content = self.cbox.getLogData(lines, maxSize)
+ content = self.cbox.get_log_data(lines, max_size)
return "
".join(content)
diff --git a/plugins/logs/unittests.py b/plugins/logs/unittests.py
index fe18d6b..c51b04f 100644
--- a/plugins/logs/unittests.py
+++ b/plugins/logs/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_logs(self):
- log_url = self.URL + "logs"
+ log_url = self.url + "logs"
self.register_auth(log_url)
self.cmd.go(log_url)
self.cmd.find('class="console"')
@@ -31,13 +33,13 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_write_logs(self):
log_text = "unittest - just a marker - please ignore"
self.cbox.log.error(log_text)
- log_url = self.URL + "logs"
+ log_url = self.url + "logs"
self.register_auth(log_url)
self.cmd.go(log_url + "?pattern=ERROR")
self.cmd.find(log_text)
def test_invalid_args(self):
- log_url = self.URL + "logs"
+ log_url = self.url + "logs"
self.cmd.go(log_url + "?lines=10")
self.cmd.find('class="console"')
self.cmd.go(log_url + "?lines=0")
diff --git a/plugins/network/network.py b/plugins/network/network.py
index f1f481a..01318c8 100644
--- a/plugins/network/network.py
+++ b/plugins/network/network.py
@@ -18,23 +18,32 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""The network feature of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import subprocess
import os
import cryptobox.plugins.base
## specify (in seconds), how long we should wait before redirecting and ip change
-REDIRECT_DELAY=20
-CHANGE_IP_DELAY=1
+REDIRECT_DELAY = 10
+CHANGE_IP_DELAY = 2
class network(cryptobox.plugins.base.CryptoBoxPlugin):
+ """The network feature of the CryptoBox.
+ """
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences" ]
- requestAuth = True
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences" ]
+ request_auth = True
rank = 30
- def doAction(self, store=None, redirected="", ip1="", ip2="", ip3="", ip4=""):
+ def do_action(self, store=None, redirected="", ip1="", ip2="", ip3="", ip4=""):
+ """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":
@@ -46,58 +55,68 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
try:
for ip_in in (ip1, ip2, ip3, ip4):
if (int(ip_in) < 0) or (int(ip_in) > 255):
- self.cbox.log.info("invalid IP supplied: %s" % str((ip1,ip2,ip3,ip4)))
+ self.cbox.log.info("invalid IP supplied: %s" % \
+ str((ip1, ip2, ip3, ip4)))
raise ValueError
- ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4))
+ new_ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4))
except ValueError:
self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
- self.__prepareFormData()
+ self.__prepare_form_data()
return "form_network"
- if self.__setIP(ip):
- self.cbox.log.info("the IP was successfully changed: %s" % ip)
+ if self.__set_ip(new_ip):
+ self.cbox.log.info("the IP was successfully changed: %s" % new_ip)
self.hdf["Data.Success"] = "Plugins.network.IPChanged"
- self.hdf["Data.Redirect.URL"] = self.__getRedirectDestination(ip)
+ self.hdf["Data.Redirect.URL"] = self.__get_redirect_destination(new_ip)
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
return None
else:
- self.cbox.log.warn("failed to change IP address to: %s" % ip)
+ self.cbox.log.warn("failed to change IP address to: %s" % new_ip)
self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
- self.__prepareFormData()
+ self.__prepare_form_data()
return "form_network"
else:
self.cbox.log.debug("network plugin: show form")
## just show the form
- self.__prepareFormData()
+ self.__prepare_form_data()
return "form_network"
- def getStatus(self):
- return "%d.%d.%d.%d" % self.__getCurrentIP()
+ def get_status(self):
+ """The current IP is the status of this feature.
+ """
+ return "%d.%d.%d.%d" % self.__get_current_ip()
- def __getRedirectDestination(self, ip):
+ 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)
+ dest = "%s://%s" % (base_parts[0], ip)
if len(base_parts) == 3:
dest += ":%s" % base_parts[2]
return dest
- def __prepareFormData(self):
- (oc1, oc2, oc3, oc4) = self.__getCurrentIP()
+ def __prepare_form_data(self):
+ """Set some hdf values.
+ """
+ (oc1, oc2, oc3, oc4) = self.__get_current_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
- def __getCurrentIP(self):
+ def __get_current_ip(self):
+ """Retrieve the current IP.
+ """
import re
import imp
## load some values from the root_action.py script
- root_action_plug = imp.load_source("root_action", os.path.join(self.pluginDir, "root_action.py"))
+ root_action_plug = imp.load_source("root_action",
+ os.path.join(self.plugin_dir, "root_action.py"))
## get the current IP of the network interface
proc = subprocess.Popen(
shell = False,
@@ -106,20 +125,25 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
root_action_plug.IFCONFIG_BIN,
root_action_plug.IFACE])
(stdout, stderr) = proc.communicate()
- if proc.returncode != 0: return (0,0,0,0)
+ if proc.returncode != 0:
+ return (0,0,0,0)
## this regex matches the four numbers of the IP
match = re.search(u'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)
+ return (0, 0, 0, 0)
- def __setIP(self, ip):
+ def __set_ip(self, new_ip):
+ """Change the IP.
+ """
import threading
## call the root_action script after some seconds - so we can deliver the page before
- def delayedIPchange():
+ def delayed_ip_change():
+ """A threaded function to change the IP.
+ """
import time
time.sleep(CHANGE_IP_DELAY)
proc = subprocess.Popen(
@@ -129,19 +153,17 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
- os.path.join(self.pluginDir, "root_action.py"),
- ip])
+ os.path.join(self.plugin_dir, "root_action.py"),
+ new_ip])
proc.wait()
if proc.returncode != 0:
- self.cbox.log.warn("failed to change IP address: %s" % ip)
+ 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 = delayedIPchange
+ thread.run = delayed_ip_change
thread.setDaemon(True)
thread.start()
# TODO: how could we guess, if it failed?
return True
-
-
diff --git a/plugins/network/root_action.py b/plugins/network/root_action.py
index 4625a0c..83edb12 100755
--- a/plugins/network/root_action.py
+++ b/plugins/network/root_action.py
@@ -19,6 +19,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
#TODO: add netmask and gateway
diff --git a/plugins/network/unittests.py b/plugins/network/unittests.py
index 4c2e779..f49a5d4 100644
--- a/plugins/network/unittests.py
+++ b/plugins/network/unittests.py
@@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
from network import CHANGE_IP_DELAY
@@ -28,43 +30,47 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
'''change of network address'''
## the time module is necessary for the CHANGE_IP_DELAY
import time
- self.register_auth(self.URL + "network")
- self.cmd.go(self.URL + "network")
+ 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 getCurrentIP():
- self.cmd.go(self.URL + "network")
+ def get_current_ip():
+ self.register_auth(self.url + "network")
+ self.cmd.go(self.url + "network")
self.cmd.find(u'Data.Status.Plugins.network=([0-9\.]*)$', "m")
return self.locals["__match__"]
- origIPtext = getCurrentIP()
- origIPocts = origIPtext.split(".")
+ 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(origIPocts))
- wrongIP = "192.168.123.321"
- def setIP((ip1, ip2, ip3, ip4)):
- self.cmd.go(self.URL + "network")
+ self.assertEquals(4, len(orig_ip_octs))
+ def set_ip((ip1, ip2, ip3, ip4)):
+ self.cmd.go(self.url + "network")
self.cmd.formvalue("set_ip", "ip1", str(ip1))
self.cmd.formvalue("set_ip", "ip2", str(ip2))
self.cmd.formvalue("set_ip", "ip3", str(ip3))
self.cmd.formvalue("set_ip", "ip4", str(ip4))
self.cmd.submit()
## sleep a little bit longer than the delay necessary for ip-change
- time.sleep(CHANGE_IP_DELAY + 0.2)
- setIP([1,-2,0,1])
- self.assertEquals(origIPtext, getCurrentIP())
- setIP([1,0,0,256])
- self.assertEquals(origIPtext, getCurrentIP())
- setIP([1,"foo",0,1])
- self.assertEquals(origIPtext, getCurrentIP())
- setIP([10,12,0,2])
- self.assertEquals("10.12.0.2", getCurrentIP())
- setIP(origIPocts)
- self.assertEquals(origIPtext, getCurrentIP())
+ 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):
- self.register_auth(self.URL + "network")
- self.cmd.go(self.URL + "network" + "?redirected=1")
+ 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=1")
+ self.cmd.go(self.url + "network" + "?store=1")
self.cmd.find("invalid network address")
diff --git a/plugins/partition/partition.py b/plugins/partition/partition.py
index 43c2518..6d7cda6 100644
--- a/plugins/partition/partition.py
+++ b/plugins/partition/partition.py
@@ -18,114 +18,141 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""The partition feature of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import subprocess
import os
import logging
import cryptobox.core.tools as cbxTools
import cryptobox.plugins.base
-class partition(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences" ]
- requestAuth = True
+PARTTYPES = {
+ "windows" : ["0xC", "vfat"],
+ "linux" : ["L", "ext3"]}
+
+CONFIGPARTITION = {
+ "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.
+ """
+
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences" ]
+ request_auth = True
rank = 80
- PartTypes = {
- "windows" : ["0xC", "vfat"],
- "linux" : ["L", "ext3"]}
-
- ConfigPartition = {
- "size" : 5, # size of configuration partition (if necessary) in MB
- "type" : "L",
- "fs" : "ext2"}
-
-
- def doAction(self, **args):
+ def do_action(self, **args):
+ """Show the partitioning form and execute the requested action.
+ """
## load default hdf values
- self.__prepareDataset()
+ self.__prepare_dataset()
## retrieve some values from 'args' - defaults are empty
- self.device = self.__getSelectedDevice(args)
- self.withConfigPartition = self.__isWithConfigPartition()
+ self.device = 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.device))
- self.deviceSize = self.__getAvailableDeviceSize(self.device)
+ self.device_size = self.__get_available_device_size(self.device)
try:
step = args["step"]
del args["step"]
except KeyError:
step = "select_device"
try:
- ## this way of selecting the easy setup is necessary: see select_device.py for details
- if args["easy"]: step = "easy"
+ ## this way of selecting the easy setup is necessary:
+ ## see select_device.cs for details (button values for ie)
+ if args["easy"]:
+ step = "easy"
except KeyError:
pass
## no (or invalid) device was supplied
if not self.device:
step = "select_device"
if step == "add_partition":
- return self.__actionAddPartition(args)
+ return self.__action_add_partition(args)
elif step == "del_partition":
- return self.__actionDelPartition(args)
+ return self.__action_del_partition(args)
elif step == "finish":
- return self.__actionFinish(args)
+ return self.__action_finish(args)
elif step == "easy":
- return self.__actionEasySetup(args)
+ return self.__action_easy_setup()
else: # for "select_device" and for invalid targets
- return self.__actionSelectDevice(args)
+ return self.__action_select_device()
- def getStatus(self):
- return "%s / %s / %s" % (self.device, self.deviceSize, self.withConfigPartition)
+ def get_status(self):
+ """The status of this plugin is the selected device and some information.
+ """
+ return "%s / %s / %s" % (self.device, self.device_size,
+ self.with_config_partition)
- def __prepareDataset(self):
- self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.join(self.pluginDir, "partition.css")
+ def __prepare_dataset(self):
+ """Set some hdf values.
+ """
+ self.hdf[self.hdf_prefix + "StyleSheetFile"] = \
+ os.path.join(self.plugin_dir, "partition.css")
- def __getSelectedDevice(self, args):
+ def __get_selected_device(self, args):
+ """Check the selected device (valid, not busy, ...).
+ """
try:
device = args["block_device"]
except KeyError:
return None
- if not self.__isDeviceValid(device):
+ if not self.__is_device_valid(device):
return None
- if self.__isDeviceBusy(device):
+ if self.__is_device_busy(device):
self.hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
return None
return device
- def __isDeviceValid(self, device):
+ def __is_device_valid(self, device):
+ """Check if the device is valid and allowed.
+ """
if not device:
return False
- if not self.cbox.isDeviceAllowed(device):
+ if not self.cbox.is_device_allowed(device):
return False
- if not device in cbxTools.getParentBlockDevices():
+ if not device in cbxTools.get_parent_blockdevices():
return False
return True
- def __isDeviceBusy(self, device):
- """check if the device (or one of its partitions) is mounted"""
+ def __is_device_busy(self, device):
+ """check if the device (or one of its partitions) is mounted
+ """
# the config partition is ignored, as it will get unmounted if necessary
import re
- for c in self.cbox.getContainerList():
- if re.match(device + "\d*$", c.getDevice()):
- if c.isMounted(): return True
+ for cont in self.cbox.get_container_list():
+ if re.match(device + "\d*$", cont.get_device()):
+ if cont.is_mounted():
+ return True
return False
- def __actionSelectDevice(self, args):
+ def __action_select_device(self):
+ """Show a form to select the device for partitioning.
+ """
block_devices = [e
- for e in cbxTools.getParentBlockDevices()
- if self.cbox.isDeviceAllowed(e)]
+ for e in cbxTools.get_parent_blockdevices()
+ if self.cbox.is_device_allowed(e)]
counter = 0
- for a in block_devices:
- self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = a
- self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = cbxTools.getBlockDeviceSizeHumanly(a)
- self.cbox.log.debug("found a suitable block device: %s" % a)
+ for dev in block_devices:
+ self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = dev
+ self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = \
+ cbxTools.get_blockdevice_size_humanly(dev)
+ self.cbox.log.debug("found a suitable block device: %s" % dev)
counter += 1
- if self.withConfigPartition:
+ if self.with_config_partition:
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
## there is no disk available
if not block_devices:
@@ -133,59 +160,72 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
return "select_device"
- def __actionAddPartition(self, args):
+ def __action_add_partition(self, args):
+ """Add a selected partition to the currently proposed partition table.
+ """
self.hdf[self.hdf_prefix + "Device"] = self.device
- self.hdf[self.hdf_prefix + "Device.Size"] = self.deviceSize
- parts = self.__getPartitionsFromArgs(args)
- self.__setPartitionData(parts)
+ self.hdf[self.hdf_prefix + "Device.Size"] = self.device_size
+ parts = self.__get_partitions_from_args(args)
+ self.__set_partition_data(parts)
return "set_partitions"
- def __actionDelPartition(self, args):
+ def __action_del_partition(self, args):
+ """Remove a partition from the proposed partition table.
+ """
try:
part_num = int(args["del_num"])
except (TypeError,KeyError):
- return self.__actionAddPartition(args)
+ return self.__action_add_partition(args)
self.hdf[self.hdf_prefix + "Device"] = self.device
- self.hdf[self.hdf_prefix + "Device.Size"] = self.deviceSize
- parts = self.__getPartitionsFromArgs(args)
+ self.hdf[self.hdf_prefix + "Device.Size"] = self.device_size
+ parts = self.__get_partitions_from_args(args)
## valid partition number to be deleted?
if part_num < len(parts):
del parts[part_num]
else:
- return self.__actionAddPartition(args)
- self.__setPartitionData(parts)
+ return self.__action_add_partition(args)
+ self.__set_partition_data(parts)
return "set_partitions"
- def __actionFinish(self, args):
- parts = self.__getPartitionsFromArgs(args)
+ def __action_finish(self, args):
+ """Write the partition table.
+ """
+ parts = self.__get_partitions_from_args(args)
if parts:
- self.__setPartitionData(parts)
- if cbxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
- self.cbox.prefs.umountPartition()
- if not self.__runFDisk(parts):
+ self.__set_partition_data(parts)
+ if cbxTools.is_part_of_blockdevice(self.device,
+ 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.device)
- return self.__actionAddPartition(args)
+ self.cbox.log.warn(
+ "partition: failed to partition device: %s" % self.device)
+ 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.reReadContainerList()
+ ## 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()
def result_generator():
+ """Generate the results of formatting - may be threaded.
+ """
counter = 0
## initialize the generator
- formatPart_gen = self.__formatPartitions(parts)
+ format_part_gen = self.__format_partitions(parts)
while counter < len(parts):
## first part: get the device name
- yield formatPart_gen.next()
+ yield format_part_gen.next()
counter += 1
## second part: do the real formatting of a partition
- result = formatPart_gen.next()
- ## after the first partiton, we can reRead the containerList (as the possible config partition was already created)
- if self.withConfigPartition and (counter == 1):
- ## important: reRead the containerList - but somehow it breaks the flow (hanging process)
+ 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.mountPartition()
@@ -200,24 +240,28 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
"template": "show_format_progress",
"generator": result_generator}
else:
- return self.__actionAddPartition(args)
+ return self.__action_add_partition(args)
- def __actionEasySetup(self, 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.deviceSize, "type": "windows" } ]
+ parts = [ { "size": self.device_size, "type": "windows" } ]
## umount partition if necessary
- if cbxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
- self.cbox.prefs.umountPartition()
+ if cbxTools.is_part_of_blockdevice(self.device,
+ self.cbox.prefs.get_active_partition()):
+ self.cbox.prefs.umount_partition()
## partition it
- if not self.__runFDisk(parts):
+ 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.__formatPartitions(parts) if type(e) == types.BooleanType]
- if self.withConfigPartition:
- self.cbox.prefs.mountPartition()
+ result = [e for e in self.__format_partitions(parts)
+ if type(e) == types.BooleanType]
+ if self.with_config_partition:
+ self.cbox.prefs.mount_partition()
self.cbox.prefs.write()
## check if there is a "False" return value
if False in result:
@@ -229,50 +273,59 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
## 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
+ ## do not show the disk overview immediately
+ ## it does not get updated that fast
return { "plugin":"system_preferences", "values":[] }
- def __setPartitionData(self, parts):
- availSize = self.deviceSize
+ def __set_partition_data(self, parts):
+ """Set some hdf values for the currently proposed partition table.
+ """
+ avail_size = self.device_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"]
- availSize -= part["size"]
+ avail_size -= part["size"]
i += 1
- self.hdf[self.hdf_prefix + "availSize"] = availSize
- if self.withConfigPartition:
+ self.hdf[self.hdf_prefix + "availSize"] = avail_size
+ if self.with_config_partition:
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
- for t in self.PartTypes.keys():
- self.hdf[self.hdf_prefix + "Types.%s" % t] = t
+ 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.getContainerList() if cbxTools.isPartOfBlockDevice(self.device, e.getDevice()) ]
- for (index, t) in enumerate(current_containers):
- self.hdf[self.hdf_prefix + "ExistingContainers.%d.name" % index] = t.getName()
- self.hdf[self.hdf_prefix + "ExistingContainers.%d.size" % index] = cbxTools.getBlockDeviceSizeHumanly(t.getDevice())
+ current_containers = [ e for e in self.cbox.get_container_list()
+ if cbxTools.is_part_of_blockdevice(self.device, e.get_device()) ]
+ for (index, cont) in enumerate(current_containers):
+ self.hdf[self.hdf_prefix + "ExistingContainers.%d.name" % index] = \
+ cont.get_name()
+ self.hdf[self.hdf_prefix + "ExistingContainers.%d.size" % index] = \
+ cbxTools.get_blockdevice_size_humanly(cont.get_device())
- def __getPartitionsFromArgs(self, args):
+ def __get_partitions_from_args(self, args):
+ """Filter the given arguments and construct a partition table.
+ """
parts = []
done = False
- availSize = self.deviceSize
+ avail_size = self.device_size
i = -1
while not done:
i += 1
try:
size = int(args["part%d_size" % i])
- partType = args["part%d_type" % i]
- if int(size) > availSize:
+ 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 partType in self.PartTypes.keys(): continue
- parts.append({"size":size, "type":partType})
- availSize -= size
+ if not part_type in PARTTYPES.keys():
+ continue
+ parts.append({"size":size, "type":part_type})
+ avail_size -= size
except TypeError:
pass
except KeyError:
@@ -280,33 +333,40 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
return parts
- def __getAvailableDeviceSize(self, device):
+ def __get_available_device_size(self, device):
"""calculate the available size (MB) of the device
- also consider a (possible) configuration partition"""
- deviceSize = cbxTools.getBlockDeviceSize(device)
- if deviceSize < 0: return 0
- if self.withConfigPartition:
- deviceSize -= self.ConfigPartition["size"]
- return deviceSize
+ also consider a (possible) configuration partition
+ """
+ device_size = cbxTools.get_blockdevice_size(device)
+ if device_size < 0:
+ return 0
+ if self.with_config_partition:
+ device_size -= CONFIGPARTITION["size"]
+ return device_size
- def __isWithConfigPartition(self):
- """check if we have to create a configuration partition"""
- if self.cbox.prefs.requiresPartition():
- active = self.cbox.prefs.getActivePartition()
+ 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
+ if not active:
+ return True
## check if the active one is part of the current device
- return cbxTools.isPartOfBlockDevice(self.device, active)
+ return cbxTools.is_part_of_blockdevice(self.device, active)
return False
- def __runFDisk(self, parts):
+ 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.deviceSize
- for d in parts: avail_size -= d["size"]
+ avail_size = self.device_size
+ for one_part in parts:
+ avail_size -= one_part["size"]
self.cbox.log.debug("remaining size: %d" % avail_size)
- isFilled = avail_size == 0
+ is_filled = avail_size == 0
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
@@ -316,81 +376,91 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
- os.path.join(self.pluginDir, "root_action.py"),
+ os.path.join(self.plugin_dir, "root_action.py"),
"partition",
self.device])
- for line in self.__getSFDiskLayout(parts, isFilled):
+ for line in self.__get_sfdisk_layout(parts, is_filled):
proc.stdin.write(line + "\n")
(output, error) = proc.communicate()
- if proc.returncode != 0: self.cbox.log.debug("partitioning failed: %s" % error)
+ if proc.returncode != 0:
+ self.cbox.log.debug("partitioning failed: %s" % error)
return proc.returncode == 0
- def __getSFDiskLayout(self, paramParts, isFilled):
- """this generator returns the input lines for sfdisk"""
- parts = paramParts[:]
+ 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.withConfigPartition:
+ if self.with_config_partition:
## fill the main table (including a config partition)
- yield ",%d,%s" % (self.ConfigPartition["size"], self.ConfigPartition["type"])
+ yield ",%d,%s" % (CONFIGPARTITION["size"], CONFIGPARTITION["type"])
## one primary partition
- if isFilled and (len(parts) == 1):
+ if is_filled and (len(parts) == 1):
## fill the rest of the device
- yield ",,%s,*" % self.PartTypes[parts[0]["type"]][0]
+ yield ",,%s,*" % PARTTYPES[parts[0]["type"]][0]
else:
## only use the specified size
- yield ",%d,%s,*" % (parts[0]["size"], self.PartTypes[parts[0]["type"]][0])
+ 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
+ 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.withConfigPartition: yield ";"
+ if not self.with_config_partition:
+ yield ";"
while parts:
- if isFilled and (len(parts) == 1):
- yield ",,%s" % (self.PartTypes[parts[0]["type"]][0],)
+ if is_filled and (len(parts) == 1):
+ yield ",,%s" % (PARTTYPES[parts[0]["type"]][0],)
else:
- yield ",%d,%s" % (parts[0]["size"], self.PartTypes[parts[0]["type"]][0])
+ yield ",%d,%s" % (parts[0]["size"], PARTTYPES[parts[0]["type"]][0])
del parts[0]
- def __formatPartitions(self, paramParts):
- parts = paramParts[:]
+ def __format_partitions(self, param_parts):
+ """Format all partitions of the device.
+ """
+ parts = param_parts[:]
part_num = 1
## maybe a config partition?
- if self.withConfigPartition:
+ if self.with_config_partition:
dev_name = self.device + str(part_num)
self.cbox.log.info("formatting config partition (%s)" % dev_name)
- if self.__formatOnePartition(dev_name, self.ConfigPartition["fs"]):
- self.__setLabelOfPartition(dev_name, self.cbox.prefs["Main"]["ConfigVolumeLabel"])
+ 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.device + str(part_num)
- partType = self.PartTypes[parts[0]["type"]][1]
- self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
+ part_type = PARTTYPES[parts[0]["type"]][1]
+ self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
yield dev_name
- yield self.__formatOnePartition(dev_name, partType)
+ yield self.__format_one_partition(dev_name, part_type)
del parts[0]
## other data partitions
part_num = 5
while parts:
dev_name = self.device + str(part_num)
- partType = self.PartTypes[parts[0]["type"]][1]
- self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
+ part_type = PARTTYPES[parts[0]["type"]][1]
+ self.cbox.log.info("formatting partition (%s) as '%s'" % \
+ (dev_name, part_type))
yield dev_name
- yield self.__formatOnePartition(dev_name, partType)
+ yield self.__format_one_partition(dev_name, part_type)
part_num += 1
del parts[0]
return
- def __formatOnePartition(self, dev_name, type):
+ def __format_one_partition(self, dev_name, fs_type):
+ """Format a single partition
+ """
## first: retrieve UUID - it can be removed from the database afterwards
- volDB = self.cbox.prefs.volumesDB
- prev_name = [e.getName() for e in self.cbox.getContainerList() if e.getDevice() == dev_name]
+ prev_name = [e.get_name() for e in self.cbox.get_container_list()
+ if e.get_device() == dev_name]
## call "mkfs"
proc = subprocess.Popen(
shell = False,
@@ -398,10 +468,10 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
- os.path.join(self.pluginDir, "root_action.py"),
+ os.path.join(self.plugin_dir, "root_action.py"),
"format",
dev_name,
- type])
+ fs_type])
(output, error) = proc.communicate()
if proc.returncode != 0:
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
@@ -409,11 +479,13 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
else:
## remove unused volume entry
if prev_name:
- self.cbox.prefs.volumesDB[prev_name[0]]
+ del self.cbox.prefs.volumes_db[prev_name[0]]
return True
- def __setLabelOfPartition(self, dev_name, label):
+ 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,
@@ -422,7 +494,7 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
- os.path.join(self.pluginDir, "root_action.py"),
+ os.path.join(self.plugin_dir, "root_action.py"),
"label",
dev_name,
label])
diff --git a/plugins/partition/root_action.py b/plugins/partition/root_action.py
index 0b54124..f7fe5b5 100755
--- a/plugins/partition/root_action.py
+++ b/plugins/partition/root_action.py
@@ -19,6 +19,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
PLUGIN_TYPE = "cryptobox"
diff --git a/plugins/partition/unittests.py b/plugins/partition/unittests.py
index 696c67a..36ba4c9 100644
--- a/plugins/partition/unittests.py
+++ b/plugins/partition/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "partition?weblang=en"
+ url = self.url + "partition?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('VERY careful')
diff --git a/plugins/plugin-interface.txt b/plugins/plugin-interface.txt
index a90f379..321415c 100644
--- a/plugins/plugin-interface.txt
+++ b/plugins/plugin-interface.txt
@@ -7,7 +7,7 @@ The following directory structure is required:
Python code interface:
- create a class with the same name as the plugin - it must inherit CryptoBoxPlugin
- - function "doAction":
+ - function "do_action":
- this function will get called whenever this plugins is involved in a request
- all arguments should be optional (e.g. for displaying a form without previous input values)
- the argument "store" should be used to process a form submission (just a recommendation)
@@ -27,15 +27,15 @@ Python code interface:
* values: a dictionary of variables that should be defined for this plugin
- an empty (e.g. None) return value can be used to go to the default page ("disks"
or "volume_mount" (for volume plugins))
- - function "getStatus":
+ - function "get_status":
- returns a string, that describes a state connected to this plugin (e.g. the current date and
time (for the "date" plugin))
- - the class variable "pluginCapabilities" must be an array of strings (supported: "system" and
+ - the class variable "plugin_capabilities" must be an array of strings (supported: "system" and
"volume")
- - the class variable "pluginVisibility" may contain one or more of the following items:
- menu/preferences/volume. This obviously should fit to the 'pluginCapabilities' variable.
- An empty list is interpreted as a disabled plugin.
- - the class variable "requestAuth" is boolean and defines, if admin authentication is necessary
+ - the class variable "plugin_visibility" may contain one or more of the following items:
+ menu/preferences/volume. This should fit to the 'plugin_capabilities' variable.
+ An empty list is interpreted as an invisible plugin.
+ - the class variable "request_auth" is boolean and defines, if admin authentication is necessary
for this plugin
- the class variable "rank" is an integer in the range of 0..100 - it determines the order
of plugins in listings (lower value -> higher priority)
diff --git a/plugins/plugin_manager/plugin_manager.py b/plugins/plugin_manager/plugin_manager.py
index bb5a0e7..61b918a 100644
--- a/plugins/plugin_manager/plugin_manager.py
+++ b/plugins/plugin_manager/plugin_manager.py
@@ -18,27 +18,31 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
import cryptobox.plugins.manage
class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences" ]
- requestAuth = True
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences" ]
+ request_auth = True
rank = 90
- def doAction(self, store=None, action=None, plugin_name=None, **args):
+ def do_action(self, store=None, action=None, plugin_name=None, **args):
import re
if plugin_name:
## check for invalid characters
if re.search(u'\W', plugin_name): return "plugin_list"
- pluginList = cryptobox.plugins.manage.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
- plugin = pluginList.getPlugin(plugin_name)
+ 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 pluginList.getPlugins() if e.pluginCapabilities == plugin.pluginCapabilities]
+ self.plugins = [e for e in plugin_manager.get_plugins()
+ if e.plugin_capabilities == plugin.plugin_capabilities]
if action == "up":
self.__move_up(plugin)
elif action == "down":
@@ -50,44 +54,48 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
if not re.search(u'\W',key):
self.__setConfig(key[:-7], args)
else:
- self.cbox.log.info("plugin_manager: invalid plugin name (%s)" % str(key[:-7]))
+ self.cbox.log.info("plugin_manager: invalid plugin name (%s)" % \
+ str(key[:-7]))
try:
- self.cbox.prefs.pluginConf.write()
+ self.cbox.prefs.plugin_conf.write()
except IOError:
self.cbox.log.warn("failed to write plugin configuration")
return "plugin_list"
- def getStatus(self):
+ def get_status(self):
return "no status"
- def __sortPlugins(self):
+ def __sort_plugins(self):
"""sort all plugins in the list according to their rank"""
def cmp_func(x,y):
- xRank = x.getRank()
- yRank = y.getRank()
- if xRank < yRank: return -1
- elif xRank == yRank: return 0
- else: return 1
+ 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 __distributeRanks(self):
+ def __distribute_ranks(self):
"""evenly distribute the 'rank' values according to the current order of
the list"""
dist = 100/len(self.plugins)
for index,pl in enumerate(self.plugins):
try:
- self.cbox.prefs.pluginConf[pl.getName()]["rank"] = dist*index
+ self.cbox.prefs.plugin_conf[pl.get_name()]["rank"] = dist*index
except KeyError:
- self.cbox.prefs.pluginConf[pl.getName()] = {}
- self.cbox.prefs.pluginConf[pl.getName()]["rank"] = dist*index
- self.cbox.prefs.pluginConf.write()
+ self.cbox.prefs.plugin_conf[pl.get_name()] = {}
+ self.cbox.prefs.plugin_conf[pl.get_name()]["rank"] = dist*index
+ self.cbox.prefs.plugin_conf.write()
def __move_up(self, plugin):
- self.__sortPlugins()
+ self.__sort_plugins()
try:
index = self.plugins.index(plugin)
## first elements may not move up
@@ -97,11 +105,11 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
return
self.plugins.remove(plugin)
self.plugins.insert(index-1, plugin)
- self.__distributeRanks()
+ self.__distribute_ranks()
def __move_down(self, plugin):
- self.__sortPlugins()
+ self.__sort_plugins()
try:
index = self.plugins.index(plugin)
## last elements may not move down
@@ -111,7 +119,7 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
return
self.plugins.remove(plugin)
self.plugins.insert(index+1, plugin)
- self.__distributeRanks()
+ self.__distribute_ranks()
def __setConfig(self, name, args):
@@ -137,5 +145,5 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
setting["requestAuth"] = True
except (KeyError, ValueError):
pass
- self.cbox.prefs.pluginConf[name] = setting
+ self.cbox.prefs.plugin_conf[name] = setting
diff --git a/plugins/plugin_manager/unittests.py b/plugins/plugin_manager/unittests.py
index 8252461..4738fa5 100644
--- a/plugins/plugin_manager/unittests.py
+++ b/plugins/plugin_manager/unittests.py
@@ -18,19 +18,21 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "plugin_manager?weblang=en"
+ url = self.url + "plugin_manager?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Plugin Manager')
def test_set_options(self):
- url = self.URL + "plugin_manager"
+ url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + u"?plugin_name=t/-!")
self.cmd.find('Plugin Manager')
@@ -55,8 +57,8 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_move_up(self):
- ## TODO: if we want to be perfect, then we should check the change of the rank
- url = self.URL + "plugin_manager"
+ #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 + u"?plugin_name=disks&action=up")
self.cmd.find('Plugin Manager')
@@ -68,7 +70,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_move_down(self):
## TODO: if we want to be perfect, then we should check the change of the rank
- url = self.URL + "plugin_manager"
+ url = self.url + "plugin_manager"
self.register_auth(url)
self.cmd.go(url + u"?plugin_name=disks&action=down")
self.cmd.find('Plugin Manager')
diff --git a/plugins/shutdown/root_action.py b/plugins/shutdown/root_action.py
index 5259d75..25809eb 100755
--- a/plugins/shutdown/root_action.py
+++ b/plugins/shutdown/root_action.py
@@ -19,6 +19,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
PLUGIN_TYPE = "cryptobox"
diff --git a/plugins/shutdown/shutdown.py b/plugins/shutdown/shutdown.py
index f240cc7..7a3cebe 100644
--- a/plugins/shutdown/shutdown.py
+++ b/plugins/shutdown/shutdown.py
@@ -18,29 +18,31 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
REDIRECT_DELAY = 180
class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences", "menu" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences", "menu" ]
+ request_auth = False
rank = 90
- def doAction(self, type=None):
+ def do_action(self, type=None):
if not type:
return "form_shutdown"
elif type == "shutdown":
- if self.__doShutdown("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.__doShutdown("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
@@ -52,11 +54,11 @@ class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
return "form_shutdown"
- def getStatus(self):
+ def get_status(self):
return "the box is up'n'running"
- def __doShutdown(self, action):
+ def __do_shutdown(self, action):
import subprocess
import os
proc = subprocess.Popen(
@@ -65,7 +67,7 @@ class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"plugin",
- os.path.join(self.pluginDir, "root_action.py"),
+ os.path.join(self.plugin_dir, "root_action.py"),
action])
proc.wait()
return proc.returncode == 0
diff --git a/plugins/shutdown/unittests.py b/plugins/shutdown/unittests.py
index 2d506f9..bfc2105 100644
--- a/plugins/shutdown/unittests.py
+++ b/plugins/shutdown/unittests.py
@@ -18,13 +18,15 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.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"
+ url = self.url + "shutdown"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('shutdown')
diff --git a/plugins/system_preferences/system_preferences.py b/plugins/system_preferences/system_preferences.py
index 6cd0da8..0d1aadf 100644
--- a/plugins/system_preferences/system_preferences.py
+++ b/plugins/system_preferences/system_preferences.py
@@ -18,20 +18,23 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
class system_preferences(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "menu" ]
- requestAuth = False
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "menu" ]
+ request_auth = False
rank = 20
- def doAction(self):
+ def do_action(self):
return "show_plugins"
- def getStatus(self):
- return ":".join([p.getName() for p in self.site.pluginList.getPlugins()])
-
+ 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()])
diff --git a/plugins/system_preferences/unittests.py b/plugins/system_preferences/unittests.py
index b904f19..716975c 100644
--- a/plugins/system_preferences/unittests.py
+++ b/plugins/system_preferences/unittests.py
@@ -18,17 +18,19 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- self.cmd.go(self.URL + "system_preferences")
+ 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.go(self.url + "system_preferences")
self.cmd.find(u'Data.Status.Plugins.system_preferences=(.*)$', "m")
plugins = self.locals["__match__"].split(":")
self.assertTrue(len(plugins) > 1)
diff --git a/plugins/user_manager/unittests.py b/plugins/user_manager/unittests.py
index 86f6023..eb9d821 100644
--- a/plugins/user_manager/unittests.py
+++ b/plugins/user_manager/unittests.py
@@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
## this user may not be removed
@@ -35,7 +37,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_test_wrong_credentials(self):
"""check if the user_manager is protected"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url,"foo","bar")
self.cmd.go(url)
self.cmd.notfind("Manage users")
@@ -43,7 +45,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_add_existing_user(self):
"""adding an existing user should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self._add_user("admin","foo","foo")
self.cmd.find("The choosen username does already exist")
@@ -51,7 +53,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_add_invalid_username(self):
"""adding an invalid username should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self._add_user("foo/bar","foo","foo")
self.cmd.find("Invalid username")
@@ -60,7 +62,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_add_without_password(self):
"""adding a user without password should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","","foo")
@@ -70,7 +72,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_add_with_different_passwords(self):
"""adding a user with different passwords should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","foo")
@@ -80,7 +82,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_change_pw_for_invalid_user(self):
"""changing a password of a non existing user should fail"""
- url = self.URL + "user_manager"
+ 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")
@@ -89,7 +91,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_change_pw_without_password(self):
"""changing a password without a new password should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","bar")
@@ -102,7 +104,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_change_pw_wit_different_passwords(self):
"""changing a password while supplying different passwords should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("foo" in self._getUsers())
self._add_user("foo","bar","bar")
@@ -115,7 +117,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def _remove_reserved_user(self):
"""removing a reserved user should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.assertTrue("admin" in self._getUsers())
self._del_user("admin")
@@ -125,7 +127,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def _remove_non_existing_user(self):
"""removing a non-existing user should fail"""
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.assertFalse("barfoo" in self._getUsers())
self._del_user("barfoo")
@@ -134,7 +136,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_manage_users(self):
"""add a new user, change its password and remove the user afterwards"""
- url = self.URL + "user_manager"
+ 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
@@ -158,13 +160,13 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_invalid_input(self):
"""check all combinations of invalid input"""
- url = self.URL + "user_manager"
+ 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.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)
@@ -172,13 +174,13 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def _del_user(self, username):
- self.cmd.go(self.URL + "user_manager")
+ 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.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)
@@ -186,7 +188,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def _getUsers(self):
- url = self.URL + "user_manager"
+ url = self.url + "user_manager"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find("Data.Status.Plugins.user_manager=([\w:]+)")
diff --git a/plugins/user_manager/user_manager.py b/plugins/user_manager/user_manager.py
index 556d241..f4c2420 100644
--- a/plugins/user_manager/user_manager.py
+++ b/plugins/user_manager/user_manager.py
@@ -18,21 +18,23 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
RESERVED_USERS = [ "admin" ]
class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "system" ]
- pluginVisibility = [ "preferences" ]
- requestAuth = True
+ plugin_capabilities = [ "system" ]
+ plugin_visibility = [ "preferences" ]
+ request_auth = True
rank = 45
- def doAction(self, store=None, user=None, new_pw=None, new_pw2=None):
+ def do_action(self, store=None, user=None, new_pw=None, new_pw2=None):
import re
- adminDict = self.cbox.prefs.userDB["admins"]
- self.__cleanHDF()
+ admin_dict = self.cbox.prefs.user_db["admins"]
+ self.__clean_hdf()
if store is None:
pass
elif store == "add_user":
@@ -42,13 +44,13 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
- elif user in adminDict.keys():
+ elif user in admin_dict.keys():
self.hdf["Data.Warning"] = "Plugins.user_manager.UserAlreadyExists"
else:
- adminDict[user] = self.cbox.prefs.userDB.getDigest(new_pw)
+ admin_dict[user] = self.cbox.prefs.user_db.get_digest(new_pw)
self.hdf["Data.Success"] = "Plugins.user_manager.UserAdded"
try:
- self.cbox.prefs.userDB.write()
+ self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
elif store == "change_password":
@@ -56,11 +58,11 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
self.hdf["Data.Warning"] = "EmptyNewPassword"
elif new_pw != new_pw2:
self.hdf["Data.Warning"] = "DifferentPasswords"
- elif user in adminDict.keys():
- adminDict[user] = self.cbox.prefs.userDB.getDigest(new_pw)
+ 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.userDB.write()
+ self.cbox.prefs.user_db.write()
except IOError:
self.cbox.log.warn("failed to write user database")
else:
@@ -69,31 +71,31 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
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 adminDict.keys():
- del adminDict[user]
+ elif user in admin_dict.keys():
+ del admin_dict[user]
self.hdf["Data.Success"] = "Plugins.user_manager.UserRemoved"
try:
- self.cbox.prefs.userDB.write()
+ 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.__prepareHDF(adminDict)
+ self.__prepare_hdf(admin_dict)
return "user_list"
- def getStatus(self):
- return ":".join(self.cbox.prefs.userDB["admins"].keys())
+ def get_status(self):
+ return ":".join(self.cbox.prefs.user_db["admins"].keys())
- def __cleanHDF(self):
+ def __clean_hdf(self):
for key in self.hdf.keys():
del self.hdf[key]
- def __prepareHDF(self, dict):
+ def __prepare_hdf(self, dict):
## sort by name
users = dict.keys()
users.sort()
diff --git a/plugins/volume_automount/unittests.py b/plugins/volume_automount/unittests.py
index f4645f5..6701cd1 100644
--- a/plugins/volume_automount/unittests.py
+++ b/plugins/volume_automount/unittests.py
@@ -18,13 +18,15 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
"""try to read automount form"""
- url = self.URL + "volume_automount?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_automount?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Activate during startup')
@@ -32,21 +34,21 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_toggle(self):
"""try to toggle automount property"""
- url = self.URL + "volume_automount"
+ url = self.url + "volume_automount"
self.register_auth(url)
- self.cmd.go(url + "?device=%%2Fdev%%2F%s1&action=disable" % self.device)
+ self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=disable" % self.device)
self.cmd.find("Automatic activation disabled")
self.cmd.find("is disabled")
- self.cmd.go(url + "?device=%%2Fdev%%2F%s1&action=enable" % self.device)
+ self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=enable" % self.device)
self.cmd.find("Automatic activation enabled")
self.cmd.notfind("is disabled")
def test_invalid_input(self):
"""check invalid inputs"""
- url = self.URL + "volume_automount"
+ url = self.url + "volume_automount"
self.register_auth(url)
- self.cmd.go(url + "?device=%%2Fdev%%2F%s1&action=foobar" % self.device)
+ self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=foobar" % self.device)
self.cmd.notfind("Automatic activation disabled")
self.cmd.notfind("Automatic activation enabled")
diff --git a/plugins/volume_automount/volume_automount.py b/plugins/volume_automount/volume_automount.py
index c0df4f2..6a87c14 100644
--- a/plugins/volume_automount/volume_automount.py
+++ b/plugins/volume_automount/volume_automount.py
@@ -18,58 +18,60 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_automount(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "properties" ]
- requestAuth = False
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "properties" ]
+ request_auth = False
rank = 80
- trueString = "yes"
- falseString = "no"
+ true_string = "yes"
+ false_string = "no"
- def doAction(self, action=None):
- container = self.cbox.getContainer(self.device)
+ def do_action(self, action=None):
+ container = self.cbox.get_container(self.device)
if action is None:
pass
elif action == "enable":
- container.attributes["automount"] = self.trueString
+ container.attributes["automount"] = self.true_string
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountEnabled"
self.cbox.log.info("volume_automount: enabled for device '%s'" % self.device)
- self.cbox.prefs.volumesDB.write()
+ self.cbox.prefs.volumes_db.write()
elif action == "disable":
- container.attributes["automount"] = self.falseString
+ container.attributes["automount"] = self.false_string
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountDisabled"
self.cbox.log.info("volume_automount: disabled for device '%s'" % self.device)
- self.cbox.prefs.volumesDB.write()
+ self.cbox.prefs.volumes_db.write()
else:
self.cbox.log.info("volume_automount: invalid action (%s)" % str(action))
- self.__prepareHDF()
+ self.__prepare_hdf()
return "volume_automount"
- def getStatus(self):
- return str(self.__isAutoMount())
+ def get_status(self):
+ return str(self.__is_auto_mount())
- def __prepareHDF(self):
- if self.__isAutoMount():
+ def __prepare_hdf(self):
+ if self.__is_auto_mount():
self.hdf[self.hdf_prefix + "automount_setting"] = "1"
else:
self.hdf[self.hdf_prefix + "automount_setting"] = "0"
- def __isAutoMount(self):
- container = self.cbox.getContainer(self.device)
+ def __is_auto_mount(self):
+ container = self.cbox.get_container(self.device)
if not container:
return False
if container.attributes.has_key("automount"):
- return container.attributes["automount"] == self.trueString
+ return container.attributes["automount"] == self.true_string
else:
return False
diff --git a/plugins/volume_chpasswd/unittests.py b/plugins/volume_chpasswd/unittests.py
index 55871d9..5ad7f7a 100644
--- a/plugins/volume_chpasswd/unittests.py
+++ b/plugins/volume_chpasswd/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "volume_chpasswd?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_chpasswd?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('hange')
diff --git a/plugins/volume_chpasswd/volume_chpasswd.py b/plugins/volume_chpasswd/volume_chpasswd.py
index f307368..8482950 100644
--- a/plugins/volume_chpasswd/volume_chpasswd.py
+++ b/plugins/volume_chpasswd/volume_chpasswd.py
@@ -18,24 +18,26 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "properties" ]
- requestAuth = False
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "properties" ]
+ request_auth = False
rank = 70
- def doAction(self, store=None, old_pw=None, new_pw=None, new_pw2=None):
- self.container = self.cbox.getContainer(self.device)
+ 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.__changePassword(old_pw, new_pw, new_pw2)
+ return self.__change_password(old_pw, new_pw, new_pw2)
elif not store:
return "volume_chpasswd"
else:
@@ -43,11 +45,11 @@ class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
return "volume_chpasswd"
- def getStatus(self):
+ def get_status(self):
return "TODO"
- def __changePassword(self, old_pw, new_pw, new_pw2):
+ def __change_password(self, old_pw, new_pw, new_pw2):
if not old_pw:
self.hdf["Data.Warning"] = "EmptyPassword"
elif not new_pw:
@@ -59,13 +61,13 @@ class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
pass
else:
try:
- self.container.changePassword(old_pw, new_pw)
- except CBInvalidType, errMsg:
- self.cbox.log.info("plugin 'volume_chpasswd' - cannot change passphrase for non-encrypted container (%s): %s" % (self.device, errMsg))
+ 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, errMsg:
- self.cbox.log.warn("plugin 'volume_chpasswd' - cannot change password for device (%s): %s" % (self.device, errMsg))
+ 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"
diff --git a/plugins/volume_details/unittests.py b/plugins/volume_details/unittests.py
index 8835883..cad34fe 100644
--- a/plugins/volume_details/unittests.py
+++ b/plugins/volume_details/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "volume_details?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_details?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Technical details')
diff --git a/plugins/volume_details/volume_details.py b/plugins/volume_details/volume_details.py
index 2694a6e..4bfbdde 100644
--- a/plugins/volume_details/volume_details.py
+++ b/plugins/volume_details/volume_details.py
@@ -18,22 +18,24 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
class volume_details(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "volume" ]
- requestAuth = False
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "volume" ]
+ request_auth = False
rank = 100
- def doAction(self):
+ def do_action(self):
## all variables are already set somewhere else
return "volume_details"
- def getStatus(self):
+ def get_status(self):
return "no status"
diff --git a/plugins/volume_format_fs/unittests.py b/plugins/volume_format_fs/unittests.py
index 12d3938..c58738b 100644
--- a/plugins/volume_format_fs/unittests.py
+++ b/plugins/volume_format_fs/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "volume_format_fs?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_format_fs?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Initializing filesystem')
diff --git a/plugins/volume_format_fs/volume_format_fs.py b/plugins/volume_format_fs/volume_format_fs.py
index f7e1364..4f3ffbd 100644
--- a/plugins/volume_format_fs/volume_format_fs.py
+++ b/plugins/volume_format_fs/volume_format_fs.py
@@ -18,32 +18,33 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
-import cryptobox.core.container as cbxContainer
+import cryptobox.core.container as cbx_container
+
+## map filesystem types to the appropriate arguments for 'mkfs'
+FSTYPES = {
+ "windows": "vfat",
+ "linux": "ext3" }
+
class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "volume" ]
- requestAuth = True
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "volume" ]
+ request_auth = True
rank = 60
- ## map filesystem types to the appropriate arguments for 'mkfs'
- fsTypes = {
- "windows": "vfat",
- "linux": "ext3" }
-
- containerTypes = [ "luks", "plain" ]
-
- def doAction(self, store=None, fs_type="windows", container_type="luks", crypto_password=None, crypto_password2=None, confirm=None):
- if not fs_type in self.fsTypes.keys():
+ def do_action(self, store=None, fs_type="windows", container_type="luks", crypto_password=None, crypto_password2=None, confirm=None):
+ if not fs_type in FSTYPES.keys():
self.cbox.info
return "format_volume"
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
self.hdf[self.hdf_prefix + "container_type"] = container_type
- for t in self.fsTypes.keys():
+ for t in FSTYPES.keys():
self.hdf[self.hdf_prefix + "fs_types." + t] = t
if store == "step1":
if not confirm:
@@ -67,14 +68,14 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
return "volume_format"
- def getStatus(self):
+ def get_status(self):
return "no status"
def __format_plain(self, fsType):
try:
- container = self.cbox.getContainer(self.device)
- container.create(cbxContainer.ContainerTypes["plain"])
+ container = self.cbox.get_container(self.device)
+ container.create(cbx_container.CONTAINERTYPES["plain"])
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)
@@ -98,9 +99,9 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
self.hdf["Data.Warning"] = "DifferentPasswords"
self.cbox.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % self.device)
return "volume_format"
- container = self.cbox.getContainer(self.device)
+ container = self.cbox.get_container(self.device)
try:
- container.create(cbxContainer.ContainerTypes["luks"], pw)
+ container.create(cbx_container.CONTAINERTYPES["luks"], 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)
diff --git a/plugins/volume_mount/unittests.py b/plugins/volume_mount/unittests.py
index 609258f..2aa68f5 100644
--- a/plugins/volume_mount/unittests.py
+++ b/plugins/volume_mount/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "volume_mount?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_mount?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('ctivate volume')
diff --git a/plugins/volume_mount/volume_mount.py b/plugins/volume_mount/volume_mount.py
index 1136348..97e4c6d 100644
--- a/plugins/volume_mount/volume_mount.py
+++ b/plugins/volume_mount/volume_mount.py
@@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
import cryptobox.core.container as cbxContainer
@@ -25,20 +27,20 @@ import cryptobox.core.container as cbxContainer
class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "volume" ]
- requestAuth = False
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "volume" ]
+ request_auth = False
rank = 0
- def doAction(self, action=None, pw=None):
- self.container = self.cbox.getContainer(self.device)
+ def do_action(self, action=None, pw=None):
+ self.container = self.cbox.get_container(self.device)
if action == "mount_plain":
- return self.__doMountPlain()
+ return self.__do_mount_plain()
elif action == "mount_luks":
- return self.__doMountLuks(pw)
+ return self.__do_mount_luks(pw)
elif action == "umount":
- return self.__doUmount()
+ return self.__do_umount()
elif not action:
return "volume_status"
else:
@@ -46,43 +48,43 @@ class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
return None
- def getStatus(self):
- container = self.cbox.getContainer(self.device)
+ def get_status(self):
+ container = self.cbox.get_container(self.device)
if not self.container:
return "invalid device"
- if container.isMounted():
+ if container.is_mounted():
return "active"
else:
return "passive"
- def __doMountPlain(self):
- if self.container.isMounted():
+ 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.getType() != cbxContainer.ContainerTypes["plain"]:
+ 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, errMsg:
+ 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, errMsg))
+ self.cbox.log.warn("failed to mount the device (%s): %s" % (self.device, err_msg))
return "volume_status"
- except CBContainerError, errMsg:
+ 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, errMsg))
+ 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 __doMountLuks(self, pw):
- if self.container.isMounted():
+ def __do_mount_luks(self, pw):
+ 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"
@@ -90,35 +92,35 @@ class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
self.dataset["Data.Warning"] = "EmptyPassword"
self.log.info("no password was supplied for mounting of device: '%s'" % self.device)
return "volume_status"
- if self.container.getType() != cbxContainer.ContainerTypes["luks"]:
+ 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"
try:
self.container.mount(pw)
- except CBMountError, errMsg:
+ 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, errMsg))
+ self.cbox.log.warn("failed to mount the device (%s): %s" % (self.device, err_msg))
return "volume_status"
- except CBContainerError, errMsg:
+ 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, errMsg))
+ 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 __doUmount(self):
- if not self.container.isMounted():
+ 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, errMsg:
+ except CBUmountError, err_msg:
self.hdf["Data.Warning"] = "UmountFailed"
- self.cbox.log.warn("could not umount the volume (%s): %s" % (self.device, errMsg))
+ 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"
diff --git a/plugins/volume_props/unittests.py b/plugins/volume_props/unittests.py
index 1f8d802..f2c7281 100644
--- a/plugins/volume_props/unittests.py
+++ b/plugins/volume_props/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "volume_props?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_props?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Properties')
diff --git a/plugins/volume_props/volume_props.py b/plugins/volume_props/volume_props.py
index 9e9a7af..9e9e937 100644
--- a/plugins/volume_props/volume_props.py
+++ b/plugins/volume_props/volume_props.py
@@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
import cryptobox.plugins.manage
from cryptobox.core.exceptions import *
@@ -25,51 +27,54 @@ from cryptobox.core.exceptions import *
class volume_props(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "volume" ]
- requestAuth = False
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "volume" ]
+ request_auth = False
rank = 30
- def doAction(self, **args):
+ def do_action(self, **args):
import os
- self.props_plugins = [e for e in cryptobox.plugins.manage.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"]).getPlugins() if "properties" in e.getVisibility()]
+ 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()]
## sort plugins by rank
- self.props_plugins.sort(cmp = self.__cmpPluginsRank)
+ self.props_plugins.sort(cmp = self.__cmp_plugins_rank)
## set the name of the templates for every plugin
- loadString = ""
+ load_string = ""
for p in self.props_plugins:
p.device = self.device
- plfname = os.path.join(p.pluginDir, str(p.doAction(**args)) + ".cs")
- loadString += "" % plfname
+ plfname = os.path.join(p.plugin_dir, str(p.do_action(**args)) + ".cs")
+ load_string += "" % 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') commands
## as a hdf variable - then we can include it via 'evar'
- self.hdf[self.hdf_prefix + 'includePlugins'] = loadString
+ self.hdf[self.hdf_prefix + 'includePlugins'] = load_string
return "volume_properties"
- def getStatus(self):
+ def get_status(self):
return "TODO"
- def loadDataSet(self, hdf):
+ def load_dataset(self, hdf):
"""override the parent's function
we have to get the data from all included plugins"""
- for p in self.props_plugins:
- p.loadDataSet(hdf)
+ for plugin in self.props_plugins:
+ plugin.load_dataset(hdf)
## call our parent's method
- cryptobox.plugins.base.CryptoBoxPlugin.loadDataSet(self, hdf)
+ cryptobox.plugins.base.CryptoBoxPlugin.load_dataset(self, hdf)
- def __cmpPluginsRank(self, p1, p2):
- order = p1.getRank() - p2.getRank()
+ 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
+
diff --git a/plugins/volume_rename/unittests.py b/plugins/volume_rename/unittests.py
index 97b5a72..dd83de6 100644
--- a/plugins/volume_rename/unittests.py
+++ b/plugins/volume_rename/unittests.py
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.web.testclass
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
def test_read_form(self):
- url = self.URL + "volume_rename?weblang=en&device=%2Fdev%2F" + self.device + "1"
+ url = self.url + "volume_rename?weblang=en&device=%2Fdev%2F" + self.device
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('name')
diff --git a/plugins/volume_rename/volume_rename.py b/plugins/volume_rename/volume_rename.py
index 60fc65f..5a0d036 100644
--- a/plugins/volume_rename/volume_rename.py
+++ b/plugins/volume_rename/volume_rename.py
@@ -18,49 +18,51 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+__revision__ = "$Id"
+
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_rename(cryptobox.plugins.base.CryptoBoxPlugin):
- pluginCapabilities = [ "volume" ]
- pluginVisibility = [ "properties" ]
- requestAuth = False
+ plugin_capabilities = [ "volume" ]
+ plugin_visibility = [ "properties" ]
+ request_auth = False
rank = 60
- def doAction(self, store=None, vol_name=None):
- self.container = self.cbox.getContainer(self.device)
+ def do_action(self, store=None, vol_name=None):
+ self.container = self.cbox.get_container(self.device)
if not self.container:
return None
- self.__prepareHDF()
+ self.__prepare_hdf()
if store and vol_name:
- return self.__setVolumeName(vol_name)
+ return self.__set_volume_name(vol_name)
else:
return "volume_rename"
- def getStatus(self):
- self.container = self.cbox.getContainer(self.device)
+ def get_status(self):
+ self.container = self.cbox.get_container(self.device)
if not self.container:
return "invalid device"
- return "name=%s" % self.container.getName()
+ return "name=%s" % self.container.get_name()
- def __prepareHDF(self):
- self.hdf[self.hdf_prefix + "vol_name"] = self.container.getName()
+ def __prepare_hdf(self):
+ self.hdf[self.hdf_prefix + "vol_name"] = self.container.get_name()
- def __setVolumeName(self, vol_name):
+ def __set_volume_name(self, vol_name):
if not vol_name:
self.hdf["Data.Warning"] = "Plugins.volume_rename.InvalidVolumeName"
return "volume_rename"
- if vol_name == self.container.getName():
+ if vol_name == self.container.get_name():
## nothing has to be done
return "volume_rename"
try:
- self.container.setName(vol_name)
+ self.container.set_name(vol_name)
self.hdf["Data.Success"] = "Plugins.volume_rename.VolumeNameChanged"
except CBVolumeIsActive:
self.hdf["Data.Warning"] = "Plugins.volume_rename.NoRenameIfActive"
@@ -71,6 +73,6 @@ class volume_rename(cryptobox.plugins.base.CryptoBoxPlugin):
except CBContainerError:
self.hdf["Data.Warning"] = "Plugins.volume_rename.SetVolumeNameFailed"
## reread the volume name
- self.__prepareHDF()
+ self.__prepare_hdf()
return "volume_rename"
diff --git a/src/cryptobox/__init__.py b/src/cryptobox/__init__.py
index 161c961..c261d92 100644
--- a/src/cryptobox/__init__.py
+++ b/src/cryptobox/__init__.py
@@ -1 +1,13 @@
-__all__ = ['core','web','plugins','tests']
+"""CryptoBox package
+
+The CryptoBox is a webserver. It enables you to control your encrypted
+(cryptsetup-luks) and plaintext disks via an easy to use web interface.
+The CryptoBox is especially suitable for non-desktop fileservers with
+encrypted partitions.
+"""
+
+__all__ = ['core', 'web', 'plugins', 'tests']
+__revision__ = "$Id$"
+
+__version__ = "0.2.99~1"
+
diff --git a/src/cryptobox/core/__init__.py b/src/cryptobox/core/__init__.py
index e69de29..3b001bf 100644
--- a/src/cryptobox/core/__init__.py
+++ b/src/cryptobox/core/__init__.py
@@ -0,0 +1,7 @@
+"""Core management functions of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
+__all__ = [ 'main', 'container', 'exceptions', 'tools', 'settings' ]
+
diff --git a/src/cryptobox/core/container.py b/src/cryptobox/core/container.py
index 539b0fe..c2d4d6b 100644
--- a/src/cryptobox/core/container.py
+++ b/src/cryptobox/core/container.py
@@ -18,21 +18,18 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-## check python version
-import sys
-(ver_major, ver_minor, ver_sub, ver_desc, ver_subsub) = sys.version_info
-if (ver_major < 2) or ((ver_major == 2) and (ver_minor < 4)):
- sys.stderr.write("You need a python version >= 2.4\nCurrent version is:\n %s\n" % sys.version)
- sys.exit(1)
+"""Manage a single container of the CryptoBox
+"""
+
+__revision__ = "$Id"
import subprocess
import os
import re
-import logging
from cryptobox.core.exceptions import *
-ContainerTypes = {
+CONTAINERTYPES = {
"unused":0,
"plain":1,
"luks":2,
@@ -46,11 +43,12 @@ MOUNT_DIR_MARKER = '_cryptobox_mount_dir_'
class CryptoBoxContainer:
+ """Manage a container of the CryptoBox
+ """
__fsTypes = {
- "plain":["ext3", "ext2", "vfat", "reiser"],
+ "plain":["ext3", "ext2", "vfat", "reiserfs"],
"swap":["swap"]}
- # TODO: more filesystem types? / check 'reiser'
__dmDir = "/dev/mapper"
@@ -58,41 +56,58 @@ class CryptoBoxContainer:
def __init__(self, device, cbox):
self.device = device
self.cbox = cbox
- self.log = logging.getLogger("CryptoBox")
- self.resetObject()
+ self.uuid = None
+ self.name = None
+ self.cont_type = None
+ self.mount = None
+ self.umount = None
+ self.attributes = None
+ self.reset_object()
- def getName(self):
+ def get_name(self):
+ """Return a humanly readable name for the container.
+ """
return self.name
- def __setAttributes(self):
+ def __set_attributes(self):
+ """Define the default attributes of a container.
+
+ At least there should be a uuid.
+ Other attributes may be added by features (e.g. automount).
+ """
try:
## is there already an entry in the database?
- self.attributes = self.cbox.prefs.volumesDB[self.getName()]
+ self.attributes = self.cbox.prefs.volumes_db[self.get_name()]
self.attributes["uuid"] = self.uuid
except KeyError:
## set default values
self.attributes = { "uuid": self.uuid }
- self.cbox.prefs.volumesDB[self.getName()] = self.attributes
+ self.cbox.prefs.volumes_db[self.get_name()] = self.attributes
- def setName(self, new_name):
- old_name = self.getName()
- if new_name == self.name: return
+ def set_name(self, new_name):
+ """Define a humanly readable name of this container.
+
+ this also manages the name database
+ """
+ old_name = self.get_name()
+ if new_name == self.name:
+ return
## renaming is not possible, if the volume is active, as the mountpoint name
## is the same as the volume name
- if self.isMounted():
+ if self.is_mounted():
raise CBVolumeIsActive("the container must not be active during renaming")
if not re.search(r'^[a-zA-Z0-9_\.\- ]+$', new_name):
raise CBInvalidName("the supplied new name contains illegal characters")
## check for another partitions with the same name
- if self.cbox.getContainerList(filterName=new_name):
+ if self.cbox.get_container_list(filter_name=new_name):
raise CBNameIsInUse("the supplied new name is already in use for anonther partition")
## maybe there a is an entry in the volumes database (but the partition is not active
try:
## remove possibly existing inactive database item
- del self.cbox.prefs.volumesDB[new_name]
+ del self.cbox.prefs.volumes_db[new_name]
except KeyError:
## no entry - so nothing happens
pass
@@ -100,99 +115,116 @@ class CryptoBoxContainer:
self.name = new_name
## remove old database entry
try:
- del self.cbox.prefs.volumesDB[old_name]
+ del self.cbox.prefs.volumes_db[old_name]
except KeyError:
pass
## set new volumes database entry
- self.cbox.prefs.volumesDB[new_name] = self.attributes
- self.cbox.prefs.volumesDB.write()
+ self.cbox.prefs.volumes_db[new_name] = self.attributes
+ self.cbox.prefs.volumes_db.write()
- def getDevice(self):
+ def get_device(self):
+ """Return the device name of the container
+
+ e.g.: /dev/hdc1
+ """
return self.device
- def getType(self):
- return self.type
+ def get_type(self):
+ """Return the type (int) of this container.
+ """
+ return self.cont_type
- def isMounted(self):
- return os.path.ismount(self.__getMountPoint())
+ def is_mounted(self):
+ """Check if the container is currently mounted.
+ """
+ return os.path.ismount(self.__get_mount_point())
- def getCapacity(self):
- """return the current capacity state of the volume
+ def get_capacity(self):
+ """Return the current capacity state of the volume.
the volume may not be mounted
the result is a tuple of values in megabyte:
(size, available, used)
"""
- info = os.statvfs(self.__getMountPoint())
+ info = os.statvfs(self.__get_mount_point())
return (
int(info.f_bsize*info.f_blocks/1024/1024),
int(info.f_bsize*info.f_bavail/1024/1024),
int(info.f_bsize*(info.f_blocks-info.f_bavail)/1024/1024))
- def getSize(self):
+ def get_size(self):
"""return the size of the block device (_not_ of the filesystem)
the result is a value in megabyte
an error is indicated by "-1"
"""
import cryptobox.core.tools as cbxtools
- return cbxtools.getBlockDeviceSize(self.device)
+ return cbxtools.get_blockdevice_size(self.device)
- def resetObject(self):
+ def reset_object(self):
""" recheck the information about this container
this is especially useful after changing the type via 'create' """
- self.uuid = self.__getUUID()
- self.type = self.__getTypeOfPartition()
- self.name = self.__getNameOfContainer()
- self.__setAttributes()
- if self.type == ContainerTypes["luks"]:
- self.mount = self.__mountLuks
- self.umount = self.__umountLuks
- elif self.type == ContainerTypes["plain"]:
- self.mount = self.__mountPlain
- self.umount = self.__umountPlain
+ self.uuid = self.__get_uuid()
+ self.cont_type = self.__get_type_of_partition()
+ self.name = self.__get_name_of_container()
+ self.__set_attributes()
+ if self.cont_type == CONTAINERTYPES["luks"]:
+ self.mount = self.__mount_luks
+ self.umount = self.__umount_luks
+ elif self.cont_type == CONTAINERTYPES["plain"]:
+ self.mount = self.__mount_plain
+ self.umount = self.__umount_plain
- def create(self, type, password=None):
- old_name = self.getName()
- if type == ContainerTypes["luks"]:
- self.__createLuks(password)
- elif type == ContainerTypes["plain"]:
- self.__createPlain()
+ def create(self, cont_type, password=None):
+ """Format a container.
+
+ Also set a password for encrypted container.
+ """
+ old_name = self.get_name()
+ if cont_type == CONTAINERTYPES["luks"]:
+ self.__create_luks(password)
+ elif cont_type == CONTAINERTYPES["plain"]:
+ self.__create_plain()
else:
- raise CBInvalidType("invalid container type (%d) supplied" % (type, ))
+ raise CBInvalidType("invalid container type (%d) supplied" % (cont_type, ))
## no exception was raised during creation -> we can continue
## reset the properties (encryption state, ...) of the device
- self.resetObject()
- ## restore the old name (must be after resetObject)
- self.setName(old_name)
+ self.reset_object()
+ ## restore the old name (must be after reset_object)
+ self.set_name(old_name)
- def changePassword(self, oldpw, newpw):
- if self.type != ContainerTypes["luks"]:
+ def change_password(self, oldpw, newpw):
+ """Change the password of an encrypted container.
+
+ Raises an exception for plaintext container.
+ """
+ if self.cont_type != CONTAINERTYPES["luks"]:
raise CBInvalidType("changing of password is possible only for luks containers")
if not oldpw:
raise CBInvalidPassword("no old password supplied for password change")
if not newpw:
raise CBInvalidPassword("no new password supplied for password change")
- "return if new and old passwords are the same"
- if oldpw == newpw: return
- if self.isMounted():
+ ## return if new and old passwords are the same
+ if oldpw == newpw:
+ return
+ if self.is_mounted():
raise CBVolumeIsActive("this container is currently active")
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
- "remove any potential open luks mapping"
- self.__umountLuks()
- "create the luks header"
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
+ ## remove any potential open luks mapping
+ self.__umount_luks()
+ ## create the luks header
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
@@ -208,16 +240,17 @@ class CryptoBoxContainer:
proc.stdin.write("%s\n%s" % (oldpw, newpw))
(output, errout) = proc.communicate()
if proc.returncode != 0:
- errorMsg = "Could not add a new luks key: %s - %s" % (output.strip(), errout.strip(), )
- self.log.error(errorMsg)
- raise CBChangePasswordError(errorMsg)
+ error_msg = "Could not add a new luks key: %s - %s" \
+ % (output.strip(), errout.strip(), )
+ self.cbox.log.error(error_msg)
+ raise CBChangePasswordError(error_msg)
## retrieve the key slot we used for unlocking
keys_found = re.search(r'key slot (\d{1,3}) unlocked', output).groups()
if keys_found:
keyslot = int(keys_found[0])
else:
raise CBChangePasswordError("could not get the old key slot")
- "remove the old key"
+ ## remove the old key
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -231,40 +264,43 @@ class CryptoBoxContainer:
"%d" % (keyslot, )])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not remove the old luks key: %s" % (proc.stderr.read().strip(), )
- self.log.error(errorMsg)
- raise CBChangePasswordError(errorMsg)
+ error_msg = "Could not remove the old luks key: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.error(error_msg)
+ raise CBChangePasswordError(error_msg)
- " ****************** internal stuff ********************* "
+ ## ****************** internal stuff *********************
- def __getNameOfContainer(self):
+ def __get_name_of_container(self):
"""retrieve the name of the container by querying the database
call this function only for the initial setup of the container object"""
found_name = None
- for key in self.cbox.prefs.volumesDB.keys():
- if self.cbox.prefs.volumesDB[key]["uuid"] == self.uuid:
+ for key in self.cbox.prefs.volumes_db.keys():
+ if self.cbox.prefs.volumes_db[key]["uuid"] == self.uuid:
found_name = key
- if found_name: return found_name
+ if found_name:
+ return found_name
## there is no name defined for this uuid - we will propose a good one
prefix = self.cbox.prefs["Main"]["DefaultVolumePrefix"]
unused_found = False
counter = 1
while not unused_found:
guess = prefix + str(counter)
- if self.cbox.prefs.volumesDB.has_key(guess):
+ if self.cbox.prefs.volumes_db.has_key(guess):
counter += 1
else:
unused_found = True
return guess
- def __getUUID(self):
- if self.__getTypeOfPartition() == ContainerTypes["luks"]:
- guess = self.__getLuksUUID()
+ def __get_uuid(self):
+ """Retrieve the uuid of the container device.
+ """
+ if self.__get_type_of_partition() == CONTAINERTYPES["luks"]:
+ guess = self.__get_luks_uuid()
else:
- guess = self.__getNonLuksUUID()
+ guess = self.__get_non_luks_uuid()
## did we get a valid value?
if guess:
return guess
@@ -273,7 +309,7 @@ class CryptoBoxContainer:
return self.device.replace(os.path.sep, "_")
- def __getLuksUUID(self):
+ def __get_luks_uuid(self):
"""get uuid for luks devices"""
proc = subprocess.Popen(
shell = False,
@@ -284,17 +320,18 @@ class CryptoBoxContainer:
self.device])
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
- self.cbox.log.info("could not retrieve luks uuid (%s): %s", (self.device, stderr.strip()))
+ self.cbox.log.info("could not retrieve luks uuid (%s): %s",
+ (self.device, stderr.strip()))
return None
return stdout.strip()
- def __getNonLuksUUID(self):
+ def __get_non_luks_uuid(self):
"""return UUID for ext2/3 and vfat filesystems"""
try:
devnull = open(os.devnull, "w")
except IOError:
- self.warn("Could not open %s" % (os.devnull, ))
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
proc = subprocess.Popen(
shell=False,
stdout=subprocess.PIPE,
@@ -309,30 +346,36 @@ class CryptoBoxContainer:
devnull.close()
## execution failed?
if proc.returncode != 0:
- self.log.info("retrieving of partition type (%s) via 'blkid' failed: %s - maybe it is encrypted?" % (self.device, stderr.strip()))
+ self.cbox.log.info("retrieving of partition type (" + str(self.device) \
+ + ") via 'blkid' failed: " + str(stderr.strip()) \
+ + " - maybe it is encrypted?")
return None
## return output of blkid
return stdout.strip()
- def __getTypeOfPartition(self):
- "retrieve the type of the given partition (see cryptobox.core.container.ContainerTypes)"
- if self.__isLuksPartition(): return ContainerTypes["luks"]
- typeOfPartition = self.__getTypeIdOfPartition()
- if typeOfPartition in self.__fsTypes["plain"]:
- return ContainerTypes["plain"]
- if typeOfPartition in self.__fsTypes["swap"]:
- return ContainerTypes["swap"]
- return ContainerTypes["unused"]
+ def __get_type_of_partition(self):
+ """Retrieve the type of the given partition.
+
+ see cryptobox.core.container.CONTAINERTYPES
+ """
+ if self.__is_luks_partition():
+ return CONTAINERTYPES["luks"]
+ type_of_partition = self.__get_type_id_of_partition()
+ if type_of_partition in self.__fsTypes["plain"]:
+ return CONTAINERTYPES["plain"]
+ if type_of_partition in self.__fsTypes["swap"]:
+ return CONTAINERTYPES["swap"]
+ return CONTAINERTYPES["unused"]
- def __getTypeIdOfPartition(self):
+ def __get_type_id_of_partition(self):
"returns the type of the partition (see 'man blkid')"
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
proc = subprocess.Popen(
shell=False,
stdin=None,
@@ -347,19 +390,20 @@ class CryptoBoxContainer:
proc.wait()
output = proc.stdout.read().strip()
if proc.returncode != 0:
- self.log.warn("retrieving of partition type via 'blkid' failed: %s" % (proc.stderr.read().strip(), ))
+ self.cbox.log.warn("retrieving of partition type via 'blkid' failed: %s" % \
+ (proc.stderr.read().strip(), ))
return None
devnull.close()
return output
- def __isLuksPartition(self):
+ def __is_luks_partition(self):
"check if the given device is a luks partition"
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -375,29 +419,30 @@ class CryptoBoxContainer:
return proc.returncode == 0
- def __getMountPoint(self):
+ def __get_mount_point(self):
"return the name of the mountpoint of this volume"
return os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], self.name)
- def __mountLuks(self, password):
+ def __mount_luks(self, password):
"mount a luks partition"
if not password:
raise CBInvalidPassword("no password supplied for luksOpen")
- if self.isMounted(): raise CBVolumeIsActive("this container is already active")
- self.__umountLuks()
+ if self.is_mounted():
+ raise CBVolumeIsActive("this container is already active")
+ self.__umount_luks()
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
- self.__cleanMountDirs()
- if not os.path.exists(self.__getMountPoint()):
- self.__createMountDirectory(self.__getMountPoint())
- if not os.path.exists(self.__getMountPoint()):
- errorMsg = "Could not create mountpoint (%s)" % (self.__getMountPoint(), )
- self.log.error(errorMsg)
- raise CBMountError(errorMsg)
- self.cbox.sendEventNotification("premount", self.__getEventArgs())
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
+ self.__clean_mount_dirs()
+ if not os.path.exists(self.__get_mount_point()):
+ self.__create_mount_directory(self.__get_mount_point())
+ if not os.path.exists(self.__get_mount_point()):
+ err_msg = "Could not create mountpoint (%s)" % (self.__get_mount_point(), )
+ self.cbox.log.error(err_msg)
+ raise CBMountError(err_msg)
+ self.cbox.send_event_notification("premount", self.__get_event_args())
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
@@ -414,9 +459,9 @@ class CryptoBoxContainer:
proc.stdin.write(password)
(output, errout) = proc.communicate()
if proc.returncode != 0:
- errorMsg = "Could not open the luks mapping: %s" % (errout.strip(), )
- self.log.warn(errorMsg)
- raise CBMountError(errorMsg)
+ err_msg = "Could not open the luks mapping: %s" % (errout.strip(), )
+ self.cbox.log.warn(err_msg)
+ raise CBMountError(err_msg)
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -427,25 +472,25 @@ class CryptoBoxContainer:
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"mount",
os.path.join(self.__dmDir, self.name),
- self.__getMountPoint()])
+ self.__get_mount_point()])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
- self.log.warn(errorMsg)
- raise CBMountError(errorMsg)
+ err_msg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.warn(err_msg)
+ raise CBMountError(err_msg)
devnull.close()
- self.cbox.sendEventNotification("postmount", self.__getEventArgs())
+ self.cbox.send_event_notification("postmount", self.__get_event_args())
- def __umountLuks(self):
+ def __umount_luks(self):
"umount a luks partition"
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
- self.cbox.sendEventNotification("preumount", self.__getEventArgs())
- if self.isMounted():
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
+ self.cbox.send_event_notification("preumount", self.__get_event_args())
+ if self.is_mounted():
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -455,12 +500,12 @@ class CryptoBoxContainer:
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"umount",
- self.__getMountPoint()])
+ self.__get_mount_point()])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
- self.log.warn(errorMsg)
- raise CBUmountError(errorMsg)
+ err_msg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.warn(err_msg)
+ raise CBUmountError(err_msg)
if os.path.exists(os.path.join(self.__dmDir, self.name)):
proc = subprocess.Popen(
shell = False,
@@ -476,29 +521,30 @@ class CryptoBoxContainer:
"--batch-mode"])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not remove the luks mapping: %s" % (proc.stderr.read().strip(), )
- self.log.warn(errorMsg)
- raise CBUmountError(errorMsg)
+ err_msg = "Could not remove the luks mapping: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.warn(err_msg)
+ raise CBUmountError(err_msg)
devnull.close()
- self.cbox.sendEventNotification("postumount", self.__getEventArgs())
+ self.cbox.send_event_notification("postumount", self.__get_event_args())
- def __mountPlain(self):
+ def __mount_plain(self):
"mount a plaintext partition"
- if self.isMounted(): raise CBVolumeIsActive("this container is already active")
+ if self.is_mounted():
+ raise CBVolumeIsActive("this container is already active")
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
- self.__cleanMountDirs()
- if not os.path.exists(self.__getMountPoint()):
- self.__createMountDirectory(self.__getMountPoint())
- if not os.path.exists(self.__getMountPoint()):
- errorMsg = "Could not create mountpoint (%s)" % (self.__getMountPoint(), )
- self.log.error(errorMsg)
- raise CBMountError(errorMsg)
- self.cbox.sendEventNotification("premount", self.__getEventArgs())
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
+ self.__clean_mount_dirs()
+ if not os.path.exists(self.__get_mount_point()):
+ self.__create_mount_directory(self.__get_mount_point())
+ if not os.path.exists(self.__get_mount_point()):
+ err_msg = "Could not create mountpoint (%s)" % (self.__get_mount_point(), )
+ self.cbox.log.error(err_msg)
+ raise CBMountError(err_msg)
+ self.cbox.send_event_notification("premount", self.__get_event_args())
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -509,27 +555,28 @@ class CryptoBoxContainer:
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"mount",
self.device,
- self.__getMountPoint()])
+ self.__get_mount_point()])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
- self.log.warn(errorMsg)
- raise CBMountError(errorMsg)
+ err_msg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.warn(err_msg)
+ raise CBMountError(err_msg)
devnull.close()
- self.cbox.sendEventNotification("postmount", self.__getEventArgs())
+ self.cbox.send_event_notification("postmount", self.__get_event_args())
- def __umountPlain(self):
+ def __umount_plain(self):
"umount a plaintext partition"
- if not self.isMounted():
- self.cbox.log.info("trying to umount while volume (%s) is mounted" % self.getDevice())
+ if not self.is_mounted():
+ self.cbox.log.info("trying to umount while volume (%s) is mounted" % \
+ self.get_device())
return
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
- self.cbox.sendEventNotification("preumount", self.__getEventArgs())
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
+ self.cbox.send_event_notification("preumount", self.__get_event_args())
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -539,25 +586,25 @@ class CryptoBoxContainer:
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"umount",
- self.__getMountPoint()])
+ self.__get_mount_point()])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
- self.log.warn(errorMsg)
- raise CBUmountError(errorMsg)
+ err_msg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.warn(err_msg)
+ raise CBUmountError(err_msg)
devnull.close()
- self.cbox.sendEventNotification("postumount", self.__getEventArgs())
+ self.cbox.send_event_notification("postumount", self.__get_event_args())
- def __createPlain(self):
+ def __create_plain(self):
"make a plaintext partition"
- if self.isMounted():
+ if self.is_mounted():
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -568,26 +615,27 @@ class CryptoBoxContainer:
self.device])
proc.wait()
if proc.returncode != 0:
- errorMsg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
- self.log.error(errorMsg)
- raise CBCreateError(errorMsg)
+ err_msg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.error(err_msg)
+ raise CBCreateError(err_msg)
devnull.close()
- def __createLuks(self, password):
- "make a luks partition"
+ def __create_luks(self, password):
+ """Create a luks partition.
+ """
if not password:
raise CBInvalidPassword("no password supplied for new luks mapping")
- if self.isMounted():
+ if self.is_mounted():
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
devnull = None
try:
devnull = open(os.devnull, "w")
except IOError:
- self.log.warn("Could not open %s" % (os.devnull, ))
- "remove any potential open luks mapping"
- self.__umountLuks()
- "create the luks header"
+ self.cbox.log.warn("Could not open %s" % (os.devnull, ))
+ ## remove any potential open luks mapping
+ self.__umount_luks()
+ ## create the luks header
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
@@ -605,10 +653,10 @@ class CryptoBoxContainer:
proc.stdin.write(password)
(output, errout) = proc.communicate()
if proc.returncode != 0:
- errorMsg = "Could not create the luks header: %s" % (errout.strip(), )
- self.log.error(errorMsg)
- raise CBCreateError(errorMsg)
- "open the luks container for mkfs"
+ err_msg = "Could not create the luks header: %s" % (errout.strip(), )
+ self.cbox.log.error(err_msg)
+ raise CBCreateError(err_msg)
+ ## open the luks container for mkfs
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
@@ -625,10 +673,10 @@ class CryptoBoxContainer:
proc.stdin.write(password)
(output, errout) = proc.communicate()
if proc.returncode != 0:
- errorMsg = "Could not open the new luks mapping: %s" % (errout.strip(), )
- self.log.error(errorMsg)
- raise CBCreateError(errorMsg)
- "make the filesystem"
+ err_msg = "Could not open the new luks mapping: %s" % (errout.strip(), )
+ self.cbox.log.error(err_msg)
+ raise CBCreateError(err_msg)
+ ## make the filesystem
proc = subprocess.Popen(
shell = False,
stdin = None,
@@ -638,50 +686,54 @@ class CryptoBoxContainer:
self.cbox.prefs["Programs"]["mkfs-data"],
os.path.join(self.__dmDir, self.name)])
proc.wait()
- "remove the mapping - for every exit status"
- self.__umountLuks()
+ ## remove the mapping - for every exit status
+ self.__umount_luks()
if proc.returncode != 0:
- errorMsg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
- self.log.error(errorMsg)
- "remove the luks mapping"
- raise CBCreateError(errorMsg)
+ err_msg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
+ self.cbox.log.error(err_msg)
+ ## remove the luks mapping
+ raise CBCreateError(err_msg)
devnull.close()
- def __cleanMountDirs(self):
+ def __clean_mount_dirs(self):
""" remove all unnecessary subdirs of the mount parent directory
this should be called for every (u)mount """
subdirs = os.listdir(self.cbox.prefs["Locations"]["MountParentDir"])
- for d in subdirs:
- abs_dir = os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], d)
+ for one_dir in subdirs:
+ abs_dir = os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], one_dir)
if (not os.path.islink(abs_dir)) \
and os.path.isdir(abs_dir) \
and (not os.path.ismount(abs_dir)) \
and (os.path.isfile(os.path.join(abs_dir,MOUNT_DIR_MARKER))) \
and (len(os.listdir(abs_dir)) == 1):
try:
- os.remove(os.path.join(abs_dir,MOUNT_DIR_MARKER))
+ os.remove(os.path.join(abs_dir, MOUNT_DIR_MARKER))
os.rmdir(abs_dir)
- except OSError,errMsg:
+ except OSError, err_msg:
## we do not care too much about unclean cleaning ...
- self.log.info("failed to clean a mountpoint (%s): %s" % (abs_dir,str(errMsg)))
+ self.cbox.log.info("failed to clean a mountpoint (%s): %s" % \
+ (abs_dir, str(err_msg)))
- def __createMountDirectory(self,dirname):
+ def __create_mount_directory(self, dirname):
"""create and mark a mount directory
this marking helps to remove old mountdirs safely"""
os.mkdir(dirname)
try:
- f = file(os.path.join(dirname,MOUNT_DIR_MARKER),"w")
- f.close()
- except OSError,errMsg:
+ mark_file = file(os.path.join(dirname, MOUNT_DIR_MARKER), "w")
+ mark_file.close()
+ except OSError, err_msg:
## we do not care too much about the marking
- self.log.info("failed to mark a mountpoint (%s): %s" % (dirname,str(errMsg)))
+ self.cbox.log.info("failed to mark a mountpoint (%s): %s" % (dirname, str(err_msg)))
- def __getEventArgs(self):
- """return an array of arguments for event scripts handling pre/post-mount/umount
- events"""
- typeText = [e for e in ContainerTypes.keys() if ContainerTypes[e] == self.getType()][0]
- return [self.getDevice(), self.getName(), typeText, self.__getMountPoint()]
+ def __get_event_args(self):
+ """Return an array of arguments for event scripts.
+
+ for now supported: pre/post-mount/umount events
+ """
+ type_text = [e for e in CONTAINERTYPES.keys()
+ if CONTAINERTYPES[e] == self.get_type()][0]
+ return [self.get_device(), self.get_name(), type_text, self.__get_mount_point()]
diff --git a/src/cryptobox/core/exceptions.py b/src/cryptobox/core/exceptions.py
index c80b07d..c3f0343 100644
--- a/src/cryptobox/core/exceptions.py
+++ b/src/cryptobox/core/exceptions.py
@@ -22,6 +22,8 @@
exceptions of the cryptobox package
"""
+__revision__ = "$Id"
+
class CBError(Exception):
"""base class for exceptions of the cryptobox"""
@@ -54,13 +56,16 @@ class CBConfigUndefinedError(CBConfigError):
self.name = name
def __str__(self):
- # is it a settings or a section?
+ """Output the appropriate string: for a setting or a section.
+ """
if self.name:
# setting
- return "undefined configuration setting: [%s]->%s - please check your configuration file" % (self.section, self.name)
+ return "undefined configuration setting: [" + str(self.section) \
+ + "]->" + str(self.name) + " - please check your configuration file"
else:
# section
- return "undefined configuration section: [%s] - please check your configuration file" % (self.section, )
+ return "undefined configuration section: [" + str(self.section) \
+ + "] - please check your configuration file"
@@ -73,8 +78,12 @@ class CBConfigInvalidValueError(CBConfigError):
self.value = value
self.reason = reason
+
def __str__(self):
- return "invalid configuration setting [%s]->%s (%s): %s" % (self.section, self.name, self.value, self.reason)
+ """Return the error description.
+ """
+ return "invalid configuration setting [%s]->%s (%s): %s" % \
+ (self.section, self.name, self.value, self.reason)
class CBEnvironmentError(CBError):
@@ -86,42 +95,58 @@ class CBEnvironmentError(CBError):
self.desc = desc
def __str__(self):
+ """Return the error description.
+ """
return "misconfiguration detected: %s" % self.desc
class CBContainerError(CBError):
- """any error raised while manipulating a cryptobox container"""
+ """Any error raised while manipulating a cryptobox container.
+ """
+
- def __init__(self, desc):
- self.desc = desc
-
- def __str__(self):
- return self.desc
-
class CBCreateError(CBContainerError):
+ """Raised if a container could not be created (formatted).
+ """
pass
class CBVolumeIsActive(CBContainerError):
+ """Raised if a container was active even if it may not for a specific action.
+ """
pass
class CBInvalidName(CBContainerError):
+ """Raised if someone tried to set an invalid container name.
+ """
pass
class CBNameIsInUse(CBContainerError):
+ """Raised if the new name of a container is already in use.
+ """
pass
class CBInvalidType(CBContainerError):
+ """Raised if a container is of an invalid type for a choosen action.
+ """
pass
class CBInvalidPassword(CBContainerError):
+ """Someone tried to open an ecnrypted container with the wrong password.
+ """
pass
class CBChangePasswordError(CBContainerError):
+ """Changing of the password of an encrypted container failed.
+ """
pass
class CBMountError(CBContainerError):
+ """Failed to mount a container.
+ """
pass
class CBUmountError(CBContainerError):
+ """Failed to umount a container.
+ """
pass
diff --git a/src/cryptobox/core/main.py b/src/cryptobox/core/main.py
index e0d6ba5..e0baf2a 100644
--- a/src/cryptobox/core/main.py
+++ b/src/cryptobox/core/main.py
@@ -22,23 +22,17 @@
This is the web interface for a fileserver managing encrypted filesystems.
'''
-# check python version
-import sys
-(ver_major, ver_minor, ver_sub, ver_desc, ver_subsub) = sys.version_info
-if (ver_major < 2) or ((ver_major == 2) and (ver_minor < 4)):
- sys.stderr.write("You need a python version >= 2.4\nCurrent version is:\n %s\n" % sys.version)
- sys.exit(1)
+__revision__ = "$Id"
+import sys
import cryptobox.core.container as cbxContainer
-from cryptobox.core.exceptions import *
+from cryptobox.core.exceptions import CBEnvironmentError, CBConfigUndefinedError
import re
import os
import cryptobox.core.tools as cbxTools
import subprocess
-VERSION = "0.3~1"
-
class CryptoBox:
'''this class rules them all!
@@ -48,14 +42,15 @@ class CryptoBox:
def __init__(self, config_file=None):
import cryptobox.core.settings as cbxSettings
- self.log = self.__getStartupLogger()
+ self.log = self.__get_startup_logger()
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
- self.__runTests()
+ self.__run_tests()
+ self.__containers = []
+ self.reread_container_list()
- def __getStartupLogger(self):
- import logging
- '''initialises the logging system
+ def __get_startup_logger(self):
+ """Initialize the configured logging facility of the CryptoBox.
use it with: 'self.log.[debug|info|warning|error|critical](logmessage)'
all classes should get the logging instance during __init__:
@@ -63,13 +58,15 @@ class CryptoBox:
first we output all warnings/errors to stderr
as soon as we opened the config file successfully, we redirect debug output
- to the configured destination'''
+ to the configured destination
+ """
+ import logging
## basicConfig(...) needs python >= 2.4
try:
log_handler = logging.getLogger("CryptoBox")
logging.basicConfig(
- format='%(asctime)s CryptoBox %(levelname)s: %(message)s',
- stderr=sys.stderr)
+ format = '%(asctime)s CryptoBox %(levelname)s: %(message)s',
+ stderr = sys.stderr)
log_handler.setLevel(logging.ERROR)
log_handler.info("loggingsystem is up'n running")
## from now on everything can be logged via self.log...
@@ -78,19 +75,15 @@ class CryptoBox:
return log_handler
- # do some initial checks
- def __runTests(self):
- #self.__runTestUID()
- self.__runTestRootPriv()
+ def __run_tests(self):
+ """Do some initial tests.
+ """
+ self.__run_test_root_priv()
- def __runTestUID(self):
- if os.geteuid() == 0:
- raise CBEnvironmentError("you may not run the cryptobox as root")
-
-
- def __runTestRootPriv(self):
- """try to run 'super' with 'CryptoBoxRootActions'"""
+ def __run_test_root_priv(self):
+ """Try to run 'super' with 'CryptoBoxRootActions'.
+ """
try:
devnull = open(os.devnull, "w")
except IOError:
@@ -110,46 +103,39 @@ class CryptoBox:
stderr = devnull,
args = [prog_super, prog_rootactions, "check"])
except OSError:
- raise CBEnvironmentError("failed to execute 'super' (%s)" % self.prefs["Programs"]["super"])
+ raise CBEnvironmentError(
+ "failed to execute 'super' (%s)" % self.prefs["Programs"]["super"])
proc.wait()
if proc.returncode != 0:
- raise CBEnvironmentError("failed to call CryptoBoxRootActions (%s) via 'super' - maybe you did not add the appropriate line to /etc/super.tab?" % prog_rootactions)
+ raise CBEnvironmentError("failed to call CryptoBoxRootActions ("
+ + prog_rootactions + ") via 'super' - maybe you did not add the "
+ + "appropriate line to '/etc/super.tab'?")
- # this method just demonstrates inheritance effects - may be removed
- def cbx_inheritance_test(self, string="you lucky widow"):
- self.log.info(string)
-
+ def reread_container_list(self):
+ """Reinitialize the list of available containers.
-# RFC: why should CryptoBoxProps inherit CryptoBox? [l]
-# RFC: shouldn't we move all useful functions of CryptoBoxProps to CryptoBox? [l]
-class CryptoBoxProps(CryptoBox):
- '''Get and set the properties of a CryptoBox
-
- This class contains all available devices that may be accessed.
- All properties of the cryptobox can be accessed by this class.
- '''
-
- def __init__(self, config_file=None):
- '''read config and fill class variables'''
- CryptoBox.__init__(self, config_file)
- self.reReadContainerList()
-
-
- def reReadContainerList(self):
+ This should be called whenever the available containers may have changed.
+ E.g.: after partitioning and after device addition/removal
+ """
self.log.debug("rereading container list")
- self.containers = []
- for device in cbxTools.getAvailablePartitions():
- if self.isDeviceAllowed(device) and not self.isConfigPartition(device):
- self.containers.append(cbxContainer.CryptoBoxContainer(device, self))
+ self.__containers = []
+ for device in cbxTools.get_available_partitions():
+ if self.is_device_allowed(device) and not self.is_config_partition(device):
+ self.__containers.append(cbxContainer.CryptoBoxContainer(device, self))
## sort by container name
- self.containers.sort(cmp = lambda x,y: x.getName() < y.getName() and -1 or 1)
+ self.__containers.sort(cmp = lambda x, y: x.get_name() < y.get_name() and -1 or 1)
- def isConfigPartition(self, device):
+ def is_config_partition(self, device):
+ """Check if a given partition contains configuration informations.
+
+ The check is done by comparing the label of the filesystem with a string.
+ """
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE,
args = [
self.prefs["Programs"]["blkid"],
"-c", os.path.devnull,
@@ -160,70 +146,77 @@ class CryptoBoxProps(CryptoBox):
return output.strip() == self.prefs["Main"]["ConfigVolumeLabel"]
- def isDeviceAllowed(self, devicename):
+ def is_device_allowed(self, devicename):
"check if a device is white-listed for being used as cryptobox containers"
import types
allowed = self.prefs["Main"]["AllowedDevices"]
- if type(allowed) == types.StringType: allowed = [allowed]
+ if type(allowed) == types.StringType:
+ allowed = [allowed]
for a_dev in allowed:
- "remove double dots and so on ..."
+ ## remove double dots and so on ...
real_device = os.path.realpath(devicename)
- if a_dev and re.search('^' + a_dev, real_device): return True
+ if a_dev and re.search('^' + a_dev, real_device):
+ return True
return False
- def getLogData(self, lines=None, maxSize=None):
+ def get_log_data(self, lines=None, max_size=None):
"""get the most recent log entries of the cryptobox
- the maximum number and size of these entries can be limited by 'lines' and 'maxSize'
+ the maximum number and size of these entries can be limited by
+ 'lines' and 'max_size'
"""
# return nothing if the currently selected log output is not a file
try:
- if self.prefs["Log"]["Destination"].upper() != "FILE": return []
+ if self.prefs["Log"]["Destination"].upper() != "FILE":
+ return []
log_file = self.prefs["Log"]["Details"]
except KeyError:
- self.log.error("could not evaluate one of the following config settings: [Log]->Destination or [Log]->Details")
+ self.log.error("could not evaluate one of the following config settings: "
+ + "[Log]->Destination or [Log]->Details")
return []
try:
- fd = open(log_file, "r")
- if maxSize: fd.seek(-maxSize, 2) # seek relative to the end of the file
- content = fd.readlines()
- fd.close()
+ 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.log.warn("failed to read the log file (%s)" % log_file)
return []
- if lines: content = content[-lines:]
+ if lines:
+ content = content[-lines:]
content.reverse()
return content
- def getContainerList(self, filterType=None, filterName=None):
+ def get_container_list(self, filter_type=None, filter_name=None):
"retrieve the list of all containers of this cryptobox"
try:
- result = self.containers[:]
- if filterType != None:
- if filterType in range(len(cbxContainer.ContainerTypes)):
- return [e for e in self.containers if e.getType() == filterType]
+ result = self.__containers[:]
+ if filter_type != None:
+ if filter_type in range(len(cbxContainer.CONTAINERTYPES)):
+ return [e for e in self.__containers if e.get_type() == filter_type]
else:
- self.log.info("invalid filterType (%d)" % filterType)
+ self.log.info("invalid filter_type (%d)" % filter_type)
result.clear()
- if filterName != None:
- result = [e for e in self.containers if e.getName() == filterName]
+ if filter_name != None:
+ result = [e for e in self.__containers if e.get_name() == filter_name]
return result
except AttributeError:
return []
- def getContainer(self, device):
+ def get_container(self, device):
"retrieve the container element for this device"
- all = [e for e in self.getContainerList() if e.device == device]
+ all = [e for e in self.get_container_list() if e.device == device]
if all:
return all[0]
else:
return None
- def sendEventNotification(self, event, event_infos):
+ def send_event_notification(self, event, event_infos):
"""call all available scripts in the event directory with some event information"""
event_dir = self.prefs["Locations"]["EventDir"]
for fname in os.listdir(event_dir):
@@ -240,11 +233,14 @@ class CryptoBoxProps(CryptoBox):
args = cmd_args)
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
- self.log.warn("an event script (%s) failed (exitcode=%d) to handle an event (%s): %s" % (real_fname, proc.returncode, event, stderr.strip()))
+ self.log.warn(
+ "an event script (%s) failed (exitcode=%d) to handle an event (%s): %s" %
+ (real_fname, proc.returncode, event, stderr.strip()))
else:
- self.log.info("event handler (%s) finished successfully: %s" % (real_fname, event))
+ self.log.info("event handler (%s) finished successfully: %s" %
+ (real_fname, event))
if __name__ == "__main__":
- cb = CryptoBoxProps()
+ CryptoBox()
diff --git a/src/cryptobox/core/settings.py b/src/cryptobox/core/settings.py
index 6162cdf..f519ea0 100644
--- a/src/cryptobox/core/settings.py
+++ b/src/cryptobox/core/settings.py
@@ -18,22 +18,21 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Manage the configuration of a CryptoBox
+"""
+
+__revision__ = "$Id"
+
from cryptobox.core.exceptions import *
import logging
-try:
- import validate
-except:
- raise CBEnvironmentError("couldn't import 'validate'! Try 'apt-get install python-formencode'.")
-import os
import subprocess
-try:
- import configobj ## needed for reading and writing of the config file
-except:
- raise CBEnvironmentError("couldn't import 'configobj'! Try 'apt-get install python-configobj'.")
-
+import os
+import configobj, validate
class CryptoBoxSettings:
+ """Manage the various configuration files of the CryptoBox
+ """
CONF_LOCATIONS = [
"./cryptobox.conf",
@@ -47,76 +46,85 @@ class CryptoBoxSettings:
def __init__(self, config_file=None):
self.log = logging.getLogger("CryptoBox")
- config_file = self.__getConfigFileName(config_file)
+ config_file = self.__get_config_filename(config_file)
self.log.info("loading config file: %s" % config_file)
- self.prefs = self.__getPreferences(config_file)
- self.__validateConfig()
- self.__configureLogHandler()
- self.__checkUnknownPreferences()
- self.preparePartition()
- self.volumesDB = self.__getVolumesDatabase()
- self.pluginConf = self.__getPluginConfig()
- self.userDB = self.__getUserDB()
- self.misc_files = self.__getMiscFiles()
+ self.prefs = self.__get_preferences(config_file)
+ self.__validate_config()
+ self.__configure_log_handler()
+ self.__check_unknown_preferences()
+ self.prepare_partition()
+ self.volumes_db = self.__get_volumes_database()
+ self.plugin_conf = self.__get_plugin_config()
+ self.user_db = self.__get_user_db()
+ self.misc_files = self.__get_misc_files()
def write(self):
"""
write all local setting files including the content of the "misc" subdirectory
"""
- ok = True
+ status = True
try:
- self.volumesDB.write()
+ self.volumes_db.write()
except IOError:
self.log.warn("could not save the volume database")
- ok = False
+ status = False
try:
- self.pluginConf.write()
+ self.plugin_conf.write()
except IOError:
self.log.warn("could not save the plugin configuration")
- ok = False
+ status = False
try:
- self.userDB.write()
+ self.user_db.write()
except IOError:
self.log.warn("could not save the user database")
- ok = False
+ status = False
for misc_file in self.misc_files:
if not misc_file.save():
self.log.warn("could not save a misc setting file (%s)" % misc_file.filename)
- ok = False
- return ok
+ status = False
+ return status
- def requiresPartition(self):
+ def requires_partition(self):
return bool(self.prefs["Main"]["UseConfigPartition"])
- def getActivePartition(self):
+ def get_active_partition(self):
+ """Return the currently active cnfiguration partition.
+ """
settings_dir = self.prefs["Locations"]["SettingsDir"]
- if not os.path.ismount(settings_dir): return None
+ if not os.path.ismount(settings_dir):
+ return None
for line in file("/proc/mounts"):
fields = line.split(" ")
mount_dir = fields[1]
try:
- if os.path.samefile(mount_dir, settings_dir): return fields[0]
+ if os.path.samefile(mount_dir, settings_dir):
+ return fields[0]
except OSError:
pass
## no matching entry found
return None
- def mountPartition(self):
+ def mount_partition(self):
+ """Mount a config partition.
+ """
self.log.debug("trying to mount configuration partition")
- if not self.requiresPartition():
- self.log.warn("mountConfigPartition: configuration partition is not required - mounting anyway")
- if self.getActivePartition():
- self.log.warn("mountConfigPartition: configuration partition already mounted - not mounting again")
+ if not self.requires_partition():
+ self.log.warn("mountConfigPartition: configuration partition is "
+ + "not required - mounting anyway")
+ if self.get_active_partition():
+ self.log.warn("mountConfigPartition: configuration partition already "
+ + "mounted - not mounting again")
return False
- confPartitions = self.getAvailablePartitions()
- if not confPartitions:
- self.log.error("no configuration partitions found - you have to create it first")
+ conf_partitions = self.get_available_partitions()
+ if not conf_partitions:
+ self.log.error("no configuration partition found - you have to create "
+ + "it first")
return False
- partition = confPartitions[0]
+ partition = conf_partitions[0]
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
@@ -136,8 +144,10 @@ class CryptoBoxSettings:
return True
- def umountPartition(self):
- if not self.getActivePartition():
+ def umount_partition(self):
+ """Umount the currently active configuration partition.
+ """
+ if not self.get_active_partition():
self.log.warn("umountConfigPartition: no configuration partition mounted")
return False
proc = subprocess.Popen(
@@ -158,7 +168,7 @@ class CryptoBoxSettings:
return True
- def getAvailablePartitions(self):
+ def get_available_partitions(self):
"""returns a sequence of found config partitions"""
proc = subprocess.Popen(
shell = False,
@@ -169,14 +179,16 @@ class CryptoBoxSettings:
"-t", "LABEL=%s" % self.prefs["Main"]["ConfigVolumeLabel"] ])
(output, error) = proc.communicate()
if output:
- return [e.strip().split(":",1)[0] for e in output.splitlines()]
+ return [e.strip().split(":", 1)[0] for e in output.splitlines()]
else:
return []
- def preparePartition(self):
- if self.requiresPartition() and not self.getActivePartition():
- self.mountPartition()
+ def prepare_partition(self):
+ """Mount a config partition if necessary.
+ """
+ if self.requires_partition() and not self.get_active_partition():
+ self.mount_partition()
def __getitem__(self, key):
@@ -184,7 +196,9 @@ class CryptoBoxSettings:
return self.prefs[key]
- def __getPreferences(self, config_file):
+ def __get_preferences(self, config_file):
+ """Load the CryptoBox configuration.
+ """
import StringIO
config_rules = StringIO.StringIO(self.validation_spec)
try:
@@ -192,86 +206,111 @@ class CryptoBoxSettings:
if prefs:
self.log.info("found config: %s" % prefs.items())
else:
- raise CBConfigUnavailableError("failed to load the config file: %s" % config_file)
+ raise CBConfigUnavailableError(
+ "failed to load the config file: %s" % config_file)
except IOError:
- raise CBConfigUnavailableError("unable to open the config file: %s" % config_file)
+ raise CBConfigUnavailableError(
+ "unable to open the config file: %s" % config_file)
return prefs
- def __validateConfig(self):
+ def __validate_config(self):
+ """Check the configuration settings and cast value types.
+ """
result = self.prefs.validate(CryptoBoxSettingsValidator(), preserve_errors=True)
error_list = configobj.flatten_errors(self.prefs, result)
- if not error_list: return
- errorMsgs = []
+ if not error_list:
+ return
+ error_msgs = []
for sections, key, text in error_list:
section_name = "->".join(sections)
if not text:
- errorMsg = "undefined configuration value (%s) in section '%s'" % (key, section_name)
+ error_msg = "undefined configuration value (%s) in section '%s'" % \
+ (key, section_name)
else:
- errorMsg = "invalid configuration value (%s) in section '%s': %s" % (key, section_name, text)
- errorMsgs.append(errorMsg)
- raise CBConfigError, "\n".join(errorMsgs)
+ error_msg = "invalid configuration value (%s) in section '%s': %s" % \
+ (key, section_name, text)
+ error_msgs.append(error_msg)
+ raise CBConfigError, "\n".join(error_msgs)
- def __checkUnknownPreferences(self):
+ def __check_unknown_preferences(self):
+ """Check the configuration file for unknown settings to avoid spelling mistakes.
+ """
import StringIO
- config_rules = configobj.ConfigObj(StringIO.StringIO(self.validation_spec), list_values=False)
- self.__recursiveConfigSectionCheck("", self.prefs, config_rules)
+ config_rules = configobj.ConfigObj(StringIO.StringIO(self.validation_spec),
+ list_values=False)
+ self.__recursive_section_check("", self.prefs, config_rules)
- def __recursiveConfigSectionCheck(self, section_path, section_config, section_rules):
- """should be called by '__checkUnknownPreferences' for every section
+ def __recursive_section_check(self, section_path, section_config, section_rules):
+ """should be called by '__check_unknown_preferences' for every section
sends a warning message to the logger for every undefined (see validation_spec)
configuration setting
"""
- for e in section_config.keys():
- element_path = section_path + e
- if e in section_rules.keys():
- if isinstance(section_config[e], configobj.Section):
- if isinstance(section_rules[e], configobj.Section):
- self.__recursiveConfigSectionCheck(element_path + "->", section_config[e], section_rules[e])
+ for section in section_config.keys():
+ element_path = section_path + section
+ if section in section_rules.keys():
+ if isinstance(section_config[section], configobj.Section):
+ if isinstance(section_rules[section], configobj.Section):
+ self.__recursive_section_check(element_path + "->",
+ section_config[section], section_rules[section])
else:
- self.log.warn("configuration setting should be a value instead of a section name: %s" % element_path)
+ self.log.warn("configuration setting should be a value "
+ + "instead of a section name: %s" % element_path)
else:
- if not isinstance(section_rules[e], configobj.Section):
+ if not isinstance(section_rules[section], configobj.Section):
pass # good - the setting is valid
else:
- self.log.warn("configuration setting should be a section name instead of a value: %s" % element_path)
+ self.log.warn("configuration setting should be a section "
+ + "name instead of a value: %s" % element_path)
else:
self.log.warn("unknown configuration setting: %s" % element_path)
- def __getPluginConfig(self):
+ def __get_plugin_config(self):
+ """Load the plugin configuration file if it exists.
+ """
import StringIO
plugin_rules = StringIO.StringIO(self.pluginValidationSpec)
try:
try:
- pluginConf_file = os.path.join(self.prefs["Locations"]["SettingsDir"], self.PLUGINCONF_FILE)
+ plugin_conf_file = os.path.join(
+ self.prefs["Locations"]["SettingsDir"], self.PLUGINCONF_FILE)
except KeyError:
raise CBConfigUndefinedError("Locations", "SettingsDir")
except SyntaxError:
- raise CBConfigInvalidValueError("Locations", "SettingsDir", pluginConf_file, "failed to interprete the filename of the plugin config file correctly (%s)" % pluginConf_file)
- ## create pluginConf_file if necessary
- if os.path.exists(pluginConf_file):
- pluginConf = configobj.ConfigObj(pluginConf_file, configspec=plugin_rules)
+ raise CBConfigInvalidValueError("Locations", "SettingsDir", plugin_conf_file,
+ "failed to interprete the filename of the plugin config file "
+ + "correctly (%s)" % plugin_conf_file)
+ ## create plugin_conf_file if necessary
+ if os.path.exists(plugin_conf_file):
+ plugin_conf = configobj.ConfigObj(plugin_conf_file, configspec=plugin_rules)
else:
- pluginConf = configobj.ConfigObj(pluginConf_file, configspec=plugin_rules, create_empty=True)
+ plugin_conf = configobj.ConfigObj(plugin_conf_file, configspec=plugin_rules,
+ create_empty=True)
## validate and convert values according to the spec
- pluginConf.validate(validate.Validator())
- ## check if pluginConf_file file was created successfully?
- if not os.path.exists(pluginConf_file):
- raise CBEnvironmentError("failed to create plugin configuration file (%s)" % pluginConf_file)
- return pluginConf
+ plugin_conf.validate(validate.Validator())
+ ## check if plugin_conf_file file was created successfully?
+ if not os.path.exists(plugin_conf_file):
+ raise CBEnvironmentError(
+ "failed to create plugin configuration file (%s)" % plugin_conf_file)
+ return plugin_conf
- def __getVolumesDatabase(self):
+ def __get_volumes_database(self):
+ """Load the volume database file if it exists.
+ """
try:
try:
- conf_file = os.path.join(self.prefs["Locations"]["SettingsDir"], self.VOLUMESDB_FILE)
+ conf_file = os.path.join(
+ self.prefs["Locations"]["SettingsDir"], self.VOLUMESDB_FILE)
except KeyError:
raise CBConfigUndefinedError("Locations", "SettingsDir")
except SyntaxError:
- raise CBConfigInvalidValueError("Locations", "SettingsDir", conf_file, "failed to interprete the filename of the volume database correctly (%s)" % conf_file)
+ raise CBConfigInvalidValueError("Locations", "SettingsDir", conf_file,
+ "failed to interprete the filename of the volume database "
+ + "correctly (%s)" % conf_file)
## create conf_file if necessary
if os.path.exists(conf_file):
conf = configobj.ConfigObj(conf_file)
@@ -279,36 +318,48 @@ class CryptoBoxSettings:
conf = configobj.ConfigObj(conf_file, create_empty=True)
## check if conf_file file was created successfully?
if not os.path.exists(conf_file):
- raise CBEnvironmentError("failed to create volume database file (%s)" % conf_file)
+ raise CBEnvironmentError(
+ "failed to create volume database file (%s)" % conf_file)
return conf
- def __getUserDB(self):
+ def __get_user_db(self):
+ """Load the user database file if it exists.
+ """
import StringIO, sha
- userDB_rules = StringIO.StringIO(self.userDatabaseSpec)
+ user_db_rules = StringIO.StringIO(self.userDatabaseSpec)
try:
try:
- userDB_file = os.path.join(self.prefs["Locations"]["SettingsDir"], self.USERDB_FILE)
+ user_db_file = os.path.join(
+ self.prefs["Locations"]["SettingsDir"], self.USERDB_FILE)
except KeyError:
raise CBConfigUndefinedError("Locations", "SettingsDir")
except SyntaxError:
- raise CBConfigInvalidValueError("Locations", "SettingsDir", userDB_file, "failed to interprete the filename of the users database file correctly (%s)" % userDB_file)
- ## create userDB_file if necessary
- if os.path.exists(userDB_file):
- userDB = configobj.ConfigObj(userDB_file, configspec=userDB_rules)
+ raise CBConfigInvalidValueError("Locations", "SettingsDir", user_db_file,
+ "failed to interprete the filename of the users database file "
+ + "correctly (%s)" % user_db_file)
+ ## create user_db_file if necessary
+ if os.path.exists(user_db_file):
+ user_db = configobj.ConfigObj(user_db_file, configspec=user_db_rules)
else:
- userDB = configobj.ConfigObj(userDB_file, configspec=userDB_rules, create_empty=True)
+ user_db = configobj.ConfigObj(user_db_file, configspec=user_db_rules,
+ create_empty=True)
## validate and set default value for "admin" user
- userDB.validate(validate.Validator())
- ## check if userDB file was created successfully?
- if not os.path.exists(userDB_file):
- raise CBEnvironmentError("failed to create user database file (%s)" % userDB_file)
+ user_db.validate(validate.Validator())
+ ## check if user_db file was created successfully?
+ if not os.path.exists(user_db_file):
+ raise CBEnvironmentError(
+ "failed to create user database file (%s)" % user_db_file)
## define password hash function - never use "sha" directly - SPOT
- userDB.getDigest = lambda password: sha.new(password).hexdigest()
- return userDB
+ user_db.get_digest = lambda password: sha.new(password).hexdigest()
+ return user_db
- def __getMiscFiles(self):
+ def __get_misc_files(self):
+ """Load miscelleanous configuration files.
+
+ e.g.: an ssl certificate, ...
+ """
misc_dir = os.path.join(self.prefs["Locations"]["SettingsDir"], "misc")
if (not os.path.isdir(misc_dir)) or (not os.access(misc_dir, os.X_OK)):
return []
@@ -317,8 +368,9 @@ class CryptoBoxSettings:
if os.path.isfile(os.path.join(misc_dir, f))]
- def __getConfigFileName(self, config_file):
- # search for the configuration file
+ def __get_config_filename(self, config_file):
+ """Search for the configuration file.
+ """
import types
if config_file is None:
# no config file was specified - we will look for it in the ususal locations
@@ -332,13 +384,17 @@ class CryptoBoxSettings:
else:
# a config file was specified (e.g. via command line)
if type(config_file) != types.StringType:
- raise CBConfigUnavailableError("invalid config file specified: %s" % config_file)
+ raise CBConfigUnavailableError(
+ "invalid config file specified: %s" % config_file)
if not os.path.exists(config_file):
- raise CBConfigUnavailableError("could not find the specified configuration file (%s)" % config_file)
+ raise CBConfigUnavailableError(
+ "could not find the specified configuration file (%s)" % config_file)
return config_file
- def __configureLogHandler(self):
+ def __configure_log_handler(self):
+ """Configure the log handler of the CryptoBox according to the config.
+ """
try:
log_level = self.prefs["Log"]["Level"].upper()
log_level_avail = ["DEBUG", "INFO", "WARN", "ERROR"]
@@ -347,15 +403,18 @@ class CryptoBoxSettings:
except KeyError:
raise CBConfigUndefinedError("Log", "Level")
except TypeError:
- raise CBConfigInvalidValueError("Log", "Level", log_level, "invalid log level: only %s are allowed" % log_level_avail)
+ raise CBConfigInvalidValueError("Log", "Level", log_level,
+ "invalid log level: only %s are allowed" % log_level_avail)
try:
try:
log_handler = logging.FileHandler(self.prefs["Log"]["Details"])
except KeyError:
raise CBConfigUndefinedError("Log", "Details")
except IOError:
- raise CBEnvironmentError("could not create the log file (%s)" % self.prefs["Log"]["Details"])
- log_handler.setFormatter(logging.Formatter('%(asctime)s CryptoBox %(levelname)s: %(message)s'))
+ raise CBEnvironmentError("could not create the log file (%s)" % \
+ self.prefs["Log"]["Details"])
+ log_handler.setFormatter(
+ logging.Formatter('%(asctime)s CryptoBox %(levelname)s: %(message)s'))
cbox_log = logging.getLogger("CryptoBox")
## remove previous handlers
cbox_log.handlers = []
@@ -364,7 +423,7 @@ class CryptoBoxSettings:
## do not call parent's handlers
cbox_log.propagate = False
## 'log_level' is a string -> use 'getattr'
- cbox_log.setLevel(getattr(logging,log_level))
+ cbox_log.setLevel(getattr(logging, log_level))
## the logger named "CryptoBox" is configured now
@@ -420,16 +479,20 @@ admin = string(default=d033e22ae348aeb5660fc2140aec35850c4da997)
class CryptoBoxSettingsValidator(validate.Validator):
+ """Some custom configuration check functions.
+ """
def __init__(self):
validate.Validator.__init__(self)
- self.functions["directoryExists"] = self.check_directoryExists
- self.functions["fileExecutable"] = self.check_fileExecutable
- self.functions["fileWriteable"] = self.check_fileWriteable
- self.functions["listOfExistingDirectories"] = self.check_listOfExistingDirectories
+ self.functions["directoryExists"] = self.check_directory_exists
+ self.functions["fileExecutable"] = self.check_file_executable
+ self.functions["fileWriteable"] = self.check_file_writeable
+ self.functions["listOfExistingDirectories"] = self.check_existing_directories
- def check_directoryExists(self, value):
+ def check_directory_exists(self, value):
+ """Is the directory accessible?
+ """
dir_path = os.path.abspath(value)
if not os.path.isdir(dir_path):
raise validate.VdtValueError("%s (not found)" % value)
@@ -438,7 +501,9 @@ class CryptoBoxSettingsValidator(validate.Validator):
return dir_path
- def check_fileExecutable(self, value):
+ def check_file_executable(self, value):
+ """Is the file executable?
+ """
file_path = os.path.abspath(value)
if not os.path.isfile(file_path):
raise validate.VdtValueError("%s (not found)" % value)
@@ -447,7 +512,9 @@ class CryptoBoxSettingsValidator(validate.Validator):
return file_path
- def check_fileWriteable(self, value):
+ def check_file_writeable(self, value):
+ """Is the file writeable?
+ """
file_path = os.path.abspath(value)
if os.path.isfile(file_path):
if not os.access(file_path, os.W_OK):
@@ -460,18 +527,22 @@ class CryptoBoxSettingsValidator(validate.Validator):
return file_path
- def check_listOfExistingDirectories(self, value):
+ def check_existing_directories(self, value):
+ """Are these directories accessible?
+ """
if not value:
raise validate.VdtValueError("no plugin directory specified")
- if not isinstance(value,list):
+ if not isinstance(value, list):
value = [value]
result = []
- for d in value:
- dir_path = os.path.abspath(d)
+ for one_dir in value:
+ dir_path = os.path.abspath(one_dir)
if not os.path.isdir(dir_path):
- raise validate.VdtValueError("%s (plugin directory not found)" % d)
+ raise validate.VdtValueError(
+ "%s (plugin directory not found)" % one_dir)
if not os.access(dir_path, os.X_OK):
- raise validate.VdtValueError("%s (access denied for plugin directory)" % d)
+ raise validate.VdtValueError(
+ "%s (access denied for plugin directory)" % one_dir)
result.append(dir_path)
return result
@@ -484,19 +555,25 @@ class MiscConfigFile:
def __init__(self, filename, logger):
self.filename = filename
self.log = logger
+ self.content = None
self.load()
def load(self):
- fd = open(self.filename, "rb")
+ """Load a configuration file into memory.
+ """
+ fdesc = open(self.filename, "rb")
## limit the maximum size
- self.content = fd.read(self.maxSize)
- if fd.tell() == self.maxSize:
- self.log.warn("file in misc settings directory (%s) is bigger than allowed (%s)" % (self.filename, self.maxSize))
- fd.close()
+ self.content = fdesc.read(self.maxSize)
+ if fdesc.tell() == self.maxSize:
+ self.log.warn("file in misc settings directory (" + str(self.filename) \
+ + ") is bigger than allowed (" + str(self.maxSize) + ")")
+ fdesc.close()
def save(self):
+ """Save a configuration file to disk.
+ """
save_dir = os.path.dirname(self.filename)
## create the directory, if necessary
if not os.path.isdir(save_dir):
@@ -506,14 +583,14 @@ class MiscConfigFile:
return False
## save the content of the file
try:
- fd = open(self.filename, "wb")
+ fdesc = open(self.filename, "wb")
except IOError:
return False
try:
- fd.write(self.content)
- fd.close()
+ fdesc.write(self.content)
+ fdesc.close()
return True
except IOError:
- fd.close()
+ fdesc.close()
return False
diff --git a/src/cryptobox/core/tools.py b/src/cryptobox/core/tools.py
index a7b8676..e574f59 100644
--- a/src/cryptobox/core/tools.py
+++ b/src/cryptobox/core/tools.py
@@ -18,137 +18,169 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Some useful functions for the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
import logging
import os
import re
-logger = logging.getLogger("CryptoBox")
+LOGGER = logging.getLogger("CryptoBox")
-def getAvailablePartitions():
+def get_available_partitions():
"retrieve a list of all available containers"
ret_list = []
try:
- "the following reads all lines of /proc/partitions and adds the mentioned devices"
+ ## the following reads all lines of /proc/partitions and adds the mentioned devices
fpart = open("/proc/partitions", "r")
try:
line = fpart.readline()
while line:
p_details = line.split()
if (len(p_details) == 4):
- "the following code prevents double entries like /dev/hda and /dev/hda1"
+ ## the following code prevents double entries like /dev/hda and /dev/hda1
(p_major, p_minor, p_size, p_device) = p_details
## ignore lines with: invalid minor/major or extend partitions (size=1)
- if re.search('^[0-9]*$', p_major) and re.search('^[0-9]*$', p_minor) and (p_size != "1"):
+ if re.search('^[0-9]*$', p_major) and \
+ re.search('^[0-9]*$', p_minor) and (p_size != "1"):
p_parent = re.sub('[1-9]?[0-9]$', '', p_device)
if p_parent == p_device:
- if [e for e in ret_list if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]:
- "major partition - its children are already in the list"
+ if [e for e in ret_list
+ if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]:
+ ## major partition - its children are already in the list
pass
else:
- "major partition - but there are no children for now"
+ ## major partition - but there are no children for now
ret_list.append(p_device)
else:
- "minor partition - remove parent if necessary"
- if p_parent in ret_list: ret_list.remove(p_parent)
+ ## minor partition - remove parent if necessary
+ if p_parent in ret_list:
+ ret_list.remove(p_parent)
ret_list.append(p_device)
line = fpart.readline()
finally:
fpart.close()
- return map(getAbsoluteDeviceName, ret_list)
+ return [ get_absolute_devicename(e) for e in ret_list ]
except IOError:
- logger.warning("Could not read /proc/partitions")
+ LOGGER.warning("Could not read /proc/partitions")
return []
-def getAbsoluteDeviceName(shortname):
+def get_absolute_devicename(shortname):
""" returns the absolute file name of a device (e.g.: "hda1" -> "/dev/hda1")
this does also work for device mapper devices
- if the result is non-unique, one arbitrary value is returned"""
- if re.search('^/', shortname): return shortname
+ if the result is non-unique, one arbitrary value is returned
+ """
+ if re.search('^/', shortname):
+ return shortname
default = os.path.join("/dev", shortname)
- if os.path.exists(default): return default
- result = findMajorMinorOfDevice(shortname)
- "if no valid major/minor was found -> exit"
- if not result: return default
+ if os.path.exists(default):
+ return default
+ result = find_major_minor_of_device(shortname)
+ ## if no valid major/minor was found -> exit
+ if not result:
+ return default
(major, minor) = result
- "for device-mapper devices (major == 254) ..."
+ ## for device-mapper devices (major == 254) ...
if major == 254:
- result = findMajorMinorDeviceName("/dev/mapper", major, minor)
- if result: return result[0]
- "now check all files in /dev"
- result = findMajorMinorDeviceName("/dev", major, minor)
- if result: return result[0]
+ result = find_major_minor_device("/dev/mapper", major, minor)
+ if result:
+ return result[0]
+ ## now check all files in /dev
+ result = find_major_minor_device("/dev", major, minor)
+ if result:
+ return result[0]
return default
-def findMajorMinorOfDevice(device):
- "return the major/minor numbers of a block device"
- if re.match("/", device) or not os.path.exists(os.path.join(os.path.sep,"sys","block",device)):
+def find_major_minor_of_device(device):
+ """Return the major/minor numbers of a block device.
+ """
+ if re.match("/", device) or \
+ not os.path.exists(os.path.join(os.path.sep, "sys", "block", device)):
## maybe it is an absolute device name
- if not os.path.exists(device): return None
+ if not os.path.exists(device):
+ return None
## okay - it seems to to a device node
rdev = os.stat(device).st_rdev
return (os.major(rdev), os.minor(rdev))
- blockdev_info_file = os.path.join(os.path.join(os.path.sep,"sys","block", device), "dev")
+ blockdev_info_file = os.path.join(os.path.join(
+ os.path.sep,"sys","block", device), "dev")
try:
f_blockdev_info = open(blockdev_info_file, "r")
blockdev_info = f_blockdev_info.read()
f_blockdev_info.close()
(str_major, str_minor) = blockdev_info.split(":")
- "numeric conversion"
+ ## numeric conversion
try:
major = int(str_major)
minor = int(str_minor)
return (major, minor)
except ValueError:
- "unknown device numbers -> stop guessing"
+ ## unknown device numbers -> stop guessing
return None
except IOError:
pass
return None
-def findMajorMinorDeviceName(dir, major, minor):
- "returns the names of devices with the specified major and minor number"
+def find_major_minor_device(dirpath, major, minor):
+ """Returns the names of devices with the specified major and minor number.
+ """
collected = []
try:
- subdirs = [os.path.join(dir, e) for e in os.listdir(dir) if (not os.path.islink(os.path.join(dir, e))) and os.path.isdir(os.path.join(dir, e))]
- "do a recursive call to parse the directory tree"
+ subdirs = [os.path.join(dirpath, e) for e in os.listdir(dirpath)
+ if (not os.path.islink(os.path.join(dirpath, e))) and \
+ os.path.isdir(os.path.join(dirpath, e))]
+ ## do a recursive call to parse the directory tree
for dirs in subdirs:
- collected.extend(findMajorMinorDeviceName(dirs, major, minor))
- "filter all device inodes in this directory"
- collected.extend([os.path.realpath(os.path.join(dir, e)) for e in os.listdir(dir) if (os.major(os.stat(os.path.join(dir, e)).st_rdev) == major) and (os.minor(os.stat(os.path.join(dir, e)).st_rdev) == minor)])
+ collected.extend(find_major_minor_device(dirs, major, minor))
+ ## filter all device inodes in this directory
+ collected.extend([os.path.realpath(os.path.join(dirpath, e))
+ for e in os.listdir(dirpath)
+ if (os.major(os.stat(os.path.join(dirpath, e)).st_rdev) == major) \
+ and (os.minor(os.stat(os.path.join(dirpath, e)).st_rdev) == minor)])
## remove double entries
result = []
- for e in collected:
- if e not in result: result.append(e)
+ for item in collected:
+ if item not in result:
+ result.append(item)
return result
except OSError:
return []
-def getParentBlockDevices():
+def get_parent_blockdevices():
+ """Return a list of all block devices that contain other devices.
+ """
devs = []
for line in file("/proc/partitions"):
p_details = line.split()
## we expect four values - otherwise continue with next iteration
- if len(p_details) != 4: continue
+ if len(p_details) != 4:
+ continue
(p_major, p_minor, p_size, p_device) = p_details
## we expect numeric values in the first two columns
- if re.search(u'\D',p_major) or re.search(u'\D',p_minor): continue
+ if re.search(u'\D', p_major) or re.search(u'\D', p_minor):
+ continue
## now let us check, if it is a (parent) block device or a partition
- if not os.path.isdir(os.path.join(os.path.sep, "sys", "block", p_device)): continue
+ if not os.path.isdir(os.path.join(os.path.sep, "sys", "block", p_device)):
+ continue
devs.append(p_device)
- return map(getAbsoluteDeviceName, devs)
+ return [ get_absolute_devicename(e) for e in devs ]
-def isPartOfBlockDevice(parent, subdevice):
- """check if the given block device is a parent of 'subdevice'
- e.g. for checking if a partition belongs to a block device"""
+def is_part_of_blockdevice(parent, subdevice):
+ """Check if the given block device is a parent of 'subdevice'.
+
+ e.g. for checking if a partition belongs to a block device
+ """
try:
- (par_major, par_minor) = findMajorMinorOfDevice(parent)
- (sub_major, sub_minor) = findMajorMinorOfDevice(subdevice)
+ (par_major, par_minor) = find_major_minor_of_device(parent)
+ (sub_major, sub_minor) = find_major_minor_of_device(subdevice)
except TypeError:
## at least one of these devices did not return a valid major/minor combination
return False
@@ -158,7 +190,8 @@ def isPartOfBlockDevice(parent, subdevice):
blpath = os.path.join(root, bldev, 'dev')
if os.access(blpath, os.R_OK):
try:
- if (str(par_major), str(par_minor)) == tuple([e for e in file(blpath)][0].strip().split(":",1)):
+ if (str(par_major), str(par_minor)) == tuple([e
+ for e in file(blpath)][0].strip().split(":",1)):
parent_path = os.path.join(root, bldev)
break
except (IndexError, OSError):
@@ -170,7 +203,8 @@ def isPartOfBlockDevice(parent, subdevice):
subblpath = os.path.join(parent_path, subbldev, "dev")
if os.access(subblpath, os.R_OK):
try:
- if (str(sub_major), str(sub_minor)) == tuple([e for e in file(subblpath)][0].strip().split(":",1)):
+ if (str(sub_major), str(sub_minor)) == tuple([e
+ for e in file(subblpath)][0].strip().split(":",1)):
## the name of the subdevice node is not important - we found it!
return True
except (IndexError, OSError):
@@ -178,18 +212,22 @@ def isPartOfBlockDevice(parent, subdevice):
return False
-def getBlockDeviceSize(device):
- if not device: return -1
+def get_blockdevice_size(device):
+ """Return the size of a blockdevice.
+ """
+ if not device:
+ return -1
try:
rdev = os.stat(device).st_rdev
except OSError:
return -1
minor = os.minor(rdev)
major = os.major(rdev)
- for f in file("/proc/partitions"):
+ for line in file("/proc/partitions"):
try:
- elements = f.split()
- if len(elements) != 4: continue
+ elements = line.split()
+ if len(elements) != 4:
+ continue
if (int(elements[0]) == major) and (int(elements[1]) == minor):
return int(elements[2])/1024
except ValueError:
@@ -197,8 +235,10 @@ def getBlockDeviceSize(device):
return -1
-def getBlockDeviceSizeHumanly(device):
- size = getBlockDeviceSize(device)
+def get_blockdevice_size_humanly(device):
+ """Return a human readable size of a blockdevice.
+ """
+ size = get_blockdevice_size(device)
if size > 5120:
return "%sGB" % size/1024
else:
diff --git a/src/cryptobox/plugins/__init__.py b/src/cryptobox/plugins/__init__.py
index e69de29..eedeafc 100644
--- a/src/cryptobox/plugins/__init__.py
+++ b/src/cryptobox/plugins/__init__.py
@@ -0,0 +1,7 @@
+"""Features may be easily added to the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
+__all__ = [ 'base', 'manage' ]
+
diff --git a/src/cryptobox/plugins/base.py b/src/cryptobox/plugins/base.py
index 65f5f91..5d50965 100644
--- a/src/cryptobox/plugins/base.py
+++ b/src/cryptobox/plugins/base.py
@@ -21,161 +21,189 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""All features should inherit from this class.
+"""
+
+__revision__ = "$Id"
import os
import cherrypy
class CryptoBoxPlugin:
+ """The base class of all features.
+ """
## default capability is "system" - the other supported capability is: "volume"
- pluginCapabilities = [ "system" ]
+ plugin_capabilities = [ "system" ]
## where should the plugin be visible by default?
- pluginVisibility = [ "preferences" ]
+ plugin_visibility = [ "preferences" ]
## does this plugin require admin authentification?
- requestAuth = False
+ request_auth = False
## default rank (0..100) of the plugin in listings (lower value means higher priority)
rank = 80
## default icon of this plugin (relative path)
- defaultIconFileName = "plugin_icon.gif"
+ default_icon_filename = "plugin_icon.gif"
## fallback icon file (in the common plugin directory)
- fallbackIconFileName = "plugin_icon_unknown.gif"
+ fallback_icon_filename = "plugin_icon_unknown.gif"
- def __init__(self, cbox, pluginDir, siteClass=None):
+ def __init__(self, cbox, plugin_dir, site_class=None):
self.cbox = cbox
self.hdf = {}
- self.pluginDir = pluginDir
- self.hdf_prefix = "Data.Plugins.%s." % self.getName()
- self.site = siteClass
+ self.plugin_dir = plugin_dir
+ self.hdf_prefix = "Data.Plugins.%s." % self.get_name()
+ self.site = site_class
- def doAction(self, **args):
- """override doAction with your plugin code"""
- raise Exception, "undefined action handler ('doAction') in plugin '%'" % self.getName()
+ def do_action(self, **args):
+ """Override do_action with your plugin code
+ """
+ raise Exception, \
+ "undefined action handler ('do_action') in plugin '%s'" % self.get_name()
- def getStatus(self):
- """you should override this, to supply useful state information"""
- raise Exception, "undefined state handler ('getStatus') in plugin '%'" % self.getName()
+ def get_status(self):
+ """you should override this, to supply useful state information
+ """
+ raise Exception, \
+ "undefined state handler ('get_status') in plugin '%s'" % self.get_name()
- def getName(self):
- """the name of the python file (module) should be the name of the plugin"""
+ def get_name(self):
+ """the name of the python file (module) should be the name of the plugin
+ """
return self.__module__
@cherrypy.expose
- def getIcon(self, image=None, **kargs):
+ def get_icon(self, image=None, **kargs):
"""return the image data of the icon of the plugin
the parameter 'image' may be used for alternative image locations (relative
to the directory of the plugin)
- '**kargs' is necessary, as a 'weblang' attribute may be specified (and ignored)"""
- import cherrypy, re
- if (image is None): # or (re.search(u'[\w-\.]', image)):
- plugin_icon_file = os.path.join(self.pluginDir, self.defaultIconFileName)
+ '**kargs' is necessary, as a 'weblang' attribute may be specified (and ignored)
+ """
+ import re
+ if (image is None) or (not re.match(u'[\w\-\.]*$', image)):
+ plugin_icon_file = os.path.join(self.plugin_dir, self.default_icon_filename)
else:
- plugin_icon_file = os.path.join(self.pluginDir, image)
+ plugin_icon_file = os.path.join(self.plugin_dir, image)
if not os.access(plugin_icon_file, os.R_OK):
- plugin_icon_file = os.path.join(self.cbox.prefs["Locations"]["PluginDir"], self.fallbackIconFileName)
+ plugin_icon_file = os.path.join(
+ self.cbox.prefs["Locations"]["PluginDir"], self.fallback_icon_filename)
return cherrypy.lib.cptools.serveFile(plugin_icon_file)
- def getTemplateFileName(self, template_name):
+ def get_template_filename(self, template_name):
"""return the filename of the template, if it is part of this plugin
use this function to check, if the plugin provides the specified template
"""
- result_file = os.path.join(self.pluginDir, template_name + ".cs")
+ result_file = os.path.join(self.plugin_dir, template_name + ".cs")
if os.access(result_file, os.R_OK) and os.path.isfile(result_file):
return result_file
else:
return None
- def getLanguageData(self):
+ def get_language_data(self):
+ """Retrieve the language data of the feature.
+
+ Typically this is the content of the language.hdf file as a HDF object.
+ """
import neo_cgi, neo_util
lang_hdf = neo_util.HDF()
- langFile = os.path.join(self.pluginDir, 'language.hdf')
+ lang_file = os.path.join(self.plugin_dir, 'language.hdf')
try:
- lang_hdf.readFile(langFile)
- except (neo_util.Error, neo_util.ParseError), errMsg:
- self.cbox.log.error("failed to load language file (%s) of plugin (%s):" % (langFile,self.getName()))
+ lang_hdf.readFile(lang_file)
+ except (neo_util.Error, neo_util.ParseError):
+ self.cbox.log.error("failed to load language file (%s) of plugin (%s):" % \
+ (lang_file, self.get_name()))
return lang_hdf
- def loadDataSet(self, hdf):
+ def load_dataset(self, hdf):
+ """Add the local values of the feature to the hdf dataset.
+ """
for (key, value) in self.hdf.items():
hdf.setValue(key, str(value))
- def isAuthRequired(self):
+ def is_auth_required(self):
"""check if this plugin requires authentication
first step: check plugin configuration
- second step: check default value of plugin"""
+ second step: check default value of plugin
+ """
try:
- if self.cbox.prefs.pluginConf[self.getName()]["requestAuth"] is None:
- return self.requestAuth
- if self.cbox.prefs.pluginConf[self.getName()]["requestAuth"]:
+ if self.cbox.prefs.plugin_conf[self.get_name()]["requestAuth"] is None:
+ return self.request_auth
+ if self.cbox.prefs.plugin_conf[self.get_name()]["requestAuth"]:
return True
else:
return False
except KeyError:
- return self.requestAuth
+ return self.request_auth
- def isEnabled(self):
+ def is_enabled(self):
"""check if this plugin is enabled
first step: check plugin configuration
- second step: check default value of plugin"""
- fallback = bool(self.pluginVisibility)
+ second step: check default value of plugin
+ """
+ fallback = bool(self.plugin_visibility)
try:
- if self.cbox.prefs.pluginConf[self.getName()]["visibility"] is None:
+ if self.cbox.prefs.plugin_conf[self.get_name()]["visibility"] is None:
return fallback
- return bool(self.cbox.prefs.pluginConf[self.getName()]["visibility"])
+ return bool(self.cbox.prefs.plugin_conf[self.get_name()]["visibility"])
except KeyError:
return fallback
- def getRank(self):
+ def get_rank(self):
"""check the rank of this plugin
first step: check plugin configuration
- second step: check default value of plugin"""
+ second step: check default value of plugin
+ """
try:
- if self.cbox.prefs.pluginConf[self.getName()]["rank"] is None:
+ if self.cbox.prefs.plugin_conf[self.get_name()]["rank"] is None:
return self.rank
- return int(self.cbox.prefs.pluginConf[self.getName()]["rank"])
+ return int(self.cbox.prefs.plugin_conf[self.get_name()]["rank"])
except (KeyError, TypeError):
return self.rank
- def getVisibility(self):
+ def get_visibility(self):
+ """Check which visibility flags of the feature are set.
+ """
try:
- if self.cbox.prefs.pluginConf[self.getName()]["visibility"] is None:
- return self.pluginVisibility[:]
- return self.cbox.prefs.pluginConf[self.getName()]["visibility"]
+ if self.cbox.prefs.plugin_conf[self.get_name()]["visibility"] is None:
+ return self.plugin_visibility[:]
+ return self.cbox.prefs.plugin_conf[self.get_name()]["visibility"]
except KeyError:
- return self.pluginVisibility
+ return self.plugin_visibility
- def getTestClass(self):
+ def get_test_class(self):
+ """Return the unittest class of the feature.
+ """
import imp
- pl_file = os.path.join(self.pluginDir, "unittests.py")
+ pl_file = os.path.join(self.plugin_dir, "unittests.py")
if os.access(pl_file, os.R_OK) and os.path.isfile(pl_file):
try:
- return getattr(imp.load_source("unittests_%s" % self.getName(), pl_file), "unittests")
+ return imp.load_source("unittests_%s" % self.get_name(), pl_file).unittests
except AttributeError:
pass
try:
- self.cbox.log.info("could not load unittests for plugin: %s" % self.getName())
+ self.cbox.log.info("could not load unittests for plugin: %s" % \
+ self.get_name())
except AttributeError:
pass
return None
diff --git a/src/cryptobox/plugins/manage.py b/src/cryptobox/plugins/manage.py
index bfe0067..78c7916 100644
--- a/src/cryptobox/plugins/manage.py
+++ b/src/cryptobox/plugins/manage.py
@@ -19,46 +19,56 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Manages the pluggable features of the CryptoBox.
+"""
+
+__revision__ = "$Id"
-import imp
import os
-import logging
class PluginManager:
"""manage available plugins"""
- def __init__(self, cbox, plugin_dirs=".", siteClass=None):
+ def __init__(self, cbox, plugin_dirs=".", site_class=None):
self.cbox = cbox
- self.log = logging.getLogger("CryptoBox")
- self.site = siteClass
+ self.site = site_class
if hasattr(plugin_dirs, "__iter__"):
- self.plugin_dirs = [os.path.abspath(dir) for dir in plugin_dirs]
+ self.plugin_dirs = [os.path.abspath(d) for d in plugin_dirs]
else:
self.plugin_dirs = [os.path.abspath(plugin_dirs)]
- self.pluginList = self.__getAllPlugins()
+ self.plugin_list = self.__get_all_plugins()
- def getPlugins(self):
- return self.pluginList[:]
+ def get_plugins(self):
+ """Return a list of all feature instances.
+ """
+ return self.plugin_list[:]
- def getPlugin(self, name):
- for p in self.pluginList[:]:
- if p.getName() == name:
- return p
+ def get_plugin(self, name):
+ """Return the specified feature as an instance.
+ """
+ for plugin in self.plugin_list[:]:
+ if plugin.get_name() == name:
+ return plugin
return None
- def __getAllPlugins(self):
- list = []
- for plfile in self.__getPluginFiles():
- list.append(self.__getPluginClass(os.path.basename(plfile)[:-3]))
- return list
+ def __get_all_plugins(self):
+ """Return all available features as instances.
+ """
+ plist = []
+ for plfile in self.__get_plugin_files():
+ plist.append(self.__get_plugin_class(os.path.basename(plfile)[:-3]))
+ return plist
- def __getPluginClass(self, name):
- for plfile in self.__getPluginFiles():
+ def __get_plugin_class(self, name):
+ """Return a instance object of the give feature.
+ """
+ import imp
+ for plfile in self.__get_plugin_files():
if name == os.path.basename(plfile)[:-3]:
try:
pl_class = getattr(imp.load_source(name, plfile), name)
@@ -69,18 +79,23 @@ class PluginManager:
return None
- def __getPluginFiles(self):
+ def __get_plugin_files(self):
+ """Retrieve all python files that may potentially be a feature.
+ """
result = []
if self.cbox and self.cbox.prefs["Main"]["DisabledPlugins"]:
disabled = self.cbox.prefs["Main"]["DisabledPlugins"]
else:
disabled = []
- for dir in [os.path.abspath(e) for e in self.plugin_dirs if os.access(e, os.R_OK) and os.path.isdir(e)]:
- for plname in [f for f in os.listdir(dir)]:
+ for pdir in [os.path.abspath(e) for e in self.plugin_dirs
+ if os.access(e, os.R_OK) and os.path.isdir(e)]:
+ for plname in [f for f in os.listdir(pdir)]:
if plname in disabled:
- if self.cbox: self.cbox.log.info("skipped plugin '%s' (disabled via config)" % plname)
+ if self.cbox:
+ self.cbox.log.info(
+ "skipped plugin '%s' (disabled via config)" % plname)
continue
- pldir = os.path.join(dir, plname)
+ pldir = os.path.join(pdir, plname)
plfile = os.path.join(pldir, plname + ".py")
if os.path.isfile(plfile) and os.access(plfile, os.R_OK):
result.append(plfile)
@@ -88,8 +103,8 @@ class PluginManager:
if __name__ == "__main__":
- x = PluginManager(None, "../plugins")
- for a in x.getPlugins():
- if not a is None:
- print "Plugin: %s" % a.getName()
+ MANAGER = PluginManager(None, "../plugins")
+ for one_plugin in MANAGER.get_plugins():
+ if not one_plugin is None:
+ print "Plugin: %s" % one_plugin.get_name()
diff --git a/src/cryptobox/tests/__init__.py b/src/cryptobox/tests/__init__.py
index e69de29..afc7ca5 100644
--- a/src/cryptobox/tests/__init__.py
+++ b/src/cryptobox/tests/__init__.py
@@ -0,0 +1,7 @@
+"""Some unittests for the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
+__all__ = [ 'test.cryptobox', 'test.cryptoboxtools', 'test.plugins', 'test.websites' ]
+
diff --git a/src/cryptobox/tests/test.cryptobox.py b/src/cryptobox/tests/test.cryptobox.py
index 07ffc21..c0e722e 100755
--- a/src/cryptobox/tests/test.cryptobox.py
+++ b/src/cryptobox/tests/test.cryptobox.py
@@ -19,33 +19,41 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Some unittests for the core CryptoBox modules.
+"""
+
+__revision__ = "$Id"
+
import unittest
import sys
import cryptobox.core.main
from cryptobox.core.exceptions import *
import cryptobox.core.settings
+import os
-class CryptoBoxPropsDeviceTests(unittest.TestCase):
- cb = cryptobox.core.main.CryptoBoxProps()
+class CryptoBoxDeviceTests(unittest.TestCase):
+ """Some unittests for the CryptoBox
+ """
+
+ cb = cryptobox.core.main.CryptoBox()
- def testAllowedDevices(self):
- '''isDeviceAllowed should accept permitted devices'''
- self.assertTrue(self.cb.isDeviceAllowed("/dev/loop"))
- self.assertTrue(self.cb.isDeviceAllowed("/dev/loop1"))
- self.assertTrue(self.cb.isDeviceAllowed("/dev/loop/urgd"))
- self.assertTrue(self.cb.isDeviceAllowed("/dev/usb/../loop1"))
+ def test_allowed_devices(self):
+ '''is_device_allowed should accept permitted devices'''
+ self.assertTrue(self.cb.is_device_allowed("/dev/loop"))
+ self.assertTrue(self.cb.is_device_allowed("/dev/loop1"))
+ self.assertTrue(self.cb.is_device_allowed("/dev/loop/urgd"))
+ self.assertTrue(self.cb.is_device_allowed("/dev/usb/../loop1"))
- def testDeniedDevices(self):
- '''isDeviceAllowed should fail with not explicitly allowed devices'''
- self.assertFalse(self.cb.isDeviceAllowed("/dev/hda"))
- self.assertFalse(self.cb.isDeviceAllowed("/dev/loopa/../hda"))
- self.assertFalse(self.cb.isDeviceAllowed("/"))
+ def test_denied_devices(self):
+ '''is_device_allowed should fail with not explicitly allowed devices'''
+ self.assertFalse(self.cb.is_device_allowed("/dev/hda"))
+ self.assertFalse(self.cb.is_device_allowed("/dev/loopa/../hda"))
+ self.assertFalse(self.cb.is_device_allowed("/"))
-class CryptoBoxPropsConfigTests(unittest.TestCase):
+class CryptoBoxConfigTests(unittest.TestCase):
'''test here if everything with the config turns right'''
- import os
files = {
"configFileOK" : "cbox-test_ok.conf",
"configFileBroken" : "cbox-test_broken.conf",
@@ -86,71 +94,89 @@ CryptoBoxRootActions = CryptoBoxRootActions
def setUp(self):
'''generate all files in tmp and remember the names'''
import tempfile
- os = self.os
self.tmpdirname = tempfile.mkdtemp(prefix="cbox-")
- for file in self.files.keys():
- self.filenames[file] = os.path.join(self.tmpdirname, self.files[file])
- self.writeConfig()
+ for tfile in self.files.keys():
+ self.filenames[tfile] = os.path.join(self.tmpdirname, self.files[tfile])
+ self.write_config()
def tearDown(self):
'''remove the created tmpfiles'''
- os = self.os
# remove temp files
- for file in self.filenames.values():
- compl_name = os.path.join(self.tmpdirname, file)
+ for tfile in self.filenames.values():
+ compl_name = os.path.join(self.tmpdirname, tfile)
if os.path.exists(compl_name):
os.remove(compl_name)
# remove temp dir
os.rmdir(self.tmpdirname)
- def testConfigInit(self):
+ def test_config_init(self):
'''Check various branches of config file loading'''
- import os
- self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps,"/invalid/path/to/config/file")
- self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps,"/etc/shadow")
- """ check one of the following things:
- 1) are we successfully using an existing config file?
- 2) do we break, if no config file is there?
- depending on the existence of a config file, only one of these conditions
- can be checked - hints for more comprehensive tests are appreciated :) """
- for a in ['cryptobox.conf']:
- if os.path.exists(a):
- cryptobox.core.main.CryptoBoxProps()
+ self.assertRaises(CBConfigUnavailableError,
+ cryptobox.core.main.CryptoBox,"/invalid/path/to/config/file")
+ self.assertRaises(CBConfigUnavailableError,
+ cryptobox.core.main.CryptoBox,"/etc/shadow")
+ ## check one of the following things:
+ ## 1) are we successfully using an existing config file?
+ ## 2) do we break, if no config file is there?
+ ## depending on the existence of a config file, only one of these conditions
+ ## can be checked - hints for more comprehensive tests are appreciated :)
+ for cfile in ['cryptobox.conf']:
+ if os.path.exists(cfile):
+ cryptobox.core.main.CryptoBox()
break # this skips the 'else' clause
- else: self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps)
- self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps,[])
+ else:
+ self.assertRaises(CBConfigUnavailableError,
+ cryptobox.core.main.CryptoBox)
+ self.assertRaises(CBConfigUnavailableError,
+ cryptobox.core.main.CryptoBox,[])
- def testBrokenConfigs(self):
- """Check various broken configurations"""
- self.writeConfig("SettingsDir", "SettingsDir=/foo/bar", filename=self.filenames["configFileBroken"])
- self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
- self.writeConfig("Level", "Level = ho", filename=self.filenames["configFileBroken"])
- self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
- self.writeConfig("Details", "#out", filename=self.filenames["configFileBroken"])
- self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
- self.writeConfig("super", "super=/bin/invalid/no", filename=self.filenames["configFileBroken"])
- self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
- self.writeConfig("CryptoBoxRootActions", "#not here", filename=self.filenames["configFileBroken"])
- self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
- self.writeConfig("CryptoBoxRootActions", "CryptoBoxRootActions = /bin/false", filename=self.filenames["configFileBroken"])
- self.assertRaises(CBEnvironmentError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
+ def test_broken_configs(self):
+ """Check various broken configurations
+ """
+ self.write_config("SettingsDir", "SettingsDir=/foo/bar",
+ filename=self.filenames["configFileBroken"])
+ self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
+ self.filenames["configFileBroken"])
+ self.write_config("Level", "Level = ho",
+ filename=self.filenames["configFileBroken"])
+ self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
+ self.filenames["configFileBroken"])
+ self.write_config("Details", "#out",
+ filename=self.filenames["configFileBroken"])
+ self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
+ self.filenames["configFileBroken"])
+ self.write_config("super", "super=/bin/invalid/no",
+ filename=self.filenames["configFileBroken"])
+ self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
+ self.filenames["configFileBroken"])
+ self.write_config("CryptoBoxRootActions", "#not here",
+ filename=self.filenames["configFileBroken"])
+ self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
+ self.filenames["configFileBroken"])
+ self.write_config("CryptoBoxRootActions", "CryptoBoxRootActions = /bin/false",
+ filename=self.filenames["configFileBroken"])
+ self.assertRaises(CBEnvironmentError, cryptobox.core.main.CryptoBox,
+ self.filenames["configFileBroken"])
- def writeConfig(self, replace=None, newline=None, filename=None):
+ def write_config(self, replace=None, newline=None, filename=None):
"""write a config file and (optional) replace a line in it"""
import re
- if not filename: filename = self.filenames["configFileOK"]
- content = self.configContentOK % (self.tmpdirname, self.tmpdirname, self.tmpdirname)
+ if not filename:
+ filename = self.filenames["configFileOK"]
+ content = self.configContentOK % \
+ (self.tmpdirname, self.tmpdirname, self.tmpdirname)
if replace:
pattern = re.compile('^' + replace + '\\s*=.*$', flags=re.M)
content = re.sub(pattern, newline, content)
- cf = open(filename, "w")
- cf.write(content)
- cf.close()
+ cfile = open(filename, "w")
+ cfile.write(content)
+ cfile.close()
if __name__ == "__main__":
unittest.main()
+
diff --git a/src/cryptobox/tests/test.cryptoboxtools.py b/src/cryptobox/tests/test.cryptoboxtools.py
index 02e460a..f8eb101 100755
--- a/src/cryptobox/tests/test.cryptoboxtools.py
+++ b/src/cryptobox/tests/test.cryptoboxtools.py
@@ -19,9 +19,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Unittests for cryptobox.core.tools
+"""
+
+__revision__ = "$Id"
+
import unittest
-import cryptobox.core.tools as cbxTools
+import cryptobox.core.tools as cbx_tools
import os
## use /dev/ubd? if possible - otherwise /dev/hd?
@@ -36,30 +41,40 @@ else:
class CryptoBoxToolsTests(unittest.TestCase):
+ """All unittests for cryptoboxtools
+ """
- def testGetAbsoluteDeviceName(self):
- func = cbxTools.getAbsoluteDeviceName
+ def test_get_absolute_devicename(self):
+ """check the get_absolute_devicename function
+ """
+ func = cbx_tools.get_absolute_devicename
self.assertTrue(func(device) == "/dev/%s" % device)
self.assertTrue(func("loop0") == "/dev/loop0")
self.assertTrue(func(os.path.devnull) == os.path.devnull)
- def testFindMajorMinorOfDevice(self):
- func = cbxTools.findMajorMinorOfDevice
- self.assertTrue(func(os.path.devnull) == (1,3))
+ def test_find_major_minor_of_device(self):
+ """check the find_major_minor_of_device function
+ """
+ func = cbx_tools.find_major_minor_of_device
+ self.assertTrue(func(os.path.devnull) == (1, 3))
self.assertTrue(func("/dev/nothere") is None)
- def testFindMajorMinorDeviceName(self):
- func = cbxTools.findMajorMinorDeviceName
- dir = os.path.join(os.path.sep, "dev")
- self.assertTrue(os.path.devnull in func(dir,1,3))
- self.assertFalse(os.path.devnull in func(dir,2,3))
- self.assertFalse(None in func(dir,17,23))
+ def test_find_major_minor_device(self):
+ """check the find_major_minor_device function
+ """
+ func = cbx_tools.find_major_minor_device
+ path = os.path.join(os.path.sep, "dev")
+ self.assertTrue(os.path.devnull in func(path, 1, 3))
+ self.assertFalse(os.path.devnull in func(path, 2, 3))
+ self.assertFalse(None in func(path, 17, 23))
- def testIsPartOfBlockDevice(self):
- func = cbxTools.isPartOfBlockDevice
+ def test_is_part_of_blockdevice(self):
+ """check the is_part_of_blockdevice function
+ """
+ func = cbx_tools.is_part_of_blockdevice
self.assertTrue(func("/dev/%s" % device, "/dev/%s1" % device))
self.assertFalse(func("/dev/%s" % device, "/dev/%s" % device))
self.assertFalse(func("/dev/%s1" % device, "/dev/%s" % device))
diff --git a/src/cryptobox/tests/test.plugins.py b/src/cryptobox/tests/test.plugins.py
index eeb9a5a..d9172fa 100755
--- a/src/cryptobox/tests/test.plugins.py
+++ b/src/cryptobox/tests/test.plugins.py
@@ -19,6 +19,10 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""This module handles the unittests of all features.
+"""
+
+__revision__ = "$Id"
import unittest
import cryptobox.plugins.manage
@@ -28,20 +32,21 @@ class CheckForUndefinedTestCases(unittest.TestCase):
def create_testcases():
-
- plugins = cryptobox.plugins.manage.PluginManager(None, "../plugins").getPlugins()
+ """Create functions that execute unittests for all features.
+ """
+ plugins = cryptobox.plugins.manage.PluginManager(None, "../plugins").get_plugins()
glob_dict = globals()
loc_dict = locals()
- for pl in plugins:
- test_class = pl.getTestClass()
+ for plugin in plugins:
+ test_class = plugin.get_test_class()
if test_class:
## add the testclass to the global dictionary
- glob_dict["unittest" + pl.getName()] = test_class
+ glob_dict["unittest" + plugin.get_name()] = test_class
else:
- subname = "test_existence_%s" % pl.getName()
+ subname = "test_existence_%s" % plugin.get_name()
def test_existence(self):
- """check if the plugin (%s) contains tests""" % pl.getName()
- self.fail("no tests defined for plugin: %s" % pl.getName())
+ """check if the plugin (%s) contains tests""" % plugin.get_name()
+ self.fail("no tests defined for plugin: %s" % plugin.get_name())
## add this function to the class above
setattr(CheckForUndefinedTestCases, subname, test_existence)
#FIXME: the failure output always contains the same name for all plugins
diff --git a/src/cryptobox/tests/test.websites.py b/src/cryptobox/tests/test.websites.py
index 5dbc75b..3a6ab6f 100755
--- a/src/cryptobox/tests/test.websites.py
+++ b/src/cryptobox/tests/test.websites.py
@@ -19,6 +19,12 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Base class for all unittests involving the webserver.
+
+This class uses twill.
+"""
+
+__revision__ = "$Id"
import unittest
@@ -32,28 +38,32 @@ import cryptobox.web.testclass
class WebServer(cryptobox.web.testclass.WebInterfaceTestClass):
+ """Basic tests for the webserver.
+ """
def test_is_server_running(self):
'''the server should run under given name and port'''
- self.register_auth(self.URL)
- self.cmd.go(self.URL)
+ self.register_auth(self.url)
+ self.cmd.go(self.url)
self.cmd.find("CBOX-STATUS")
## other URLs must not be checked, as we do not know, if they are valid
class BuiltinPages(cryptobox.web.testclass.WebInterfaceTestClass):
+ """Basic test of builtin pages (no features).
+ """
def test_goto_index(self):
'''display all devices'''
- self.register_auth(self.URL)
- self.cmd.go(self.URL)
+ self.register_auth(self.url)
+ self.cmd.go(self.url)
self.cmd.find("The CryptoBox")
- self.cmd.go(self.URL + "?weblang=de")
+ self.cmd.go(self.url + "?weblang=de")
self.cmd.find("Die CryptoBox")
- self.cmd.go(self.URL + "?weblang=sl")
+ self.cmd.go(self.url + "?weblang=sl")
self.cmd.find("Privatnost v vsako vas")
- self.cmd.go(self.URL + "?weblang=fr")
+ self.cmd.go(self.url + "?weblang=fr")
self.cmd.find("La CryptoBox")
diff --git a/src/cryptobox/web/__init__.py b/src/cryptobox/web/__init__.py
index e69de29..f524565 100644
--- a/src/cryptobox/web/__init__.py
+++ b/src/cryptobox/web/__init__.py
@@ -0,0 +1,7 @@
+"""The webinterface of the CryptoBox.
+"""
+
+__revision__ = "$Id"
+
+__all__ = [ 'dataset', 'languages', 'sites', 'testclass' ]
+
diff --git a/src/cryptobox/web/dataset.py b/src/cryptobox/web/dataset.py
index 7ba2865..c04cf17 100644
--- a/src/cryptobox/web/dataset.py
+++ b/src/cryptobox/web/dataset.py
@@ -18,8 +18,12 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""Manage the hdf dataset of the cryptobox web sites.
+"""
+
+__revision__ = "$Id"
+
import os
-from cryptobox.core.exceptions import *
import cryptobox.core.container as cbxContainer
import cryptobox.core.tools as cbxTools
@@ -30,20 +34,24 @@ class WebInterfaceDataset(dict):
"""
def __init__(self, cbox, prefs, plugins):
+ super(WebInterfaceDataset, self).__init__()
self.prefs = prefs
self.cbox = cbox
- self.__setConfigValues()
+ self.__set_config_values()
self.plugins = plugins
- self.setCryptoBoxState()
- self.setPluginData()
- self.setContainersState()
+ self.set_crypto_box_state()
+ self.set_plugin_data()
+ self.set_containers_state()
- def setCryptoBoxState(self):
+ def set_crypto_box_state(self):
+ """Set some hdf values according to the cryptobox as a whole.
+ """
import cherrypy
import cryptobox.core.main
import cryptobox.web.languages
- self["Data.Version"] = cryptobox.core.main.VERSION
+ import cryptobox
+ self["Data.Version"] = cryptobox.__version__
langs = self.cbox.prefs["WebSettings"]["Languages"][:]
langs.sort()
for (index, lang) in enumerate(langs):
@@ -58,10 +66,11 @@ class WebInterfaceDataset(dict):
try:
self["Data.ScriptURL.Prot"] = cherrypy.request.scheme
host = cherrypy.request.headers["Host"]
- self["Data.ScriptURL.Host"] = host.split(":",1)[0]
- complete_url = "%s://%s" % (self["Data.ScriptURL.Prot"], self["Data.ScriptURL.Host"])
+ self["Data.ScriptURL.Host"] = host.split(":", 1)[0]
+ complete_url = "%s://%s" % \
+ (self["Data.ScriptURL.Prot"], self["Data.ScriptURL.Host"])
try:
- port = int(host.split(":",1)[1])
+ port = int(host.split(":", 1)[1])
complete_url += ":%s" % port
except (IndexError, ValueError):
if cherrypy.request.scheme == "http":
@@ -70,7 +79,8 @@ class WebInterfaceDataset(dict):
port = 443
else:
## unknown scheme -> port 0
- self.cbox.log.info("unknown protocol scheme used: %s" % (cherrypy.request.scheme,))
+ self.cbox.log.info(
+ "unknown protocol scheme used: %s" % (cherrypy.request.scheme,))
port = 0
self["Data.ScriptURL.Port"] = port
## retrieve the relative address of the CGI (or the cherrypy base address)
@@ -83,20 +93,25 @@ class WebInterfaceDataset(dict):
self["Data.ScriptURL"] = ""
- def setCurrentDiskState(self, device):
- for container in self.cbox.getContainerList():
- if container.getDevice() == device:
- isEncrypted = (container.getType() == cbxContainer.ContainerTypes["luks"]) and 1 or 0
- isPlain = (container.getType() == cbxContainer.ContainerTypes["plain"]) and 1 or 0
- isMounted = container.isMounted() and 1 or 0
- self["Data.CurrentDisk.device"] = container.getDevice()
- self["Data.CurrentDisk.name"] = container.getName()
- self["Data.CurrentDisk.encryption"] = isEncrypted
- self["Data.CurrentDisk.plaintext"] = isPlain
- self["Data.CurrentDisk.active"] = isMounted
- self["Data.CurrentDisk.size"] = cbxTools.getBlockDeviceSizeHumanly(container.getDevice())
- if isMounted:
- (size, avail, used) = container.getCapacity()
+ def set_current_disk_state(self, device):
+ """Set some hdf values according to the currently active disk.
+ """
+ for container in self.cbox.get_container_list():
+ if container.get_device() == device:
+ is_encrypted = (container.get_type() == \
+ cbxContainer.CONTAINERTYPES["luks"]) and 1 or 0
+ is_plain = (container.get_type() == \
+ cbxContainer.CONTAINERTYPES["plain"]) and 1 or 0
+ is_mounted = container.is_mounted() and 1 or 0
+ self["Data.CurrentDisk.device"] = container.get_device()
+ self["Data.CurrentDisk.name"] = container.get_name()
+ self["Data.CurrentDisk.encryption"] = is_encrypted
+ self["Data.CurrentDisk.plaintext"] = is_plain
+ self["Data.CurrentDisk.active"] = is_mounted
+ self["Data.CurrentDisk.size"] = cbxTools.get_blockdevice_size_humanly(
+ container.get_device())
+ if is_mounted:
+ (size, avail, used) = container.get_capacity()
percent = used / size
self["Data.CurrentDisk.capacity.used"] = used
self["Data.CurrentDisk.capacity.free"] = avail
@@ -105,51 +120,63 @@ class WebInterfaceDataset(dict):
self["Settings.LinkAttrs.device"] = device
- def setContainersState(self):
+ def set_containers_state(self):
+ """Set some hdf values according to the list of available containers.
+ """
avail_counter = 0
active_counter = 0
- for container in self.cbox.getContainerList():
+ for container in self.cbox.get_container_list():
## useful if the container was changed during an action
- container.resetObject()
- isEncrypted = (container.getType() == cbxContainer.ContainerTypes["luks"]) and 1 or 0
- isPlain = (container.getType() == cbxContainer.ContainerTypes["plain"]) and 1 or 0
- isMounted = container.isMounted() and 1 or 0
- self["Data.Disks.%d.device" % avail_counter] = container.getDevice()
- self["Data.Disks.%d.name" % avail_counter] = container.getName()
- self["Data.Disks.%d.encryption" % avail_counter] = isEncrypted
- self["Data.Disks.%d.plaintext" % avail_counter] = isPlain
- self["Data.Disks.%d.active" % avail_counter] = isMounted
- self["Data.Disks.%d.size" % avail_counter] = cbxTools.getBlockDeviceSizeHumanly(container.getDevice())
- if isMounted: active_counter += 1
+ container.reset_object()
+ is_encrypted = (container.get_type() == \
+ cbxContainer.CONTAINERTYPES["luks"]) and 1 or 0
+ is_plain = (container.get_type() == \
+ cbxContainer.CONTAINERTYPES["plain"]) and 1 or 0
+ is_mounted = container.is_mounted() and 1 or 0
+ self["Data.Disks.%d.device" % avail_counter] = container.get_device()
+ self["Data.Disks.%d.name" % avail_counter] = container.get_name()
+ self["Data.Disks.%d.encryption" % avail_counter] = is_encrypted
+ self["Data.Disks.%d.plaintext" % avail_counter] = is_plain
+ self["Data.Disks.%d.active" % avail_counter] = is_mounted
+ self["Data.Disks.%d.size" % avail_counter] = \
+ cbxTools.get_blockdevice_size_humanly(container.get_device())
+ if is_mounted:
+ active_counter += 1
avail_counter += 1
self["Data.activeDisksCount"] = active_counter
- def setPluginData(self):
- for p in self.plugins:
- entryName = "Settings.PluginList." + p.getName()
+ def set_plugin_data(self):
+ """Set some hdf values according to the available features.
+ """
+ for plugin in self.plugins:
+ entry_name = "Settings.PluginList." + plugin.get_name()
## first: remove all existing settings of this plugin
for key in self.keys():
- if key.startswith(entryName): del self[key]
- lang_data = p.getLanguageData()
- self[entryName] = p.getName()
- self[entryName + ".Name"] = lang_data.getValue("Name", p.getName())
- self[entryName + ".Link"] = lang_data.getValue("Link", p.getName())
- self[entryName + ".Rank"] = p.getRank()
- self[entryName + ".RequestAuth"] = p.isAuthRequired() and "1" or "0"
- for a in p.pluginCapabilities:
- self[entryName + ".Types." + a] = "1"
- for a in p.getVisibility():
- self[entryName + ".Visible." + a] = "1"
+ if key.startswith(entry_name):
+ del self[key]
+ lang_data = plugin.get_language_data()
+ self[entry_name] = plugin.get_name()
+ self[entry_name + ".Name"] = lang_data.getValue("Name", plugin.get_name())
+ self[entry_name + ".Link"] = lang_data.getValue("Link", plugin.get_name())
+ self[entry_name + ".Rank"] = plugin.get_rank()
+ self[entry_name + ".RequestAuth"] = plugin.is_auth_required() and "1" or "0"
+ for capy in plugin.plugin_capabilities:
+ self[entry_name + ".Types." + capy] = "1"
+ for visi in plugin.get_visibility():
+ self[entry_name + ".Visible." + visi] = "1"
- def __setConfigValues(self):
- self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"])
+ def __set_config_values(self):
+ """Set some hdf values according to configuration settings.
+ """
+ self["Settings.TemplateDir"] = os.path.abspath(
+ self.prefs["Locations"]["TemplateDir"])
self["Settings.DocDir"] = os.path.abspath(self.prefs["Locations"]["DocDir"])
self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"]
self["Settings.Language"] = self.prefs["WebSettings"]["Languages"][0]
- for num,d in enumerate(self.prefs["Locations"]["PluginDir"]):
- self["Settings.PluginDir.%d" % num] = d
+ for (num, dpath) in enumerate(self.prefs["Locations"]["PluginDir"]):
+ self["Settings.PluginDir.%d" % num] = dpath
## store the first directory in this settings variable - backward compatibility
self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"][0]
self["Settings.SettingsDir"] = self.prefs["Locations"]["SettingsDir"]
diff --git a/src/cryptobox/web/languages.py b/src/cryptobox/web/languages.py
index e0e857c..51f0a29 100644
--- a/src/cryptobox/web/languages.py
+++ b/src/cryptobox/web/languages.py
@@ -22,23 +22,28 @@
"""supply information about existing languages
"""
+__revision__ = "$Id"
+
## every language information should contain (name, pluralformat)
LANGUAGE_INFO = {
- "cs": ('Český', ('3', '(n==1) ? 0 : (n>=2 && n< =4) ? 1 : 2')),
- "da": ('Dansk', ('2', '(n != 1)')),
- "de": ('Deutsch', ('2', '(n != 1)')),
- "en": ('English', ('2', '(n != 1)')),
- "es": ('Español', ('2', '(n != 1)')),
- "fi": ('Suomi', ('2', '(n != 1)')),
- "fr": ('Français', ('2', '(n != 1)')),
- "hu": ('Magyar', ('1', '0')),
- "it": ('Italiano', ('2', '(n != 1)')),
- "ja": ('日本語', ('1', '0')),
- "nl": ('Nederlands', ('2', '(n != 1)')),
- "pl": ('Polski', ('3', '(n==1 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 || n%100>=20) ? 1 : 2)')),
- "pt": ('Português', ('2', '(n != 1)')),
- "ru": ('Русский', ('3', '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 || n%100>=20) ? 1 : 2)')),
- "sl": ('Slovensko', ('4', '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)')),
- "sv": ('Svenska', ('2', '(n != 1)')),
- }
+ "cs": ('Český', ('3', '(n==1) ? 0 : (n>=2 && n< =4) ? 1 : 2')),
+ "da": ('Dansk', ('2', '(n != 1)')),
+ "de": ('Deutsch', ('2', '(n != 1)')),
+ "en": ('English', ('2', '(n != 1)')),
+ "es": ('Español', ('2', '(n != 1)')),
+ "fi": ('Suomi', ('2', '(n != 1)')),
+ "fr": ('Français', ('2', '(n != 1)')),
+ "hu": ('Magyar', ('1', '0')),
+ "it": ('Italiano', ('2', '(n != 1)')),
+ "ja": ('日本語', ('1', '0')),
+ "nl": ('Nederlands', ('2', '(n != 1)')),
+ "pl": ('Polski', ('3', '(n==1 ? 0 : n%10>=2 && n%10< =4 '
+ + '&& (n%100<10 || n%100>=20) ? 1 : 2)')),
+ "pt": ('Português', ('2', '(n != 1)')),
+ "ru": ('Русский', ('3', '(n%10==1 && n%100!=11 ? 0 : '
+ + 'n%10>=2 && n%10< =4 && (n%100<10 || n%100>=20) ? 1 : 2)')),
+ "sl": ('Slovensko', ('4', '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || '
+ + 'n%100==4 ? 2 : 3)')),
+ "sv": ('Svenska', ('2', '(n != 1)')),
+ }
diff --git a/src/cryptobox/web/sites.py b/src/cryptobox/web/sites.py
index 7347b82..f9eb04b 100644
--- a/src/cryptobox/web/sites.py
+++ b/src/cryptobox/web/sites.py
@@ -17,103 +17,150 @@
# along with the CryptoBox; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+""" this module handles all http requests and renders a website """
+
+__revision__ = "$Id$"
import cryptobox.core.main
import cryptobox.web.dataset
import cryptobox.plugins.manage
-from cryptobox.core.exceptions import *
+import cryptobox.core.exceptions
import re
import cherrypy
-import types
import os
+import sys
try:
import neo_cgi, neo_util, neo_cs
except ImportError:
- errorMsg = "Could not import clearsilver module. Try 'apt-get install python-clearsilver'."
- self.log.error(errorMsg)
- sys.stderr.write(errorMsg)
- raise ImportError, errorMsg
+ _ERRMSG = "Could not import clearsilver module. \
+ Try 'apt-get install python-clearsilver'."
+ sys.stderr.write(_ERRMSG)
+ raise ImportError, _ERRMSG
GETTEXT_DOMAIN = 'cryptobox-server'
class PluginIconHandler:
+ """deliver the icons of available plugins via cherrypy"""
def __init__(self, plugins):
- for plugin in plugins.getPlugins():
- if not plugin: continue
- plname = plugin.getName()
- ## expose the getIcon function of this plugin
- setattr(self, plname, plugin.getIcon)
+ for plugin in plugins.get_plugins():
+ if not plugin:
+ continue
+ plname = plugin.get_name()
+ ## expose the get_icon function of this plugin
+ setattr(self, plname, plugin.get_icon)
class WebInterfaceSites:
- '''
- '''
+ """handle all http requests and render pages
+
+ this includes:
+ - filtering common arguments
+ - calling feature actions
+ - translating content
+
+ all available features are dynamically exposed
+ """
## this template is used under strange circumstances
defaultTemplate = "empty"
def __init__(self, conf_file=None):
- import logging,sys
- self.cbox = cryptobox.core.main.CryptoBoxProps(conf_file)
- self.log = logging.getLogger("CryptoBox")
- self.prefs = self.cbox.prefs
- self.__resetDataset()
+ ## we should only use variables preceded by "__" to avoid name conflicts
+ ## when loading features
+ self.cbox = cryptobox.core.main.CryptoBox(conf_file)
+ self.__cached_language_data = None
+ self.__dataset = None
+ self.icons = None
+ self.__plugin_manager = None
+ self.__reset_dataset()
## store the original http error handler
- self._cp_on_http_error = self.newHTTPErrorHandler
+ self._cp_on_http_error = self.new_http_error_handler
## set initial language order
- self.langOrder = self.cbox.prefs["WebSettings"]["Languages"][:]
+ self.lang_order = self.cbox.prefs["WebSettings"]["Languages"][:]
- def __resetDataset(self):
+ def __reset_dataset(self):
"""this method has to be called at the beginning of every "site" action
important: only at the beginning of an action (to not loose information)
important: for _every_ "site" action (cherrypy is stateful)
also take care for the plugins, as they also contain datasets
"""
- self.__loadPlugins()
- self.dataset = cryptobox.web.dataset.WebInterfaceDataset(self.cbox, self.prefs, self.pluginList.getPlugins())
+ self.__load_plugins()
+ self.__dataset = cryptobox.web.dataset.WebInterfaceDataset(
+ self.cbox, self.cbox.prefs, self.__plugin_manager.get_plugins())
## publish plugin icons
- self.icons = PluginIconHandler(self.pluginList)
+ self.icons = PluginIconHandler(self.__plugin_manager)
self.icons.exposed = True
## check, if a configuration partition has become available
- self.cbox.prefs.preparePartition()
+ self.cbox.prefs.prepare_partition()
- def __loadPlugins(self):
- self.pluginList = cryptobox.plugins.manage.PluginManager(self.cbox, self.prefs["Locations"]["PluginDir"], self)
- for plugin in self.pluginList.getPlugins():
- if not plugin: continue
- plname = plugin.getName()
- if plugin.isEnabled():
- self.cbox.log.info("Plugin '%s' loaded" % plname)
- ## this should be the "easiest" way to expose all plugins as URLs
- setattr(self, plname, self.return_plugin_action(plugin))
- setattr(getattr(self, plname), "exposed", True)
- # TODO: check, if this really works - for now the "stream_response" feature seems to be broken
- #setattr(getattr(self, plname), "stream_respones", True)
- else:
- self.cbox.log.info("Plugin '%s' is disabled" % plname)
- ## remove the plugin, if it was active before
- setattr(self, plname, None)
+ def __load_plugins(self):
+ """reinitialize the list of available plugins
+
+ this includes the following:
+ - reload all plugins and check their state (disabled or not)
+ - reinitilize the datasets of all plugins
+ """
+ self.__plugin_manager = cryptobox.plugins.manage.PluginManager(
+ self.cbox, self.cbox.prefs["Locations"]["PluginDir"], self)
+ for plugin in self.__plugin_manager.get_plugins():
+ if not plugin:
+ continue
+ plname = plugin.get_name()
+ ## check if there are name conflicts: e.g. a local variable has the
+ ## same name as a plugin to be loaded -> skip these plugins
+ ## if we do not check this here, nasty side effects may occour ...
+ try:
+ prev_obj = getattr(self, plname)
+ if not callable(prev_obj) \
+ or not prev_obj.exposed:
+ self.cbox.log.error("Skipped feature (%s) as its name"
+ + " conflicts with a local variable - see"
+ + " module cryptobox.web.sites" % plname)
+ ## skip this plugin
+ continue
+ except (NameError, AttributeError):
+ ## an attribute with the same name does not exist -> ok
+ if plugin.is_enabled():
+ self.cbox.log.info("Plugin '%s' loaded" % plname)
+ ## expose all features as URLs
+ setattr(self, plname, self.return_plugin_action(plugin))
+ getattr(self, plname).exposed = True
+ #TODO: check, if this really works
+ #for now the "stream_response" feature seems to be broken
+ #setattr(getattr(self, plname), "stream_respones", True)
+ else:
+ self.cbox.log.info("Plugin '%s' is disabled" % plname)
+ ## remove the plugin, if it was active before
+ setattr(self, plname, None)
- ## this is a function decorator to check authentication
- ## it has to be defined before any page definition requiring authentification
- def __requestAuth(self=None):
+ ## sub pages requiring authentication may not be defined above
+ def __request_auth(self=None):
+ """ this is a function decorator to check authentication
+ """
def check_credentials(site):
+ """ see description of _inner_wrapper - please simplify this!
+ """
def _inner_wrapper(self, *args, **kargs):
+ """this function was necessary while trying around with the
+ function decorator - if someone can implement the decorator
+ with less effort, then any suggestions are welcome!
+ """
import base64
## define a "non-allowed" function
user, password = None, None
try:
- resp = cherrypy.request.headers["Authorization"][6:] # ignore "Basic "
- (user, password) = base64.b64decode(resp).split(":",1)
+ ## ignore the "Basic " (first six letters) part
+ resp = cherrypy.request.headers["Authorization"][6:]
+ (user, password) = base64.b64decode(resp).split(":", 1)
except KeyError:
## no "authorization" header was sent
pass
@@ -123,18 +170,20 @@ class WebInterfaceSites:
except AttributeError:
## no cherrypy response header defined
pass
- authDict = self.cbox.prefs.userDB["admins"]
- if user in authDict.keys():
- if self.cbox.prefs.userDB.getDigest(password) == authDict[user]:
+ auth_dict = self.cbox.prefs.user_db["admins"]
+ if user in auth_dict.keys():
+ if self.cbox.prefs.user_db.get_digest(password) == auth_dict[user]:
## ok: return the choosen page
self.cbox.log.info("access granted for: %s" % user)
return site(self, *args, **kargs)
else:
- self.cbox.log.info("wrong password supplied for: %s" % user)
+ self.cbox.log.info(
+ "wrong password supplied for: %s" % user)
else:
self.cbox.log.info("unknown user: %s" % str(user))
## wrong credentials: return "access denied"
- cherrypy.response.headers["WWW-Authenticate"] = '''Basic realm="CryptoBox"'''
+ cherrypy.response.headers["WWW-Authenticate"] = \
+ '''Basic realm="CryptoBox"'''
cherrypy.response.status = 401
return self.__render("access_denied")
return _inner_wrapper
@@ -147,15 +196,18 @@ class WebInterfaceSites:
@cherrypy.expose
def index(self, weblang=""):
- self.__resetDataset()
- self.__setWebLang(weblang)
- self.__checkEnvironment()
+ """the default page on startup - we show the list of available disks
+ """
+ self.__reset_dataset()
+ self.__set_web_lang(weblang)
+ self.__check_environment()
## do not forget the language!
param_dict = {"weblang":weblang}
## render "disks" plugin by default
- return self.return_plugin_action(self.pluginList.getPlugin("disks"))(**param_dict)
+ return self.return_plugin_action(
+ self.__plugin_manager.get_plugin("disks"))(**param_dict)
- def newHTTPErrorHandler(self, errorCode, message):
+ def new_http_error_handler(self, error_code, message):
"""handle http errors gracefully
404 - not found errors: ignored if url is below /cryptobox-misc/
@@ -163,148 +215,164 @@ class WebInterfaceSites:
500 - runtime errors: return "ok" exit code and show a polite excuse
others: are there any other possible http errors?
"""
- import traceback, sys
+ import traceback
## we ignore uninteresting not-found errors
- if (errorCode == 404) and \
+ if (error_code == 404) and \
(cherrypy.request.path.startswith("/cryptobox-misc/") or \
cherrypy.request.path in ['/robots.txt','/favicon.ico']):
- cherrypy.response.status = errorCode
+ cherrypy.response.status = error_code
return
## an invalid action was requested
- if errorCode == 404:
+ if error_code == 404:
## we send a not-found error (with the usual interface)
- cherrypy.response.status = errorCode
- self.dataset["Data.Warning"] = "InvalidAction"
+ cherrypy.response.status = error_code
+ self.__dataset["Data.Warning"] = "InvalidAction"
cherrypy.response.body = self.__render("empty")
return
## are there still bugs in the code?
- if errorCode == 500:
+ if error_code == 500:
## we fix the error code (200 is "OK")
cherrypy.response.status = 200
- self.cbox.log.error("HTTP-ERROR[500] - a runtime error occoured: %s" % str(message))
+ self.cbox.log.error(
+ "HTTP-ERROR[500] - runtime error: %s" % str(message))
## add a traceback and exception information to the lo
- for a in traceback.format_exception(*sys.exc_info()):
- self.cbox.log.error("\t%s" % a)
- self.dataset["Data.Warning"] = "RuntimeError"
+ for log_line in traceback.format_exception(*sys.exc_info()):
+ self.cbox.log.error("\t%s" % log_line)
+ self.__dataset["Data.Warning"] = "RuntimeError"
cherrypy.response.body = self.__render("empty")
return
## unknown error type
- cherrypy.response.status = errorCode
- self.cbox.log.warn("HTTP-ERROR[%d] - an unknown error occoured: %s" % (errorCode, message))
+ cherrypy.response.status = error_code
+ self.cbox.log.warn("HTTP-ERROR[%d] - an unknown error occoured: %s" \
+ % (error_code, message))
cherrypy.response.body = self.__render("empty")
def return_plugin_action(self, plugin):
+ """ returns a function that is suitable for handling a cherrypy
+ page request
+ """
def handler(self, **args):
- self.__resetDataset()
- self.__checkEnvironment()
- args_orig = dict(args)
+ """this function handles a cherrypy page request
+ """
+ self.__reset_dataset()
+ self.__check_environment()
## set web interface language
try:
- self.__setWebLang(args["weblang"])
+ self.__set_web_lang(args["weblang"])
del args["weblang"]
except KeyError:
- self.__setWebLang("")
- ## we always read the "device" setting - otherwise volume-plugin links
- ## would not work easily (see "volume_props" linking to "volume_format_fs")
+ self.__set_web_lang("")
+ ## we always read the "device" setting - otherwise volume-plugin
+ ## links would not work easily
+ ## (see "volume_props" linking to "volume_format_fs")
## it will get ignored for non-volume plugins
try:
plugin.device = None
- if self.__setDevice(args["device"]):
+ if self.__set_device(args["device"]):
plugin.device = args["device"]
del args["device"]
except KeyError:
- pass
+ plugin.device = None
## check the device argument of volume plugins
- if "volume" in plugin.pluginCapabilities:
+ if "volume" in plugin.plugin_capabilities:
## initialize the dataset of the selected device if necessary
if plugin.device:
- self.dataset.setCurrentDiskState(plugin.device)
+ self.__dataset.set_current_disk_state(plugin.device)
else:
## invalid (or missing) device setting
return self.__render(self.defaultTemplate)
- ## check if there is a "redirect" setting - this will override the return
- ## value of the doAction function (e.g. useful for umount-before-format)
+ ## check if there is a "redirect" setting - this will override
+ ## the return value of the do_action function
+ ## (e.g. useful for umount-before-format)
try:
if args["redirect"]:
- override_nextTemplate = { "plugin":args["redirect"] }
- if "volume" in plugin.pluginCapabilities:
- override_nextTemplate["values"] = {"device":plugin.device}
+ override_next_template = { "plugin":args["redirect"] }
+ if "volume" in plugin.plugin_capabilities:
+ override_next_template["values"] = {"device":plugin.device}
del args["redirect"]
except KeyError:
- override_nextTemplate = None
+ override_next_template = None
## check for information to be kept after the last call
try:
keep_values = args["message_keep"]
del args["message_keep"]
for key, value in keep_values["dataset"].items():
- self.dataset[key] = value
+ self.__dataset[key] = value
except KeyError:
keep_values = None
## call the plugin handler
- nextTemplate = plugin.doAction(**args)
+ next_template = plugin.do_action(**args)
## for 'volume' plugins: reread the dataset of the current disk
## additionally: set the default template for plugins
- if "volume" in plugin.pluginCapabilities:
+ if "volume" in plugin.plugin_capabilities:
## maybe the state of the current volume was changed?
- self.dataset.setCurrentDiskState(plugin.device)
- if not nextTemplate: nextTemplate = { "plugin":"volume_mount", "values":{"device":plugin.device}}
+ self.__dataset.set_current_disk_state(plugin.device)
+ if not next_template:
+ next_template = { "plugin":"volume_mount",
+ "values":{"device":plugin.device}}
else:
- ## maybe a non-volume plugin changed some plugin settings (e.g. plugin_manager)
- self.dataset.setPluginData()
- ## update the container hdf-dataset (maybe a plugin changed the state of a container)
- self.dataset.setContainersState()
+ ## some non-volume plugins change the internal state of other
+ ## plugins - e.g.: plugin_manager
+ self.__dataset.set_plugin_data()
+ ## some non-volume plugins may change the state of containers
+ self.__dataset.set_containers_state()
## default page for non-volume plugins is the disk selection
- if not nextTemplate: nextTemplate = { "plugin":"disks", "values":{} }
+ if not next_template:
+ next_template = { "plugin":"disks", "values":{} }
## was a redirect requested?
- if override_nextTemplate:
- nextTemplate = override_nextTemplate
- ## if another plugins was choosen for 'nextTemplate', then do it!
- if isinstance(nextTemplate, types.DictType) \
- and "plugin" in nextTemplate.keys() \
- and "values" in nextTemplate.keys() \
- and self.pluginList.getPlugin(nextTemplate["plugin"]):
- valueDict = dict(nextTemplate["values"])
+ if override_next_template:
+ next_template = override_next_template
+ ## if another plugins was choosen for 'next_template', then do it!
+ if isinstance(next_template, dict) \
+ and "plugin" in next_template.keys() \
+ and "values" in next_template.keys() \
+ and self.__plugin_manager.get_plugin(next_template["plugin"]):
+ value_dict = dict(next_template["values"])
## force the current weblang attribute - otherwise it gets lost
- valueDict["weblang"] = self.dataset["Settings.Language"]
+ value_dict["weblang"] = self.__dataset["Settings.Language"]
## check for warnings/success messages, that should be kept
- if "Data.Warning" in plugin.hdf.keys() \
- or "Data.Success" in plugin.hdf.keys():
- self.cbox.log.info("keep warning message")
- valueDict["message_keep"] = { "plugin":plugin, "dataset":{}}
+ if "Data.Success" in plugin.hdf.keys() \
+ or "Data.Warning" in plugin.hdf.keys():
+ value_dict["message_keep"] = {"plugin":plugin, "dataset":{}}
for keep_key in ("Data.Warning", "Data.Success"):
if keep_key in plugin.hdf.keys():
- valueDict["message_keep"]["dataset"][keep_key] = plugin.hdf[keep_key]
- new_plugin = self.pluginList.getPlugin(nextTemplate["plugin"])
- return self.return_plugin_action(new_plugin)(**valueDict)
+ self.cbox.log.info("keeping message: %s" % \
+ plugin.hdf[keep_key])
+ value_dict["message_keep"]["dataset"][keep_key] = \
+ plugin.hdf[keep_key]
+ new_plugin = self.__plugin_manager.get_plugin(next_template["plugin"])
+ return self.return_plugin_action(new_plugin)(**value_dict)
## save the currently active plugin name
- self.dataset["Data.ActivePlugin"] = plugin.getName()
- return self.__render(nextTemplate, plugin)
+ self.__dataset["Data.ActivePlugin"] = plugin.get_name()
+ return self.__render(next_template, plugin)
## apply authentication?
- if plugin.isAuthRequired():
- return lambda **args: self.__requestAuth()(handler)(self, **args)
+ if plugin.is_auth_required():
+ return lambda **args: self.__request_auth()(handler)(self, **args)
else:
return lambda **args: handler(self, **args)
- ## test authentication
@cherrypy.expose
- @__requestAuth
+ @__request_auth
def test(self, weblang=""):
- self.__resetDataset()
- self.__setWebLang(weblang)
- self.__checkEnvironment()
+ """test authentication - this function may be safely removed
+ """
+ self.__reset_dataset()
+ self.__set_web_lang(weblang)
+ self.__check_environment()
return "test passed"
@cherrypy.expose
def test_stream(self):
"""just for testing purposes - to check if the "stream_response" feature
- actually works - for now (September 02006) it does not seem to be ok"""
+ actually works - for now (September 02006) it does not seem to be ok
+ """
import time
yield "