changed coding style according to pylint
This commit is contained in:
parent
f6295a4b2d
commit
fe69eb38ae
|
@ -31,6 +31,8 @@ Syntax:
|
||||||
this script will always return with an exitcode 0 (true), if "check" is the only argument
|
this script will always return with an exitcode 0 (true), if "check" is the only argument
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
|
@ -24,16 +24,42 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import os, sys
|
import os, sys
|
||||||
import cryptobox.web.sites
|
import cryptobox.web.sites
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
from optparse import OptionParser
|
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:
|
try:
|
||||||
import cherrypy
|
import cherrypy
|
||||||
except:
|
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)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,17 +155,22 @@ def close_open_files():
|
||||||
|
|
||||||
|
|
||||||
def write_pid_file(pid_file):
|
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:
|
try:
|
||||||
pidf = open(pid_file,"w")
|
pidf = open(pid_file,"w")
|
||||||
pidf.write(str(os.getpid()))
|
pidf.write(str(os.getpid()))
|
||||||
pidf.close()
|
pidf.close()
|
||||||
except (IOError, OSError), errMsg:
|
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
|
## it is just a warning - no need to break
|
||||||
|
|
||||||
|
|
||||||
def parseOptions():
|
def parseOptions():
|
||||||
version = "%prog" + cryptobox.core.main.VERSION
|
import cryptobox
|
||||||
|
version = "%prog" + cryptobox.__version__
|
||||||
parser = OptionParser(version=version)
|
parser = OptionParser(version=version)
|
||||||
parser.set_defaults(conffile="/etc/cryptobox-server/cryptobox.conf",
|
parser.set_defaults(conffile="/etc/cryptobox-server/cryptobox.conf",
|
||||||
pidfile="/var/run/cryptobox-server/webserver.pid",
|
pidfile="/var/run/cryptobox-server/webserver.pid",
|
||||||
|
|
33
bin/do_pylint.sh
Executable file
33
bin/do_pylint.sh
Executable file
|
@ -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
|
||||||
|
|
19
debian/cryptobox-server.init
vendored
19
debian/cryptobox-server.init
vendored
|
@ -16,7 +16,6 @@
|
||||||
# Short-Description: start CryptoBox webserver
|
# Short-Description: start CryptoBox webserver
|
||||||
### END INIT INFO
|
### END INIT INFO
|
||||||
|
|
||||||
|
|
||||||
# read the default setting file, if it exists
|
# read the default setting file, if it exists
|
||||||
[ -r /etc/default/cryptobox-server ] && source /etc/default/cryptobox-server
|
[ -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
|
[ "$NO_START" = "1" ] && exit 0
|
||||||
|
|
||||||
DAEMON=/usr/sbin/CryptoBoxWebserver
|
DAEMON=/usr/sbin/CryptoBoxWebserver
|
||||||
|
PYTHON_EXEC=/usr/bin/python
|
||||||
PIDFILE=/var/run/cryptobox-server/webserver.pid
|
PIDFILE=/var/run/cryptobox-server/webserver.pid
|
||||||
DESC="CryptoBox Daemon (webinterface)"
|
DESC="CryptoBox Daemon (webinterface)"
|
||||||
OPTIONS="-B --pidfile=$PIDFILE --config=$CONF_FILE --logfile=$LOGFILE --host=$HOST --port=$PORT $SERVER_OPTS"
|
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
|
case "$1" in
|
||||||
start )
|
start )
|
||||||
# TODO: mount config dir
|
# create the directory of the pid file if necessary
|
||||||
# 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
|
|
||||||
PIDDIR=$(dirname "$PIDFILE")
|
PIDDIR=$(dirname "$PIDFILE")
|
||||||
if [ -d "$PIDDIR" ]
|
if [ -d "$PIDDIR" ]
|
||||||
then mkdir -p "$PIDDIR"
|
then mkdir -p "$PIDDIR"
|
||||||
|
@ -60,14 +56,21 @@ case "$1" in
|
||||||
if start-stop-daemon \
|
if start-stop-daemon \
|
||||||
--chuid $RUNAS: --quiet --start \
|
--chuid $RUNAS: --quiet --start \
|
||||||
--user $RUNAS --pidfile "$PIDFILE" \
|
--user $RUNAS --pidfile "$PIDFILE" \
|
||||||
--exec /usr/bin/python --startas "$DAEMON" -- $OPTIONS
|
--startas "$PYTHON_EXEC" -- "$DAEMON" $OPTIONS
|
||||||
then log_end_msg 0
|
then log_end_msg 0
|
||||||
else log_end_msg 1
|
else log_end_msg 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
stop )
|
stop )
|
||||||
log_daemon_msg "Stopping cryptobox webserver" "$DESC"
|
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" \
|
--pidfile "$PIDFILE" \
|
||||||
--user "$RUNAS"
|
--user "$RUNAS"
|
||||||
then test -e "$PIDFILE" && rm "$PIDFILE"
|
then test -e "$PIDFILE" && rm "$PIDFILE"
|
||||||
|
|
|
@ -18,29 +18,39 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""Change date and time.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
|
|
||||||
class date(cryptobox.plugins.base.CryptoBoxPlugin):
|
class date(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
"""The date feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "preferences" ]
|
plugin_visibility = [ "preferences" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 10
|
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
|
import datetime
|
||||||
if store:
|
if store:
|
||||||
try:
|
try:
|
||||||
year, month, day = int(year), int(month), int(day)
|
year, month, day = int(year), int(month), int(day)
|
||||||
hour, minute = int(hour), int(minute)
|
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:
|
except ValueError:
|
||||||
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
||||||
self.__prepareFormData()
|
self.__prepare_form_data()
|
||||||
return "form_date"
|
return "form_date"
|
||||||
date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
|
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.cbox.log.info("changed date to: %s" % date)
|
||||||
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
|
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
|
||||||
return None
|
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)
|
## 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.cbox.log.info("failed to set date: %s" % date)
|
||||||
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
||||||
self.__prepareFormData()
|
self.__prepare_form_data()
|
||||||
return "form_date"
|
return "form_date"
|
||||||
else:
|
else:
|
||||||
self.__prepareFormData()
|
self.__prepare_form_data()
|
||||||
return "form_date"
|
return "form_date"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
now = self.__getCurrentDate()
|
"""Retrieve the status of the feature.
|
||||||
return "%d/%d/%d/%d/%d/%d" % (now.year, now.month, now.day, now.hour, now.minute, now.second)
|
"""
|
||||||
|
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):
|
def __prepare_form_data(self):
|
||||||
date = self.__getCurrentDate()
|
"""Set some hdf values.
|
||||||
self.hdf[self.hdf_prefix + "year"] = date.year
|
"""
|
||||||
self.hdf[self.hdf_prefix + "month"] = date.month
|
cur_date = self.__get_current_date()
|
||||||
self.hdf[self.hdf_prefix + "day"] = date.day
|
self.hdf[self.hdf_prefix + "year"] = cur_date.year
|
||||||
self.hdf[self.hdf_prefix + "hour"] = date.hour
|
self.hdf[self.hdf_prefix + "month"] = cur_date.month
|
||||||
self.hdf[self.hdf_prefix + "minute"] = date.minute
|
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
|
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 subprocess
|
||||||
import os
|
import os
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
|
@ -83,7 +102,7 @@ class date(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(self.pluginDir, "root_action.py"),
|
os.path.join(self.plugin_dir, "root_action.py"),
|
||||||
date])
|
date])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
return proc.returncode == 0
|
return proc.returncode == 0
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
||||||
PLUGIN_TYPE = "cryptobox"
|
PLUGIN_TYPE = "cryptobox"
|
||||||
|
|
|
@ -18,18 +18,20 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_get_date(self):
|
def test_get_date(self):
|
||||||
"""retrieve the current date"""
|
"""retrieve the current date"""
|
||||||
date = self._getCurrentDate()
|
date = self._get_current_date()
|
||||||
|
|
||||||
|
|
||||||
def test_change_date(self):
|
def test_change_date(self):
|
||||||
"""set the date back and forth"""
|
"""set the date back and forth"""
|
||||||
now = self._getCurrentDate()
|
now = self._get_current_date()
|
||||||
## copy current time
|
## copy current time
|
||||||
new_date = dict(now)
|
new_date = dict(now)
|
||||||
## move three minutes forward (more is not nice because of screensavers)
|
## 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)
|
new_date["hour"] = now["hour"] + ((now["minute"] + 3) / 60)
|
||||||
## move forward ...
|
## move forward ...
|
||||||
self._setDate(new_date)
|
self._setDate(new_date)
|
||||||
self.assertEquals(new_date, self._getCurrentDate())
|
self.assertEquals(new_date, self._get_current_date())
|
||||||
## ... and backward
|
## ... and backward
|
||||||
self._setDate(now)
|
self._setDate(now)
|
||||||
self.assertEquals(now, self._getCurrentDate())
|
self.assertEquals(now, self._get_current_date())
|
||||||
|
|
||||||
|
|
||||||
def test_try_broken_date(self):
|
def test_try_broken_date(self):
|
||||||
|
@ -54,8 +56,8 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
self.cmd.find("invalid value for date")
|
self.cmd.find("invalid value for date")
|
||||||
|
|
||||||
|
|
||||||
def _getCurrentDate(self):
|
def _get_current_date(self):
|
||||||
date_url = self.URL + "date"
|
date_url = self.url + "date"
|
||||||
self.register_auth(date_url)
|
self.register_auth(date_url)
|
||||||
self.cmd.go(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")
|
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):
|
def _setDate(self, date):
|
||||||
"""for now we have to use this function instead of the one below"""
|
"""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["year"]), str(date["month"]), str(date["day"]),
|
||||||
str(date["hour"]), str(date["minute"]))
|
str(date["hour"]), str(date["minute"]))
|
||||||
self.register_auth(date_url)
|
self.register_auth(date_url)
|
||||||
|
@ -83,7 +85,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
def _setDateBroken(self, date):
|
def _setDateBroken(self, date):
|
||||||
"""this should work, but the parsing of twill seems to be broken
|
"""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"""
|
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.register_auth(date_url)
|
||||||
self.cmd.go(date_url)
|
self.cmd.go(date_url)
|
||||||
self.cmd.formvalue("set_date", "year", str(date["year"]))
|
self.cmd.formvalue("set_date", "year", str(date["year"]))
|
||||||
|
|
|
@ -18,21 +18,31 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""The disks feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
class disks(cryptobox.plugins.base.CryptoBoxPlugin):
|
class disks(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
"""The disk feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "menu" ]
|
plugin_visibility = [ "menu" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 10
|
rank = 10
|
||||||
|
|
||||||
def doAction(self):
|
def do_action(self):
|
||||||
self.cbox.reReadContainerList()
|
"""The action handler.
|
||||||
|
"""
|
||||||
|
self.cbox.reread_container_list()
|
||||||
return "disks"
|
return "disks"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return ":".join([e.getDevice() for e in self.cbox.getContainerList()])
|
"""Retrieve the current status of the feature.
|
||||||
|
"""
|
||||||
|
return ":".join([e.get_device() for e in self.cbox.get_container_list()])
|
||||||
|
|
||||||
|
|
|
@ -18,24 +18,26 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
'''display all devices'''
|
'''display all devices'''
|
||||||
self.register_auth(self.URL)
|
self.register_auth(self.url)
|
||||||
self.cmd.go(self.URL + "disks?weblang=en")
|
self.cmd.go(self.url + "disks?weblang=en")
|
||||||
self.cmd.find("Available disks")
|
self.cmd.find("Available disks")
|
||||||
|
|
||||||
|
|
||||||
def test_is_device_in_list(self):
|
def test_is_device_in_list(self):
|
||||||
"""check if the device-under-test is in the device list"""
|
"""check if the device-under-test is in the device list"""
|
||||||
self.register_auth(self.URL)
|
self.register_auth(self.url)
|
||||||
self.cmd.go(self.URL + "disks?weblang=en")
|
self.cmd.go(self.url + "disks?weblang=en")
|
||||||
self.cmd.find("Available disks")
|
self.cmd.find("Available disks")
|
||||||
self.cmd.find(u'Data.Status.Plugins.disks=(.*)$', "m")
|
self.cmd.find(u'Data.Status.Plugins.disks=(.*)$', "m")
|
||||||
devices = self.locals["__match__"].split(":")
|
devices = self.locals["__match__"].split(":")
|
||||||
self.assertTrue(len(devices)>0)
|
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)
|
||||||
|
|
||||||
|
|
|
@ -18,26 +18,34 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""The help feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
class help(cryptobox.plugins.base.CryptoBoxPlugin):
|
class help(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
"""The help feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "menu" ]
|
plugin_visibility = [ "menu" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 80
|
rank = 80
|
||||||
|
|
||||||
default_lang = 'en'
|
default_lang = 'en'
|
||||||
default_page = "CryptoBoxUser"
|
default_page = "CryptoBoxUser"
|
||||||
|
|
||||||
def doAction(self, page=""):
|
def do_action(self, page=""):
|
||||||
'''prints the offline wikipage
|
'''prints the offline wikipage
|
||||||
'''
|
'''
|
||||||
import re,os
|
import re, os
|
||||||
## check for invalid characters and if the page exists in the default language
|
## check for invalid characters and if the page exists in the default language
|
||||||
if page and \
|
if page and \
|
||||||
not re.search(u'\W', 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
|
## everything is ok
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -49,20 +57,23 @@ class help(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
## store the name of the page
|
## store the name of the page
|
||||||
self.hdf[self.hdf_prefix + "Page"] = page
|
self.hdf[self.hdf_prefix + "Page"] = page
|
||||||
## choose the right language
|
## choose the right language
|
||||||
for l in self.site.langOrder:
|
for lang in self.site.lang_order:
|
||||||
if os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"], l, page + '.html')):
|
if os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
|
||||||
lang = l
|
lang, page + '.html')):
|
||||||
|
doc_lang = lang
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
lang = self.default_lang
|
doc_lang = self.default_lang
|
||||||
self.hdf[self.hdf_prefix + "Language"] = lang
|
self.hdf[self.hdf_prefix + "Language"] = doc_lang
|
||||||
## store the current setting for a later "getStatus" call
|
## store the current setting for a later "getStatus" call
|
||||||
self.current_lang = lang
|
self.current_lang = doc_lang
|
||||||
self.current_page = page
|
self.current_page = page
|
||||||
return "doc"
|
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)
|
return "%s:%s" % (self.current_lang, self.current_page)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
from twill.errors import *
|
from twill.errors import *
|
||||||
|
|
||||||
|
@ -27,7 +29,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
'''help pages should be available in different languages'''
|
'''help pages should be available in different languages'''
|
||||||
|
|
||||||
## check english help pages
|
## 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("Table of Contents")
|
||||||
self.cmd.find("Getting started")
|
self.cmd.find("Getting started")
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
|
@ -35,7 +37,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
self.assertTrue(page == "CryptoBoxUser")
|
self.assertTrue(page == "CryptoBoxUser")
|
||||||
|
|
||||||
## check german help pages
|
## 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("Table of Contents")
|
||||||
self.cmd.find("Wie geht es los")
|
self.cmd.find("Wie geht es los")
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
|
@ -43,7 +45,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
self.assertTrue(page == "CryptoBoxUser")
|
self.assertTrue(page == "CryptoBoxUser")
|
||||||
|
|
||||||
## check slovene help pages
|
## 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")
|
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
|
||||||
## add a slovene text here, as soon as the help is translated
|
## add a slovene text here, as soon as the help is translated
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
|
@ -52,7 +54,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
self.assertTrue(page == "CryptoBoxUser")
|
self.assertTrue(page == "CryptoBoxUser")
|
||||||
|
|
||||||
## check french help pages
|
## 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")
|
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
|
||||||
## add a french text here, as soon as the help is translated
|
## add a french text here, as soon as the help is translated
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
|
@ -61,7 +63,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
self.assertTrue(page == "CryptoBoxUser")
|
self.assertTrue(page == "CryptoBoxUser")
|
||||||
|
|
||||||
## test a random language - it should fall back to english
|
## 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")
|
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
self.assertTrue(lang == "en")
|
self.assertTrue(lang == "en")
|
||||||
|
@ -70,18 +72,18 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_help_pages(self):
|
def test_help_pages(self):
|
||||||
"""check invalid page requests"""
|
"""check invalid page requests"""
|
||||||
self.cmd.go(self.URL + "help?page=foobar")
|
self.cmd.go(self.url + "help?page=foobar")
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
self.assertTrue(page == "CryptoBoxUser")
|
self.assertTrue(page == "CryptoBoxUser")
|
||||||
|
|
||||||
self.cmd.go(self.URL + "help?page=CryptoBoxUser")
|
self.cmd.go(self.url + "help?page=CryptoBoxUser")
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
self.assertTrue(page == "CryptoBoxUser")
|
self.assertTrue(page == "CryptoBoxUser")
|
||||||
|
|
||||||
|
|
||||||
def test_help_default_languages(self):
|
def test_help_default_languages(self):
|
||||||
"""check invalid page requests"""
|
"""check invalid page requests"""
|
||||||
self.cmd.go(self.URL + "help?weblang=foobar")
|
self.cmd.go(self.url + "help?weblang=foobar")
|
||||||
(lang,page) = self._getHelpStatus()
|
(lang,page) = self._getHelpStatus()
|
||||||
self.assertTrue(lang == "en")
|
self.assertTrue(lang == "en")
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,31 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
|
|
||||||
class language_selection(cryptobox.plugins.base.CryptoBoxPlugin):
|
class language_selection(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
"""The language_selection feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "menu", "preferences" ]
|
plugin_visibility = [ "menu", "preferences" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 60
|
rank = 60
|
||||||
|
|
||||||
def doAction(self):
|
def do_action(self):
|
||||||
|
"""Show all available languages.
|
||||||
|
"""
|
||||||
return "language_selection"
|
return "language_selection"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return ":".join(self.site.langOrder)
|
"""The current status of the feature is defined as the current language.
|
||||||
|
"""
|
||||||
|
return ":".join(self.site.lang_order)
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,21 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
url = self.URL + "language_selection?weblang=en"
|
url = self.url + "language_selection?weblang=en"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('hoose an interface language')
|
self.cmd.find('hoose an interface language')
|
||||||
|
|
||||||
|
|
||||||
def test_check_language_list(self):
|
def test_check_language_list(self):
|
||||||
url = self.URL + "language_selection"
|
url = self.url + "language_selection"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find(u'Data.Status.Plugins.language_selection=(.*)$', "m")
|
self.cmd.find(u'Data.Status.Plugins.language_selection=(.*)$', "m")
|
||||||
|
|
|
@ -18,56 +18,76 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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 cryptobox.plugins.base
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
|
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
"""The logs feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "preferences" ]
|
plugin_visibility = [ "preferences" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 90
|
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
|
import re
|
||||||
## filter input
|
## filter input
|
||||||
try:
|
try:
|
||||||
lines = int(lines)
|
lines = int(lines)
|
||||||
if lines <= 0: raise(ValueError)
|
if lines <= 0:
|
||||||
|
raise(ValueError)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
lines = 50
|
lines = 50
|
||||||
try:
|
try:
|
||||||
size = int(size)
|
size = int(size)
|
||||||
if size <= 0: raise(ValueError)
|
if size <= 0:
|
||||||
|
raise(ValueError)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
size = 3000
|
size = 3000
|
||||||
if not pattern is None:
|
if not pattern is None:
|
||||||
pattern = str(pattern)
|
pattern = str(pattern)
|
||||||
if re.search(u'\W', pattern): pattern = None
|
if re.search(u'\W', pattern):
|
||||||
self.hdf[self.hdf_prefix + "Content"] = self.__getLogContent(lines, size, pattern)
|
pattern = None
|
||||||
self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.abspath(os.path.join(self.pluginDir, "logs.css"))
|
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"
|
return "show_log"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
|
"""The current status includes the log configuration details.
|
||||||
|
"""
|
||||||
return "%s:%s:%s" % (
|
return "%s:%s:%s" % (
|
||||||
self.cbox.prefs["Log"]["Level"],
|
self.cbox.prefs["Log"]["Level"],
|
||||||
self.cbox.prefs["Log"]["Destination"],
|
self.cbox.prefs["Log"]["Destination"],
|
||||||
self.cbox.prefs["Log"]["Details"])
|
self.cbox.prefs["Log"]["Details"])
|
||||||
|
|
||||||
|
|
||||||
def __getLogContent(self, lines, maxSize, pattern):
|
def __get_log_content(self, lines, max_size, pattern):
|
||||||
import re
|
"""Filter, sort and shorten the log content.
|
||||||
|
"""
|
||||||
if pattern:
|
if pattern:
|
||||||
content = []
|
content = []
|
||||||
current_length = 0
|
current_length = 0
|
||||||
for line in self.cbox.getLogData():
|
for line in self.cbox.get_log_data():
|
||||||
if line.find(pattern) != -1:
|
if line.find(pattern) != -1:
|
||||||
content.append(line)
|
content.append(line)
|
||||||
current_length += len(line)
|
current_length += len(line)
|
||||||
if lines and len(content) >=lines: break
|
if lines and len(content) >= lines:
|
||||||
if maxSize and current_length >=maxSize: break
|
break
|
||||||
|
if max_size and current_length >= max_size:
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
content = self.cbox.getLogData(lines, maxSize)
|
content = self.cbox.get_log_data(lines, max_size)
|
||||||
return "<br/>".join(content)
|
return "<br/>".join(content)
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_logs(self):
|
def test_read_logs(self):
|
||||||
log_url = self.URL + "logs"
|
log_url = self.url + "logs"
|
||||||
self.register_auth(log_url)
|
self.register_auth(log_url)
|
||||||
self.cmd.go(log_url)
|
self.cmd.go(log_url)
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('class="console"')
|
||||||
|
@ -31,13 +33,13 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
def test_write_logs(self):
|
def test_write_logs(self):
|
||||||
log_text = "unittest - just a marker - please ignore"
|
log_text = "unittest - just a marker - please ignore"
|
||||||
self.cbox.log.error(log_text)
|
self.cbox.log.error(log_text)
|
||||||
log_url = self.URL + "logs"
|
log_url = self.url + "logs"
|
||||||
self.register_auth(log_url)
|
self.register_auth(log_url)
|
||||||
self.cmd.go(log_url + "?pattern=ERROR")
|
self.cmd.go(log_url + "?pattern=ERROR")
|
||||||
self.cmd.find(log_text)
|
self.cmd.find(log_text)
|
||||||
|
|
||||||
def test_invalid_args(self):
|
def test_invalid_args(self):
|
||||||
log_url = self.URL + "logs"
|
log_url = self.url + "logs"
|
||||||
self.cmd.go(log_url + "?lines=10")
|
self.cmd.go(log_url + "?lines=10")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('class="console"')
|
||||||
self.cmd.go(log_url + "?lines=0")
|
self.cmd.go(log_url + "?lines=0")
|
||||||
|
|
|
@ -18,23 +18,32 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""The network feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
|
|
||||||
## specify (in seconds), how long we should wait before redirecting and ip change
|
## specify (in seconds), how long we should wait before redirecting and ip change
|
||||||
REDIRECT_DELAY=20
|
REDIRECT_DELAY = 10
|
||||||
CHANGE_IP_DELAY=1
|
CHANGE_IP_DELAY = 2
|
||||||
|
|
||||||
class network(cryptobox.plugins.base.CryptoBoxPlugin):
|
class network(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
"""The network feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "preferences" ]
|
plugin_visibility = [ "preferences" ]
|
||||||
requestAuth = True
|
request_auth = True
|
||||||
rank = 30
|
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
|
## if we were redirected, then we should display the default page
|
||||||
self.cbox.log.debug("executing network plugin")
|
self.cbox.log.debug("executing network plugin")
|
||||||
if redirected == "1":
|
if redirected == "1":
|
||||||
|
@ -46,58 +55,68 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
try:
|
try:
|
||||||
for ip_in in (ip1, ip2, ip3, ip4):
|
for ip_in in (ip1, ip2, ip3, ip4):
|
||||||
if (int(ip_in) < 0) or (int(ip_in) > 255):
|
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
|
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:
|
except ValueError:
|
||||||
self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
self.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
||||||
self.__prepareFormData()
|
self.__prepare_form_data()
|
||||||
return "form_network"
|
return "form_network"
|
||||||
if self.__setIP(ip):
|
if self.__set_ip(new_ip):
|
||||||
self.cbox.log.info("the IP was successfully changed: %s" % ip)
|
self.cbox.log.info("the IP was successfully changed: %s" % new_ip)
|
||||||
self.hdf["Data.Success"] = "Plugins.network.IPChanged"
|
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
|
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
|
||||||
return None
|
return None
|
||||||
else:
|
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.hdf["Data.Warning"] = "Plugins.network.InvalidIP"
|
||||||
self.__prepareFormData()
|
self.__prepare_form_data()
|
||||||
return "form_network"
|
return "form_network"
|
||||||
else:
|
else:
|
||||||
self.cbox.log.debug("network plugin: show form")
|
self.cbox.log.debug("network plugin: show form")
|
||||||
## just show the form
|
## just show the form
|
||||||
self.__prepareFormData()
|
self.__prepare_form_data()
|
||||||
return "form_network"
|
return "form_network"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "%d.%d.%d.%d" % self.__getCurrentIP()
|
"""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
|
import cherrypy
|
||||||
req = cherrypy.request
|
req = cherrypy.request
|
||||||
base_parts = req.base.split(":")
|
base_parts = req.base.split(":")
|
||||||
dest = "%s:%s" % (base_parts[0], ip)
|
dest = "%s://%s" % (base_parts[0], ip)
|
||||||
if len(base_parts) == 3:
|
if len(base_parts) == 3:
|
||||||
dest += ":%s" % base_parts[2]
|
dest += ":%s" % base_parts[2]
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
|
|
||||||
def __prepareFormData(self):
|
def __prepare_form_data(self):
|
||||||
(oc1, oc2, oc3, oc4) = self.__getCurrentIP()
|
"""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.oc1"] = oc1
|
||||||
self.hdf[self.hdf_prefix + "ip.oc2"] = oc2
|
self.hdf[self.hdf_prefix + "ip.oc2"] = oc2
|
||||||
self.hdf[self.hdf_prefix + "ip.oc3"] = oc3
|
self.hdf[self.hdf_prefix + "ip.oc3"] = oc3
|
||||||
self.hdf[self.hdf_prefix + "ip.oc4"] = oc4
|
self.hdf[self.hdf_prefix + "ip.oc4"] = oc4
|
||||||
|
|
||||||
|
|
||||||
def __getCurrentIP(self):
|
def __get_current_ip(self):
|
||||||
|
"""Retrieve the current IP.
|
||||||
|
"""
|
||||||
import re
|
import re
|
||||||
import imp
|
import imp
|
||||||
## load some values from the root_action.py script
|
## 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
|
## get the current IP of the network interface
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
|
@ -106,20 +125,25 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
root_action_plug.IFCONFIG_BIN,
|
root_action_plug.IFCONFIG_BIN,
|
||||||
root_action_plug.IFACE])
|
root_action_plug.IFACE])
|
||||||
(stdout, stderr) = proc.communicate()
|
(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
|
## 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)
|
match = re.search(u'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s', stdout)
|
||||||
if match:
|
if match:
|
||||||
## use the previously matched numbers
|
## use the previously matched numbers
|
||||||
return tuple([int(e) for e in match.groups()])
|
return tuple([int(e) for e in match.groups()])
|
||||||
else:
|
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
|
import threading
|
||||||
## call the root_action script after some seconds - so we can deliver the page before
|
## 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
|
import time
|
||||||
time.sleep(CHANGE_IP_DELAY)
|
time.sleep(CHANGE_IP_DELAY)
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
|
@ -129,19 +153,17 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(self.pluginDir, "root_action.py"),
|
os.path.join(self.plugin_dir, "root_action.py"),
|
||||||
ip])
|
new_ip])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
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()))
|
self.cbox.log.warn("error output: %s" % str(proc.stderr.read()))
|
||||||
return
|
return
|
||||||
thread = threading.Thread()
|
thread = threading.Thread()
|
||||||
thread.run = delayedIPchange
|
thread.run = delayed_ip_change
|
||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
# TODO: how could we guess, if it failed?
|
# TODO: how could we guess, if it failed?
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
#TODO: add netmask and gateway
|
#TODO: add netmask and gateway
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
from network import CHANGE_IP_DELAY
|
from network import CHANGE_IP_DELAY
|
||||||
|
|
||||||
|
@ -28,43 +30,47 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
'''change of network address'''
|
'''change of network address'''
|
||||||
## the time module is necessary for the CHANGE_IP_DELAY
|
## the time module is necessary for the CHANGE_IP_DELAY
|
||||||
import time
|
import time
|
||||||
self.register_auth(self.URL + "network")
|
self.register_auth(self.url + "network")
|
||||||
self.cmd.go(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
|
## extract the current IP from the network plugin output
|
||||||
def getCurrentIP():
|
def get_current_ip():
|
||||||
self.cmd.go(self.URL + "network")
|
self.register_auth(self.url + "network")
|
||||||
|
self.cmd.go(self.url + "network")
|
||||||
self.cmd.find(u'Data.Status.Plugins.network=([0-9\.]*)$', "m")
|
self.cmd.find(u'Data.Status.Plugins.network=([0-9\.]*)$', "m")
|
||||||
return self.locals["__match__"]
|
return self.locals["__match__"]
|
||||||
origIPtext = getCurrentIP()
|
orig_ip_text = get_current_ip()
|
||||||
origIPocts = origIPtext.split(".")
|
orig_ip_octs = orig_ip_text.split(".")
|
||||||
## check, if the original IP is valid (contains four octets)
|
## check, if the original IP is valid (contains four octets)
|
||||||
self.assertEquals(4, len(origIPocts))
|
self.assertEquals(4, len(orig_ip_octs))
|
||||||
wrongIP = "192.168.123.321"
|
def set_ip((ip1, ip2, ip3, ip4)):
|
||||||
def setIP((ip1, ip2, ip3, ip4)):
|
self.cmd.go(self.url + "network")
|
||||||
self.cmd.go(self.URL + "network")
|
|
||||||
self.cmd.formvalue("set_ip", "ip1", str(ip1))
|
self.cmd.formvalue("set_ip", "ip1", str(ip1))
|
||||||
self.cmd.formvalue("set_ip", "ip2", str(ip2))
|
self.cmd.formvalue("set_ip", "ip2", str(ip2))
|
||||||
self.cmd.formvalue("set_ip", "ip3", str(ip3))
|
self.cmd.formvalue("set_ip", "ip3", str(ip3))
|
||||||
self.cmd.formvalue("set_ip", "ip4", str(ip4))
|
self.cmd.formvalue("set_ip", "ip4", str(ip4))
|
||||||
self.cmd.submit()
|
self.cmd.submit()
|
||||||
## sleep a little bit longer than the delay necessary for ip-change
|
## sleep a little bit longer than the delay necessary for ip-change
|
||||||
time.sleep(CHANGE_IP_DELAY + 0.2)
|
time.sleep(CHANGE_IP_DELAY + 3)
|
||||||
setIP([1,-2,0,1])
|
set_ip([1,-2,0,1])
|
||||||
self.assertEquals(origIPtext, getCurrentIP())
|
self.assertEquals(orig_ip_text, get_current_ip())
|
||||||
setIP([1,0,0,256])
|
set_ip([1,0,0,256])
|
||||||
self.assertEquals(origIPtext, getCurrentIP())
|
self.assertEquals(orig_ip_text, get_current_ip())
|
||||||
setIP([1,"foo",0,1])
|
set_ip([1,"foo",0,1])
|
||||||
self.assertEquals(origIPtext, getCurrentIP())
|
self.assertEquals(orig_ip_text, get_current_ip())
|
||||||
setIP([10,12,0,2])
|
new_ip = orig_ip_octs[:]
|
||||||
self.assertEquals("10.12.0.2", getCurrentIP())
|
new_ip[3] = str((int(orig_ip_octs[3]) + 128) % 256)
|
||||||
setIP(origIPocts)
|
set_ip(new_ip)
|
||||||
self.assertEquals(origIPtext, getCurrentIP())
|
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):
|
def test_inputs(self):
|
||||||
self.register_auth(self.URL + "network")
|
self.register_auth(self.url + "network")
|
||||||
self.cmd.go(self.URL + "network" + "?redirected=1")
|
self.cmd.go(self.url + "network" + "?redirected=1")
|
||||||
self.cmd.notfind("problem")
|
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")
|
self.cmd.find("invalid network address")
|
||||||
|
|
||||||
|
|
|
@ -18,114 +18,141 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""The partition feature of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import cryptobox.core.tools as cbxTools
|
import cryptobox.core.tools as cbxTools
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
PARTTYPES = {
|
||||||
pluginVisibility = [ "preferences" ]
|
"windows" : ["0xC", "vfat"],
|
||||||
requestAuth = True
|
"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
|
rank = 80
|
||||||
|
|
||||||
PartTypes = {
|
def do_action(self, **args):
|
||||||
"windows" : ["0xC", "vfat"],
|
"""Show the partitioning form and execute the requested action.
|
||||||
"linux" : ["L", "ext3"]}
|
"""
|
||||||
|
|
||||||
ConfigPartition = {
|
|
||||||
"size" : 5, # size of configuration partition (if necessary) in MB
|
|
||||||
"type" : "L",
|
|
||||||
"fs" : "ext2"}
|
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, **args):
|
|
||||||
## load default hdf values
|
## load default hdf values
|
||||||
self.__prepareDataset()
|
self.__prepare_dataset()
|
||||||
## retrieve some values from 'args' - defaults are empty
|
## retrieve some values from 'args' - defaults are empty
|
||||||
self.device = self.__getSelectedDevice(args)
|
self.device = self.__get_selected_device(args)
|
||||||
self.withConfigPartition = self.__isWithConfigPartition()
|
self.with_config_partition = self.__is_with_config_partition()
|
||||||
self.cbox.log.debug("partition plugin: selected device=%s" % str(self.device))
|
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:
|
try:
|
||||||
step = args["step"]
|
step = args["step"]
|
||||||
del args["step"]
|
del args["step"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
step = "select_device"
|
step = "select_device"
|
||||||
try:
|
try:
|
||||||
## this way of selecting the easy setup is necessary: see select_device.py for details
|
## this way of selecting the easy setup is necessary:
|
||||||
if args["easy"]: step = "easy"
|
## see select_device.cs for details (button values for ie)
|
||||||
|
if args["easy"]:
|
||||||
|
step = "easy"
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
## no (or invalid) device was supplied
|
## no (or invalid) device was supplied
|
||||||
if not self.device:
|
if not self.device:
|
||||||
step = "select_device"
|
step = "select_device"
|
||||||
if step == "add_partition":
|
if step == "add_partition":
|
||||||
return self.__actionAddPartition(args)
|
return self.__action_add_partition(args)
|
||||||
elif step == "del_partition":
|
elif step == "del_partition":
|
||||||
return self.__actionDelPartition(args)
|
return self.__action_del_partition(args)
|
||||||
elif step == "finish":
|
elif step == "finish":
|
||||||
return self.__actionFinish(args)
|
return self.__action_finish(args)
|
||||||
elif step == "easy":
|
elif step == "easy":
|
||||||
return self.__actionEasySetup(args)
|
return self.__action_easy_setup()
|
||||||
else: # for "select_device" and for invalid targets
|
else: # for "select_device" and for invalid targets
|
||||||
return self.__actionSelectDevice(args)
|
return self.__action_select_device()
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "%s / %s / %s" % (self.device, self.deviceSize, self.withConfigPartition)
|
"""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):
|
def __prepare_dataset(self):
|
||||||
self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.join(self.pluginDir, "partition.css")
|
"""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:
|
try:
|
||||||
device = args["block_device"]
|
device = args["block_device"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
if not self.__isDeviceValid(device):
|
if not self.__is_device_valid(device):
|
||||||
return None
|
return None
|
||||||
if self.__isDeviceBusy(device):
|
if self.__is_device_busy(device):
|
||||||
self.hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
|
self.hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
|
||||||
return None
|
return None
|
||||||
return device
|
return device
|
||||||
|
|
||||||
|
|
||||||
def __isDeviceValid(self, device):
|
def __is_device_valid(self, device):
|
||||||
|
"""Check if the device is valid and allowed.
|
||||||
|
"""
|
||||||
if not device:
|
if not device:
|
||||||
return False
|
return False
|
||||||
if not self.cbox.isDeviceAllowed(device):
|
if not self.cbox.is_device_allowed(device):
|
||||||
return False
|
return False
|
||||||
if not device in cbxTools.getParentBlockDevices():
|
if not device in cbxTools.get_parent_blockdevices():
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def __isDeviceBusy(self, device):
|
def __is_device_busy(self, device):
|
||||||
"""check if the device (or one of its partitions) is mounted"""
|
"""check if the device (or one of its partitions) is mounted
|
||||||
|
"""
|
||||||
# the config partition is ignored, as it will get unmounted if necessary
|
# the config partition is ignored, as it will get unmounted if necessary
|
||||||
import re
|
import re
|
||||||
for c in self.cbox.getContainerList():
|
for cont in self.cbox.get_container_list():
|
||||||
if re.match(device + "\d*$", c.getDevice()):
|
if re.match(device + "\d*$", cont.get_device()):
|
||||||
if c.isMounted(): return True
|
if cont.is_mounted():
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __actionSelectDevice(self, args):
|
def __action_select_device(self):
|
||||||
|
"""Show a form to select the device for partitioning.
|
||||||
|
"""
|
||||||
block_devices = [e
|
block_devices = [e
|
||||||
for e in cbxTools.getParentBlockDevices()
|
for e in cbxTools.get_parent_blockdevices()
|
||||||
if self.cbox.isDeviceAllowed(e)]
|
if self.cbox.is_device_allowed(e)]
|
||||||
counter = 0
|
counter = 0
|
||||||
for a in block_devices:
|
for dev in block_devices:
|
||||||
self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = a
|
self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = dev
|
||||||
self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = cbxTools.getBlockDeviceSizeHumanly(a)
|
self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = \
|
||||||
self.cbox.log.debug("found a suitable block device: %s" % a)
|
cbxTools.get_blockdevice_size_humanly(dev)
|
||||||
|
self.cbox.log.debug("found a suitable block device: %s" % dev)
|
||||||
counter += 1
|
counter += 1
|
||||||
if self.withConfigPartition:
|
if self.with_config_partition:
|
||||||
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
|
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
|
||||||
## there is no disk available
|
## there is no disk available
|
||||||
if not block_devices:
|
if not block_devices:
|
||||||
|
@ -133,59 +160,72 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return "select_device"
|
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"] = self.device
|
||||||
self.hdf[self.hdf_prefix + "Device.Size"] = self.deviceSize
|
self.hdf[self.hdf_prefix + "Device.Size"] = self.device_size
|
||||||
parts = self.__getPartitionsFromArgs(args)
|
parts = self.__get_partitions_from_args(args)
|
||||||
self.__setPartitionData(parts)
|
self.__set_partition_data(parts)
|
||||||
return "set_partitions"
|
return "set_partitions"
|
||||||
|
|
||||||
|
|
||||||
def __actionDelPartition(self, args):
|
def __action_del_partition(self, args):
|
||||||
|
"""Remove a partition from the proposed partition table.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
part_num = int(args["del_num"])
|
part_num = int(args["del_num"])
|
||||||
except (TypeError,KeyError):
|
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"] = self.device
|
||||||
self.hdf[self.hdf_prefix + "Device.Size"] = self.deviceSize
|
self.hdf[self.hdf_prefix + "Device.Size"] = self.device_size
|
||||||
parts = self.__getPartitionsFromArgs(args)
|
parts = self.__get_partitions_from_args(args)
|
||||||
## valid partition number to be deleted?
|
## valid partition number to be deleted?
|
||||||
if part_num < len(parts):
|
if part_num < len(parts):
|
||||||
del parts[part_num]
|
del parts[part_num]
|
||||||
else:
|
else:
|
||||||
return self.__actionAddPartition(args)
|
return self.__action_add_partition(args)
|
||||||
self.__setPartitionData(parts)
|
self.__set_partition_data(parts)
|
||||||
return "set_partitions"
|
return "set_partitions"
|
||||||
|
|
||||||
|
|
||||||
def __actionFinish(self, args):
|
def __action_finish(self, args):
|
||||||
parts = self.__getPartitionsFromArgs(args)
|
"""Write the partition table.
|
||||||
|
"""
|
||||||
|
parts = self.__get_partitions_from_args(args)
|
||||||
if parts:
|
if parts:
|
||||||
self.__setPartitionData(parts)
|
self.__set_partition_data(parts)
|
||||||
if cbxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
|
if cbxTools.is_part_of_blockdevice(self.device,
|
||||||
self.cbox.prefs.umountPartition()
|
self.cbox.prefs.get_active_partition()):
|
||||||
if not self.__runFDisk(parts):
|
self.cbox.prefs.umount_partition()
|
||||||
|
if not self.__run_fdisk(parts):
|
||||||
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
||||||
self.cbox.log.warn("partition: failed to partition device: %s" % self.device)
|
self.cbox.log.warn(
|
||||||
return self.__actionAddPartition(args)
|
"partition: failed to partition device: %s" % self.device)
|
||||||
|
return self.__action_add_partition(args)
|
||||||
else:
|
else:
|
||||||
"""
|
## tricky problem: if the device was partitioned, then a created config
|
||||||
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
|
## partition is still part of the containerlist, as the label is not
|
||||||
"""
|
## checked again - very ugly!!! So we will call reReadContainerList
|
||||||
self.cbox.reReadContainerList()
|
## after formatting the last partition - see below
|
||||||
|
self.cbox.reread_container_list()
|
||||||
def result_generator():
|
def result_generator():
|
||||||
|
"""Generate the results of formatting - may be threaded.
|
||||||
|
"""
|
||||||
counter = 0
|
counter = 0
|
||||||
## initialize the generator
|
## initialize the generator
|
||||||
formatPart_gen = self.__formatPartitions(parts)
|
format_part_gen = self.__format_partitions(parts)
|
||||||
while counter < len(parts):
|
while counter < len(parts):
|
||||||
## first part: get the device name
|
## first part: get the device name
|
||||||
yield formatPart_gen.next()
|
yield format_part_gen.next()
|
||||||
counter += 1
|
counter += 1
|
||||||
## second part: do the real formatting of a partition
|
## second part: do the real formatting of a partition
|
||||||
result = formatPart_gen.next()
|
result = format_part_gen.next()
|
||||||
## after the first partiton, we can reRead the containerList (as the possible config partition was already created)
|
## after the first partiton, we can reRead the containerList
|
||||||
if self.withConfigPartition and (counter == 1):
|
## (as the possible config partition was already created)
|
||||||
## important: reRead the containerList - but somehow it breaks the flow (hanging process)
|
if self.with_config_partition and (counter == 1):
|
||||||
|
## important: reRead the containerList - but somehow it
|
||||||
|
## breaks the flow (hanging process)
|
||||||
#self.cbox.reReadContainerList()
|
#self.cbox.reReadContainerList()
|
||||||
## write config data
|
## write config data
|
||||||
self.cbox.prefs.mountPartition()
|
self.cbox.prefs.mountPartition()
|
||||||
|
@ -200,24 +240,28 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
"template": "show_format_progress",
|
"template": "show_format_progress",
|
||||||
"generator": result_generator}
|
"generator": result_generator}
|
||||||
else:
|
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
|
import types
|
||||||
## we do not have to take special care for a possible config partition
|
## 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
|
## umount partition if necessary
|
||||||
if cbxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
|
if cbxTools.is_part_of_blockdevice(self.device,
|
||||||
self.cbox.prefs.umountPartition()
|
self.cbox.prefs.get_active_partition()):
|
||||||
|
self.cbox.prefs.umount_partition()
|
||||||
## partition it
|
## partition it
|
||||||
if not self.__runFDisk(parts):
|
if not self.__run_fdisk(parts):
|
||||||
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
||||||
return None
|
return None
|
||||||
## "formatPartitions" is a generator, returning device names and bolean values
|
## "formatPartitions" is a generator, returning device names and bolean values
|
||||||
result = [e for e in self.__formatPartitions(parts) if type(e) == types.BooleanType]
|
result = [e for e in self.__format_partitions(parts)
|
||||||
if self.withConfigPartition:
|
if type(e) == types.BooleanType]
|
||||||
self.cbox.prefs.mountPartition()
|
if self.with_config_partition:
|
||||||
|
self.cbox.prefs.mount_partition()
|
||||||
self.cbox.prefs.write()
|
self.cbox.prefs.write()
|
||||||
## check if there is a "False" return value
|
## check if there is a "False" return value
|
||||||
if False in result:
|
if False in result:
|
||||||
|
@ -229,50 +273,59 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
## operation was successful
|
## operation was successful
|
||||||
self.hdf["Data.Success"] = "Plugins.partition.EasySetup"
|
self.hdf["Data.Success"] = "Plugins.partition.EasySetup"
|
||||||
self.cbox.log.info("easy partitioning succeeded")
|
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":[] }
|
return { "plugin":"system_preferences", "values":[] }
|
||||||
|
|
||||||
|
|
||||||
def __setPartitionData(self, parts):
|
def __set_partition_data(self, parts):
|
||||||
availSize = self.deviceSize
|
"""Set some hdf values for the currently proposed partition table.
|
||||||
|
"""
|
||||||
|
avail_size = self.device_size
|
||||||
i = 0
|
i = 0
|
||||||
for part in parts:
|
for part in parts:
|
||||||
self.cbox.log.debug(part)
|
self.cbox.log.debug(part)
|
||||||
self.hdf[self.hdf_prefix + "Parts.%d.Size" % i] = part["size"]
|
self.hdf[self.hdf_prefix + "Parts.%d.Size" % i] = part["size"]
|
||||||
self.hdf[self.hdf_prefix + "Parts.%d.Type" % i] = part["type"]
|
self.hdf[self.hdf_prefix + "Parts.%d.Type" % i] = part["type"]
|
||||||
availSize -= part["size"]
|
avail_size -= part["size"]
|
||||||
i += 1
|
i += 1
|
||||||
self.hdf[self.hdf_prefix + "availSize"] = availSize
|
self.hdf[self.hdf_prefix + "availSize"] = avail_size
|
||||||
if self.withConfigPartition:
|
if self.with_config_partition:
|
||||||
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
|
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
|
||||||
for t in self.PartTypes.keys():
|
for ptype in PARTTYPES.keys():
|
||||||
self.hdf[self.hdf_prefix + "Types.%s" % t] = t
|
self.hdf[self.hdf_prefix + "Types.%s" % ptype] = ptype
|
||||||
## store the currently existing partitions of the choosen block device
|
## 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()) ]
|
current_containers = [ e for e in self.cbox.get_container_list()
|
||||||
for (index, t) in enumerate(current_containers):
|
if cbxTools.is_part_of_blockdevice(self.device, e.get_device()) ]
|
||||||
self.hdf[self.hdf_prefix + "ExistingContainers.%d.name" % index] = t.getName()
|
for (index, cont) in enumerate(current_containers):
|
||||||
self.hdf[self.hdf_prefix + "ExistingContainers.%d.size" % index] = cbxTools.getBlockDeviceSizeHumanly(t.getDevice())
|
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 = []
|
parts = []
|
||||||
done = False
|
done = False
|
||||||
availSize = self.deviceSize
|
avail_size = self.device_size
|
||||||
i = -1
|
i = -1
|
||||||
while not done:
|
while not done:
|
||||||
i += 1
|
i += 1
|
||||||
try:
|
try:
|
||||||
size = int(args["part%d_size" % i])
|
size = int(args["part%d_size" % i])
|
||||||
partType = args["part%d_type" % i]
|
part_type = args["part%d_type" % i]
|
||||||
if int(size) > availSize:
|
if int(size) > avail_size:
|
||||||
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
|
||||||
continue
|
continue
|
||||||
if int(size) < 10:
|
if int(size) < 10:
|
||||||
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
|
self.hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
|
||||||
continue
|
continue
|
||||||
if not partType in self.PartTypes.keys(): continue
|
if not part_type in PARTTYPES.keys():
|
||||||
parts.append({"size":size, "type":partType})
|
continue
|
||||||
availSize -= size
|
parts.append({"size":size, "type":part_type})
|
||||||
|
avail_size -= size
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -280,33 +333,40 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return parts
|
return parts
|
||||||
|
|
||||||
|
|
||||||
def __getAvailableDeviceSize(self, device):
|
def __get_available_device_size(self, device):
|
||||||
"""calculate the available size (MB) of the device
|
"""calculate the available size (MB) of the device
|
||||||
also consider a (possible) configuration partition"""
|
also consider a (possible) configuration partition
|
||||||
deviceSize = cbxTools.getBlockDeviceSize(device)
|
"""
|
||||||
if deviceSize < 0: return 0
|
device_size = cbxTools.get_blockdevice_size(device)
|
||||||
if self.withConfigPartition:
|
if device_size < 0:
|
||||||
deviceSize -= self.ConfigPartition["size"]
|
return 0
|
||||||
return deviceSize
|
if self.with_config_partition:
|
||||||
|
device_size -= CONFIGPARTITION["size"]
|
||||||
|
return device_size
|
||||||
|
|
||||||
|
|
||||||
def __isWithConfigPartition(self):
|
def __is_with_config_partition(self):
|
||||||
"""check if we have to create a configuration partition"""
|
"""check if we have to create a configuration partition
|
||||||
if self.cbox.prefs.requiresPartition():
|
"""
|
||||||
active = self.cbox.prefs.getActivePartition()
|
if self.cbox.prefs.requires_partition():
|
||||||
|
active = self.cbox.prefs.get_active_partition()
|
||||||
## we need a partition, if there is no active one
|
## 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
|
## 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
|
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)
|
## check if the device is completely filled (to avoid some empty last blocks)
|
||||||
avail_size = self.deviceSize
|
avail_size = self.device_size
|
||||||
for d in parts: avail_size -= d["size"]
|
for one_part in parts:
|
||||||
|
avail_size -= one_part["size"]
|
||||||
self.cbox.log.debug("remaining size: %d" % avail_size)
|
self.cbox.log.debug("remaining size: %d" % avail_size)
|
||||||
isFilled = avail_size == 0
|
is_filled = avail_size == 0
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = subprocess.PIPE,
|
stdin = subprocess.PIPE,
|
||||||
|
@ -316,81 +376,91 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(self.pluginDir, "root_action.py"),
|
os.path.join(self.plugin_dir, "root_action.py"),
|
||||||
"partition",
|
"partition",
|
||||||
self.device])
|
self.device])
|
||||||
for line in self.__getSFDiskLayout(parts, isFilled):
|
for line in self.__get_sfdisk_layout(parts, is_filled):
|
||||||
proc.stdin.write(line + "\n")
|
proc.stdin.write(line + "\n")
|
||||||
(output, error) = proc.communicate()
|
(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
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
def __getSFDiskLayout(self, paramParts, isFilled):
|
def __get_sfdisk_layout(self, param_parts, is_filled):
|
||||||
"""this generator returns the input lines for sfdisk"""
|
"""this generator returns the input lines for sfdisk
|
||||||
parts = paramParts[:]
|
"""
|
||||||
|
parts = param_parts[:]
|
||||||
## first a (possible) configuration partition - so it will be reusable
|
## 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)
|
## 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
|
## one primary partition
|
||||||
if isFilled and (len(parts) == 1):
|
if is_filled and (len(parts) == 1):
|
||||||
## fill the rest of the device
|
## fill the rest of the device
|
||||||
yield ",,%s,*" % self.PartTypes[parts[0]["type"]][0]
|
yield ",,%s,*" % PARTTYPES[parts[0]["type"]][0]
|
||||||
else:
|
else:
|
||||||
## only use the specified size
|
## 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]
|
del parts[0]
|
||||||
## no extended partition, if there is only one disk
|
## no extended partition, if there is only one disk
|
||||||
if not parts: return
|
if not parts:
|
||||||
|
return
|
||||||
## an extended container for the rest
|
## an extended container for the rest
|
||||||
yield ",,E"
|
yield ",,E"
|
||||||
## an empty partition in main table
|
## an empty partition in main table
|
||||||
yield ";"
|
yield ";"
|
||||||
## maybe another empty partition if there is no config partition
|
## maybe another empty partition if there is no config partition
|
||||||
if not self.withConfigPartition: yield ";"
|
if not self.with_config_partition:
|
||||||
|
yield ";"
|
||||||
while parts:
|
while parts:
|
||||||
if isFilled and (len(parts) == 1):
|
if is_filled and (len(parts) == 1):
|
||||||
yield ",,%s" % (self.PartTypes[parts[0]["type"]][0],)
|
yield ",,%s" % (PARTTYPES[parts[0]["type"]][0],)
|
||||||
else:
|
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]
|
del parts[0]
|
||||||
|
|
||||||
|
|
||||||
def __formatPartitions(self, paramParts):
|
def __format_partitions(self, param_parts):
|
||||||
parts = paramParts[:]
|
"""Format all partitions of the device.
|
||||||
|
"""
|
||||||
|
parts = param_parts[:]
|
||||||
part_num = 1
|
part_num = 1
|
||||||
## maybe a config partition?
|
## maybe a config partition?
|
||||||
if self.withConfigPartition:
|
if self.with_config_partition:
|
||||||
dev_name = self.device + str(part_num)
|
dev_name = self.device + str(part_num)
|
||||||
self.cbox.log.info("formatting config partition (%s)" % dev_name)
|
self.cbox.log.info("formatting config partition (%s)" % dev_name)
|
||||||
if self.__formatOnePartition(dev_name, self.ConfigPartition["fs"]):
|
if self.__format_one_partition(dev_name, CONFIGPARTITION["fs"]):
|
||||||
self.__setLabelOfPartition(dev_name, self.cbox.prefs["Main"]["ConfigVolumeLabel"])
|
self.__set_label_of_partition(dev_name,
|
||||||
|
self.cbox.prefs["Main"]["ConfigVolumeLabel"])
|
||||||
part_num += 1
|
part_num += 1
|
||||||
## the first data partition
|
## the first data partition
|
||||||
dev_name = self.device + str(part_num)
|
dev_name = self.device + str(part_num)
|
||||||
partType = self.PartTypes[parts[0]["type"]][1]
|
part_type = PARTTYPES[parts[0]["type"]][1]
|
||||||
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
|
||||||
yield dev_name
|
yield dev_name
|
||||||
yield self.__formatOnePartition(dev_name, partType)
|
yield self.__format_one_partition(dev_name, part_type)
|
||||||
del parts[0]
|
del parts[0]
|
||||||
## other data partitions
|
## other data partitions
|
||||||
part_num = 5
|
part_num = 5
|
||||||
while parts:
|
while parts:
|
||||||
dev_name = self.device + str(part_num)
|
dev_name = self.device + str(part_num)
|
||||||
partType = self.PartTypes[parts[0]["type"]][1]
|
part_type = PARTTYPES[parts[0]["type"]][1]
|
||||||
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
self.cbox.log.info("formatting partition (%s) as '%s'" % \
|
||||||
|
(dev_name, part_type))
|
||||||
yield dev_name
|
yield dev_name
|
||||||
yield self.__formatOnePartition(dev_name, partType)
|
yield self.__format_one_partition(dev_name, part_type)
|
||||||
part_num += 1
|
part_num += 1
|
||||||
del parts[0]
|
del parts[0]
|
||||||
return
|
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
|
## first: retrieve UUID - it can be removed from the database afterwards
|
||||||
volDB = self.cbox.prefs.volumesDB
|
prev_name = [e.get_name() for e in self.cbox.get_container_list()
|
||||||
prev_name = [e.getName() for e in self.cbox.getContainerList() if e.getDevice() == dev_name]
|
if e.get_device() == dev_name]
|
||||||
## call "mkfs"
|
## call "mkfs"
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
|
@ -398,10 +468,10 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(self.pluginDir, "root_action.py"),
|
os.path.join(self.plugin_dir, "root_action.py"),
|
||||||
"format",
|
"format",
|
||||||
dev_name,
|
dev_name,
|
||||||
type])
|
fs_type])
|
||||||
(output, error) = proc.communicate()
|
(output, error) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
|
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:
|
else:
|
||||||
## remove unused volume entry
|
## remove unused volume entry
|
||||||
if prev_name:
|
if prev_name:
|
||||||
self.cbox.prefs.volumesDB[prev_name[0]]
|
del self.cbox.prefs.volumes_db[prev_name[0]]
|
||||||
return True
|
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(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
|
@ -422,7 +494,7 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(self.pluginDir, "root_action.py"),
|
os.path.join(self.plugin_dir, "root_action.py"),
|
||||||
"label",
|
"label",
|
||||||
dev_name,
|
dev_name,
|
||||||
label])
|
label])
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
||||||
PLUGIN_TYPE = "cryptobox"
|
PLUGIN_TYPE = "cryptobox"
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
url = self.URL + "partition?weblang=en"
|
url = self.url + "partition?weblang=en"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('VERY careful')
|
self.cmd.find('VERY careful')
|
||||||
|
|
|
@ -7,7 +7,7 @@ The following directory structure is required:
|
||||||
|
|
||||||
Python code interface:
|
Python code interface:
|
||||||
- create a class with the same name as the plugin - it must inherit CryptoBoxPlugin
|
- 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
|
- 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)
|
- 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)
|
- 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
|
* 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"
|
- an empty (e.g. None) return value can be used to go to the default page ("disks"
|
||||||
or "volume_mount" (for volume plugins))
|
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
|
- returns a string, that describes a state connected to this plugin (e.g. the current date and
|
||||||
time (for the "date" plugin))
|
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")
|
"volume")
|
||||||
- the class variable "pluginVisibility" may contain one or more of the following items:
|
- the class variable "plugin_visibility" may contain one or more of the following items:
|
||||||
menu/preferences/volume. This obviously should fit to the 'pluginCapabilities' variable.
|
menu/preferences/volume. This should fit to the 'plugin_capabilities' variable.
|
||||||
An empty list is interpreted as a disabled plugin.
|
An empty list is interpreted as an invisible plugin.
|
||||||
- the class variable "requestAuth" is boolean and defines, if admin authentication is necessary
|
- the class variable "request_auth" is boolean and defines, if admin authentication is necessary
|
||||||
for this plugin
|
for this plugin
|
||||||
- the class variable "rank" is an integer in the range of 0..100 - it determines the order
|
- 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)
|
of plugins in listings (lower value -> higher priority)
|
||||||
|
|
|
@ -18,27 +18,31 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
import cryptobox.plugins.manage
|
import cryptobox.plugins.manage
|
||||||
|
|
||||||
|
|
||||||
class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "preferences" ]
|
plugin_visibility = [ "preferences" ]
|
||||||
requestAuth = True
|
request_auth = True
|
||||||
rank = 90
|
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
|
import re
|
||||||
if plugin_name:
|
if plugin_name:
|
||||||
## check for invalid characters
|
## check for invalid characters
|
||||||
if re.search(u'\W', plugin_name): return "plugin_list"
|
if re.search(u'\W', plugin_name): return "plugin_list"
|
||||||
pluginList = cryptobox.plugins.manage.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
|
plugin_manager = cryptobox.plugins.manage.PluginManager(
|
||||||
plugin = pluginList.getPlugin(plugin_name)
|
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
|
||||||
|
plugin = plugin_manager.get_plugin(plugin_name)
|
||||||
if not plugin: return "plugin_list"
|
if not plugin: return "plugin_list"
|
||||||
## take only plugins, that are of the same type as the choosen one
|
## 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":
|
if action == "up":
|
||||||
self.__move_up(plugin)
|
self.__move_up(plugin)
|
||||||
elif action == "down":
|
elif action == "down":
|
||||||
|
@ -50,44 +54,48 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
if not re.search(u'\W',key):
|
if not re.search(u'\W',key):
|
||||||
self.__setConfig(key[:-7], args)
|
self.__setConfig(key[:-7], args)
|
||||||
else:
|
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:
|
try:
|
||||||
self.cbox.prefs.pluginConf.write()
|
self.cbox.prefs.plugin_conf.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.cbox.log.warn("failed to write plugin configuration")
|
self.cbox.log.warn("failed to write plugin configuration")
|
||||||
return "plugin_list"
|
return "plugin_list"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "no status"
|
return "no status"
|
||||||
|
|
||||||
|
|
||||||
def __sortPlugins(self):
|
def __sort_plugins(self):
|
||||||
"""sort all plugins in the list according to their rank"""
|
"""sort all plugins in the list according to their rank"""
|
||||||
def cmp_func(x,y):
|
def cmp_func(x,y):
|
||||||
xRank = x.getRank()
|
x_rank = x.get_rank()
|
||||||
yRank = y.getRank()
|
y_rank = y.get_rank()
|
||||||
if xRank < yRank: return -1
|
if x_rank < y_rank:
|
||||||
elif xRank == yRank: return 0
|
return -1
|
||||||
else: return 1
|
elif x_rank == y_rank:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
self.plugins.sort(cmp = cmp_func)
|
self.plugins.sort(cmp = cmp_func)
|
||||||
|
|
||||||
|
|
||||||
def __distributeRanks(self):
|
def __distribute_ranks(self):
|
||||||
"""evenly distribute the 'rank' values according to the current order of
|
"""evenly distribute the 'rank' values according to the current order of
|
||||||
the list"""
|
the list"""
|
||||||
dist = 100/len(self.plugins)
|
dist = 100/len(self.plugins)
|
||||||
for index,pl in enumerate(self.plugins):
|
for index,pl in enumerate(self.plugins):
|
||||||
try:
|
try:
|
||||||
self.cbox.prefs.pluginConf[pl.getName()]["rank"] = dist*index
|
self.cbox.prefs.plugin_conf[pl.get_name()]["rank"] = dist*index
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.cbox.prefs.pluginConf[pl.getName()] = {}
|
self.cbox.prefs.plugin_conf[pl.get_name()] = {}
|
||||||
self.cbox.prefs.pluginConf[pl.getName()]["rank"] = dist*index
|
self.cbox.prefs.plugin_conf[pl.get_name()]["rank"] = dist*index
|
||||||
self.cbox.prefs.pluginConf.write()
|
self.cbox.prefs.plugin_conf.write()
|
||||||
|
|
||||||
|
|
||||||
def __move_up(self, plugin):
|
def __move_up(self, plugin):
|
||||||
self.__sortPlugins()
|
self.__sort_plugins()
|
||||||
try:
|
try:
|
||||||
index = self.plugins.index(plugin)
|
index = self.plugins.index(plugin)
|
||||||
## first elements may not move up
|
## first elements may not move up
|
||||||
|
@ -97,11 +105,11 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return
|
return
|
||||||
self.plugins.remove(plugin)
|
self.plugins.remove(plugin)
|
||||||
self.plugins.insert(index-1, plugin)
|
self.plugins.insert(index-1, plugin)
|
||||||
self.__distributeRanks()
|
self.__distribute_ranks()
|
||||||
|
|
||||||
|
|
||||||
def __move_down(self, plugin):
|
def __move_down(self, plugin):
|
||||||
self.__sortPlugins()
|
self.__sort_plugins()
|
||||||
try:
|
try:
|
||||||
index = self.plugins.index(plugin)
|
index = self.plugins.index(plugin)
|
||||||
## last elements may not move down
|
## last elements may not move down
|
||||||
|
@ -111,7 +119,7 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return
|
return
|
||||||
self.plugins.remove(plugin)
|
self.plugins.remove(plugin)
|
||||||
self.plugins.insert(index+1, plugin)
|
self.plugins.insert(index+1, plugin)
|
||||||
self.__distributeRanks()
|
self.__distribute_ranks()
|
||||||
|
|
||||||
|
|
||||||
def __setConfig(self, name, args):
|
def __setConfig(self, name, args):
|
||||||
|
@ -137,5 +145,5 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
setting["requestAuth"] = True
|
setting["requestAuth"] = True
|
||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
pass
|
pass
|
||||||
self.cbox.prefs.pluginConf[name] = setting
|
self.cbox.prefs.plugin_conf[name] = setting
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,21 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
url = self.URL + "plugin_manager?weblang=en"
|
url = self.url + "plugin_manager?weblang=en"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
|
||||||
|
|
||||||
def test_set_options(self):
|
def test_set_options(self):
|
||||||
url = self.URL + "plugin_manager"
|
url = self.url + "plugin_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url + u"?plugin_name=t/-!")
|
self.cmd.go(url + u"?plugin_name=t/-!")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
@ -55,8 +57,8 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
|
|
||||||
def test_move_up(self):
|
def test_move_up(self):
|
||||||
## TODO: if we want to be perfect, then we should check the change of the rank
|
#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.register_auth(url)
|
||||||
self.cmd.go(url + u"?plugin_name=disks&action=up")
|
self.cmd.go(url + u"?plugin_name=disks&action=up")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
@ -68,7 +70,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_move_down(self):
|
def test_move_down(self):
|
||||||
## TODO: if we want to be perfect, then we should check the change of the rank
|
## 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.register_auth(url)
|
||||||
self.cmd.go(url + u"?plugin_name=disks&action=down")
|
self.cmd.go(url + u"?plugin_name=disks&action=down")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
||||||
PLUGIN_TYPE = "cryptobox"
|
PLUGIN_TYPE = "cryptobox"
|
||||||
|
|
|
@ -18,29 +18,31 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
REDIRECT_DELAY = 180
|
REDIRECT_DELAY = 180
|
||||||
|
|
||||||
class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
|
class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "preferences", "menu" ]
|
plugin_visibility = [ "preferences", "menu" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 90
|
rank = 90
|
||||||
|
|
||||||
def doAction(self, type=None):
|
def do_action(self, type=None):
|
||||||
if not type:
|
if not type:
|
||||||
return "form_shutdown"
|
return "form_shutdown"
|
||||||
elif type == "shutdown":
|
elif type == "shutdown":
|
||||||
if self.__doShutdown("shutdown"):
|
if self.__do_shutdown("shutdown"):
|
||||||
self.hdf["Data.Success"] = "Plugins.shutdown.Shutdown"
|
self.hdf["Data.Success"] = "Plugins.shutdown.Shutdown"
|
||||||
return "progress_shutdown"
|
return "progress_shutdown"
|
||||||
else:
|
else:
|
||||||
self.hdf["Data.Warning"] = "Plugins.shutdown.ShutdownFailed"
|
self.hdf["Data.Warning"] = "Plugins.shutdown.ShutdownFailed"
|
||||||
return "form_shutdown"
|
return "form_shutdown"
|
||||||
elif type == "reboot":
|
elif type == "reboot":
|
||||||
if self.__doShutdown("reboot"):
|
if self.__do_shutdown("reboot"):
|
||||||
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
|
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
|
||||||
self.hdf["Data.Redirect.URL"] = ""
|
self.hdf["Data.Redirect.URL"] = ""
|
||||||
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
|
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
|
||||||
|
@ -52,11 +54,11 @@ class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return "form_shutdown"
|
return "form_shutdown"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "the box is up'n'running"
|
return "the box is up'n'running"
|
||||||
|
|
||||||
|
|
||||||
def __doShutdown(self, action):
|
def __do_shutdown(self, action):
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
|
@ -65,7 +67,7 @@ class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"plugin",
|
"plugin",
|
||||||
os.path.join(self.pluginDir, "root_action.py"),
|
os.path.join(self.plugin_dir, "root_action.py"),
|
||||||
action])
|
action])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
return proc.returncode == 0
|
return proc.returncode == 0
|
||||||
|
|
|
@ -18,13 +18,15 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
"""just read the form - I do not know of a way how to check success"""
|
"""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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('shutdown')
|
self.cmd.find('shutdown')
|
||||||
|
|
|
@ -18,20 +18,23 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
class system_preferences(cryptobox.plugins.base.CryptoBoxPlugin):
|
class system_preferences(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "menu" ]
|
plugin_visibility = [ "menu" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 20
|
rank = 20
|
||||||
|
|
||||||
def doAction(self):
|
def do_action(self):
|
||||||
return "show_plugins"
|
return "show_plugins"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return ":".join([p.getName() for p in self.site.pluginList.getPlugins()])
|
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()])
|
||||||
|
|
||||||
|
|
|
@ -18,17 +18,19 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
self.cmd.go(self.URL + "system_preferences")
|
self.cmd.go(self.url + "system_preferences")
|
||||||
self.cmd.find("Preferences")
|
self.cmd.find("Preferences")
|
||||||
|
|
||||||
|
|
||||||
def test_check_plugins(self):
|
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")
|
self.cmd.find(u'Data.Status.Plugins.system_preferences=(.*)$', "m")
|
||||||
plugins = self.locals["__match__"].split(":")
|
plugins = self.locals["__match__"].split(":")
|
||||||
self.assertTrue(len(plugins) > 1)
|
self.assertTrue(len(plugins) > 1)
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
## this user may not be removed
|
## this user may not be removed
|
||||||
|
@ -35,7 +37,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_test_wrong_credentials(self):
|
def test_test_wrong_credentials(self):
|
||||||
"""check if the user_manager is protected"""
|
"""check if the user_manager is protected"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url,"foo","bar")
|
self.register_auth(url,"foo","bar")
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.notfind("Manage users")
|
self.cmd.notfind("Manage users")
|
||||||
|
@ -43,7 +45,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_add_existing_user(self):
|
def test_add_existing_user(self):
|
||||||
"""adding an existing user should fail"""
|
"""adding an existing user should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self._add_user("admin","foo","foo")
|
self._add_user("admin","foo","foo")
|
||||||
self.cmd.find("The choosen username does already exist")
|
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):
|
def test_add_invalid_username(self):
|
||||||
"""adding an invalid username should fail"""
|
"""adding an invalid username should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self._add_user("foo/bar","foo","foo")
|
self._add_user("foo/bar","foo","foo")
|
||||||
self.cmd.find("Invalid username")
|
self.cmd.find("Invalid username")
|
||||||
|
@ -60,7 +62,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_add_without_password(self):
|
def test_add_without_password(self):
|
||||||
"""adding a user without password should fail"""
|
"""adding a user without password should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.assertFalse("foo" in self._getUsers())
|
self.assertFalse("foo" in self._getUsers())
|
||||||
self._add_user("foo","","foo")
|
self._add_user("foo","","foo")
|
||||||
|
@ -70,7 +72,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_add_with_different_passwords(self):
|
def test_add_with_different_passwords(self):
|
||||||
"""adding a user with different passwords should fail"""
|
"""adding a user with different passwords should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.assertFalse("foo" in self._getUsers())
|
self.assertFalse("foo" in self._getUsers())
|
||||||
self._add_user("foo","bar","foo")
|
self._add_user("foo","bar","foo")
|
||||||
|
@ -80,7 +82,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_change_pw_for_invalid_user(self):
|
def test_change_pw_for_invalid_user(self):
|
||||||
"""changing a password of a non existing user should fail"""
|
"""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.register_auth(url)
|
||||||
self.assertFalse("barfoo" in self._getUsers())
|
self.assertFalse("barfoo" in self._getUsers())
|
||||||
self.cmd.go(url + "?store=change_password&user=foobar&new_pw=foo&new_pw2=foo")
|
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):
|
def test_change_pw_without_password(self):
|
||||||
"""changing a password without a new password should fail"""
|
"""changing a password without a new password should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.assertFalse("foo" in self._getUsers())
|
self.assertFalse("foo" in self._getUsers())
|
||||||
self._add_user("foo","bar","bar")
|
self._add_user("foo","bar","bar")
|
||||||
|
@ -102,7 +104,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_change_pw_wit_different_passwords(self):
|
def test_change_pw_wit_different_passwords(self):
|
||||||
"""changing a password while supplying different passwords should fail"""
|
"""changing a password while supplying different passwords should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.assertFalse("foo" in self._getUsers())
|
self.assertFalse("foo" in self._getUsers())
|
||||||
self._add_user("foo","bar","bar")
|
self._add_user("foo","bar","bar")
|
||||||
|
@ -115,7 +117,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def _remove_reserved_user(self):
|
def _remove_reserved_user(self):
|
||||||
"""removing a reserved user should fail"""
|
"""removing a reserved user should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.assertTrue("admin" in self._getUsers())
|
self.assertTrue("admin" in self._getUsers())
|
||||||
self._del_user("admin")
|
self._del_user("admin")
|
||||||
|
@ -125,7 +127,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def _remove_non_existing_user(self):
|
def _remove_non_existing_user(self):
|
||||||
"""removing a non-existing user should fail"""
|
"""removing a non-existing user should fail"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.assertFalse("barfoo" in self._getUsers())
|
self.assertFalse("barfoo" in self._getUsers())
|
||||||
self._del_user("barfoo")
|
self._del_user("barfoo")
|
||||||
|
@ -134,7 +136,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_manage_users(self):
|
def test_manage_users(self):
|
||||||
"""add a new user, change its password and remove the user afterwards"""
|
"""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)
|
self.register_auth(url)
|
||||||
## remove the user that should be added - just in case a previous run was unclean
|
## remove the user that should be added - just in case a previous run was unclean
|
||||||
## check its existence before
|
## check its existence before
|
||||||
|
@ -158,13 +160,13 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_invalid_input(self):
|
def test_invalid_input(self):
|
||||||
"""check all combinations of invalid input"""
|
"""check all combinations of invalid input"""
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url + "?store=foobar")
|
self.cmd.go(url + "?store=foobar")
|
||||||
|
|
||||||
|
|
||||||
def _add_user(self, username, pw, pw2):
|
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","user",username)
|
||||||
self.cmd.formvalue("add_user","new_pw",pw)
|
self.cmd.formvalue("add_user","new_pw",pw)
|
||||||
self.cmd.formvalue("add_user","new_pw2",pw2)
|
self.cmd.formvalue("add_user","new_pw2",pw2)
|
||||||
|
@ -172,13 +174,13 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
|
|
||||||
def _del_user(self, username):
|
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.formvalue("del_user","user",username)
|
||||||
self.cmd.submit()
|
self.cmd.submit()
|
||||||
|
|
||||||
|
|
||||||
def _change_password(self, username, pw, pw2):
|
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","user",username)
|
||||||
self.cmd.formvalue("change_password","new_pw",pw)
|
self.cmd.formvalue("change_password","new_pw",pw)
|
||||||
self.cmd.formvalue("change_password","new_pw2",pw2)
|
self.cmd.formvalue("change_password","new_pw2",pw2)
|
||||||
|
@ -186,7 +188,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
|
|
||||||
def _getUsers(self):
|
def _getUsers(self):
|
||||||
url = self.URL + "user_manager"
|
url = self.url + "user_manager"
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find("Data.Status.Plugins.user_manager=([\w:]+)")
|
self.cmd.find("Data.Status.Plugins.user_manager=([\w:]+)")
|
||||||
|
|
|
@ -18,21 +18,23 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
RESERVED_USERS = [ "admin" ]
|
RESERVED_USERS = [ "admin" ]
|
||||||
|
|
||||||
class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
pluginVisibility = [ "preferences" ]
|
plugin_visibility = [ "preferences" ]
|
||||||
requestAuth = True
|
request_auth = True
|
||||||
rank = 45
|
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
|
import re
|
||||||
adminDict = self.cbox.prefs.userDB["admins"]
|
admin_dict = self.cbox.prefs.user_db["admins"]
|
||||||
self.__cleanHDF()
|
self.__clean_hdf()
|
||||||
if store is None:
|
if store is None:
|
||||||
pass
|
pass
|
||||||
elif store == "add_user":
|
elif store == "add_user":
|
||||||
|
@ -42,13 +44,13 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.hdf["Data.Warning"] = "EmptyNewPassword"
|
self.hdf["Data.Warning"] = "EmptyNewPassword"
|
||||||
elif new_pw != new_pw2:
|
elif new_pw != new_pw2:
|
||||||
self.hdf["Data.Warning"] = "DifferentPasswords"
|
self.hdf["Data.Warning"] = "DifferentPasswords"
|
||||||
elif user in adminDict.keys():
|
elif user in admin_dict.keys():
|
||||||
self.hdf["Data.Warning"] = "Plugins.user_manager.UserAlreadyExists"
|
self.hdf["Data.Warning"] = "Plugins.user_manager.UserAlreadyExists"
|
||||||
else:
|
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"
|
self.hdf["Data.Success"] = "Plugins.user_manager.UserAdded"
|
||||||
try:
|
try:
|
||||||
self.cbox.prefs.userDB.write()
|
self.cbox.prefs.user_db.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.cbox.log.warn("failed to write user database")
|
self.cbox.log.warn("failed to write user database")
|
||||||
elif store == "change_password":
|
elif store == "change_password":
|
||||||
|
@ -56,11 +58,11 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.hdf["Data.Warning"] = "EmptyNewPassword"
|
self.hdf["Data.Warning"] = "EmptyNewPassword"
|
||||||
elif new_pw != new_pw2:
|
elif new_pw != new_pw2:
|
||||||
self.hdf["Data.Warning"] = "DifferentPasswords"
|
self.hdf["Data.Warning"] = "DifferentPasswords"
|
||||||
elif user in adminDict.keys():
|
elif user in admin_dict.keys():
|
||||||
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.PasswordChanged"
|
self.hdf["Data.Success"] = "Plugins.user_manager.PasswordChanged"
|
||||||
try:
|
try:
|
||||||
self.cbox.prefs.userDB.write()
|
self.cbox.prefs.user_db.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.cbox.log.warn("failed to write user database")
|
self.cbox.log.warn("failed to write user database")
|
||||||
else:
|
else:
|
||||||
|
@ -69,31 +71,31 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
if user in RESERVED_USERS:
|
if user in RESERVED_USERS:
|
||||||
self.cbox.log.info("user_manager: tried to remove reserved user (%s)" % user)
|
self.cbox.log.info("user_manager: tried to remove reserved user (%s)" % user)
|
||||||
self.hdf["Data.Warning"] = "NeverRemoveReservedUser"
|
self.hdf["Data.Warning"] = "NeverRemoveReservedUser"
|
||||||
elif user in adminDict.keys():
|
elif user in admin_dict.keys():
|
||||||
del adminDict[user]
|
del admin_dict[user]
|
||||||
self.hdf["Data.Success"] = "Plugins.user_manager.UserRemoved"
|
self.hdf["Data.Success"] = "Plugins.user_manager.UserRemoved"
|
||||||
try:
|
try:
|
||||||
self.cbox.prefs.userDB.write()
|
self.cbox.prefs.user_db.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.cbox.log.warn("failed to write user database")
|
self.cbox.log.warn("failed to write user database")
|
||||||
else:
|
else:
|
||||||
self.cbox.log.info("user_manager: tried to remove non-existing user (%s)" % str(user))
|
self.cbox.log.info("user_manager: tried to remove non-existing user (%s)" % str(user))
|
||||||
else:
|
else:
|
||||||
self.cbox.log.info("user_manager: invalid value of 'store' (%s)" % store)
|
self.cbox.log.info("user_manager: invalid value of 'store' (%s)" % store)
|
||||||
self.__prepareHDF(adminDict)
|
self.__prepare_hdf(admin_dict)
|
||||||
return "user_list"
|
return "user_list"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return ":".join(self.cbox.prefs.userDB["admins"].keys())
|
return ":".join(self.cbox.prefs.user_db["admins"].keys())
|
||||||
|
|
||||||
|
|
||||||
def __cleanHDF(self):
|
def __clean_hdf(self):
|
||||||
for key in self.hdf.keys():
|
for key in self.hdf.keys():
|
||||||
del self.hdf[key]
|
del self.hdf[key]
|
||||||
|
|
||||||
|
|
||||||
def __prepareHDF(self, dict):
|
def __prepare_hdf(self, dict):
|
||||||
## sort by name
|
## sort by name
|
||||||
users = dict.keys()
|
users = dict.keys()
|
||||||
users.sort()
|
users.sort()
|
||||||
|
|
|
@ -18,13 +18,15 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
def test_read_form(self):
|
||||||
"""try to read automount form"""
|
"""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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('Activate during startup')
|
self.cmd.find('Activate during startup')
|
||||||
|
@ -32,21 +34,21 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_toggle(self):
|
def test_toggle(self):
|
||||||
"""try to toggle automount property"""
|
"""try to toggle automount property"""
|
||||||
url = self.URL + "volume_automount"
|
url = self.url + "volume_automount"
|
||||||
self.register_auth(url)
|
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("Automatic activation disabled")
|
||||||
self.cmd.find("is 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.find("Automatic activation enabled")
|
||||||
self.cmd.notfind("is disabled")
|
self.cmd.notfind("is disabled")
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_input(self):
|
def test_invalid_input(self):
|
||||||
"""check invalid inputs"""
|
"""check invalid inputs"""
|
||||||
url = self.URL + "volume_automount"
|
url = self.url + "volume_automount"
|
||||||
self.register_auth(url)
|
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 disabled")
|
||||||
self.cmd.notfind("Automatic activation enabled")
|
self.cmd.notfind("Automatic activation enabled")
|
||||||
|
|
||||||
|
|
|
@ -18,58 +18,60 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
|
|
||||||
|
|
||||||
class volume_automount(cryptobox.plugins.base.CryptoBoxPlugin):
|
class volume_automount(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "properties" ]
|
plugin_visibility = [ "properties" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 80
|
rank = 80
|
||||||
|
|
||||||
trueString = "yes"
|
true_string = "yes"
|
||||||
falseString = "no"
|
false_string = "no"
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, action=None):
|
def do_action(self, action=None):
|
||||||
container = self.cbox.getContainer(self.device)
|
container = self.cbox.get_container(self.device)
|
||||||
if action is None:
|
if action is None:
|
||||||
pass
|
pass
|
||||||
elif action == "enable":
|
elif action == "enable":
|
||||||
container.attributes["automount"] = self.trueString
|
container.attributes["automount"] = self.true_string
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountEnabled"
|
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountEnabled"
|
||||||
self.cbox.log.info("volume_automount: enabled for device '%s'" % self.device)
|
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":
|
elif action == "disable":
|
||||||
container.attributes["automount"] = self.falseString
|
container.attributes["automount"] = self.false_string
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountDisabled"
|
self.hdf["Data.Success"] = "Plugins.volume_automount.AutoMountDisabled"
|
||||||
self.cbox.log.info("volume_automount: disabled for device '%s'" % self.device)
|
self.cbox.log.info("volume_automount: disabled for device '%s'" % self.device)
|
||||||
self.cbox.prefs.volumesDB.write()
|
self.cbox.prefs.volumes_db.write()
|
||||||
else:
|
else:
|
||||||
self.cbox.log.info("volume_automount: invalid action (%s)" % str(action))
|
self.cbox.log.info("volume_automount: invalid action (%s)" % str(action))
|
||||||
self.__prepareHDF()
|
self.__prepare_hdf()
|
||||||
return "volume_automount"
|
return "volume_automount"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return str(self.__isAutoMount())
|
return str(self.__is_auto_mount())
|
||||||
|
|
||||||
|
|
||||||
def __prepareHDF(self):
|
def __prepare_hdf(self):
|
||||||
if self.__isAutoMount():
|
if self.__is_auto_mount():
|
||||||
self.hdf[self.hdf_prefix + "automount_setting"] = "1"
|
self.hdf[self.hdf_prefix + "automount_setting"] = "1"
|
||||||
else:
|
else:
|
||||||
self.hdf[self.hdf_prefix + "automount_setting"] = "0"
|
self.hdf[self.hdf_prefix + "automount_setting"] = "0"
|
||||||
|
|
||||||
|
|
||||||
def __isAutoMount(self):
|
def __is_auto_mount(self):
|
||||||
container = self.cbox.getContainer(self.device)
|
container = self.cbox.get_container(self.device)
|
||||||
if not container:
|
if not container:
|
||||||
return False
|
return False
|
||||||
if container.attributes.has_key("automount"):
|
if container.attributes.has_key("automount"):
|
||||||
return container.attributes["automount"] == self.trueString
|
return container.attributes["automount"] == self.true_string
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('hange')
|
self.cmd.find('hange')
|
||||||
|
|
|
@ -18,24 +18,26 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
|
|
||||||
|
|
||||||
class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
|
class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "properties" ]
|
plugin_visibility = [ "properties" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 70
|
rank = 70
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, store=None, old_pw=None, new_pw=None, new_pw2=None):
|
def do_action(self, store=None, old_pw=None, new_pw=None, new_pw2=None):
|
||||||
self.container = self.cbox.getContainer(self.device)
|
self.container = self.cbox.get_container(self.device)
|
||||||
if not self.container:
|
if not self.container:
|
||||||
return None
|
return None
|
||||||
elif store == "change_pw":
|
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:
|
elif not store:
|
||||||
return "volume_chpasswd"
|
return "volume_chpasswd"
|
||||||
else:
|
else:
|
||||||
|
@ -43,11 +45,11 @@ class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return "volume_chpasswd"
|
return "volume_chpasswd"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "TODO"
|
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:
|
if not old_pw:
|
||||||
self.hdf["Data.Warning"] = "EmptyPassword"
|
self.hdf["Data.Warning"] = "EmptyPassword"
|
||||||
elif not new_pw:
|
elif not new_pw:
|
||||||
|
@ -59,13 +61,13 @@ class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.container.changePassword(old_pw, new_pw)
|
self.container.change_password(old_pw, new_pw)
|
||||||
except CBInvalidType, errMsg:
|
except CBInvalidType, err_msg:
|
||||||
self.cbox.log.info("plugin 'volume_chpasswd' - cannot change passphrase for non-encrypted container (%s): %s" % (self.device, errMsg))
|
self.cbox.log.info("plugin 'volume_chpasswd' - cannot change passphrase for non-encrypted container (%s): %s" % (self.device, err_msg))
|
||||||
except CBVolumeIsActive:
|
except CBVolumeIsActive:
|
||||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||||
except CBChangePasswordError, errMsg:
|
except CBChangePasswordError, err_msg:
|
||||||
self.cbox.log.warn("plugin 'volume_chpasswd' - cannot change password for device (%s): %s" % (self.device, errMsg))
|
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"
|
self.hdf["Data.Warning"] = "Plugins.volume_chpasswd.PasswordChange"
|
||||||
else:
|
else:
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_chpasswd.PasswordChange"
|
self.hdf["Data.Success"] = "Plugins.volume_chpasswd.PasswordChange"
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('Technical details')
|
self.cmd.find('Technical details')
|
||||||
|
|
|
@ -18,22 +18,24 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
|
||||||
|
|
||||||
class volume_details(cryptobox.plugins.base.CryptoBoxPlugin):
|
class volume_details(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "volume" ]
|
plugin_visibility = [ "volume" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 100
|
rank = 100
|
||||||
|
|
||||||
|
|
||||||
def doAction(self):
|
def do_action(self):
|
||||||
## all variables are already set somewhere else
|
## all variables are already set somewhere else
|
||||||
return "volume_details"
|
return "volume_details"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "no status"
|
return "no status"
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('Initializing filesystem')
|
self.cmd.find('Initializing filesystem')
|
||||||
|
|
|
@ -18,32 +18,33 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
from cryptobox.core.exceptions import *
|
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):
|
class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "volume" ]
|
plugin_visibility = [ "volume" ]
|
||||||
requestAuth = True
|
request_auth = True
|
||||||
rank = 60
|
rank = 60
|
||||||
|
|
||||||
## map filesystem types to the appropriate arguments for 'mkfs'
|
|
||||||
fsTypes = {
|
|
||||||
"windows": "vfat",
|
|
||||||
"linux": "ext3" }
|
|
||||||
|
|
||||||
containerTypes = [ "luks", "plain" ]
|
|
||||||
|
|
||||||
|
def do_action(self, store=None, fs_type="windows", container_type="luks", crypto_password=None, crypto_password2=None, confirm=None):
|
||||||
def doAction(self, store=None, fs_type="windows", container_type="luks", crypto_password=None, crypto_password2=None, confirm=None):
|
if not fs_type in FSTYPES.keys():
|
||||||
if not fs_type in self.fsTypes.keys():
|
|
||||||
self.cbox.info
|
self.cbox.info
|
||||||
return "format_volume"
|
return "format_volume"
|
||||||
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
|
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
|
||||||
self.hdf[self.hdf_prefix + "container_type"] = container_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
|
self.hdf[self.hdf_prefix + "fs_types." + t] = t
|
||||||
if store == "step1":
|
if store == "step1":
|
||||||
if not confirm:
|
if not confirm:
|
||||||
|
@ -67,14 +68,14 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return "volume_format"
|
return "volume_format"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "no status"
|
return "no status"
|
||||||
|
|
||||||
|
|
||||||
def __format_plain(self, fsType):
|
def __format_plain(self, fsType):
|
||||||
try:
|
try:
|
||||||
container = self.cbox.getContainer(self.device)
|
container = self.cbox.get_container(self.device)
|
||||||
container.create(cbxContainer.ContainerTypes["plain"])
|
container.create(cbx_container.CONTAINERTYPES["plain"])
|
||||||
except CBVolumeIsActive:
|
except CBVolumeIsActive:
|
||||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
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.hdf["Data.Warning"] = "DifferentPasswords"
|
||||||
self.cbox.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % self.device)
|
self.cbox.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % self.device)
|
||||||
return "volume_format"
|
return "volume_format"
|
||||||
container = self.cbox.getContainer(self.device)
|
container = self.cbox.get_container(self.device)
|
||||||
try:
|
try:
|
||||||
container.create(cbxContainer.ContainerTypes["luks"], pw)
|
container.create(cbx_container.CONTAINERTYPES["luks"], pw)
|
||||||
except CBVolumeIsActive:
|
except CBVolumeIsActive:
|
||||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('ctivate volume')
|
self.cmd.find('ctivate volume')
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
import cryptobox.core.container as cbxContainer
|
import cryptobox.core.container as cbxContainer
|
||||||
|
@ -25,20 +27,20 @@ import cryptobox.core.container as cbxContainer
|
||||||
|
|
||||||
class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
|
class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "volume" ]
|
plugin_visibility = [ "volume" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 0
|
rank = 0
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, action=None, pw=None):
|
def do_action(self, action=None, pw=None):
|
||||||
self.container = self.cbox.getContainer(self.device)
|
self.container = self.cbox.get_container(self.device)
|
||||||
if action == "mount_plain":
|
if action == "mount_plain":
|
||||||
return self.__doMountPlain()
|
return self.__do_mount_plain()
|
||||||
elif action == "mount_luks":
|
elif action == "mount_luks":
|
||||||
return self.__doMountLuks(pw)
|
return self.__do_mount_luks(pw)
|
||||||
elif action == "umount":
|
elif action == "umount":
|
||||||
return self.__doUmount()
|
return self.__do_umount()
|
||||||
elif not action:
|
elif not action:
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
else:
|
else:
|
||||||
|
@ -46,43 +48,43 @@ class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
container = self.cbox.getContainer(self.device)
|
container = self.cbox.get_container(self.device)
|
||||||
if not self.container:
|
if not self.container:
|
||||||
return "invalid device"
|
return "invalid device"
|
||||||
if container.isMounted():
|
if container.is_mounted():
|
||||||
return "active"
|
return "active"
|
||||||
else:
|
else:
|
||||||
return "passive"
|
return "passive"
|
||||||
|
|
||||||
|
|
||||||
def __doMountPlain(self):
|
def __do_mount_plain(self):
|
||||||
if self.container.isMounted():
|
if self.container.is_mounted():
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
|
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
|
||||||
self.cbox.log.info("the device (%s) is already mounted" % self.device)
|
self.cbox.log.info("the device (%s) is already mounted" % self.device)
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
if self.container.getType() != cbxContainer.ContainerTypes["plain"]:
|
if self.container.get_type() != cbxContainer.CONTAINERTYPES["plain"]:
|
||||||
## not a plain container
|
## not a plain container
|
||||||
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
|
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.InvalidContainerType"
|
self.hdf["Data.Warning"] = "Plugins.volume_mount.InvalidContainerType"
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
try:
|
try:
|
||||||
self.container.mount()
|
self.container.mount()
|
||||||
except CBMountError, errMsg:
|
except CBMountError, err_msg:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
|
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"
|
return "volume_status"
|
||||||
except CBContainerError, errMsg:
|
except CBContainerError, err_msg:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
|
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"
|
return "volume_status"
|
||||||
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
|
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
|
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
|
|
||||||
|
|
||||||
def __doMountLuks(self, pw):
|
def __do_mount_luks(self, pw):
|
||||||
if self.container.isMounted():
|
if self.container.is_mounted():
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
|
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
|
||||||
self.cbox.log.info("the device (%s) is already mounted" % self.device)
|
self.cbox.log.info("the device (%s) is already mounted" % self.device)
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
|
@ -90,35 +92,35 @@ class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.dataset["Data.Warning"] = "EmptyPassword"
|
self.dataset["Data.Warning"] = "EmptyPassword"
|
||||||
self.log.info("no password was supplied for mounting of device: '%s'" % self.device)
|
self.log.info("no password was supplied for mounting of device: '%s'" % self.device)
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
if self.container.getType() != cbxContainer.ContainerTypes["luks"]:
|
if self.container.get_type() != cbxContainer.CONTAINERTYPES["luks"]:
|
||||||
## not a luks container - fail silently
|
## not a luks container - fail silently
|
||||||
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
|
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
try:
|
try:
|
||||||
self.container.mount(pw)
|
self.container.mount(pw)
|
||||||
except CBMountError, errMsg:
|
except CBMountError, err_msg:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
|
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"
|
return "volume_status"
|
||||||
except CBContainerError, errMsg:
|
except CBContainerError, err_msg:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
|
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"
|
return "volume_status"
|
||||||
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
|
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
|
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
|
|
||||||
|
|
||||||
def __doUmount(self):
|
def __do_umount(self):
|
||||||
if not self.container.isMounted():
|
if not self.container.is_mounted():
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsNotMounted"
|
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsNotMounted"
|
||||||
self.cbox.log.info("the device (%s) is currently not mounted" % self.device)
|
self.cbox.log.info("the device (%s) is currently not mounted" % self.device)
|
||||||
return "volume_status"
|
return "volume_status"
|
||||||
try:
|
try:
|
||||||
self.container.umount()
|
self.container.umount()
|
||||||
except CBUmountError, errMsg:
|
except CBUmountError, err_msg:
|
||||||
self.hdf["Data.Warning"] = "UmountFailed"
|
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"
|
return "volume_status"
|
||||||
self.cbox.log.info("successfully unmounted the container: %s" % self.device)
|
self.cbox.log.info("successfully unmounted the container: %s" % self.device)
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_mount.UmountDone"
|
self.hdf["Data.Success"] = "Plugins.volume_mount.UmountDone"
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('Properties')
|
self.cmd.find('Properties')
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
import cryptobox.plugins.manage
|
import cryptobox.plugins.manage
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
|
@ -25,51 +27,54 @@ from cryptobox.core.exceptions import *
|
||||||
|
|
||||||
class volume_props(cryptobox.plugins.base.CryptoBoxPlugin):
|
class volume_props(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "volume" ]
|
plugin_visibility = [ "volume" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 30
|
rank = 30
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, **args):
|
def do_action(self, **args):
|
||||||
import os
|
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
|
## 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
|
## set the name of the templates for every plugin
|
||||||
loadString = ""
|
load_string = ""
|
||||||
for p in self.props_plugins:
|
for p in self.props_plugins:
|
||||||
p.device = self.device
|
p.device = self.device
|
||||||
plfname = os.path.join(p.pluginDir, str(p.doAction(**args)) + ".cs")
|
plfname = os.path.join(p.plugin_dir, str(p.do_action(**args)) + ".cs")
|
||||||
loadString += "<?cs include:'%s' ?>" % plfname
|
load_string += "<?cs include:'%s' ?>" % plfname
|
||||||
## this is a little bit ugly: as it is not possible, to load cs files via
|
## 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
|
## 'linclude' (see clearsilver doc) if they use previously defined macros (see
|
||||||
## clearsilver mailing list thread 'linclude file which calls a macro' - 27th
|
## clearsilver mailing list thread 'linclude file which calls a macro' - 27th
|
||||||
## December 02005)
|
## December 02005)
|
||||||
## our workaround: define the appropriate "include" (not 'linclude') commands
|
## our workaround: define the appropriate "include" (not 'linclude') commands
|
||||||
## as a hdf variable - then we can include it via 'evar'
|
## 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"
|
return "volume_properties"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
return "TODO"
|
return "TODO"
|
||||||
|
|
||||||
|
|
||||||
def loadDataSet(self, hdf):
|
def load_dataset(self, hdf):
|
||||||
"""override the parent's function
|
"""override the parent's function
|
||||||
we have to get the data from all included plugins"""
|
we have to get the data from all included plugins"""
|
||||||
for p in self.props_plugins:
|
for plugin in self.props_plugins:
|
||||||
p.loadDataSet(hdf)
|
plugin.load_dataset(hdf)
|
||||||
## call our parent's method
|
## 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):
|
def __cmp_plugins_rank(self, p1, p2):
|
||||||
order = p1.getRank() - p2.getRank()
|
order = p1.get_rank() - p2.get_rank()
|
||||||
if order < 0:
|
if order < 0:
|
||||||
return -1
|
return -1
|
||||||
elif order == 0:
|
elif order == 0:
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.web.testclass
|
import cryptobox.web.testclass
|
||||||
|
|
||||||
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
def test_read_form(self):
|
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.register_auth(url)
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('name')
|
self.cmd.find('name')
|
||||||
|
|
|
@ -18,49 +18,51 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
|
|
||||||
|
|
||||||
class volume_rename(cryptobox.plugins.base.CryptoBoxPlugin):
|
class volume_rename(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
|
|
||||||
pluginCapabilities = [ "volume" ]
|
plugin_capabilities = [ "volume" ]
|
||||||
pluginVisibility = [ "properties" ]
|
plugin_visibility = [ "properties" ]
|
||||||
requestAuth = False
|
request_auth = False
|
||||||
rank = 60
|
rank = 60
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, store=None, vol_name=None):
|
def do_action(self, store=None, vol_name=None):
|
||||||
self.container = self.cbox.getContainer(self.device)
|
self.container = self.cbox.get_container(self.device)
|
||||||
if not self.container:
|
if not self.container:
|
||||||
return None
|
return None
|
||||||
self.__prepareHDF()
|
self.__prepare_hdf()
|
||||||
if store and vol_name:
|
if store and vol_name:
|
||||||
return self.__setVolumeName(vol_name)
|
return self.__set_volume_name(vol_name)
|
||||||
else:
|
else:
|
||||||
return "volume_rename"
|
return "volume_rename"
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
self.container = self.cbox.getContainer(self.device)
|
self.container = self.cbox.get_container(self.device)
|
||||||
if not self.container:
|
if not self.container:
|
||||||
return "invalid device"
|
return "invalid device"
|
||||||
return "name=%s" % self.container.getName()
|
return "name=%s" % self.container.get_name()
|
||||||
|
|
||||||
|
|
||||||
def __prepareHDF(self):
|
def __prepare_hdf(self):
|
||||||
self.hdf[self.hdf_prefix + "vol_name"] = self.container.getName()
|
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:
|
if not vol_name:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_rename.InvalidVolumeName"
|
self.hdf["Data.Warning"] = "Plugins.volume_rename.InvalidVolumeName"
|
||||||
return "volume_rename"
|
return "volume_rename"
|
||||||
if vol_name == self.container.getName():
|
if vol_name == self.container.get_name():
|
||||||
## nothing has to be done
|
## nothing has to be done
|
||||||
return "volume_rename"
|
return "volume_rename"
|
||||||
try:
|
try:
|
||||||
self.container.setName(vol_name)
|
self.container.set_name(vol_name)
|
||||||
self.hdf["Data.Success"] = "Plugins.volume_rename.VolumeNameChanged"
|
self.hdf["Data.Success"] = "Plugins.volume_rename.VolumeNameChanged"
|
||||||
except CBVolumeIsActive:
|
except CBVolumeIsActive:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_rename.NoRenameIfActive"
|
self.hdf["Data.Warning"] = "Plugins.volume_rename.NoRenameIfActive"
|
||||||
|
@ -71,6 +73,6 @@ class volume_rename(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
except CBContainerError:
|
except CBContainerError:
|
||||||
self.hdf["Data.Warning"] = "Plugins.volume_rename.SetVolumeNameFailed"
|
self.hdf["Data.Warning"] = "Plugins.volume_rename.SetVolumeNameFailed"
|
||||||
## reread the volume name
|
## reread the volume name
|
||||||
self.__prepareHDF()
|
self.__prepare_hdf()
|
||||||
return "volume_rename"
|
return "volume_rename"
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""Core management functions of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
__all__ = [ 'main', 'container', 'exceptions', 'tools', 'settings' ]
|
||||||
|
|
|
@ -18,21 +18,18 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
## check python version
|
"""Manage a single container of the CryptoBox
|
||||||
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)):
|
__revision__ = "$Id"
|
||||||
sys.stderr.write("You need a python version >= 2.4\nCurrent version is:\n %s\n" % sys.version)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import logging
|
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
|
|
||||||
|
|
||||||
ContainerTypes = {
|
CONTAINERTYPES = {
|
||||||
"unused":0,
|
"unused":0,
|
||||||
"plain":1,
|
"plain":1,
|
||||||
"luks":2,
|
"luks":2,
|
||||||
|
@ -46,11 +43,12 @@ MOUNT_DIR_MARKER = '_cryptobox_mount_dir_'
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxContainer:
|
class CryptoBoxContainer:
|
||||||
|
"""Manage a container of the CryptoBox
|
||||||
|
"""
|
||||||
|
|
||||||
__fsTypes = {
|
__fsTypes = {
|
||||||
"plain":["ext3", "ext2", "vfat", "reiser"],
|
"plain":["ext3", "ext2", "vfat", "reiserfs"],
|
||||||
"swap":["swap"]}
|
"swap":["swap"]}
|
||||||
# TODO: more filesystem types? / check 'reiser'
|
|
||||||
|
|
||||||
__dmDir = "/dev/mapper"
|
__dmDir = "/dev/mapper"
|
||||||
|
|
||||||
|
@ -58,41 +56,58 @@ class CryptoBoxContainer:
|
||||||
def __init__(self, device, cbox):
|
def __init__(self, device, cbox):
|
||||||
self.device = device
|
self.device = device
|
||||||
self.cbox = cbox
|
self.cbox = cbox
|
||||||
self.log = logging.getLogger("CryptoBox")
|
self.uuid = None
|
||||||
self.resetObject()
|
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
|
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:
|
try:
|
||||||
## is there already an entry in the database?
|
## 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
|
self.attributes["uuid"] = self.uuid
|
||||||
except KeyError:
|
except KeyError:
|
||||||
## set default values
|
## set default values
|
||||||
self.attributes = { "uuid": self.uuid }
|
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):
|
def set_name(self, new_name):
|
||||||
old_name = self.getName()
|
"""Define a humanly readable name of this container.
|
||||||
if new_name == self.name: return
|
|
||||||
|
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
|
## renaming is not possible, if the volume is active, as the mountpoint name
|
||||||
## is the same as the volume 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")
|
raise CBVolumeIsActive("the container must not be active during renaming")
|
||||||
if not re.search(r'^[a-zA-Z0-9_\.\- ]+$', new_name):
|
if not re.search(r'^[a-zA-Z0-9_\.\- ]+$', new_name):
|
||||||
raise CBInvalidName("the supplied new name contains illegal characters")
|
raise CBInvalidName("the supplied new name contains illegal characters")
|
||||||
## check for another partitions with the same name
|
## 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")
|
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
|
## maybe there a is an entry in the volumes database (but the partition is not active
|
||||||
try:
|
try:
|
||||||
## remove possibly existing inactive database item
|
## remove possibly existing inactive database item
|
||||||
del self.cbox.prefs.volumesDB[new_name]
|
del self.cbox.prefs.volumes_db[new_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
## no entry - so nothing happens
|
## no entry - so nothing happens
|
||||||
pass
|
pass
|
||||||
|
@ -100,99 +115,116 @@ class CryptoBoxContainer:
|
||||||
self.name = new_name
|
self.name = new_name
|
||||||
## remove old database entry
|
## remove old database entry
|
||||||
try:
|
try:
|
||||||
del self.cbox.prefs.volumesDB[old_name]
|
del self.cbox.prefs.volumes_db[old_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
## set new volumes database entry
|
## set new volumes database entry
|
||||||
self.cbox.prefs.volumesDB[new_name] = self.attributes
|
self.cbox.prefs.volumes_db[new_name] = self.attributes
|
||||||
self.cbox.prefs.volumesDB.write()
|
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
|
return self.device
|
||||||
|
|
||||||
|
|
||||||
def getType(self):
|
def get_type(self):
|
||||||
return self.type
|
"""Return the type (int) of this container.
|
||||||
|
"""
|
||||||
|
return self.cont_type
|
||||||
|
|
||||||
|
|
||||||
def isMounted(self):
|
def is_mounted(self):
|
||||||
return os.path.ismount(self.__getMountPoint())
|
"""Check if the container is currently mounted.
|
||||||
|
"""
|
||||||
|
return os.path.ismount(self.__get_mount_point())
|
||||||
|
|
||||||
|
|
||||||
def getCapacity(self):
|
def get_capacity(self):
|
||||||
"""return the current capacity state of the volume
|
"""Return the current capacity state of the volume.
|
||||||
|
|
||||||
the volume may not be mounted
|
the volume may not be mounted
|
||||||
the result is a tuple of values in megabyte:
|
the result is a tuple of values in megabyte:
|
||||||
(size, available, used)
|
(size, available, used)
|
||||||
"""
|
"""
|
||||||
info = os.statvfs(self.__getMountPoint())
|
info = os.statvfs(self.__get_mount_point())
|
||||||
return (
|
return (
|
||||||
int(info.f_bsize*info.f_blocks/1024/1024),
|
int(info.f_bsize*info.f_blocks/1024/1024),
|
||||||
int(info.f_bsize*info.f_bavail/1024/1024),
|
int(info.f_bsize*info.f_bavail/1024/1024),
|
||||||
int(info.f_bsize*(info.f_blocks-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)
|
"""return the size of the block device (_not_ of the filesystem)
|
||||||
|
|
||||||
the result is a value in megabyte
|
the result is a value in megabyte
|
||||||
an error is indicated by "-1"
|
an error is indicated by "-1"
|
||||||
"""
|
"""
|
||||||
import cryptobox.core.tools as cbxtools
|
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
|
""" recheck the information about this container
|
||||||
this is especially useful after changing the type via 'create' """
|
this is especially useful after changing the type via 'create' """
|
||||||
self.uuid = self.__getUUID()
|
self.uuid = self.__get_uuid()
|
||||||
self.type = self.__getTypeOfPartition()
|
self.cont_type = self.__get_type_of_partition()
|
||||||
self.name = self.__getNameOfContainer()
|
self.name = self.__get_name_of_container()
|
||||||
self.__setAttributes()
|
self.__set_attributes()
|
||||||
if self.type == ContainerTypes["luks"]:
|
if self.cont_type == CONTAINERTYPES["luks"]:
|
||||||
self.mount = self.__mountLuks
|
self.mount = self.__mount_luks
|
||||||
self.umount = self.__umountLuks
|
self.umount = self.__umount_luks
|
||||||
elif self.type == ContainerTypes["plain"]:
|
elif self.cont_type == CONTAINERTYPES["plain"]:
|
||||||
self.mount = self.__mountPlain
|
self.mount = self.__mount_plain
|
||||||
self.umount = self.__umountPlain
|
self.umount = self.__umount_plain
|
||||||
|
|
||||||
|
|
||||||
def create(self, type, password=None):
|
def create(self, cont_type, password=None):
|
||||||
old_name = self.getName()
|
"""Format a container.
|
||||||
if type == ContainerTypes["luks"]:
|
|
||||||
self.__createLuks(password)
|
Also set a password for encrypted container.
|
||||||
elif type == ContainerTypes["plain"]:
|
"""
|
||||||
self.__createPlain()
|
old_name = self.get_name()
|
||||||
|
if cont_type == CONTAINERTYPES["luks"]:
|
||||||
|
self.__create_luks(password)
|
||||||
|
elif cont_type == CONTAINERTYPES["plain"]:
|
||||||
|
self.__create_plain()
|
||||||
else:
|
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
|
## no exception was raised during creation -> we can continue
|
||||||
## reset the properties (encryption state, ...) of the device
|
## reset the properties (encryption state, ...) of the device
|
||||||
self.resetObject()
|
self.reset_object()
|
||||||
## restore the old name (must be after resetObject)
|
## restore the old name (must be after reset_object)
|
||||||
self.setName(old_name)
|
self.set_name(old_name)
|
||||||
|
|
||||||
|
|
||||||
def changePassword(self, oldpw, newpw):
|
def change_password(self, oldpw, newpw):
|
||||||
if self.type != ContainerTypes["luks"]:
|
"""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")
|
raise CBInvalidType("changing of password is possible only for luks containers")
|
||||||
if not oldpw:
|
if not oldpw:
|
||||||
raise CBInvalidPassword("no old password supplied for password change")
|
raise CBInvalidPassword("no old password supplied for password change")
|
||||||
if not newpw:
|
if not newpw:
|
||||||
raise CBInvalidPassword("no new password supplied for password change")
|
raise CBInvalidPassword("no new password supplied for password change")
|
||||||
"return if new and old passwords are the same"
|
## return if new and old passwords are the same
|
||||||
if oldpw == newpw: return
|
if oldpw == newpw:
|
||||||
if self.isMounted():
|
return
|
||||||
|
if self.is_mounted():
|
||||||
raise CBVolumeIsActive("this container is currently active")
|
raise CBVolumeIsActive("this container is currently active")
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
"remove any potential open luks mapping"
|
## remove any potential open luks mapping
|
||||||
self.__umountLuks()
|
self.__umount_luks()
|
||||||
"create the luks header"
|
## create the luks header
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = subprocess.PIPE,
|
stdin = subprocess.PIPE,
|
||||||
|
@ -208,16 +240,17 @@ class CryptoBoxContainer:
|
||||||
proc.stdin.write("%s\n%s" % (oldpw, newpw))
|
proc.stdin.write("%s\n%s" % (oldpw, newpw))
|
||||||
(output, errout) = proc.communicate()
|
(output, errout) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not add a new luks key: %s - %s" % (output.strip(), errout.strip(), )
|
error_msg = "Could not add a new luks key: %s - %s" \
|
||||||
self.log.error(errorMsg)
|
% (output.strip(), errout.strip(), )
|
||||||
raise CBChangePasswordError(errorMsg)
|
self.cbox.log.error(error_msg)
|
||||||
|
raise CBChangePasswordError(error_msg)
|
||||||
## retrieve the key slot we used for unlocking
|
## retrieve the key slot we used for unlocking
|
||||||
keys_found = re.search(r'key slot (\d{1,3}) unlocked', output).groups()
|
keys_found = re.search(r'key slot (\d{1,3}) unlocked', output).groups()
|
||||||
if keys_found:
|
if keys_found:
|
||||||
keyslot = int(keys_found[0])
|
keyslot = int(keys_found[0])
|
||||||
else:
|
else:
|
||||||
raise CBChangePasswordError("could not get the old key slot")
|
raise CBChangePasswordError("could not get the old key slot")
|
||||||
"remove the old key"
|
## remove the old key
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -231,40 +264,43 @@ class CryptoBoxContainer:
|
||||||
"%d" % (keyslot, )])
|
"%d" % (keyslot, )])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not remove the old luks key: %s" % (proc.stderr.read().strip(), )
|
error_msg = "Could not remove the old luks key: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(error_msg)
|
||||||
raise CBChangePasswordError(errorMsg)
|
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
|
"""retrieve the name of the container by querying the database
|
||||||
call this function only for the initial setup of the container object"""
|
call this function only for the initial setup of the container object"""
|
||||||
found_name = None
|
found_name = None
|
||||||
for key in self.cbox.prefs.volumesDB.keys():
|
for key in self.cbox.prefs.volumes_db.keys():
|
||||||
if self.cbox.prefs.volumesDB[key]["uuid"] == self.uuid:
|
if self.cbox.prefs.volumes_db[key]["uuid"] == self.uuid:
|
||||||
found_name = key
|
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
|
## there is no name defined for this uuid - we will propose a good one
|
||||||
prefix = self.cbox.prefs["Main"]["DefaultVolumePrefix"]
|
prefix = self.cbox.prefs["Main"]["DefaultVolumePrefix"]
|
||||||
unused_found = False
|
unused_found = False
|
||||||
counter = 1
|
counter = 1
|
||||||
while not unused_found:
|
while not unused_found:
|
||||||
guess = prefix + str(counter)
|
guess = prefix + str(counter)
|
||||||
if self.cbox.prefs.volumesDB.has_key(guess):
|
if self.cbox.prefs.volumes_db.has_key(guess):
|
||||||
counter += 1
|
counter += 1
|
||||||
else:
|
else:
|
||||||
unused_found = True
|
unused_found = True
|
||||||
return guess
|
return guess
|
||||||
|
|
||||||
|
|
||||||
def __getUUID(self):
|
def __get_uuid(self):
|
||||||
if self.__getTypeOfPartition() == ContainerTypes["luks"]:
|
"""Retrieve the uuid of the container device.
|
||||||
guess = self.__getLuksUUID()
|
"""
|
||||||
|
if self.__get_type_of_partition() == CONTAINERTYPES["luks"]:
|
||||||
|
guess = self.__get_luks_uuid()
|
||||||
else:
|
else:
|
||||||
guess = self.__getNonLuksUUID()
|
guess = self.__get_non_luks_uuid()
|
||||||
## did we get a valid value?
|
## did we get a valid value?
|
||||||
if guess:
|
if guess:
|
||||||
return guess
|
return guess
|
||||||
|
@ -273,7 +309,7 @@ class CryptoBoxContainer:
|
||||||
return self.device.replace(os.path.sep, "_")
|
return self.device.replace(os.path.sep, "_")
|
||||||
|
|
||||||
|
|
||||||
def __getLuksUUID(self):
|
def __get_luks_uuid(self):
|
||||||
"""get uuid for luks devices"""
|
"""get uuid for luks devices"""
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
|
@ -284,17 +320,18 @@ class CryptoBoxContainer:
|
||||||
self.device])
|
self.device])
|
||||||
(stdout, stderr) = proc.communicate()
|
(stdout, stderr) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
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 None
|
||||||
return stdout.strip()
|
return stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
def __getNonLuksUUID(self):
|
def __get_non_luks_uuid(self):
|
||||||
"""return UUID for ext2/3 and vfat filesystems"""
|
"""return UUID for ext2/3 and vfat filesystems"""
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell=False,
|
shell=False,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
|
@ -309,30 +346,36 @@ class CryptoBoxContainer:
|
||||||
devnull.close()
|
devnull.close()
|
||||||
## execution failed?
|
## execution failed?
|
||||||
if proc.returncode != 0:
|
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 None
|
||||||
## return output of blkid
|
## return output of blkid
|
||||||
return stdout.strip()
|
return stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
def __getTypeOfPartition(self):
|
def __get_type_of_partition(self):
|
||||||
"retrieve the type of the given partition (see cryptobox.core.container.ContainerTypes)"
|
"""Retrieve the type of the given partition.
|
||||||
if self.__isLuksPartition(): return ContainerTypes["luks"]
|
|
||||||
typeOfPartition = self.__getTypeIdOfPartition()
|
see cryptobox.core.container.CONTAINERTYPES
|
||||||
if typeOfPartition in self.__fsTypes["plain"]:
|
"""
|
||||||
return ContainerTypes["plain"]
|
if self.__is_luks_partition():
|
||||||
if typeOfPartition in self.__fsTypes["swap"]:
|
return CONTAINERTYPES["luks"]
|
||||||
return ContainerTypes["swap"]
|
type_of_partition = self.__get_type_id_of_partition()
|
||||||
return ContainerTypes["unused"]
|
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')"
|
"returns the type of the partition (see 'man blkid')"
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell=False,
|
shell=False,
|
||||||
stdin=None,
|
stdin=None,
|
||||||
|
@ -347,19 +390,20 @@ class CryptoBoxContainer:
|
||||||
proc.wait()
|
proc.wait()
|
||||||
output = proc.stdout.read().strip()
|
output = proc.stdout.read().strip()
|
||||||
if proc.returncode != 0:
|
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
|
return None
|
||||||
devnull.close()
|
devnull.close()
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def __isLuksPartition(self):
|
def __is_luks_partition(self):
|
||||||
"check if the given device is a luks partition"
|
"check if the given device is a luks partition"
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -375,29 +419,30 @@ class CryptoBoxContainer:
|
||||||
return proc.returncode == 0
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
def __getMountPoint(self):
|
def __get_mount_point(self):
|
||||||
"return the name of the mountpoint of this volume"
|
"return the name of the mountpoint of this volume"
|
||||||
return os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], self.name)
|
return os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], self.name)
|
||||||
|
|
||||||
|
|
||||||
def __mountLuks(self, password):
|
def __mount_luks(self, password):
|
||||||
"mount a luks partition"
|
"mount a luks partition"
|
||||||
if not password:
|
if not password:
|
||||||
raise CBInvalidPassword("no password supplied for luksOpen")
|
raise CBInvalidPassword("no password supplied for luksOpen")
|
||||||
if self.isMounted(): raise CBVolumeIsActive("this container is already active")
|
if self.is_mounted():
|
||||||
self.__umountLuks()
|
raise CBVolumeIsActive("this container is already active")
|
||||||
|
self.__umount_luks()
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
self.__cleanMountDirs()
|
self.__clean_mount_dirs()
|
||||||
if not os.path.exists(self.__getMountPoint()):
|
if not os.path.exists(self.__get_mount_point()):
|
||||||
self.__createMountDirectory(self.__getMountPoint())
|
self.__create_mount_directory(self.__get_mount_point())
|
||||||
if not os.path.exists(self.__getMountPoint()):
|
if not os.path.exists(self.__get_mount_point()):
|
||||||
errorMsg = "Could not create mountpoint (%s)" % (self.__getMountPoint(), )
|
err_msg = "Could not create mountpoint (%s)" % (self.__get_mount_point(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(err_msg)
|
||||||
raise CBMountError(errorMsg)
|
raise CBMountError(err_msg)
|
||||||
self.cbox.sendEventNotification("premount", self.__getEventArgs())
|
self.cbox.send_event_notification("premount", self.__get_event_args())
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = subprocess.PIPE,
|
stdin = subprocess.PIPE,
|
||||||
|
@ -414,9 +459,9 @@ class CryptoBoxContainer:
|
||||||
proc.stdin.write(password)
|
proc.stdin.write(password)
|
||||||
(output, errout) = proc.communicate()
|
(output, errout) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not open the luks mapping: %s" % (errout.strip(), )
|
err_msg = "Could not open the luks mapping: %s" % (errout.strip(), )
|
||||||
self.log.warn(errorMsg)
|
self.cbox.log.warn(err_msg)
|
||||||
raise CBMountError(errorMsg)
|
raise CBMountError(err_msg)
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -427,25 +472,25 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"mount",
|
"mount",
|
||||||
os.path.join(self.__dmDir, self.name),
|
os.path.join(self.__dmDir, self.name),
|
||||||
self.__getMountPoint()])
|
self.__get_mount_point()])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.warn(errorMsg)
|
self.cbox.log.warn(err_msg)
|
||||||
raise CBMountError(errorMsg)
|
raise CBMountError(err_msg)
|
||||||
devnull.close()
|
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"
|
"umount a luks partition"
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
self.cbox.sendEventNotification("preumount", self.__getEventArgs())
|
self.cbox.send_event_notification("preumount", self.__get_event_args())
|
||||||
if self.isMounted():
|
if self.is_mounted():
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -455,12 +500,12 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"umount",
|
"umount",
|
||||||
self.__getMountPoint()])
|
self.__get_mount_point()])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.warn(errorMsg)
|
self.cbox.log.warn(err_msg)
|
||||||
raise CBUmountError(errorMsg)
|
raise CBUmountError(err_msg)
|
||||||
if os.path.exists(os.path.join(self.__dmDir, self.name)):
|
if os.path.exists(os.path.join(self.__dmDir, self.name)):
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
|
@ -476,29 +521,30 @@ class CryptoBoxContainer:
|
||||||
"--batch-mode"])
|
"--batch-mode"])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not remove the luks mapping: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not remove the luks mapping: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.warn(errorMsg)
|
self.cbox.log.warn(err_msg)
|
||||||
raise CBUmountError(errorMsg)
|
raise CBUmountError(err_msg)
|
||||||
devnull.close()
|
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"
|
"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
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
self.__cleanMountDirs()
|
self.__clean_mount_dirs()
|
||||||
if not os.path.exists(self.__getMountPoint()):
|
if not os.path.exists(self.__get_mount_point()):
|
||||||
self.__createMountDirectory(self.__getMountPoint())
|
self.__create_mount_directory(self.__get_mount_point())
|
||||||
if not os.path.exists(self.__getMountPoint()):
|
if not os.path.exists(self.__get_mount_point()):
|
||||||
errorMsg = "Could not create mountpoint (%s)" % (self.__getMountPoint(), )
|
err_msg = "Could not create mountpoint (%s)" % (self.__get_mount_point(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(err_msg)
|
||||||
raise CBMountError(errorMsg)
|
raise CBMountError(err_msg)
|
||||||
self.cbox.sendEventNotification("premount", self.__getEventArgs())
|
self.cbox.send_event_notification("premount", self.__get_event_args())
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -509,27 +555,28 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"mount",
|
"mount",
|
||||||
self.device,
|
self.device,
|
||||||
self.__getMountPoint()])
|
self.__get_mount_point()])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.warn(errorMsg)
|
self.cbox.log.warn(err_msg)
|
||||||
raise CBMountError(errorMsg)
|
raise CBMountError(err_msg)
|
||||||
devnull.close()
|
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"
|
"umount a plaintext partition"
|
||||||
if not self.isMounted():
|
if not self.is_mounted():
|
||||||
self.cbox.log.info("trying to umount while volume (%s) is mounted" % self.getDevice())
|
self.cbox.log.info("trying to umount while volume (%s) is mounted" % \
|
||||||
|
self.get_device())
|
||||||
return
|
return
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
self.cbox.sendEventNotification("preumount", self.__getEventArgs())
|
self.cbox.send_event_notification("preumount", self.__get_event_args())
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -539,25 +586,25 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["super"],
|
self.cbox.prefs["Programs"]["super"],
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||||
"umount",
|
"umount",
|
||||||
self.__getMountPoint()])
|
self.__get_mount_point()])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.warn(errorMsg)
|
self.cbox.log.warn(err_msg)
|
||||||
raise CBUmountError(errorMsg)
|
raise CBUmountError(err_msg)
|
||||||
devnull.close()
|
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"
|
"make a plaintext partition"
|
||||||
if self.isMounted():
|
if self.is_mounted():
|
||||||
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
|
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -568,26 +615,27 @@ class CryptoBoxContainer:
|
||||||
self.device])
|
self.device])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(err_msg)
|
||||||
raise CBCreateError(errorMsg)
|
raise CBCreateError(err_msg)
|
||||||
devnull.close()
|
devnull.close()
|
||||||
|
|
||||||
|
|
||||||
def __createLuks(self, password):
|
def __create_luks(self, password):
|
||||||
"make a luks partition"
|
"""Create a luks partition.
|
||||||
|
"""
|
||||||
if not password:
|
if not password:
|
||||||
raise CBInvalidPassword("no password supplied for new luks mapping")
|
raise CBInvalidPassword("no password supplied for new luks mapping")
|
||||||
if self.isMounted():
|
if self.is_mounted():
|
||||||
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
|
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
|
||||||
devnull = None
|
devnull = None
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||||
"remove any potential open luks mapping"
|
## remove any potential open luks mapping
|
||||||
self.__umountLuks()
|
self.__umount_luks()
|
||||||
"create the luks header"
|
## create the luks header
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = subprocess.PIPE,
|
stdin = subprocess.PIPE,
|
||||||
|
@ -605,10 +653,10 @@ class CryptoBoxContainer:
|
||||||
proc.stdin.write(password)
|
proc.stdin.write(password)
|
||||||
(output, errout) = proc.communicate()
|
(output, errout) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not create the luks header: %s" % (errout.strip(), )
|
err_msg = "Could not create the luks header: %s" % (errout.strip(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(err_msg)
|
||||||
raise CBCreateError(errorMsg)
|
raise CBCreateError(err_msg)
|
||||||
"open the luks container for mkfs"
|
## open the luks container for mkfs
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = subprocess.PIPE,
|
stdin = subprocess.PIPE,
|
||||||
|
@ -625,10 +673,10 @@ class CryptoBoxContainer:
|
||||||
proc.stdin.write(password)
|
proc.stdin.write(password)
|
||||||
(output, errout) = proc.communicate()
|
(output, errout) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not open the new luks mapping: %s" % (errout.strip(), )
|
err_msg = "Could not open the new luks mapping: %s" % (errout.strip(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(err_msg)
|
||||||
raise CBCreateError(errorMsg)
|
raise CBCreateError(err_msg)
|
||||||
"make the filesystem"
|
## make the filesystem
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
|
@ -638,50 +686,54 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["mkfs-data"],
|
self.cbox.prefs["Programs"]["mkfs-data"],
|
||||||
os.path.join(self.__dmDir, self.name)])
|
os.path.join(self.__dmDir, self.name)])
|
||||||
proc.wait()
|
proc.wait()
|
||||||
"remove the mapping - for every exit status"
|
## remove the mapping - for every exit status
|
||||||
self.__umountLuks()
|
self.__umount_luks()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
errorMsg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
|
err_msg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||||
self.log.error(errorMsg)
|
self.cbox.log.error(err_msg)
|
||||||
"remove the luks mapping"
|
## remove the luks mapping
|
||||||
raise CBCreateError(errorMsg)
|
raise CBCreateError(err_msg)
|
||||||
devnull.close()
|
devnull.close()
|
||||||
|
|
||||||
|
|
||||||
def __cleanMountDirs(self):
|
def __clean_mount_dirs(self):
|
||||||
""" remove all unnecessary subdirs of the mount parent directory
|
""" remove all unnecessary subdirs of the mount parent directory
|
||||||
this should be called for every (u)mount """
|
this should be called for every (u)mount """
|
||||||
subdirs = os.listdir(self.cbox.prefs["Locations"]["MountParentDir"])
|
subdirs = os.listdir(self.cbox.prefs["Locations"]["MountParentDir"])
|
||||||
for d in subdirs:
|
for one_dir in subdirs:
|
||||||
abs_dir = os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], d)
|
abs_dir = os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], one_dir)
|
||||||
if (not os.path.islink(abs_dir)) \
|
if (not os.path.islink(abs_dir)) \
|
||||||
and os.path.isdir(abs_dir) \
|
and os.path.isdir(abs_dir) \
|
||||||
and (not os.path.ismount(abs_dir)) \
|
and (not os.path.ismount(abs_dir)) \
|
||||||
and (os.path.isfile(os.path.join(abs_dir,MOUNT_DIR_MARKER))) \
|
and (os.path.isfile(os.path.join(abs_dir,MOUNT_DIR_MARKER))) \
|
||||||
and (len(os.listdir(abs_dir)) == 1):
|
and (len(os.listdir(abs_dir)) == 1):
|
||||||
try:
|
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)
|
os.rmdir(abs_dir)
|
||||||
except OSError,errMsg:
|
except OSError, err_msg:
|
||||||
## we do not care too much about unclean cleaning ...
|
## 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
|
"""create and mark a mount directory
|
||||||
this marking helps to remove old mountdirs safely"""
|
this marking helps to remove old mountdirs safely"""
|
||||||
os.mkdir(dirname)
|
os.mkdir(dirname)
|
||||||
try:
|
try:
|
||||||
f = file(os.path.join(dirname,MOUNT_DIR_MARKER),"w")
|
mark_file = file(os.path.join(dirname, MOUNT_DIR_MARKER), "w")
|
||||||
f.close()
|
mark_file.close()
|
||||||
except OSError,errMsg:
|
except OSError, err_msg:
|
||||||
## we do not care too much about the marking
|
## 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):
|
def __get_event_args(self):
|
||||||
"""return an array of arguments for event scripts handling pre/post-mount/umount
|
"""Return an array of arguments for event scripts.
|
||||||
events"""
|
|
||||||
typeText = [e for e in ContainerTypes.keys() if ContainerTypes[e] == self.getType()][0]
|
for now supported: pre/post-mount/umount events
|
||||||
return [self.getDevice(), self.getName(), typeText, self.__getMountPoint()]
|
"""
|
||||||
|
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()]
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
exceptions of the cryptobox package
|
exceptions of the cryptobox package
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
class CBError(Exception):
|
class CBError(Exception):
|
||||||
"""base class for exceptions of the cryptobox"""
|
"""base class for exceptions of the cryptobox"""
|
||||||
|
@ -54,13 +56,16 @@ class CBConfigUndefinedError(CBConfigError):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# is it a settings or a section?
|
"""Output the appropriate string: for a setting or a section.
|
||||||
|
"""
|
||||||
if self.name:
|
if self.name:
|
||||||
# setting
|
# 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:
|
else:
|
||||||
# section
|
# 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.value = value
|
||||||
self.reason = reason
|
self.reason = reason
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
class CBEnvironmentError(CBError):
|
||||||
|
@ -86,42 +95,58 @@ class CBEnvironmentError(CBError):
|
||||||
self.desc = desc
|
self.desc = desc
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
"""Return the error description.
|
||||||
|
"""
|
||||||
return "misconfiguration detected: %s" % self.desc
|
return "misconfiguration detected: %s" % self.desc
|
||||||
|
|
||||||
|
|
||||||
class CBContainerError(CBError):
|
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):
|
class CBCreateError(CBContainerError):
|
||||||
|
"""Raised if a container could not be created (formatted).
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBVolumeIsActive(CBContainerError):
|
class CBVolumeIsActive(CBContainerError):
|
||||||
|
"""Raised if a container was active even if it may not for a specific action.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBInvalidName(CBContainerError):
|
class CBInvalidName(CBContainerError):
|
||||||
|
"""Raised if someone tried to set an invalid container name.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBNameIsInUse(CBContainerError):
|
class CBNameIsInUse(CBContainerError):
|
||||||
|
"""Raised if the new name of a container is already in use.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBInvalidType(CBContainerError):
|
class CBInvalidType(CBContainerError):
|
||||||
|
"""Raised if a container is of an invalid type for a choosen action.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBInvalidPassword(CBContainerError):
|
class CBInvalidPassword(CBContainerError):
|
||||||
|
"""Someone tried to open an ecnrypted container with the wrong password.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBChangePasswordError(CBContainerError):
|
class CBChangePasswordError(CBContainerError):
|
||||||
|
"""Changing of the password of an encrypted container failed.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBMountError(CBContainerError):
|
class CBMountError(CBContainerError):
|
||||||
|
"""Failed to mount a container.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CBUmountError(CBContainerError):
|
class CBUmountError(CBContainerError):
|
||||||
|
"""Failed to umount a container.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -22,23 +22,17 @@
|
||||||
This is the web interface for a fileserver managing encrypted filesystems.
|
This is the web interface for a fileserver managing encrypted filesystems.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# check python version
|
__revision__ = "$Id"
|
||||||
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)
|
|
||||||
|
|
||||||
|
import sys
|
||||||
import cryptobox.core.container as cbxContainer
|
import cryptobox.core.container as cbxContainer
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import CBEnvironmentError, CBConfigUndefinedError
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import cryptobox.core.tools as cbxTools
|
import cryptobox.core.tools as cbxTools
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
VERSION = "0.3~1"
|
|
||||||
|
|
||||||
class CryptoBox:
|
class CryptoBox:
|
||||||
'''this class rules them all!
|
'''this class rules them all!
|
||||||
|
|
||||||
|
@ -48,14 +42,15 @@ class CryptoBox:
|
||||||
|
|
||||||
def __init__(self, config_file=None):
|
def __init__(self, config_file=None):
|
||||||
import cryptobox.core.settings as cbxSettings
|
import cryptobox.core.settings as cbxSettings
|
||||||
self.log = self.__getStartupLogger()
|
self.log = self.__get_startup_logger()
|
||||||
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
|
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
|
||||||
self.__runTests()
|
self.__run_tests()
|
||||||
|
self.__containers = []
|
||||||
|
self.reread_container_list()
|
||||||
|
|
||||||
|
|
||||||
def __getStartupLogger(self):
|
def __get_startup_logger(self):
|
||||||
import logging
|
"""Initialize the configured logging facility of the CryptoBox.
|
||||||
'''initialises the logging system
|
|
||||||
|
|
||||||
use it with: 'self.log.[debug|info|warning|error|critical](logmessage)'
|
use it with: 'self.log.[debug|info|warning|error|critical](logmessage)'
|
||||||
all classes should get the logging instance during __init__:
|
all classes should get the logging instance during __init__:
|
||||||
|
@ -63,13 +58,15 @@ class CryptoBox:
|
||||||
|
|
||||||
first we output all warnings/errors to stderr
|
first we output all warnings/errors to stderr
|
||||||
as soon as we opened the config file successfully, we redirect debug output
|
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
|
## basicConfig(...) needs python >= 2.4
|
||||||
try:
|
try:
|
||||||
log_handler = logging.getLogger("CryptoBox")
|
log_handler = logging.getLogger("CryptoBox")
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format='%(asctime)s CryptoBox %(levelname)s: %(message)s',
|
format = '%(asctime)s CryptoBox %(levelname)s: %(message)s',
|
||||||
stderr=sys.stderr)
|
stderr = sys.stderr)
|
||||||
log_handler.setLevel(logging.ERROR)
|
log_handler.setLevel(logging.ERROR)
|
||||||
log_handler.info("loggingsystem is up'n running")
|
log_handler.info("loggingsystem is up'n running")
|
||||||
## from now on everything can be logged via self.log...
|
## from now on everything can be logged via self.log...
|
||||||
|
@ -78,19 +75,15 @@ class CryptoBox:
|
||||||
return log_handler
|
return log_handler
|
||||||
|
|
||||||
|
|
||||||
# do some initial checks
|
def __run_tests(self):
|
||||||
def __runTests(self):
|
"""Do some initial tests.
|
||||||
#self.__runTestUID()
|
"""
|
||||||
self.__runTestRootPriv()
|
self.__run_test_root_priv()
|
||||||
|
|
||||||
|
|
||||||
def __runTestUID(self):
|
def __run_test_root_priv(self):
|
||||||
if os.geteuid() == 0:
|
"""Try to run 'super' with 'CryptoBoxRootActions'.
|
||||||
raise CBEnvironmentError("you may not run the cryptobox as root")
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __runTestRootPriv(self):
|
|
||||||
"""try to run 'super' with 'CryptoBoxRootActions'"""
|
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
|
@ -110,46 +103,39 @@ class CryptoBox:
|
||||||
stderr = devnull,
|
stderr = devnull,
|
||||||
args = [prog_super, prog_rootactions, "check"])
|
args = [prog_super, prog_rootactions, "check"])
|
||||||
except OSError:
|
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()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
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 reread_container_list(self):
|
||||||
def cbx_inheritance_test(self, string="you lucky widow"):
|
"""Reinitialize the list of available containers.
|
||||||
self.log.info(string)
|
|
||||||
|
|
||||||
|
|
||||||
# RFC: why should CryptoBoxProps inherit CryptoBox? [l]
|
This should be called whenever the available containers may have changed.
|
||||||
# RFC: shouldn't we move all useful functions of CryptoBoxProps to CryptoBox? [l]
|
E.g.: after partitioning and after device addition/removal
|
||||||
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):
|
|
||||||
self.log.debug("rereading container list")
|
self.log.debug("rereading container list")
|
||||||
self.containers = []
|
self.__containers = []
|
||||||
for device in cbxTools.getAvailablePartitions():
|
for device in cbxTools.get_available_partitions():
|
||||||
if self.isDeviceAllowed(device) and not self.isConfigPartition(device):
|
if self.is_device_allowed(device) and not self.is_config_partition(device):
|
||||||
self.containers.append(cbxContainer.CryptoBoxContainer(device, self))
|
self.__containers.append(cbxContainer.CryptoBoxContainer(device, self))
|
||||||
## sort by container name
|
## 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(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
|
stderr = subprocess.PIPE,
|
||||||
args = [
|
args = [
|
||||||
self.prefs["Programs"]["blkid"],
|
self.prefs["Programs"]["blkid"],
|
||||||
"-c", os.path.devnull,
|
"-c", os.path.devnull,
|
||||||
|
@ -160,70 +146,77 @@ class CryptoBoxProps(CryptoBox):
|
||||||
return output.strip() == self.prefs["Main"]["ConfigVolumeLabel"]
|
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"
|
"check if a device is white-listed for being used as cryptobox containers"
|
||||||
import types
|
import types
|
||||||
allowed = self.prefs["Main"]["AllowedDevices"]
|
allowed = self.prefs["Main"]["AllowedDevices"]
|
||||||
if type(allowed) == types.StringType: allowed = [allowed]
|
if type(allowed) == types.StringType:
|
||||||
|
allowed = [allowed]
|
||||||
for a_dev in allowed:
|
for a_dev in allowed:
|
||||||
"remove double dots and so on ..."
|
## remove double dots and so on ...
|
||||||
real_device = os.path.realpath(devicename)
|
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
|
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
|
"""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
|
# return nothing if the currently selected log output is not a file
|
||||||
try:
|
try:
|
||||||
if self.prefs["Log"]["Destination"].upper() != "FILE": return []
|
if self.prefs["Log"]["Destination"].upper() != "FILE":
|
||||||
|
return []
|
||||||
log_file = self.prefs["Log"]["Details"]
|
log_file = self.prefs["Log"]["Details"]
|
||||||
except KeyError:
|
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 []
|
return []
|
||||||
try:
|
try:
|
||||||
fd = open(log_file, "r")
|
fdesc = open(log_file, "r")
|
||||||
if maxSize: fd.seek(-maxSize, 2) # seek relative to the end of the file
|
if max_size:
|
||||||
content = fd.readlines()
|
fdesc.seek(-max_size, 2) # seek relative to the end of the file
|
||||||
fd.close()
|
content = fdesc.readlines()
|
||||||
|
fdesc.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("failed to read the log file (%s)" % log_file)
|
self.log.warn("failed to read the log file (%s)" % log_file)
|
||||||
return []
|
return []
|
||||||
if lines: content = content[-lines:]
|
if lines:
|
||||||
|
content = content[-lines:]
|
||||||
content.reverse()
|
content.reverse()
|
||||||
return content
|
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"
|
"retrieve the list of all containers of this cryptobox"
|
||||||
try:
|
try:
|
||||||
result = self.containers[:]
|
result = self.__containers[:]
|
||||||
if filterType != None:
|
if filter_type != None:
|
||||||
if filterType in range(len(cbxContainer.ContainerTypes)):
|
if filter_type in range(len(cbxContainer.CONTAINERTYPES)):
|
||||||
return [e for e in self.containers if e.getType() == filterType]
|
return [e for e in self.__containers if e.get_type() == filter_type]
|
||||||
else:
|
else:
|
||||||
self.log.info("invalid filterType (%d)" % filterType)
|
self.log.info("invalid filter_type (%d)" % filter_type)
|
||||||
result.clear()
|
result.clear()
|
||||||
if filterName != None:
|
if filter_name != None:
|
||||||
result = [e for e in self.containers if e.getName() == filterName]
|
result = [e for e in self.__containers if e.get_name() == filter_name]
|
||||||
return result
|
return result
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def getContainer(self, device):
|
def get_container(self, device):
|
||||||
"retrieve the container element for this 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:
|
if all:
|
||||||
return all[0]
|
return all[0]
|
||||||
else:
|
else:
|
||||||
return None
|
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"""
|
"""call all available scripts in the event directory with some event information"""
|
||||||
event_dir = self.prefs["Locations"]["EventDir"]
|
event_dir = self.prefs["Locations"]["EventDir"]
|
||||||
for fname in os.listdir(event_dir):
|
for fname in os.listdir(event_dir):
|
||||||
|
@ -240,11 +233,14 @@ class CryptoBoxProps(CryptoBox):
|
||||||
args = cmd_args)
|
args = cmd_args)
|
||||||
(stdout, stderr) = proc.communicate()
|
(stdout, stderr) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
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:
|
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__":
|
if __name__ == "__main__":
|
||||||
cb = CryptoBoxProps()
|
CryptoBox()
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,21 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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 *
|
from cryptobox.core.exceptions import *
|
||||||
import logging
|
import logging
|
||||||
try:
|
|
||||||
import validate
|
|
||||||
except:
|
|
||||||
raise CBEnvironmentError("couldn't import 'validate'! Try 'apt-get install python-formencode'.")
|
|
||||||
import os
|
|
||||||
import subprocess
|
import subprocess
|
||||||
try:
|
import os
|
||||||
import configobj ## needed for reading and writing of the config file
|
import configobj, validate
|
||||||
except:
|
|
||||||
raise CBEnvironmentError("couldn't import 'configobj'! Try 'apt-get install python-configobj'.")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxSettings:
|
class CryptoBoxSettings:
|
||||||
|
"""Manage the various configuration files of the CryptoBox
|
||||||
|
"""
|
||||||
|
|
||||||
CONF_LOCATIONS = [
|
CONF_LOCATIONS = [
|
||||||
"./cryptobox.conf",
|
"./cryptobox.conf",
|
||||||
|
@ -47,76 +46,85 @@ class CryptoBoxSettings:
|
||||||
|
|
||||||
def __init__(self, config_file=None):
|
def __init__(self, config_file=None):
|
||||||
self.log = logging.getLogger("CryptoBox")
|
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.log.info("loading config file: %s" % config_file)
|
||||||
self.prefs = self.__getPreferences(config_file)
|
self.prefs = self.__get_preferences(config_file)
|
||||||
self.__validateConfig()
|
self.__validate_config()
|
||||||
self.__configureLogHandler()
|
self.__configure_log_handler()
|
||||||
self.__checkUnknownPreferences()
|
self.__check_unknown_preferences()
|
||||||
self.preparePartition()
|
self.prepare_partition()
|
||||||
self.volumesDB = self.__getVolumesDatabase()
|
self.volumes_db = self.__get_volumes_database()
|
||||||
self.pluginConf = self.__getPluginConfig()
|
self.plugin_conf = self.__get_plugin_config()
|
||||||
self.userDB = self.__getUserDB()
|
self.user_db = self.__get_user_db()
|
||||||
self.misc_files = self.__getMiscFiles()
|
self.misc_files = self.__get_misc_files()
|
||||||
|
|
||||||
|
|
||||||
def write(self):
|
def write(self):
|
||||||
"""
|
"""
|
||||||
write all local setting files including the content of the "misc" subdirectory
|
write all local setting files including the content of the "misc" subdirectory
|
||||||
"""
|
"""
|
||||||
ok = True
|
status = True
|
||||||
try:
|
try:
|
||||||
self.volumesDB.write()
|
self.volumes_db.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("could not save the volume database")
|
self.log.warn("could not save the volume database")
|
||||||
ok = False
|
status = False
|
||||||
try:
|
try:
|
||||||
self.pluginConf.write()
|
self.plugin_conf.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("could not save the plugin configuration")
|
self.log.warn("could not save the plugin configuration")
|
||||||
ok = False
|
status = False
|
||||||
try:
|
try:
|
||||||
self.userDB.write()
|
self.user_db.write()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("could not save the user database")
|
self.log.warn("could not save the user database")
|
||||||
ok = False
|
status = False
|
||||||
for misc_file in self.misc_files:
|
for misc_file in self.misc_files:
|
||||||
if not misc_file.save():
|
if not misc_file.save():
|
||||||
self.log.warn("could not save a misc setting file (%s)" % misc_file.filename)
|
self.log.warn("could not save a misc setting file (%s)" % misc_file.filename)
|
||||||
ok = False
|
status = False
|
||||||
return ok
|
return status
|
||||||
|
|
||||||
|
|
||||||
def requiresPartition(self):
|
def requires_partition(self):
|
||||||
return bool(self.prefs["Main"]["UseConfigPartition"])
|
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"]
|
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"):
|
for line in file("/proc/mounts"):
|
||||||
fields = line.split(" ")
|
fields = line.split(" ")
|
||||||
mount_dir = fields[1]
|
mount_dir = fields[1]
|
||||||
try:
|
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:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
## no matching entry found
|
## no matching entry found
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def mountPartition(self):
|
def mount_partition(self):
|
||||||
|
"""Mount a config partition.
|
||||||
|
"""
|
||||||
self.log.debug("trying to mount configuration partition")
|
self.log.debug("trying to mount configuration partition")
|
||||||
if not self.requiresPartition():
|
if not self.requires_partition():
|
||||||
self.log.warn("mountConfigPartition: configuration partition is not required - mounting anyway")
|
self.log.warn("mountConfigPartition: configuration partition is "
|
||||||
if self.getActivePartition():
|
+ "not required - mounting anyway")
|
||||||
self.log.warn("mountConfigPartition: configuration partition already mounted - not mounting again")
|
if self.get_active_partition():
|
||||||
|
self.log.warn("mountConfigPartition: configuration partition already "
|
||||||
|
+ "mounted - not mounting again")
|
||||||
return False
|
return False
|
||||||
confPartitions = self.getAvailablePartitions()
|
conf_partitions = self.get_available_partitions()
|
||||||
if not confPartitions:
|
if not conf_partitions:
|
||||||
self.log.error("no configuration partitions found - you have to create it first")
|
self.log.error("no configuration partition found - you have to create "
|
||||||
|
+ "it first")
|
||||||
return False
|
return False
|
||||||
partition = confPartitions[0]
|
partition = conf_partitions[0]
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
|
@ -136,8 +144,10 @@ class CryptoBoxSettings:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def umountPartition(self):
|
def umount_partition(self):
|
||||||
if not self.getActivePartition():
|
"""Umount the currently active configuration partition.
|
||||||
|
"""
|
||||||
|
if not self.get_active_partition():
|
||||||
self.log.warn("umountConfigPartition: no configuration partition mounted")
|
self.log.warn("umountConfigPartition: no configuration partition mounted")
|
||||||
return False
|
return False
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
|
@ -158,7 +168,7 @@ class CryptoBoxSettings:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def getAvailablePartitions(self):
|
def get_available_partitions(self):
|
||||||
"""returns a sequence of found config partitions"""
|
"""returns a sequence of found config partitions"""
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
|
@ -169,14 +179,16 @@ class CryptoBoxSettings:
|
||||||
"-t", "LABEL=%s" % self.prefs["Main"]["ConfigVolumeLabel"] ])
|
"-t", "LABEL=%s" % self.prefs["Main"]["ConfigVolumeLabel"] ])
|
||||||
(output, error) = proc.communicate()
|
(output, error) = proc.communicate()
|
||||||
if output:
|
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:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def preparePartition(self):
|
def prepare_partition(self):
|
||||||
if self.requiresPartition() and not self.getActivePartition():
|
"""Mount a config partition if necessary.
|
||||||
self.mountPartition()
|
"""
|
||||||
|
if self.requires_partition() and not self.get_active_partition():
|
||||||
|
self.mount_partition()
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
|
@ -184,7 +196,9 @@ class CryptoBoxSettings:
|
||||||
return self.prefs[key]
|
return self.prefs[key]
|
||||||
|
|
||||||
|
|
||||||
def __getPreferences(self, config_file):
|
def __get_preferences(self, config_file):
|
||||||
|
"""Load the CryptoBox configuration.
|
||||||
|
"""
|
||||||
import StringIO
|
import StringIO
|
||||||
config_rules = StringIO.StringIO(self.validation_spec)
|
config_rules = StringIO.StringIO(self.validation_spec)
|
||||||
try:
|
try:
|
||||||
|
@ -192,86 +206,111 @@ class CryptoBoxSettings:
|
||||||
if prefs:
|
if prefs:
|
||||||
self.log.info("found config: %s" % prefs.items())
|
self.log.info("found config: %s" % prefs.items())
|
||||||
else:
|
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:
|
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
|
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)
|
result = self.prefs.validate(CryptoBoxSettingsValidator(), preserve_errors=True)
|
||||||
error_list = configobj.flatten_errors(self.prefs, result)
|
error_list = configobj.flatten_errors(self.prefs, result)
|
||||||
if not error_list: return
|
if not error_list:
|
||||||
errorMsgs = []
|
return
|
||||||
|
error_msgs = []
|
||||||
for sections, key, text in error_list:
|
for sections, key, text in error_list:
|
||||||
section_name = "->".join(sections)
|
section_name = "->".join(sections)
|
||||||
if not text:
|
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:
|
else:
|
||||||
errorMsg = "invalid configuration value (%s) in section '%s': %s" % (key, section_name, text)
|
error_msg = "invalid configuration value (%s) in section '%s': %s" % \
|
||||||
errorMsgs.append(errorMsg)
|
(key, section_name, text)
|
||||||
raise CBConfigError, "\n".join(errorMsgs)
|
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
|
import StringIO
|
||||||
config_rules = configobj.ConfigObj(StringIO.StringIO(self.validation_spec), list_values=False)
|
config_rules = configobj.ConfigObj(StringIO.StringIO(self.validation_spec),
|
||||||
self.__recursiveConfigSectionCheck("", self.prefs, config_rules)
|
list_values=False)
|
||||||
|
self.__recursive_section_check("", self.prefs, config_rules)
|
||||||
|
|
||||||
|
|
||||||
def __recursiveConfigSectionCheck(self, section_path, section_config, section_rules):
|
def __recursive_section_check(self, section_path, section_config, section_rules):
|
||||||
"""should be called by '__checkUnknownPreferences' for every section
|
"""should be called by '__check_unknown_preferences' for every section
|
||||||
sends a warning message to the logger for every undefined (see validation_spec)
|
sends a warning message to the logger for every undefined (see validation_spec)
|
||||||
configuration setting
|
configuration setting
|
||||||
"""
|
"""
|
||||||
for e in section_config.keys():
|
for section in section_config.keys():
|
||||||
element_path = section_path + e
|
element_path = section_path + section
|
||||||
if e in section_rules.keys():
|
if section in section_rules.keys():
|
||||||
if isinstance(section_config[e], configobj.Section):
|
if isinstance(section_config[section], configobj.Section):
|
||||||
if isinstance(section_rules[e], configobj.Section):
|
if isinstance(section_rules[section], configobj.Section):
|
||||||
self.__recursiveConfigSectionCheck(element_path + "->", section_config[e], section_rules[e])
|
self.__recursive_section_check(element_path + "->",
|
||||||
|
section_config[section], section_rules[section])
|
||||||
else:
|
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:
|
else:
|
||||||
if not isinstance(section_rules[e], configobj.Section):
|
if not isinstance(section_rules[section], configobj.Section):
|
||||||
pass # good - the setting is valid
|
pass # good - the setting is valid
|
||||||
else:
|
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:
|
else:
|
||||||
self.log.warn("unknown configuration setting: %s" % element_path)
|
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
|
import StringIO
|
||||||
plugin_rules = StringIO.StringIO(self.pluginValidationSpec)
|
plugin_rules = StringIO.StringIO(self.pluginValidationSpec)
|
||||||
try:
|
try:
|
||||||
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:
|
except KeyError:
|
||||||
raise CBConfigUndefinedError("Locations", "SettingsDir")
|
raise CBConfigUndefinedError("Locations", "SettingsDir")
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
raise CBConfigInvalidValueError("Locations", "SettingsDir", pluginConf_file, "failed to interprete the filename of the plugin config file correctly (%s)" % pluginConf_file)
|
raise CBConfigInvalidValueError("Locations", "SettingsDir", plugin_conf_file,
|
||||||
## create pluginConf_file if necessary
|
"failed to interprete the filename of the plugin config file "
|
||||||
if os.path.exists(pluginConf_file):
|
+ "correctly (%s)" % plugin_conf_file)
|
||||||
pluginConf = configobj.ConfigObj(pluginConf_file, configspec=plugin_rules)
|
## create plugin_conf_file if necessary
|
||||||
|
if os.path.exists(plugin_conf_file):
|
||||||
|
plugin_conf = configobj.ConfigObj(plugin_conf_file, configspec=plugin_rules)
|
||||||
else:
|
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
|
## validate and convert values according to the spec
|
||||||
pluginConf.validate(validate.Validator())
|
plugin_conf.validate(validate.Validator())
|
||||||
## check if pluginConf_file file was created successfully?
|
## check if plugin_conf_file file was created successfully?
|
||||||
if not os.path.exists(pluginConf_file):
|
if not os.path.exists(plugin_conf_file):
|
||||||
raise CBEnvironmentError("failed to create plugin configuration file (%s)" % pluginConf_file)
|
raise CBEnvironmentError(
|
||||||
return pluginConf
|
"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:
|
||||||
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:
|
except KeyError:
|
||||||
raise CBConfigUndefinedError("Locations", "SettingsDir")
|
raise CBConfigUndefinedError("Locations", "SettingsDir")
|
||||||
except SyntaxError:
|
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
|
## create conf_file if necessary
|
||||||
if os.path.exists(conf_file):
|
if os.path.exists(conf_file):
|
||||||
conf = configobj.ConfigObj(conf_file)
|
conf = configobj.ConfigObj(conf_file)
|
||||||
|
@ -279,36 +318,48 @@ class CryptoBoxSettings:
|
||||||
conf = configobj.ConfigObj(conf_file, create_empty=True)
|
conf = configobj.ConfigObj(conf_file, create_empty=True)
|
||||||
## check if conf_file file was created successfully?
|
## check if conf_file file was created successfully?
|
||||||
if not os.path.exists(conf_file):
|
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
|
return conf
|
||||||
|
|
||||||
|
|
||||||
def __getUserDB(self):
|
def __get_user_db(self):
|
||||||
|
"""Load the user database file if it exists.
|
||||||
|
"""
|
||||||
import StringIO, sha
|
import StringIO, sha
|
||||||
userDB_rules = StringIO.StringIO(self.userDatabaseSpec)
|
user_db_rules = StringIO.StringIO(self.userDatabaseSpec)
|
||||||
try:
|
try:
|
||||||
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:
|
except KeyError:
|
||||||
raise CBConfigUndefinedError("Locations", "SettingsDir")
|
raise CBConfigUndefinedError("Locations", "SettingsDir")
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
raise CBConfigInvalidValueError("Locations", "SettingsDir", userDB_file, "failed to interprete the filename of the users database file correctly (%s)" % userDB_file)
|
raise CBConfigInvalidValueError("Locations", "SettingsDir", user_db_file,
|
||||||
## create userDB_file if necessary
|
"failed to interprete the filename of the users database file "
|
||||||
if os.path.exists(userDB_file):
|
+ "correctly (%s)" % user_db_file)
|
||||||
userDB = configobj.ConfigObj(userDB_file, configspec=userDB_rules)
|
## 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:
|
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
|
## validate and set default value for "admin" user
|
||||||
userDB.validate(validate.Validator())
|
user_db.validate(validate.Validator())
|
||||||
## check if userDB file was created successfully?
|
## check if user_db file was created successfully?
|
||||||
if not os.path.exists(userDB_file):
|
if not os.path.exists(user_db_file):
|
||||||
raise CBEnvironmentError("failed to create user database file (%s)" % userDB_file)
|
raise CBEnvironmentError(
|
||||||
|
"failed to create user database file (%s)" % user_db_file)
|
||||||
## define password hash function - never use "sha" directly - SPOT
|
## define password hash function - never use "sha" directly - SPOT
|
||||||
userDB.getDigest = lambda password: sha.new(password).hexdigest()
|
user_db.get_digest = lambda password: sha.new(password).hexdigest()
|
||||||
return userDB
|
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")
|
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)):
|
if (not os.path.isdir(misc_dir)) or (not os.access(misc_dir, os.X_OK)):
|
||||||
return []
|
return []
|
||||||
|
@ -317,8 +368,9 @@ class CryptoBoxSettings:
|
||||||
if os.path.isfile(os.path.join(misc_dir, f))]
|
if os.path.isfile(os.path.join(misc_dir, f))]
|
||||||
|
|
||||||
|
|
||||||
def __getConfigFileName(self, config_file):
|
def __get_config_filename(self, config_file):
|
||||||
# search for the configuration file
|
"""Search for the configuration file.
|
||||||
|
"""
|
||||||
import types
|
import types
|
||||||
if config_file is None:
|
if config_file is None:
|
||||||
# no config file was specified - we will look for it in the ususal locations
|
# no config file was specified - we will look for it in the ususal locations
|
||||||
|
@ -332,13 +384,17 @@ class CryptoBoxSettings:
|
||||||
else:
|
else:
|
||||||
# a config file was specified (e.g. via command line)
|
# a config file was specified (e.g. via command line)
|
||||||
if type(config_file) != types.StringType:
|
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):
|
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
|
return config_file
|
||||||
|
|
||||||
|
|
||||||
def __configureLogHandler(self):
|
def __configure_log_handler(self):
|
||||||
|
"""Configure the log handler of the CryptoBox according to the config.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
log_level = self.prefs["Log"]["Level"].upper()
|
log_level = self.prefs["Log"]["Level"].upper()
|
||||||
log_level_avail = ["DEBUG", "INFO", "WARN", "ERROR"]
|
log_level_avail = ["DEBUG", "INFO", "WARN", "ERROR"]
|
||||||
|
@ -347,15 +403,18 @@ class CryptoBoxSettings:
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise CBConfigUndefinedError("Log", "Level")
|
raise CBConfigUndefinedError("Log", "Level")
|
||||||
except TypeError:
|
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:
|
||||||
try:
|
try:
|
||||||
log_handler = logging.FileHandler(self.prefs["Log"]["Details"])
|
log_handler = logging.FileHandler(self.prefs["Log"]["Details"])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise CBConfigUndefinedError("Log", "Details")
|
raise CBConfigUndefinedError("Log", "Details")
|
||||||
except IOError:
|
except IOError:
|
||||||
raise CBEnvironmentError("could not create the log file (%s)" % self.prefs["Log"]["Details"])
|
raise CBEnvironmentError("could not create the log file (%s)" % \
|
||||||
log_handler.setFormatter(logging.Formatter('%(asctime)s CryptoBox %(levelname)s: %(message)s'))
|
self.prefs["Log"]["Details"])
|
||||||
|
log_handler.setFormatter(
|
||||||
|
logging.Formatter('%(asctime)s CryptoBox %(levelname)s: %(message)s'))
|
||||||
cbox_log = logging.getLogger("CryptoBox")
|
cbox_log = logging.getLogger("CryptoBox")
|
||||||
## remove previous handlers
|
## remove previous handlers
|
||||||
cbox_log.handlers = []
|
cbox_log.handlers = []
|
||||||
|
@ -364,7 +423,7 @@ class CryptoBoxSettings:
|
||||||
## do not call parent's handlers
|
## do not call parent's handlers
|
||||||
cbox_log.propagate = False
|
cbox_log.propagate = False
|
||||||
## 'log_level' is a string -> use 'getattr'
|
## '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
|
## the logger named "CryptoBox" is configured now
|
||||||
|
|
||||||
|
|
||||||
|
@ -420,16 +479,20 @@ admin = string(default=d033e22ae348aeb5660fc2140aec35850c4da997)
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxSettingsValidator(validate.Validator):
|
class CryptoBoxSettingsValidator(validate.Validator):
|
||||||
|
"""Some custom configuration check functions.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
validate.Validator.__init__(self)
|
validate.Validator.__init__(self)
|
||||||
self.functions["directoryExists"] = self.check_directoryExists
|
self.functions["directoryExists"] = self.check_directory_exists
|
||||||
self.functions["fileExecutable"] = self.check_fileExecutable
|
self.functions["fileExecutable"] = self.check_file_executable
|
||||||
self.functions["fileWriteable"] = self.check_fileWriteable
|
self.functions["fileWriteable"] = self.check_file_writeable
|
||||||
self.functions["listOfExistingDirectories"] = self.check_listOfExistingDirectories
|
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)
|
dir_path = os.path.abspath(value)
|
||||||
if not os.path.isdir(dir_path):
|
if not os.path.isdir(dir_path):
|
||||||
raise validate.VdtValueError("%s (not found)" % value)
|
raise validate.VdtValueError("%s (not found)" % value)
|
||||||
|
@ -438,7 +501,9 @@ class CryptoBoxSettingsValidator(validate.Validator):
|
||||||
return dir_path
|
return dir_path
|
||||||
|
|
||||||
|
|
||||||
def check_fileExecutable(self, value):
|
def check_file_executable(self, value):
|
||||||
|
"""Is the file executable?
|
||||||
|
"""
|
||||||
file_path = os.path.abspath(value)
|
file_path = os.path.abspath(value)
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
raise validate.VdtValueError("%s (not found)" % value)
|
raise validate.VdtValueError("%s (not found)" % value)
|
||||||
|
@ -447,7 +512,9 @@ class CryptoBoxSettingsValidator(validate.Validator):
|
||||||
return file_path
|
return file_path
|
||||||
|
|
||||||
|
|
||||||
def check_fileWriteable(self, value):
|
def check_file_writeable(self, value):
|
||||||
|
"""Is the file writeable?
|
||||||
|
"""
|
||||||
file_path = os.path.abspath(value)
|
file_path = os.path.abspath(value)
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
if not os.access(file_path, os.W_OK):
|
if not os.access(file_path, os.W_OK):
|
||||||
|
@ -460,18 +527,22 @@ class CryptoBoxSettingsValidator(validate.Validator):
|
||||||
return file_path
|
return file_path
|
||||||
|
|
||||||
|
|
||||||
def check_listOfExistingDirectories(self, value):
|
def check_existing_directories(self, value):
|
||||||
|
"""Are these directories accessible?
|
||||||
|
"""
|
||||||
if not value:
|
if not value:
|
||||||
raise validate.VdtValueError("no plugin directory specified")
|
raise validate.VdtValueError("no plugin directory specified")
|
||||||
if not isinstance(value,list):
|
if not isinstance(value, list):
|
||||||
value = [value]
|
value = [value]
|
||||||
result = []
|
result = []
|
||||||
for d in value:
|
for one_dir in value:
|
||||||
dir_path = os.path.abspath(d)
|
dir_path = os.path.abspath(one_dir)
|
||||||
if not os.path.isdir(dir_path):
|
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):
|
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)
|
result.append(dir_path)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -484,19 +555,25 @@ class MiscConfigFile:
|
||||||
def __init__(self, filename, logger):
|
def __init__(self, filename, logger):
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.log = logger
|
self.log = logger
|
||||||
|
self.content = None
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
fd = open(self.filename, "rb")
|
"""Load a configuration file into memory.
|
||||||
|
"""
|
||||||
|
fdesc = open(self.filename, "rb")
|
||||||
## limit the maximum size
|
## limit the maximum size
|
||||||
self.content = fd.read(self.maxSize)
|
self.content = fdesc.read(self.maxSize)
|
||||||
if fd.tell() == self.maxSize:
|
if fdesc.tell() == self.maxSize:
|
||||||
self.log.warn("file in misc settings directory (%s) is bigger than allowed (%s)" % (self.filename, self.maxSize))
|
self.log.warn("file in misc settings directory (" + str(self.filename) \
|
||||||
fd.close()
|
+ ") is bigger than allowed (" + str(self.maxSize) + ")")
|
||||||
|
fdesc.close()
|
||||||
|
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
"""Save a configuration file to disk.
|
||||||
|
"""
|
||||||
save_dir = os.path.dirname(self.filename)
|
save_dir = os.path.dirname(self.filename)
|
||||||
## create the directory, if necessary
|
## create the directory, if necessary
|
||||||
if not os.path.isdir(save_dir):
|
if not os.path.isdir(save_dir):
|
||||||
|
@ -506,14 +583,14 @@ class MiscConfigFile:
|
||||||
return False
|
return False
|
||||||
## save the content of the file
|
## save the content of the file
|
||||||
try:
|
try:
|
||||||
fd = open(self.filename, "wb")
|
fdesc = open(self.filename, "wb")
|
||||||
except IOError:
|
except IOError:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
fd.write(self.content)
|
fdesc.write(self.content)
|
||||||
fd.close()
|
fdesc.close()
|
||||||
return True
|
return True
|
||||||
except IOError:
|
except IOError:
|
||||||
fd.close()
|
fdesc.close()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -18,137 +18,169 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""Some useful functions for the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
logger = logging.getLogger("CryptoBox")
|
LOGGER = logging.getLogger("CryptoBox")
|
||||||
|
|
||||||
|
|
||||||
def getAvailablePartitions():
|
def get_available_partitions():
|
||||||
"retrieve a list of all available containers"
|
"retrieve a list of all available containers"
|
||||||
ret_list = []
|
ret_list = []
|
||||||
try:
|
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")
|
fpart = open("/proc/partitions", "r")
|
||||||
try:
|
try:
|
||||||
line = fpart.readline()
|
line = fpart.readline()
|
||||||
while line:
|
while line:
|
||||||
p_details = line.split()
|
p_details = line.split()
|
||||||
if (len(p_details) == 4):
|
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
|
(p_major, p_minor, p_size, p_device) = p_details
|
||||||
## ignore lines with: invalid minor/major or extend partitions (size=1)
|
## 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)
|
p_parent = re.sub('[1-9]?[0-9]$', '', p_device)
|
||||||
if p_parent == p_device:
|
if p_parent == p_device:
|
||||||
if [e for e in ret_list if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]:
|
if [e for e in ret_list
|
||||||
"major partition - its children are already in the list"
|
if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]:
|
||||||
|
## major partition - its children are already in the list
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
"major partition - but there are no children for now"
|
## major partition - but there are no children for now
|
||||||
ret_list.append(p_device)
|
ret_list.append(p_device)
|
||||||
else:
|
else:
|
||||||
"minor partition - remove parent if necessary"
|
## minor partition - remove parent if necessary
|
||||||
if p_parent in ret_list: ret_list.remove(p_parent)
|
if p_parent in ret_list:
|
||||||
|
ret_list.remove(p_parent)
|
||||||
ret_list.append(p_device)
|
ret_list.append(p_device)
|
||||||
line = fpart.readline()
|
line = fpart.readline()
|
||||||
finally:
|
finally:
|
||||||
fpart.close()
|
fpart.close()
|
||||||
return map(getAbsoluteDeviceName, ret_list)
|
return [ get_absolute_devicename(e) for e in ret_list ]
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.warning("Could not read /proc/partitions")
|
LOGGER.warning("Could not read /proc/partitions")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def getAbsoluteDeviceName(shortname):
|
def get_absolute_devicename(shortname):
|
||||||
""" returns the absolute file name of a device (e.g.: "hda1" -> "/dev/hda1")
|
""" returns the absolute file name of a device (e.g.: "hda1" -> "/dev/hda1")
|
||||||
this does also work for device mapper devices
|
this does also work for device mapper devices
|
||||||
if the result is non-unique, one arbitrary value is returned"""
|
if the result is non-unique, one arbitrary value is returned
|
||||||
if re.search('^/', shortname): return shortname
|
"""
|
||||||
|
if re.search('^/', shortname):
|
||||||
|
return shortname
|
||||||
default = os.path.join("/dev", shortname)
|
default = os.path.join("/dev", shortname)
|
||||||
if os.path.exists(default): return default
|
if os.path.exists(default):
|
||||||
result = findMajorMinorOfDevice(shortname)
|
return default
|
||||||
"if no valid major/minor was found -> exit"
|
result = find_major_minor_of_device(shortname)
|
||||||
if not result: return default
|
## if no valid major/minor was found -> exit
|
||||||
|
if not result:
|
||||||
|
return default
|
||||||
(major, minor) = result
|
(major, minor) = result
|
||||||
"for device-mapper devices (major == 254) ..."
|
## for device-mapper devices (major == 254) ...
|
||||||
if major == 254:
|
if major == 254:
|
||||||
result = findMajorMinorDeviceName("/dev/mapper", major, minor)
|
result = find_major_minor_device("/dev/mapper", major, minor)
|
||||||
if result: return result[0]
|
if result:
|
||||||
"now check all files in /dev"
|
return result[0]
|
||||||
result = findMajorMinorDeviceName("/dev", major, minor)
|
## now check all files in /dev
|
||||||
if result: return result[0]
|
result = find_major_minor_device("/dev", major, minor)
|
||||||
|
if result:
|
||||||
|
return result[0]
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def findMajorMinorOfDevice(device):
|
def find_major_minor_of_device(device):
|
||||||
"return the major/minor numbers of a block 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)):
|
"""
|
||||||
|
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
|
## 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
|
## okay - it seems to to a device node
|
||||||
rdev = os.stat(device).st_rdev
|
rdev = os.stat(device).st_rdev
|
||||||
return (os.major(rdev), os.minor(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:
|
try:
|
||||||
f_blockdev_info = open(blockdev_info_file, "r")
|
f_blockdev_info = open(blockdev_info_file, "r")
|
||||||
blockdev_info = f_blockdev_info.read()
|
blockdev_info = f_blockdev_info.read()
|
||||||
f_blockdev_info.close()
|
f_blockdev_info.close()
|
||||||
(str_major, str_minor) = blockdev_info.split(":")
|
(str_major, str_minor) = blockdev_info.split(":")
|
||||||
"numeric conversion"
|
## numeric conversion
|
||||||
try:
|
try:
|
||||||
major = int(str_major)
|
major = int(str_major)
|
||||||
minor = int(str_minor)
|
minor = int(str_minor)
|
||||||
return (major, minor)
|
return (major, minor)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
"unknown device numbers -> stop guessing"
|
## unknown device numbers -> stop guessing
|
||||||
return None
|
return None
|
||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def findMajorMinorDeviceName(dir, major, minor):
|
def find_major_minor_device(dirpath, major, minor):
|
||||||
"returns the names of devices with the specified major and minor number"
|
"""Returns the names of devices with the specified major and minor number.
|
||||||
|
"""
|
||||||
collected = []
|
collected = []
|
||||||
try:
|
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))]
|
subdirs = [os.path.join(dirpath, e) for e in os.listdir(dirpath)
|
||||||
"do a recursive call to parse the directory tree"
|
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:
|
for dirs in subdirs:
|
||||||
collected.extend(findMajorMinorDeviceName(dirs, major, minor))
|
collected.extend(find_major_minor_device(dirs, major, minor))
|
||||||
"filter all device inodes in this directory"
|
## 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([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
|
## remove double entries
|
||||||
result = []
|
result = []
|
||||||
for e in collected:
|
for item in collected:
|
||||||
if e not in result: result.append(e)
|
if item not in result:
|
||||||
|
result.append(item)
|
||||||
return result
|
return result
|
||||||
except OSError:
|
except OSError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def getParentBlockDevices():
|
def get_parent_blockdevices():
|
||||||
|
"""Return a list of all block devices that contain other devices.
|
||||||
|
"""
|
||||||
devs = []
|
devs = []
|
||||||
for line in file("/proc/partitions"):
|
for line in file("/proc/partitions"):
|
||||||
p_details = line.split()
|
p_details = line.split()
|
||||||
## we expect four values - otherwise continue with next iteration
|
## 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
|
(p_major, p_minor, p_size, p_device) = p_details
|
||||||
## we expect numeric values in the first two columns
|
## 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
|
## 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)
|
devs.append(p_device)
|
||||||
return map(getAbsoluteDeviceName, devs)
|
return [ get_absolute_devicename(e) for e in devs ]
|
||||||
|
|
||||||
|
|
||||||
def isPartOfBlockDevice(parent, subdevice):
|
def is_part_of_blockdevice(parent, subdevice):
|
||||||
"""check if the given block device is a parent of 'subdevice'
|
"""Check if the given block device is a parent of 'subdevice'.
|
||||||
e.g. for checking if a partition belongs to a block device"""
|
|
||||||
|
e.g. for checking if a partition belongs to a block device
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
(par_major, par_minor) = findMajorMinorOfDevice(parent)
|
(par_major, par_minor) = find_major_minor_of_device(parent)
|
||||||
(sub_major, sub_minor) = findMajorMinorOfDevice(subdevice)
|
(sub_major, sub_minor) = find_major_minor_of_device(subdevice)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
## at least one of these devices did not return a valid major/minor combination
|
## at least one of these devices did not return a valid major/minor combination
|
||||||
return False
|
return False
|
||||||
|
@ -158,7 +190,8 @@ def isPartOfBlockDevice(parent, subdevice):
|
||||||
blpath = os.path.join(root, bldev, 'dev')
|
blpath = os.path.join(root, bldev, 'dev')
|
||||||
if os.access(blpath, os.R_OK):
|
if os.access(blpath, os.R_OK):
|
||||||
try:
|
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)
|
parent_path = os.path.join(root, bldev)
|
||||||
break
|
break
|
||||||
except (IndexError, OSError):
|
except (IndexError, OSError):
|
||||||
|
@ -170,7 +203,8 @@ def isPartOfBlockDevice(parent, subdevice):
|
||||||
subblpath = os.path.join(parent_path, subbldev, "dev")
|
subblpath = os.path.join(parent_path, subbldev, "dev")
|
||||||
if os.access(subblpath, os.R_OK):
|
if os.access(subblpath, os.R_OK):
|
||||||
try:
|
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!
|
## the name of the subdevice node is not important - we found it!
|
||||||
return True
|
return True
|
||||||
except (IndexError, OSError):
|
except (IndexError, OSError):
|
||||||
|
@ -178,18 +212,22 @@ def isPartOfBlockDevice(parent, subdevice):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def getBlockDeviceSize(device):
|
def get_blockdevice_size(device):
|
||||||
if not device: return -1
|
"""Return the size of a blockdevice.
|
||||||
|
"""
|
||||||
|
if not device:
|
||||||
|
return -1
|
||||||
try:
|
try:
|
||||||
rdev = os.stat(device).st_rdev
|
rdev = os.stat(device).st_rdev
|
||||||
except OSError:
|
except OSError:
|
||||||
return -1
|
return -1
|
||||||
minor = os.minor(rdev)
|
minor = os.minor(rdev)
|
||||||
major = os.major(rdev)
|
major = os.major(rdev)
|
||||||
for f in file("/proc/partitions"):
|
for line in file("/proc/partitions"):
|
||||||
try:
|
try:
|
||||||
elements = f.split()
|
elements = line.split()
|
||||||
if len(elements) != 4: continue
|
if len(elements) != 4:
|
||||||
|
continue
|
||||||
if (int(elements[0]) == major) and (int(elements[1]) == minor):
|
if (int(elements[0]) == major) and (int(elements[1]) == minor):
|
||||||
return int(elements[2])/1024
|
return int(elements[2])/1024
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -197,8 +235,10 @@ def getBlockDeviceSize(device):
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
def getBlockDeviceSizeHumanly(device):
|
def get_blockdevice_size_humanly(device):
|
||||||
size = getBlockDeviceSize(device)
|
"""Return a human readable size of a blockdevice.
|
||||||
|
"""
|
||||||
|
size = get_blockdevice_size(device)
|
||||||
if size > 5120:
|
if size > 5120:
|
||||||
return "%sGB" % size/1024
|
return "%sGB" % size/1024
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""Features may be easily added to the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
__all__ = [ 'base', 'manage' ]
|
||||||
|
|
|
@ -21,161 +21,189 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""All features should inherit from this class.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import cherrypy
|
import cherrypy
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxPlugin:
|
class CryptoBoxPlugin:
|
||||||
|
"""The base class of all features.
|
||||||
|
"""
|
||||||
|
|
||||||
## default capability is "system" - the other supported capability is: "volume"
|
## default capability is "system" - the other supported capability is: "volume"
|
||||||
pluginCapabilities = [ "system" ]
|
plugin_capabilities = [ "system" ]
|
||||||
|
|
||||||
## where should the plugin be visible by default?
|
## where should the plugin be visible by default?
|
||||||
pluginVisibility = [ "preferences" ]
|
plugin_visibility = [ "preferences" ]
|
||||||
|
|
||||||
## does this plugin require admin authentification?
|
## 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)
|
## default rank (0..100) of the plugin in listings (lower value means higher priority)
|
||||||
rank = 80
|
rank = 80
|
||||||
|
|
||||||
|
|
||||||
## default icon of this plugin (relative path)
|
## 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)
|
## 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.cbox = cbox
|
||||||
self.hdf = {}
|
self.hdf = {}
|
||||||
self.pluginDir = pluginDir
|
self.plugin_dir = plugin_dir
|
||||||
self.hdf_prefix = "Data.Plugins.%s." % self.getName()
|
self.hdf_prefix = "Data.Plugins.%s." % self.get_name()
|
||||||
self.site = siteClass
|
self.site = site_class
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def doAction(self, **args):
|
def do_action(self, **args):
|
||||||
"""override doAction with your plugin code"""
|
"""Override do_action with your plugin code
|
||||||
raise Exception, "undefined action handler ('doAction') in plugin '%'" % self.getName()
|
"""
|
||||||
|
raise Exception, \
|
||||||
|
"undefined action handler ('do_action') in plugin '%s'" % self.get_name()
|
||||||
|
|
||||||
|
|
||||||
def getStatus(self):
|
def get_status(self):
|
||||||
"""you should override this, to supply useful state information"""
|
"""you should override this, to supply useful state information
|
||||||
raise Exception, "undefined state handler ('getStatus') in plugin '%'" % self.getName()
|
"""
|
||||||
|
raise Exception, \
|
||||||
|
"undefined state handler ('get_status') in plugin '%s'" % self.get_name()
|
||||||
|
|
||||||
|
|
||||||
def getName(self):
|
def get_name(self):
|
||||||
"""the name of the python file (module) should be the name of the plugin"""
|
"""the name of the python file (module) should be the name of the plugin
|
||||||
|
"""
|
||||||
return self.__module__
|
return self.__module__
|
||||||
|
|
||||||
|
|
||||||
@cherrypy.expose
|
@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
|
"""return the image data of the icon of the plugin
|
||||||
|
|
||||||
the parameter 'image' may be used for alternative image locations (relative
|
the parameter 'image' may be used for alternative image locations (relative
|
||||||
to the directory of the plugin)
|
to the directory of the plugin)
|
||||||
'**kargs' is necessary, as a 'weblang' attribute may be specified (and ignored)"""
|
'**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)):
|
import re
|
||||||
plugin_icon_file = os.path.join(self.pluginDir, self.defaultIconFileName)
|
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:
|
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):
|
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)
|
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
|
"""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
|
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):
|
if os.access(result_file, os.R_OK) and os.path.isfile(result_file):
|
||||||
return result_file
|
return result_file
|
||||||
else:
|
else:
|
||||||
return None
|
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
|
import neo_cgi, neo_util
|
||||||
lang_hdf = neo_util.HDF()
|
lang_hdf = neo_util.HDF()
|
||||||
langFile = os.path.join(self.pluginDir, 'language.hdf')
|
lang_file = os.path.join(self.plugin_dir, 'language.hdf')
|
||||||
try:
|
try:
|
||||||
lang_hdf.readFile(langFile)
|
lang_hdf.readFile(lang_file)
|
||||||
except (neo_util.Error, neo_util.ParseError), errMsg:
|
except (neo_util.Error, neo_util.ParseError):
|
||||||
self.cbox.log.error("failed to load language file (%s) of plugin (%s):" % (langFile,self.getName()))
|
self.cbox.log.error("failed to load language file (%s) of plugin (%s):" % \
|
||||||
|
(lang_file, self.get_name()))
|
||||||
return lang_hdf
|
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():
|
for (key, value) in self.hdf.items():
|
||||||
hdf.setValue(key, str(value))
|
hdf.setValue(key, str(value))
|
||||||
|
|
||||||
|
|
||||||
def isAuthRequired(self):
|
def is_auth_required(self):
|
||||||
"""check if this plugin requires authentication
|
"""check if this plugin requires authentication
|
||||||
first step: check plugin configuration
|
first step: check plugin configuration
|
||||||
second step: check default value of plugin"""
|
second step: check default value of plugin
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
if self.cbox.prefs.pluginConf[self.getName()]["requestAuth"] is None:
|
if self.cbox.prefs.plugin_conf[self.get_name()]["requestAuth"] is None:
|
||||||
return self.requestAuth
|
return self.request_auth
|
||||||
if self.cbox.prefs.pluginConf[self.getName()]["requestAuth"]:
|
if self.cbox.prefs.plugin_conf[self.get_name()]["requestAuth"]:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return self.requestAuth
|
return self.request_auth
|
||||||
|
|
||||||
|
|
||||||
def isEnabled(self):
|
def is_enabled(self):
|
||||||
"""check if this plugin is enabled
|
"""check if this plugin is enabled
|
||||||
first step: check plugin configuration
|
first step: check plugin configuration
|
||||||
second step: check default value of plugin"""
|
second step: check default value of plugin
|
||||||
fallback = bool(self.pluginVisibility)
|
"""
|
||||||
|
fallback = bool(self.plugin_visibility)
|
||||||
try:
|
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 fallback
|
||||||
return bool(self.cbox.prefs.pluginConf[self.getName()]["visibility"])
|
return bool(self.cbox.prefs.plugin_conf[self.get_name()]["visibility"])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return fallback
|
return fallback
|
||||||
|
|
||||||
|
|
||||||
def getRank(self):
|
def get_rank(self):
|
||||||
"""check the rank of this plugin
|
"""check the rank of this plugin
|
||||||
first step: check plugin configuration
|
first step: check plugin configuration
|
||||||
second step: check default value of plugin"""
|
second step: check default value of plugin
|
||||||
|
"""
|
||||||
try:
|
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 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):
|
except (KeyError, TypeError):
|
||||||
return self.rank
|
return self.rank
|
||||||
|
|
||||||
|
|
||||||
def getVisibility(self):
|
def get_visibility(self):
|
||||||
|
"""Check which visibility flags of the feature are set.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
if self.cbox.prefs.pluginConf[self.getName()]["visibility"] is None:
|
if self.cbox.prefs.plugin_conf[self.get_name()]["visibility"] is None:
|
||||||
return self.pluginVisibility[:]
|
return self.plugin_visibility[:]
|
||||||
return self.cbox.prefs.pluginConf[self.getName()]["visibility"]
|
return self.cbox.prefs.plugin_conf[self.get_name()]["visibility"]
|
||||||
except KeyError:
|
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
|
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):
|
if os.access(pl_file, os.R_OK) and os.path.isfile(pl_file):
|
||||||
try:
|
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:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
try:
|
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:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -19,46 +19,56 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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 os
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
class PluginManager:
|
class PluginManager:
|
||||||
"""manage available plugins"""
|
"""manage available plugins"""
|
||||||
|
|
||||||
def __init__(self, cbox, plugin_dirs=".", siteClass=None):
|
def __init__(self, cbox, plugin_dirs=".", site_class=None):
|
||||||
self.cbox = cbox
|
self.cbox = cbox
|
||||||
self.log = logging.getLogger("CryptoBox")
|
self.site = site_class
|
||||||
self.site = siteClass
|
|
||||||
if hasattr(plugin_dirs, "__iter__"):
|
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:
|
else:
|
||||||
self.plugin_dirs = [os.path.abspath(plugin_dirs)]
|
self.plugin_dirs = [os.path.abspath(plugin_dirs)]
|
||||||
self.pluginList = self.__getAllPlugins()
|
self.plugin_list = self.__get_all_plugins()
|
||||||
|
|
||||||
|
|
||||||
def getPlugins(self):
|
def get_plugins(self):
|
||||||
return self.pluginList[:]
|
"""Return a list of all feature instances.
|
||||||
|
"""
|
||||||
|
return self.plugin_list[:]
|
||||||
|
|
||||||
|
|
||||||
def getPlugin(self, name):
|
def get_plugin(self, name):
|
||||||
for p in self.pluginList[:]:
|
"""Return the specified feature as an instance.
|
||||||
if p.getName() == name:
|
"""
|
||||||
return p
|
for plugin in self.plugin_list[:]:
|
||||||
|
if plugin.get_name() == name:
|
||||||
|
return plugin
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def __getAllPlugins(self):
|
def __get_all_plugins(self):
|
||||||
list = []
|
"""Return all available features as instances.
|
||||||
for plfile in self.__getPluginFiles():
|
"""
|
||||||
list.append(self.__getPluginClass(os.path.basename(plfile)[:-3]))
|
plist = []
|
||||||
return list
|
for plfile in self.__get_plugin_files():
|
||||||
|
plist.append(self.__get_plugin_class(os.path.basename(plfile)[:-3]))
|
||||||
|
return plist
|
||||||
|
|
||||||
|
|
||||||
def __getPluginClass(self, name):
|
def __get_plugin_class(self, name):
|
||||||
for plfile in self.__getPluginFiles():
|
"""Return a instance object of the give feature.
|
||||||
|
"""
|
||||||
|
import imp
|
||||||
|
for plfile in self.__get_plugin_files():
|
||||||
if name == os.path.basename(plfile)[:-3]:
|
if name == os.path.basename(plfile)[:-3]:
|
||||||
try:
|
try:
|
||||||
pl_class = getattr(imp.load_source(name, plfile), name)
|
pl_class = getattr(imp.load_source(name, plfile), name)
|
||||||
|
@ -69,18 +79,23 @@ class PluginManager:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def __getPluginFiles(self):
|
def __get_plugin_files(self):
|
||||||
|
"""Retrieve all python files that may potentially be a feature.
|
||||||
|
"""
|
||||||
result = []
|
result = []
|
||||||
if self.cbox and self.cbox.prefs["Main"]["DisabledPlugins"]:
|
if self.cbox and self.cbox.prefs["Main"]["DisabledPlugins"]:
|
||||||
disabled = self.cbox.prefs["Main"]["DisabledPlugins"]
|
disabled = self.cbox.prefs["Main"]["DisabledPlugins"]
|
||||||
else:
|
else:
|
||||||
disabled = []
|
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 pdir in [os.path.abspath(e) for e in self.plugin_dirs
|
||||||
for plname in [f for f in os.listdir(dir)]:
|
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 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
|
continue
|
||||||
pldir = os.path.join(dir, plname)
|
pldir = os.path.join(pdir, plname)
|
||||||
plfile = os.path.join(pldir, plname + ".py")
|
plfile = os.path.join(pldir, plname + ".py")
|
||||||
if os.path.isfile(plfile) and os.access(plfile, os.R_OK):
|
if os.path.isfile(plfile) and os.access(plfile, os.R_OK):
|
||||||
result.append(plfile)
|
result.append(plfile)
|
||||||
|
@ -88,8 +103,8 @@ class PluginManager:
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
x = PluginManager(None, "../plugins")
|
MANAGER = PluginManager(None, "../plugins")
|
||||||
for a in x.getPlugins():
|
for one_plugin in MANAGER.get_plugins():
|
||||||
if not a is None:
|
if not one_plugin is None:
|
||||||
print "Plugin: %s" % a.getName()
|
print "Plugin: %s" % one_plugin.get_name()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""Some unittests for the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
__all__ = [ 'test.cryptobox', 'test.cryptoboxtools', 'test.plugins', 'test.websites' ]
|
||||||
|
|
|
@ -19,33 +19,41 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""Some unittests for the core CryptoBox modules.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import sys
|
import sys
|
||||||
import cryptobox.core.main
|
import cryptobox.core.main
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
import cryptobox.core.settings
|
import cryptobox.core.settings
|
||||||
|
import os
|
||||||
|
|
||||||
class CryptoBoxPropsDeviceTests(unittest.TestCase):
|
class CryptoBoxDeviceTests(unittest.TestCase):
|
||||||
cb = cryptobox.core.main.CryptoBoxProps()
|
"""Some unittests for the CryptoBox
|
||||||
|
"""
|
||||||
|
|
||||||
|
cb = cryptobox.core.main.CryptoBox()
|
||||||
|
|
||||||
def testAllowedDevices(self):
|
def test_allowed_devices(self):
|
||||||
'''isDeviceAllowed should accept permitted devices'''
|
'''is_device_allowed should accept permitted devices'''
|
||||||
self.assertTrue(self.cb.isDeviceAllowed("/dev/loop"))
|
self.assertTrue(self.cb.is_device_allowed("/dev/loop"))
|
||||||
self.assertTrue(self.cb.isDeviceAllowed("/dev/loop1"))
|
self.assertTrue(self.cb.is_device_allowed("/dev/loop1"))
|
||||||
self.assertTrue(self.cb.isDeviceAllowed("/dev/loop/urgd"))
|
self.assertTrue(self.cb.is_device_allowed("/dev/loop/urgd"))
|
||||||
self.assertTrue(self.cb.isDeviceAllowed("/dev/usb/../loop1"))
|
self.assertTrue(self.cb.is_device_allowed("/dev/usb/../loop1"))
|
||||||
|
|
||||||
def testDeniedDevices(self):
|
def test_denied_devices(self):
|
||||||
'''isDeviceAllowed should fail with not explicitly allowed devices'''
|
'''is_device_allowed should fail with not explicitly allowed devices'''
|
||||||
self.assertFalse(self.cb.isDeviceAllowed("/dev/hda"))
|
self.assertFalse(self.cb.is_device_allowed("/dev/hda"))
|
||||||
self.assertFalse(self.cb.isDeviceAllowed("/dev/loopa/../hda"))
|
self.assertFalse(self.cb.is_device_allowed("/dev/loopa/../hda"))
|
||||||
self.assertFalse(self.cb.isDeviceAllowed("/"))
|
self.assertFalse(self.cb.is_device_allowed("/"))
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxPropsConfigTests(unittest.TestCase):
|
class CryptoBoxConfigTests(unittest.TestCase):
|
||||||
'''test here if everything with the config turns right'''
|
'''test here if everything with the config turns right'''
|
||||||
import os
|
|
||||||
files = {
|
files = {
|
||||||
"configFileOK" : "cbox-test_ok.conf",
|
"configFileOK" : "cbox-test_ok.conf",
|
||||||
"configFileBroken" : "cbox-test_broken.conf",
|
"configFileBroken" : "cbox-test_broken.conf",
|
||||||
|
@ -86,71 +94,89 @@ CryptoBoxRootActions = CryptoBoxRootActions
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
'''generate all files in tmp and remember the names'''
|
'''generate all files in tmp and remember the names'''
|
||||||
import tempfile
|
import tempfile
|
||||||
os = self.os
|
|
||||||
self.tmpdirname = tempfile.mkdtemp(prefix="cbox-")
|
self.tmpdirname = tempfile.mkdtemp(prefix="cbox-")
|
||||||
for file in self.files.keys():
|
for tfile in self.files.keys():
|
||||||
self.filenames[file] = os.path.join(self.tmpdirname, self.files[file])
|
self.filenames[tfile] = os.path.join(self.tmpdirname, self.files[tfile])
|
||||||
self.writeConfig()
|
self.write_config()
|
||||||
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
'''remove the created tmpfiles'''
|
'''remove the created tmpfiles'''
|
||||||
os = self.os
|
|
||||||
# remove temp files
|
# remove temp files
|
||||||
for file in self.filenames.values():
|
for tfile in self.filenames.values():
|
||||||
compl_name = os.path.join(self.tmpdirname, file)
|
compl_name = os.path.join(self.tmpdirname, tfile)
|
||||||
if os.path.exists(compl_name):
|
if os.path.exists(compl_name):
|
||||||
os.remove(compl_name)
|
os.remove(compl_name)
|
||||||
# remove temp dir
|
# remove temp dir
|
||||||
os.rmdir(self.tmpdirname)
|
os.rmdir(self.tmpdirname)
|
||||||
|
|
||||||
|
|
||||||
def testConfigInit(self):
|
def test_config_init(self):
|
||||||
'''Check various branches of config file loading'''
|
'''Check various branches of config file loading'''
|
||||||
import os
|
self.assertRaises(CBConfigUnavailableError,
|
||||||
self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps,"/invalid/path/to/config/file")
|
cryptobox.core.main.CryptoBox,"/invalid/path/to/config/file")
|
||||||
self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps,"/etc/shadow")
|
self.assertRaises(CBConfigUnavailableError,
|
||||||
""" check one of the following things:
|
cryptobox.core.main.CryptoBox,"/etc/shadow")
|
||||||
1) are we successfully using an existing config file?
|
## check one of the following things:
|
||||||
2) do we break, if no config file is there?
|
## 1) are we successfully using an existing config file?
|
||||||
depending on the existence of a config file, only one of these conditions
|
## 2) do we break, if no config file is there?
|
||||||
can be checked - hints for more comprehensive tests are appreciated :) """
|
## depending on the existence of a config file, only one of these conditions
|
||||||
for a in ['cryptobox.conf']:
|
## can be checked - hints for more comprehensive tests are appreciated :)
|
||||||
if os.path.exists(a):
|
for cfile in ['cryptobox.conf']:
|
||||||
cryptobox.core.main.CryptoBoxProps()
|
if os.path.exists(cfile):
|
||||||
|
cryptobox.core.main.CryptoBox()
|
||||||
break # this skips the 'else' clause
|
break # this skips the 'else' clause
|
||||||
else: self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps)
|
else:
|
||||||
self.assertRaises(CBConfigUnavailableError, cryptobox.core.main.CryptoBoxProps,[])
|
self.assertRaises(CBConfigUnavailableError,
|
||||||
|
cryptobox.core.main.CryptoBox)
|
||||||
|
self.assertRaises(CBConfigUnavailableError,
|
||||||
|
cryptobox.core.main.CryptoBox,[])
|
||||||
|
|
||||||
|
|
||||||
def testBrokenConfigs(self):
|
def test_broken_configs(self):
|
||||||
"""Check various broken configurations"""
|
"""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.write_config("SettingsDir", "SettingsDir=/foo/bar",
|
||||||
self.writeConfig("Level", "Level = ho", filename=self.filenames["configFileBroken"])
|
filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
|
||||||
self.writeConfig("Details", "#out", filename=self.filenames["configFileBroken"])
|
self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.write_config("Level", "Level = ho",
|
||||||
self.writeConfig("super", "super=/bin/invalid/no", filename=self.filenames["configFileBroken"])
|
filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
|
||||||
self.writeConfig("CryptoBoxRootActions", "#not here", filename=self.filenames["configFileBroken"])
|
self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.write_config("Details", "#out",
|
||||||
self.writeConfig("CryptoBoxRootActions", "CryptoBoxRootActions = /bin/false", filename=self.filenames["configFileBroken"])
|
filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBEnvironmentError, cryptobox.core.main.CryptoBoxProps,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"""
|
"""write a config file and (optional) replace a line in it"""
|
||||||
import re
|
import re
|
||||||
if not filename: filename = self.filenames["configFileOK"]
|
if not filename:
|
||||||
content = self.configContentOK % (self.tmpdirname, self.tmpdirname, self.tmpdirname)
|
filename = self.filenames["configFileOK"]
|
||||||
|
content = self.configContentOK % \
|
||||||
|
(self.tmpdirname, self.tmpdirname, self.tmpdirname)
|
||||||
if replace:
|
if replace:
|
||||||
pattern = re.compile('^' + replace + '\\s*=.*$', flags=re.M)
|
pattern = re.compile('^' + replace + '\\s*=.*$', flags=re.M)
|
||||||
content = re.sub(pattern, newline, content)
|
content = re.sub(pattern, newline, content)
|
||||||
cf = open(filename, "w")
|
cfile = open(filename, "w")
|
||||||
cf.write(content)
|
cfile.write(content)
|
||||||
cf.close()
|
cfile.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,14 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""Unittests for cryptobox.core.tools
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import cryptobox.core.tools as cbxTools
|
import cryptobox.core.tools as cbx_tools
|
||||||
import os
|
import os
|
||||||
|
|
||||||
## use /dev/ubd? if possible - otherwise /dev/hd?
|
## use /dev/ubd? if possible - otherwise /dev/hd?
|
||||||
|
@ -36,30 +41,40 @@ else:
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxToolsTests(unittest.TestCase):
|
class CryptoBoxToolsTests(unittest.TestCase):
|
||||||
|
"""All unittests for cryptoboxtools
|
||||||
|
"""
|
||||||
|
|
||||||
def testGetAbsoluteDeviceName(self):
|
def test_get_absolute_devicename(self):
|
||||||
func = cbxTools.getAbsoluteDeviceName
|
"""check the get_absolute_devicename function
|
||||||
|
"""
|
||||||
|
func = cbx_tools.get_absolute_devicename
|
||||||
self.assertTrue(func(device) == "/dev/%s" % device)
|
self.assertTrue(func(device) == "/dev/%s" % device)
|
||||||
self.assertTrue(func("loop0") == "/dev/loop0")
|
self.assertTrue(func("loop0") == "/dev/loop0")
|
||||||
self.assertTrue(func(os.path.devnull) == os.path.devnull)
|
self.assertTrue(func(os.path.devnull) == os.path.devnull)
|
||||||
|
|
||||||
|
|
||||||
def testFindMajorMinorOfDevice(self):
|
def test_find_major_minor_of_device(self):
|
||||||
func = cbxTools.findMajorMinorOfDevice
|
"""check the find_major_minor_of_device function
|
||||||
self.assertTrue(func(os.path.devnull) == (1,3))
|
"""
|
||||||
|
func = cbx_tools.find_major_minor_of_device
|
||||||
|
self.assertTrue(func(os.path.devnull) == (1, 3))
|
||||||
self.assertTrue(func("/dev/nothere") is None)
|
self.assertTrue(func("/dev/nothere") is None)
|
||||||
|
|
||||||
|
|
||||||
def testFindMajorMinorDeviceName(self):
|
def test_find_major_minor_device(self):
|
||||||
func = cbxTools.findMajorMinorDeviceName
|
"""check the find_major_minor_device function
|
||||||
dir = os.path.join(os.path.sep, "dev")
|
"""
|
||||||
self.assertTrue(os.path.devnull in func(dir,1,3))
|
func = cbx_tools.find_major_minor_device
|
||||||
self.assertFalse(os.path.devnull in func(dir,2,3))
|
path = os.path.join(os.path.sep, "dev")
|
||||||
self.assertFalse(None in func(dir,17,23))
|
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):
|
def test_is_part_of_blockdevice(self):
|
||||||
func = cbxTools.isPartOfBlockDevice
|
"""check the is_part_of_blockdevice function
|
||||||
|
"""
|
||||||
|
func = cbx_tools.is_part_of_blockdevice
|
||||||
self.assertTrue(func("/dev/%s" % device, "/dev/%s1" % device))
|
self.assertTrue(func("/dev/%s" % device, "/dev/%s1" % device))
|
||||||
self.assertFalse(func("/dev/%s" % device, "/dev/%s" % device))
|
self.assertFalse(func("/dev/%s" % device, "/dev/%s" % device))
|
||||||
self.assertFalse(func("/dev/%s1" % device, "/dev/%s" % device))
|
self.assertFalse(func("/dev/%s1" % device, "/dev/%s" % device))
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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 unittest
|
||||||
import cryptobox.plugins.manage
|
import cryptobox.plugins.manage
|
||||||
|
@ -28,20 +32,21 @@ class CheckForUndefinedTestCases(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
def create_testcases():
|
def create_testcases():
|
||||||
|
"""Create functions that execute unittests for all features.
|
||||||
plugins = cryptobox.plugins.manage.PluginManager(None, "../plugins").getPlugins()
|
"""
|
||||||
|
plugins = cryptobox.plugins.manage.PluginManager(None, "../plugins").get_plugins()
|
||||||
glob_dict = globals()
|
glob_dict = globals()
|
||||||
loc_dict = locals()
|
loc_dict = locals()
|
||||||
for pl in plugins:
|
for plugin in plugins:
|
||||||
test_class = pl.getTestClass()
|
test_class = plugin.get_test_class()
|
||||||
if test_class:
|
if test_class:
|
||||||
## add the testclass to the global dictionary
|
## add the testclass to the global dictionary
|
||||||
glob_dict["unittest" + pl.getName()] = test_class
|
glob_dict["unittest" + plugin.get_name()] = test_class
|
||||||
else:
|
else:
|
||||||
subname = "test_existence_%s" % pl.getName()
|
subname = "test_existence_%s" % plugin.get_name()
|
||||||
def test_existence(self):
|
def test_existence(self):
|
||||||
"""check if the plugin (%s) contains tests""" % pl.getName()
|
"""check if the plugin (%s) contains tests""" % plugin.get_name()
|
||||||
self.fail("no tests defined for plugin: %s" % pl.getName())
|
self.fail("no tests defined for plugin: %s" % plugin.get_name())
|
||||||
## add this function to the class above
|
## add this function to the class above
|
||||||
setattr(CheckForUndefinedTestCases, subname, test_existence)
|
setattr(CheckForUndefinedTestCases, subname, test_existence)
|
||||||
#FIXME: the failure output always contains the same name for all plugins
|
#FIXME: the failure output always contains the same name for all plugins
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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
|
import unittest
|
||||||
|
|
||||||
|
@ -32,28 +38,32 @@ import cryptobox.web.testclass
|
||||||
|
|
||||||
|
|
||||||
class WebServer(cryptobox.web.testclass.WebInterfaceTestClass):
|
class WebServer(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
"""Basic tests for the webserver.
|
||||||
|
"""
|
||||||
|
|
||||||
def test_is_server_running(self):
|
def test_is_server_running(self):
|
||||||
'''the server should run under given name and port'''
|
'''the server should run under given name and port'''
|
||||||
self.register_auth(self.URL)
|
self.register_auth(self.url)
|
||||||
self.cmd.go(self.URL)
|
self.cmd.go(self.url)
|
||||||
self.cmd.find("CBOX-STATUS")
|
self.cmd.find("CBOX-STATUS")
|
||||||
## other URLs must not be checked, as we do not know, if they are valid
|
## other URLs must not be checked, as we do not know, if they are valid
|
||||||
|
|
||||||
|
|
||||||
class BuiltinPages(cryptobox.web.testclass.WebInterfaceTestClass):
|
class BuiltinPages(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
"""Basic test of builtin pages (no features).
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def test_goto_index(self):
|
def test_goto_index(self):
|
||||||
'''display all devices'''
|
'''display all devices'''
|
||||||
self.register_auth(self.URL)
|
self.register_auth(self.url)
|
||||||
self.cmd.go(self.URL)
|
self.cmd.go(self.url)
|
||||||
self.cmd.find("The CryptoBox")
|
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.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.find("Privatnost v vsako vas")
|
||||||
self.cmd.go(self.URL + "?weblang=fr")
|
self.cmd.go(self.url + "?weblang=fr")
|
||||||
self.cmd.find("La CryptoBox")
|
self.cmd.find("La CryptoBox")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""The webinterface of the CryptoBox.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
|
__all__ = [ 'dataset', 'languages', 'sites', 'testclass' ]
|
||||||
|
|
|
@ -18,8 +18,12 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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
|
import os
|
||||||
from cryptobox.core.exceptions import *
|
|
||||||
import cryptobox.core.container as cbxContainer
|
import cryptobox.core.container as cbxContainer
|
||||||
import cryptobox.core.tools as cbxTools
|
import cryptobox.core.tools as cbxTools
|
||||||
|
|
||||||
|
@ -30,20 +34,24 @@ class WebInterfaceDataset(dict):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cbox, prefs, plugins):
|
def __init__(self, cbox, prefs, plugins):
|
||||||
|
super(WebInterfaceDataset, self).__init__()
|
||||||
self.prefs = prefs
|
self.prefs = prefs
|
||||||
self.cbox = cbox
|
self.cbox = cbox
|
||||||
self.__setConfigValues()
|
self.__set_config_values()
|
||||||
self.plugins = plugins
|
self.plugins = plugins
|
||||||
self.setCryptoBoxState()
|
self.set_crypto_box_state()
|
||||||
self.setPluginData()
|
self.set_plugin_data()
|
||||||
self.setContainersState()
|
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 cherrypy
|
||||||
import cryptobox.core.main
|
import cryptobox.core.main
|
||||||
import cryptobox.web.languages
|
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 = self.cbox.prefs["WebSettings"]["Languages"][:]
|
||||||
langs.sort()
|
langs.sort()
|
||||||
for (index, lang) in enumerate(langs):
|
for (index, lang) in enumerate(langs):
|
||||||
|
@ -58,10 +66,11 @@ class WebInterfaceDataset(dict):
|
||||||
try:
|
try:
|
||||||
self["Data.ScriptURL.Prot"] = cherrypy.request.scheme
|
self["Data.ScriptURL.Prot"] = cherrypy.request.scheme
|
||||||
host = cherrypy.request.headers["Host"]
|
host = cherrypy.request.headers["Host"]
|
||||||
self["Data.ScriptURL.Host"] = host.split(":",1)[0]
|
self["Data.ScriptURL.Host"] = host.split(":", 1)[0]
|
||||||
complete_url = "%s://%s" % (self["Data.ScriptURL.Prot"], self["Data.ScriptURL.Host"])
|
complete_url = "%s://%s" % \
|
||||||
|
(self["Data.ScriptURL.Prot"], self["Data.ScriptURL.Host"])
|
||||||
try:
|
try:
|
||||||
port = int(host.split(":",1)[1])
|
port = int(host.split(":", 1)[1])
|
||||||
complete_url += ":%s" % port
|
complete_url += ":%s" % port
|
||||||
except (IndexError, ValueError):
|
except (IndexError, ValueError):
|
||||||
if cherrypy.request.scheme == "http":
|
if cherrypy.request.scheme == "http":
|
||||||
|
@ -70,7 +79,8 @@ class WebInterfaceDataset(dict):
|
||||||
port = 443
|
port = 443
|
||||||
else:
|
else:
|
||||||
## unknown scheme -> port 0
|
## 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
|
port = 0
|
||||||
self["Data.ScriptURL.Port"] = port
|
self["Data.ScriptURL.Port"] = port
|
||||||
## retrieve the relative address of the CGI (or the cherrypy base address)
|
## retrieve the relative address of the CGI (or the cherrypy base address)
|
||||||
|
@ -83,20 +93,25 @@ class WebInterfaceDataset(dict):
|
||||||
self["Data.ScriptURL"] = ""
|
self["Data.ScriptURL"] = ""
|
||||||
|
|
||||||
|
|
||||||
def setCurrentDiskState(self, device):
|
def set_current_disk_state(self, device):
|
||||||
for container in self.cbox.getContainerList():
|
"""Set some hdf values according to the currently active disk.
|
||||||
if container.getDevice() == device:
|
"""
|
||||||
isEncrypted = (container.getType() == cbxContainer.ContainerTypes["luks"]) and 1 or 0
|
for container in self.cbox.get_container_list():
|
||||||
isPlain = (container.getType() == cbxContainer.ContainerTypes["plain"]) and 1 or 0
|
if container.get_device() == device:
|
||||||
isMounted = container.isMounted() and 1 or 0
|
is_encrypted = (container.get_type() == \
|
||||||
self["Data.CurrentDisk.device"] = container.getDevice()
|
cbxContainer.CONTAINERTYPES["luks"]) and 1 or 0
|
||||||
self["Data.CurrentDisk.name"] = container.getName()
|
is_plain = (container.get_type() == \
|
||||||
self["Data.CurrentDisk.encryption"] = isEncrypted
|
cbxContainer.CONTAINERTYPES["plain"]) and 1 or 0
|
||||||
self["Data.CurrentDisk.plaintext"] = isPlain
|
is_mounted = container.is_mounted() and 1 or 0
|
||||||
self["Data.CurrentDisk.active"] = isMounted
|
self["Data.CurrentDisk.device"] = container.get_device()
|
||||||
self["Data.CurrentDisk.size"] = cbxTools.getBlockDeviceSizeHumanly(container.getDevice())
|
self["Data.CurrentDisk.name"] = container.get_name()
|
||||||
if isMounted:
|
self["Data.CurrentDisk.encryption"] = is_encrypted
|
||||||
(size, avail, used) = container.getCapacity()
|
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
|
percent = used / size
|
||||||
self["Data.CurrentDisk.capacity.used"] = used
|
self["Data.CurrentDisk.capacity.used"] = used
|
||||||
self["Data.CurrentDisk.capacity.free"] = avail
|
self["Data.CurrentDisk.capacity.free"] = avail
|
||||||
|
@ -105,51 +120,63 @@ class WebInterfaceDataset(dict):
|
||||||
self["Settings.LinkAttrs.device"] = device
|
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
|
avail_counter = 0
|
||||||
active_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
|
## useful if the container was changed during an action
|
||||||
container.resetObject()
|
container.reset_object()
|
||||||
isEncrypted = (container.getType() == cbxContainer.ContainerTypes["luks"]) and 1 or 0
|
is_encrypted = (container.get_type() == \
|
||||||
isPlain = (container.getType() == cbxContainer.ContainerTypes["plain"]) and 1 or 0
|
cbxContainer.CONTAINERTYPES["luks"]) and 1 or 0
|
||||||
isMounted = container.isMounted() and 1 or 0
|
is_plain = (container.get_type() == \
|
||||||
self["Data.Disks.%d.device" % avail_counter] = container.getDevice()
|
cbxContainer.CONTAINERTYPES["plain"]) and 1 or 0
|
||||||
self["Data.Disks.%d.name" % avail_counter] = container.getName()
|
is_mounted = container.is_mounted() and 1 or 0
|
||||||
self["Data.Disks.%d.encryption" % avail_counter] = isEncrypted
|
self["Data.Disks.%d.device" % avail_counter] = container.get_device()
|
||||||
self["Data.Disks.%d.plaintext" % avail_counter] = isPlain
|
self["Data.Disks.%d.name" % avail_counter] = container.get_name()
|
||||||
self["Data.Disks.%d.active" % avail_counter] = isMounted
|
self["Data.Disks.%d.encryption" % avail_counter] = is_encrypted
|
||||||
self["Data.Disks.%d.size" % avail_counter] = cbxTools.getBlockDeviceSizeHumanly(container.getDevice())
|
self["Data.Disks.%d.plaintext" % avail_counter] = is_plain
|
||||||
if isMounted: active_counter += 1
|
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
|
avail_counter += 1
|
||||||
self["Data.activeDisksCount"] = active_counter
|
self["Data.activeDisksCount"] = active_counter
|
||||||
|
|
||||||
|
|
||||||
def setPluginData(self):
|
def set_plugin_data(self):
|
||||||
for p in self.plugins:
|
"""Set some hdf values according to the available features.
|
||||||
entryName = "Settings.PluginList." + p.getName()
|
"""
|
||||||
|
for plugin in self.plugins:
|
||||||
|
entry_name = "Settings.PluginList." + plugin.get_name()
|
||||||
## first: remove all existing settings of this plugin
|
## first: remove all existing settings of this plugin
|
||||||
for key in self.keys():
|
for key in self.keys():
|
||||||
if key.startswith(entryName): del self[key]
|
if key.startswith(entry_name):
|
||||||
lang_data = p.getLanguageData()
|
del self[key]
|
||||||
self[entryName] = p.getName()
|
lang_data = plugin.get_language_data()
|
||||||
self[entryName + ".Name"] = lang_data.getValue("Name", p.getName())
|
self[entry_name] = plugin.get_name()
|
||||||
self[entryName + ".Link"] = lang_data.getValue("Link", p.getName())
|
self[entry_name + ".Name"] = lang_data.getValue("Name", plugin.get_name())
|
||||||
self[entryName + ".Rank"] = p.getRank()
|
self[entry_name + ".Link"] = lang_data.getValue("Link", plugin.get_name())
|
||||||
self[entryName + ".RequestAuth"] = p.isAuthRequired() and "1" or "0"
|
self[entry_name + ".Rank"] = plugin.get_rank()
|
||||||
for a in p.pluginCapabilities:
|
self[entry_name + ".RequestAuth"] = plugin.is_auth_required() and "1" or "0"
|
||||||
self[entryName + ".Types." + a] = "1"
|
for capy in plugin.plugin_capabilities:
|
||||||
for a in p.getVisibility():
|
self[entry_name + ".Types." + capy] = "1"
|
||||||
self[entryName + ".Visible." + a] = "1"
|
for visi in plugin.get_visibility():
|
||||||
|
self[entry_name + ".Visible." + visi] = "1"
|
||||||
|
|
||||||
|
|
||||||
def __setConfigValues(self):
|
def __set_config_values(self):
|
||||||
self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"])
|
"""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.DocDir"] = os.path.abspath(self.prefs["Locations"]["DocDir"])
|
||||||
self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"]
|
self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"]
|
||||||
self["Settings.Language"] = self.prefs["WebSettings"]["Languages"][0]
|
self["Settings.Language"] = self.prefs["WebSettings"]["Languages"][0]
|
||||||
for num,d in enumerate(self.prefs["Locations"]["PluginDir"]):
|
for (num, dpath) in enumerate(self.prefs["Locations"]["PluginDir"]):
|
||||||
self["Settings.PluginDir.%d" % num] = d
|
self["Settings.PluginDir.%d" % num] = dpath
|
||||||
## store the first directory in this settings variable - backward compatibility
|
## store the first directory in this settings variable - backward compatibility
|
||||||
self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"][0]
|
self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"][0]
|
||||||
self["Settings.SettingsDir"] = self.prefs["Locations"]["SettingsDir"]
|
self["Settings.SettingsDir"] = self.prefs["Locations"]["SettingsDir"]
|
||||||
|
|
|
@ -22,23 +22,28 @@
|
||||||
"""supply information about existing languages
|
"""supply information about existing languages
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
## every language information should contain (name, pluralformat)
|
## every language information should contain (name, pluralformat)
|
||||||
LANGUAGE_INFO = {
|
LANGUAGE_INFO = {
|
||||||
"cs": ('Český', ('3', '(n==1) ? 0 : (n>=2 && n< =4) ? 1 : 2')),
|
"cs": ('Český', ('3', '(n==1) ? 0 : (n>=2 && n< =4) ? 1 : 2')),
|
||||||
"da": ('Dansk', ('2', '(n != 1)')),
|
"da": ('Dansk', ('2', '(n != 1)')),
|
||||||
"de": ('Deutsch', ('2', '(n != 1)')),
|
"de": ('Deutsch', ('2', '(n != 1)')),
|
||||||
"en": ('English', ('2', '(n != 1)')),
|
"en": ('English', ('2', '(n != 1)')),
|
||||||
"es": ('Español', ('2', '(n != 1)')),
|
"es": ('Español', ('2', '(n != 1)')),
|
||||||
"fi": ('Suomi', ('2', '(n != 1)')),
|
"fi": ('Suomi', ('2', '(n != 1)')),
|
||||||
"fr": ('Français', ('2', '(n != 1)')),
|
"fr": ('Français', ('2', '(n != 1)')),
|
||||||
"hu": ('Magyar', ('1', '0')),
|
"hu": ('Magyar', ('1', '0')),
|
||||||
"it": ('Italiano', ('2', '(n != 1)')),
|
"it": ('Italiano', ('2', '(n != 1)')),
|
||||||
"ja": ('日本語', ('1', '0')),
|
"ja": ('日本語', ('1', '0')),
|
||||||
"nl": ('Nederlands', ('2', '(n != 1)')),
|
"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)')),
|
"pl": ('Polski', ('3', '(n==1 ? 0 : n%10>=2 && n%10< =4 '
|
||||||
"pt": ('Português', ('2', '(n != 1)')),
|
+ '&& (n%100<10 || n%100>=20) ? 1 : 2)')),
|
||||||
"ru": ('Русский', ('3', '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 || n%100>=20) ? 1 : 2)')),
|
"pt": ('Português', ('2', '(n != 1)')),
|
||||||
"sl": ('Slovensko', ('4', '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)')),
|
"ru": ('Русский', ('3', '(n%10==1 && n%100!=11 ? 0 : '
|
||||||
"sv": ('Svenska', ('2', '(n != 1)')),
|
+ '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)')),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,103 +17,150 @@
|
||||||
# along with the CryptoBox; if not, write to the Free Software
|
# along with the CryptoBox; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 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.core.main
|
||||||
import cryptobox.web.dataset
|
import cryptobox.web.dataset
|
||||||
import cryptobox.plugins.manage
|
import cryptobox.plugins.manage
|
||||||
from cryptobox.core.exceptions import *
|
import cryptobox.core.exceptions
|
||||||
import re
|
import re
|
||||||
import cherrypy
|
import cherrypy
|
||||||
import types
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import neo_cgi, neo_util, neo_cs
|
import neo_cgi, neo_util, neo_cs
|
||||||
except ImportError:
|
except ImportError:
|
||||||
errorMsg = "Could not import clearsilver module. Try 'apt-get install python-clearsilver'."
|
_ERRMSG = "Could not import clearsilver module. \
|
||||||
self.log.error(errorMsg)
|
Try 'apt-get install python-clearsilver'."
|
||||||
sys.stderr.write(errorMsg)
|
sys.stderr.write(_ERRMSG)
|
||||||
raise ImportError, errorMsg
|
raise ImportError, _ERRMSG
|
||||||
|
|
||||||
|
|
||||||
GETTEXT_DOMAIN = 'cryptobox-server'
|
GETTEXT_DOMAIN = 'cryptobox-server'
|
||||||
|
|
||||||
|
|
||||||
class PluginIconHandler:
|
class PluginIconHandler:
|
||||||
|
"""deliver the icons of available plugins via cherrypy"""
|
||||||
|
|
||||||
def __init__(self, plugins):
|
def __init__(self, plugins):
|
||||||
for plugin in plugins.getPlugins():
|
for plugin in plugins.get_plugins():
|
||||||
if not plugin: continue
|
if not plugin:
|
||||||
plname = plugin.getName()
|
continue
|
||||||
## expose the getIcon function of this plugin
|
plname = plugin.get_name()
|
||||||
setattr(self, plname, plugin.getIcon)
|
## expose the get_icon function of this plugin
|
||||||
|
setattr(self, plname, plugin.get_icon)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WebInterfaceSites:
|
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
|
## this template is used under strange circumstances
|
||||||
defaultTemplate = "empty"
|
defaultTemplate = "empty"
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, conf_file=None):
|
def __init__(self, conf_file=None):
|
||||||
import logging,sys
|
## we should only use variables preceded by "__" to avoid name conflicts
|
||||||
self.cbox = cryptobox.core.main.CryptoBoxProps(conf_file)
|
## when loading features
|
||||||
self.log = logging.getLogger("CryptoBox")
|
self.cbox = cryptobox.core.main.CryptoBox(conf_file)
|
||||||
self.prefs = self.cbox.prefs
|
self.__cached_language_data = None
|
||||||
self.__resetDataset()
|
self.__dataset = None
|
||||||
|
self.icons = None
|
||||||
|
self.__plugin_manager = None
|
||||||
|
self.__reset_dataset()
|
||||||
## store the original http error handler
|
## 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
|
## 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
|
"""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: only at the beginning of an action (to not loose information)
|
||||||
important: for _every_ "site" action (cherrypy is stateful)
|
important: for _every_ "site" action (cherrypy is stateful)
|
||||||
also take care for the plugins, as they also contain datasets
|
also take care for the plugins, as they also contain datasets
|
||||||
"""
|
"""
|
||||||
self.__loadPlugins()
|
self.__load_plugins()
|
||||||
self.dataset = cryptobox.web.dataset.WebInterfaceDataset(self.cbox, self.prefs, self.pluginList.getPlugins())
|
self.__dataset = cryptobox.web.dataset.WebInterfaceDataset(
|
||||||
|
self.cbox, self.cbox.prefs, self.__plugin_manager.get_plugins())
|
||||||
## publish plugin icons
|
## publish plugin icons
|
||||||
self.icons = PluginIconHandler(self.pluginList)
|
self.icons = PluginIconHandler(self.__plugin_manager)
|
||||||
self.icons.exposed = True
|
self.icons.exposed = True
|
||||||
## check, if a configuration partition has become available
|
## check, if a configuration partition has become available
|
||||||
self.cbox.prefs.preparePartition()
|
self.cbox.prefs.prepare_partition()
|
||||||
|
|
||||||
|
|
||||||
def __loadPlugins(self):
|
def __load_plugins(self):
|
||||||
self.pluginList = cryptobox.plugins.manage.PluginManager(self.cbox, self.prefs["Locations"]["PluginDir"], self)
|
"""reinitialize the list of available plugins
|
||||||
for plugin in self.pluginList.getPlugins():
|
|
||||||
if not plugin: continue
|
this includes the following:
|
||||||
plname = plugin.getName()
|
- reload all plugins and check their state (disabled or not)
|
||||||
if plugin.isEnabled():
|
- reinitilize the datasets of all plugins
|
||||||
self.cbox.log.info("Plugin '%s' loaded" % plname)
|
"""
|
||||||
## this should be the "easiest" way to expose all plugins as URLs
|
self.__plugin_manager = cryptobox.plugins.manage.PluginManager(
|
||||||
setattr(self, plname, self.return_plugin_action(plugin))
|
self.cbox, self.cbox.prefs["Locations"]["PluginDir"], self)
|
||||||
setattr(getattr(self, plname), "exposed", True)
|
for plugin in self.__plugin_manager.get_plugins():
|
||||||
# TODO: check, if this really works - for now the "stream_response" feature seems to be broken
|
if not plugin:
|
||||||
#setattr(getattr(self, plname), "stream_respones", True)
|
continue
|
||||||
else:
|
plname = plugin.get_name()
|
||||||
self.cbox.log.info("Plugin '%s' is disabled" % plname)
|
## check if there are name conflicts: e.g. a local variable has the
|
||||||
## remove the plugin, if it was active before
|
## same name as a plugin to be loaded -> skip these plugins
|
||||||
setattr(self, plname, None)
|
## 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
|
## sub pages requiring authentication may not be defined above
|
||||||
## it has to be defined before any page definition requiring authentification
|
def __request_auth(self=None):
|
||||||
def __requestAuth(self=None):
|
""" this is a function decorator to check authentication
|
||||||
|
"""
|
||||||
def check_credentials(site):
|
def check_credentials(site):
|
||||||
|
""" see description of _inner_wrapper - please simplify this!
|
||||||
|
"""
|
||||||
def _inner_wrapper(self, *args, **kargs):
|
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
|
import base64
|
||||||
## define a "non-allowed" function
|
## define a "non-allowed" function
|
||||||
user, password = None, None
|
user, password = None, None
|
||||||
try:
|
try:
|
||||||
resp = cherrypy.request.headers["Authorization"][6:] # ignore "Basic "
|
## ignore the "Basic " (first six letters) part
|
||||||
(user, password) = base64.b64decode(resp).split(":",1)
|
resp = cherrypy.request.headers["Authorization"][6:]
|
||||||
|
(user, password) = base64.b64decode(resp).split(":", 1)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
## no "authorization" header was sent
|
## no "authorization" header was sent
|
||||||
pass
|
pass
|
||||||
|
@ -123,18 +170,20 @@ class WebInterfaceSites:
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
## no cherrypy response header defined
|
## no cherrypy response header defined
|
||||||
pass
|
pass
|
||||||
authDict = self.cbox.prefs.userDB["admins"]
|
auth_dict = self.cbox.prefs.user_db["admins"]
|
||||||
if user in authDict.keys():
|
if user in auth_dict.keys():
|
||||||
if self.cbox.prefs.userDB.getDigest(password) == authDict[user]:
|
if self.cbox.prefs.user_db.get_digest(password) == auth_dict[user]:
|
||||||
## ok: return the choosen page
|
## ok: return the choosen page
|
||||||
self.cbox.log.info("access granted for: %s" % user)
|
self.cbox.log.info("access granted for: %s" % user)
|
||||||
return site(self, *args, **kargs)
|
return site(self, *args, **kargs)
|
||||||
else:
|
else:
|
||||||
self.cbox.log.info("wrong password supplied for: %s" % user)
|
self.cbox.log.info(
|
||||||
|
"wrong password supplied for: %s" % user)
|
||||||
else:
|
else:
|
||||||
self.cbox.log.info("unknown user: %s" % str(user))
|
self.cbox.log.info("unknown user: %s" % str(user))
|
||||||
## wrong credentials: return "access denied"
|
## 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
|
cherrypy.response.status = 401
|
||||||
return self.__render("access_denied")
|
return self.__render("access_denied")
|
||||||
return _inner_wrapper
|
return _inner_wrapper
|
||||||
|
@ -147,15 +196,18 @@ class WebInterfaceSites:
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def index(self, weblang=""):
|
def index(self, weblang=""):
|
||||||
self.__resetDataset()
|
"""the default page on startup - we show the list of available disks
|
||||||
self.__setWebLang(weblang)
|
"""
|
||||||
self.__checkEnvironment()
|
self.__reset_dataset()
|
||||||
|
self.__set_web_lang(weblang)
|
||||||
|
self.__check_environment()
|
||||||
## do not forget the language!
|
## do not forget the language!
|
||||||
param_dict = {"weblang":weblang}
|
param_dict = {"weblang":weblang}
|
||||||
## render "disks" plugin by default
|
## 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
|
"""handle http errors gracefully
|
||||||
|
|
||||||
404 - not found errors: ignored if url is below /cryptobox-misc/
|
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
|
500 - runtime errors: return "ok" exit code and show a polite excuse
|
||||||
others: are there any other possible http errors?
|
others: are there any other possible http errors?
|
||||||
"""
|
"""
|
||||||
import traceback, sys
|
import traceback
|
||||||
## we ignore uninteresting not-found errors
|
## 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.startswith("/cryptobox-misc/") or \
|
||||||
cherrypy.request.path in ['/robots.txt','/favicon.ico']):
|
cherrypy.request.path in ['/robots.txt','/favicon.ico']):
|
||||||
cherrypy.response.status = errorCode
|
cherrypy.response.status = error_code
|
||||||
return
|
return
|
||||||
## an invalid action was requested
|
## an invalid action was requested
|
||||||
if errorCode == 404:
|
if error_code == 404:
|
||||||
## we send a not-found error (with the usual interface)
|
## we send a not-found error (with the usual interface)
|
||||||
cherrypy.response.status = errorCode
|
cherrypy.response.status = error_code
|
||||||
self.dataset["Data.Warning"] = "InvalidAction"
|
self.__dataset["Data.Warning"] = "InvalidAction"
|
||||||
cherrypy.response.body = self.__render("empty")
|
cherrypy.response.body = self.__render("empty")
|
||||||
return
|
return
|
||||||
## are there still bugs in the code?
|
## are there still bugs in the code?
|
||||||
if errorCode == 500:
|
if error_code == 500:
|
||||||
## we fix the error code (200 is "OK")
|
## we fix the error code (200 is "OK")
|
||||||
cherrypy.response.status = 200
|
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
|
## add a traceback and exception information to the lo
|
||||||
for a in traceback.format_exception(*sys.exc_info()):
|
for log_line in traceback.format_exception(*sys.exc_info()):
|
||||||
self.cbox.log.error("\t%s" % a)
|
self.cbox.log.error("\t%s" % log_line)
|
||||||
self.dataset["Data.Warning"] = "RuntimeError"
|
self.__dataset["Data.Warning"] = "RuntimeError"
|
||||||
cherrypy.response.body = self.__render("empty")
|
cherrypy.response.body = self.__render("empty")
|
||||||
return
|
return
|
||||||
## unknown error type
|
## unknown error type
|
||||||
cherrypy.response.status = errorCode
|
cherrypy.response.status = error_code
|
||||||
self.cbox.log.warn("HTTP-ERROR[%d] - an unknown error occoured: %s" % (errorCode, message))
|
self.cbox.log.warn("HTTP-ERROR[%d] - an unknown error occoured: %s" \
|
||||||
|
% (error_code, message))
|
||||||
cherrypy.response.body = self.__render("empty")
|
cherrypy.response.body = self.__render("empty")
|
||||||
|
|
||||||
|
|
||||||
def return_plugin_action(self, plugin):
|
def return_plugin_action(self, plugin):
|
||||||
|
""" returns a function that is suitable for handling a cherrypy
|
||||||
|
page request
|
||||||
|
"""
|
||||||
def handler(self, **args):
|
def handler(self, **args):
|
||||||
self.__resetDataset()
|
"""this function handles a cherrypy page request
|
||||||
self.__checkEnvironment()
|
"""
|
||||||
args_orig = dict(args)
|
self.__reset_dataset()
|
||||||
|
self.__check_environment()
|
||||||
## set web interface language
|
## set web interface language
|
||||||
try:
|
try:
|
||||||
self.__setWebLang(args["weblang"])
|
self.__set_web_lang(args["weblang"])
|
||||||
del args["weblang"]
|
del args["weblang"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.__setWebLang("")
|
self.__set_web_lang("")
|
||||||
## we always read the "device" setting - otherwise volume-plugin links
|
## we always read the "device" setting - otherwise volume-plugin
|
||||||
## would not work easily (see "volume_props" linking to "volume_format_fs")
|
## links would not work easily
|
||||||
|
## (see "volume_props" linking to "volume_format_fs")
|
||||||
## it will get ignored for non-volume plugins
|
## it will get ignored for non-volume plugins
|
||||||
try:
|
try:
|
||||||
plugin.device = None
|
plugin.device = None
|
||||||
if self.__setDevice(args["device"]):
|
if self.__set_device(args["device"]):
|
||||||
plugin.device = args["device"]
|
plugin.device = args["device"]
|
||||||
del args["device"]
|
del args["device"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
plugin.device = None
|
||||||
## check the device argument of volume plugins
|
## 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
|
## initialize the dataset of the selected device if necessary
|
||||||
if plugin.device:
|
if plugin.device:
|
||||||
self.dataset.setCurrentDiskState(plugin.device)
|
self.__dataset.set_current_disk_state(plugin.device)
|
||||||
else:
|
else:
|
||||||
## invalid (or missing) device setting
|
## invalid (or missing) device setting
|
||||||
return self.__render(self.defaultTemplate)
|
return self.__render(self.defaultTemplate)
|
||||||
## check if there is a "redirect" setting - this will override the return
|
## check if there is a "redirect" setting - this will override
|
||||||
## value of the doAction function (e.g. useful for umount-before-format)
|
## the return value of the do_action function
|
||||||
|
## (e.g. useful for umount-before-format)
|
||||||
try:
|
try:
|
||||||
if args["redirect"]:
|
if args["redirect"]:
|
||||||
override_nextTemplate = { "plugin":args["redirect"] }
|
override_next_template = { "plugin":args["redirect"] }
|
||||||
if "volume" in plugin.pluginCapabilities:
|
if "volume" in plugin.plugin_capabilities:
|
||||||
override_nextTemplate["values"] = {"device":plugin.device}
|
override_next_template["values"] = {"device":plugin.device}
|
||||||
del args["redirect"]
|
del args["redirect"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
override_nextTemplate = None
|
override_next_template = None
|
||||||
## check for information to be kept after the last call
|
## check for information to be kept after the last call
|
||||||
try:
|
try:
|
||||||
keep_values = args["message_keep"]
|
keep_values = args["message_keep"]
|
||||||
del args["message_keep"]
|
del args["message_keep"]
|
||||||
for key, value in keep_values["dataset"].items():
|
for key, value in keep_values["dataset"].items():
|
||||||
self.dataset[key] = value
|
self.__dataset[key] = value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
keep_values = None
|
keep_values = None
|
||||||
## call the plugin handler
|
## call the plugin handler
|
||||||
nextTemplate = plugin.doAction(**args)
|
next_template = plugin.do_action(**args)
|
||||||
## for 'volume' plugins: reread the dataset of the current disk
|
## for 'volume' plugins: reread the dataset of the current disk
|
||||||
## additionally: set the default template for plugins
|
## 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?
|
## maybe the state of the current volume was changed?
|
||||||
self.dataset.setCurrentDiskState(plugin.device)
|
self.__dataset.set_current_disk_state(plugin.device)
|
||||||
if not nextTemplate: nextTemplate = { "plugin":"volume_mount", "values":{"device":plugin.device}}
|
if not next_template:
|
||||||
|
next_template = { "plugin":"volume_mount",
|
||||||
|
"values":{"device":plugin.device}}
|
||||||
else:
|
else:
|
||||||
## maybe a non-volume plugin changed some plugin settings (e.g. plugin_manager)
|
## some non-volume plugins change the internal state of other
|
||||||
self.dataset.setPluginData()
|
## plugins - e.g.: plugin_manager
|
||||||
## update the container hdf-dataset (maybe a plugin changed the state of a container)
|
self.__dataset.set_plugin_data()
|
||||||
self.dataset.setContainersState()
|
## 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
|
## 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?
|
## was a redirect requested?
|
||||||
if override_nextTemplate:
|
if override_next_template:
|
||||||
nextTemplate = override_nextTemplate
|
next_template = override_next_template
|
||||||
## if another plugins was choosen for 'nextTemplate', then do it!
|
## if another plugins was choosen for 'next_template', then do it!
|
||||||
if isinstance(nextTemplate, types.DictType) \
|
if isinstance(next_template, dict) \
|
||||||
and "plugin" in nextTemplate.keys() \
|
and "plugin" in next_template.keys() \
|
||||||
and "values" in nextTemplate.keys() \
|
and "values" in next_template.keys() \
|
||||||
and self.pluginList.getPlugin(nextTemplate["plugin"]):
|
and self.__plugin_manager.get_plugin(next_template["plugin"]):
|
||||||
valueDict = dict(nextTemplate["values"])
|
value_dict = dict(next_template["values"])
|
||||||
## force the current weblang attribute - otherwise it gets lost
|
## 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
|
## check for warnings/success messages, that should be kept
|
||||||
if "Data.Warning" in plugin.hdf.keys() \
|
if "Data.Success" in plugin.hdf.keys() \
|
||||||
or "Data.Success" in plugin.hdf.keys():
|
or "Data.Warning" in plugin.hdf.keys():
|
||||||
self.cbox.log.info("keep warning message")
|
value_dict["message_keep"] = {"plugin":plugin, "dataset":{}}
|
||||||
valueDict["message_keep"] = { "plugin":plugin, "dataset":{}}
|
|
||||||
for keep_key in ("Data.Warning", "Data.Success"):
|
for keep_key in ("Data.Warning", "Data.Success"):
|
||||||
if keep_key in plugin.hdf.keys():
|
if keep_key in plugin.hdf.keys():
|
||||||
valueDict["message_keep"]["dataset"][keep_key] = plugin.hdf[keep_key]
|
self.cbox.log.info("keeping message: %s" % \
|
||||||
new_plugin = self.pluginList.getPlugin(nextTemplate["plugin"])
|
plugin.hdf[keep_key])
|
||||||
return self.return_plugin_action(new_plugin)(**valueDict)
|
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
|
## save the currently active plugin name
|
||||||
self.dataset["Data.ActivePlugin"] = plugin.getName()
|
self.__dataset["Data.ActivePlugin"] = plugin.get_name()
|
||||||
return self.__render(nextTemplate, plugin)
|
return self.__render(next_template, plugin)
|
||||||
## apply authentication?
|
## apply authentication?
|
||||||
if plugin.isAuthRequired():
|
if plugin.is_auth_required():
|
||||||
return lambda **args: self.__requestAuth()(handler)(self, **args)
|
return lambda **args: self.__request_auth()(handler)(self, **args)
|
||||||
else:
|
else:
|
||||||
return lambda **args: handler(self, **args)
|
return lambda **args: handler(self, **args)
|
||||||
|
|
||||||
|
|
||||||
## test authentication
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@__requestAuth
|
@__request_auth
|
||||||
def test(self, weblang=""):
|
def test(self, weblang=""):
|
||||||
self.__resetDataset()
|
"""test authentication - this function may be safely removed
|
||||||
self.__setWebLang(weblang)
|
"""
|
||||||
self.__checkEnvironment()
|
self.__reset_dataset()
|
||||||
|
self.__set_web_lang(weblang)
|
||||||
|
self.__check_environment()
|
||||||
return "test passed"
|
return "test passed"
|
||||||
|
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def test_stream(self):
|
def test_stream(self):
|
||||||
"""just for testing purposes - to check if the "stream_response" feature
|
"""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
|
import time
|
||||||
yield "<html><head><title>neu</title></head><body><p><ul>"
|
yield "<html><head><title>neu</title></head><body><p><ul>"
|
||||||
for a in range(10):
|
for num in range(10):
|
||||||
yield "<li>yes: %d - %s</li>" % (a, str(time.time()))
|
yield "<li>yes: %d - %s</li>" % (num, str(time.time()))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
yield "</ul></p></html>"
|
yield "</ul></p></html>"
|
||||||
|
|
||||||
|
@ -312,69 +380,77 @@ class WebInterfaceSites:
|
||||||
|
|
||||||
##################### input checker ##########################
|
##################### input checker ##########################
|
||||||
|
|
||||||
def __checkEnvironment(self):
|
def __check_environment(self):
|
||||||
"""here we should place all interesting checks to inform the user of problems
|
"""inform the user of suspicious environmental problems
|
||||||
|
|
||||||
examples are: non-https, readonly-config, ...
|
examples are: non-https, readonly-config, ...
|
||||||
"""
|
"""
|
||||||
## this check is done _after_ "resetDataSet" -> a possible config partition was
|
## this check is done _after_ "reset_dataset" -> if there is
|
||||||
## loaded before
|
## a config partition, then it was loaded before
|
||||||
if self.cbox.prefs.requiresPartition() and not self.cbox.prefs.getActivePartition():
|
if self.cbox.prefs.requires_partition() \
|
||||||
self.dataset["Data.EnvironmentWarning"] = "ReadOnlyConfig"
|
and not self.cbox.prefs.get_active_partition():
|
||||||
# TODO: turn this on soon (add "not") - for now it is annoying
|
self.__dataset["Data.EnvironmentWarning"] = "ReadOnlyConfig"
|
||||||
if self.__checkHTTPS():
|
#TODO: turn this on soon (add "not") - for now it is annoying
|
||||||
self.dataset["Data.EnvironmentWarning"] = "NoSSL"
|
if self.__check_https():
|
||||||
|
self.__dataset["Data.EnvironmentWarning"] = "NoSSL"
|
||||||
|
|
||||||
|
|
||||||
def __checkHTTPS(self):
|
def __check_https(self):
|
||||||
## check the request scheme
|
"""check the request scheme
|
||||||
if cherrypy.request.scheme == "https": return True
|
"""
|
||||||
|
if cherrypy.request.scheme == "https":
|
||||||
|
return True
|
||||||
## check an environment setting - this is quite common behind proxies
|
## check an environment setting - this is quite common behind proxies
|
||||||
try:
|
try:
|
||||||
if os.environ["HTTPS"]: return True
|
if os.environ["HTTPS"]:
|
||||||
|
return True
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
## check http header for ssl information
|
||||||
## check http header TODO (check pound for the name)
|
#TODO: (check pound for the name)
|
||||||
try:
|
try:
|
||||||
if cherrypy.request.headers["TODO"]: return True
|
if cherrypy.request.headers["XXX"]:
|
||||||
except KeyError:
|
return True
|
||||||
pass
|
except KeyError:
|
||||||
## the connection seems to be unencrypted
|
## the connection seems to be unencrypted
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __setWebLang(self, value):
|
def __set_web_lang(self, value):
|
||||||
"""set the preferred priority of languages according to the following order:
|
"""set the preferred priority of languages according to this order:
|
||||||
1. language selected via web interface
|
1. language selected via web interface
|
||||||
2. preferred browser language setting
|
2. preferred browser language setting
|
||||||
3. languages defined in the config file
|
3. languages defined in the config file
|
||||||
"""
|
"""
|
||||||
## start with the configured language order
|
## start with the configured language order
|
||||||
langOrder = self.cbox.prefs["WebSettings"]["Languages"][:]
|
lang_order = self.cbox.prefs["WebSettings"]["Languages"][:]
|
||||||
self.cbox.log.debug("updating language preferences (default: %s)" % str(langOrder))
|
self.cbox.log.debug(
|
||||||
|
"updating language preferences (default: %s)" % str(lang_order))
|
||||||
## put the preferred browser language in front
|
## put the preferred browser language in front
|
||||||
guess = self.__getPreferredBrowserLanguage(langOrder)
|
guess = self.__get_browser_language(lang_order)
|
||||||
if guess:
|
if guess:
|
||||||
langOrder.remove(guess)
|
lang_order.remove(guess)
|
||||||
langOrder.insert(0,guess)
|
lang_order.insert(0, guess)
|
||||||
self.cbox.log.debug("raised priority of preferred browser language: %s" % guess)
|
self.cbox.log.debug(
|
||||||
|
"raised priority of preferred browser language: %s" % guess)
|
||||||
## is the chosen language (via web interface) valid? - put it in front
|
## is the chosen language (via web interface) valid? - put it in front
|
||||||
if value and (value in langOrder) and (not re.search(u'\W',value)):
|
if value and (value in lang_order) and (not re.search(u'\W', value)):
|
||||||
langOrder.remove(value)
|
lang_order.remove(value)
|
||||||
langOrder.insert(0,value)
|
lang_order.insert(0, value)
|
||||||
self.cbox.log.debug("raised priority of selected language: %s" % value)
|
self.cbox.log.debug(
|
||||||
|
"raised priority of selected language: %s" % value)
|
||||||
elif value:
|
elif value:
|
||||||
self.cbox.log.info("invalid language selected: %s" % value)
|
self.cbox.log.info("invalid language selected: %s" % value)
|
||||||
## store current language setting
|
## store current language setting
|
||||||
self.cbox.log.debug("current language preference: %s" % str(langOrder))
|
self.cbox.log.debug(
|
||||||
self.langOrder = langOrder
|
"current language preference: %s" % str(lang_order))
|
||||||
self.dataset["Settings.Language"] = langOrder[0]
|
self.lang_order = lang_order
|
||||||
self.dataset["Settings.LinkAttrs.weblang"] = langOrder[0]
|
self.__dataset["Settings.Language"] = lang_order[0]
|
||||||
|
self.__dataset["Settings.LinkAttrs.weblang"] = lang_order[0]
|
||||||
|
|
||||||
|
|
||||||
def __getPreferredBrowserLanguage(self, availLangs):
|
def __get_browser_language(self, avail_langs):
|
||||||
"""guess the preferred language of the user (as sent by the browser)
|
"""guess the preferred language of the user (as sent by the browser)
|
||||||
take the first language, that is part of 'availLangs'
|
take the first language, that is part of 'avail_langs'
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
pref_lang_header = cherrypy.request.headers["Accept-Language"]
|
pref_lang_header = cherrypy.request.headers["Accept-Language"]
|
||||||
|
@ -382,56 +458,64 @@ class WebInterfaceSites:
|
||||||
## no language header was specified
|
## no language header was specified
|
||||||
return None
|
return None
|
||||||
## this could be a typical 'Accept-Language' header:
|
## this could be a typical 'Accept-Language' header:
|
||||||
## de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
|
## de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
|
||||||
regex = re.compile(u"\w+(-\w+)?(;q=[\d\.]+)?$")
|
regex = re.compile(u"\w+(-\w+)?(;q=[\d\.]+)?$")
|
||||||
pref_langs = [e.split(";",1)[0]
|
pref_langs = [e.split(";", 1)[0]
|
||||||
for e in pref_lang_header.split(",")
|
for e in pref_lang_header.split(",")
|
||||||
if regex.match(e)]
|
if regex.match(e)]
|
||||||
## is one of these preferred languages available?
|
## is one of these preferred languages available?
|
||||||
for lang in pref_langs:
|
for lang in pref_langs:
|
||||||
if lang in availLangs: return lang
|
if lang in avail_langs:
|
||||||
|
return lang
|
||||||
## we try to be nice: also look for "de" if "de-de" was specified ...
|
## we try to be nice: also look for "de" if "de-de" was specified ...
|
||||||
for lang in pref_langs:
|
for lang in pref_langs:
|
||||||
## use only the first part of the language
|
## use only the first part of the language
|
||||||
short_lang = lang.split("-",1)[0]
|
short_lang = lang.split("-", 1)[0]
|
||||||
if short_lang in availLangs: return short_lang
|
if short_lang in avail_langs:
|
||||||
|
return short_lang
|
||||||
## we give up
|
## we give up
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def __setDevice(self, device):
|
def __set_device(self, device):
|
||||||
"""check a device name that was chosen via the web interface
|
"""check a device name that was chosen via the web interface
|
||||||
issue a warning if the device is invalid"""
|
issue a warning if the device is invalid"""
|
||||||
if device and re.match(u'[\w /\-]+$', device) and self.cbox.getContainer(device):
|
if device and re.match(u'[\w /\-]+$', device) \
|
||||||
self.log.debug("select device: %s" % device)
|
and self.cbox.get_container(device):
|
||||||
|
self.cbox.log.debug("select device: %s" % device)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.log.warn("invalid device: %s" % device)
|
self.cbox.log.warn("invalid device: %s" % device)
|
||||||
self.dataset["Data.Warning"] = "InvalidDevice"
|
self.__dataset["Data.Warning"] = "InvalidDevice"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __substituteGettext(self, languages, textDomain, hdf):
|
def __substitute_gettext(self, languages, text_domain, hdf):
|
||||||
"""substitute all texts in the hdf dataset with their translated
|
"""substitute all texts in the hdf dataset with their translated
|
||||||
counterparts as returned by gettext
|
counterparts as returned by gettext
|
||||||
"""
|
"""
|
||||||
import gettext
|
import gettext
|
||||||
try:
|
try:
|
||||||
translator = gettext.translation(textDomain, languages=languages)
|
translator = gettext.translation(text_domain, languages=languages)
|
||||||
except IOError, errMsg:
|
except IOError, err_msg:
|
||||||
## no translation found
|
## no translation found
|
||||||
self.cbox.log.warn("unable to load language file: %s" % errMsg)
|
self.cbox.log.warn("unable to load language file: %s" % err_msg)
|
||||||
return hdf
|
return hdf
|
||||||
def walk_tree(hdf_node):
|
def walk_tree(hdf_node):
|
||||||
|
"""iterate through all nodes"""
|
||||||
def translate_node(node):
|
def translate_node(node):
|
||||||
for (key,value) in node.attrs():
|
"""turn one single string into unicode"""
|
||||||
if key == 'LINK': return
|
for (key, value) in node.attrs():
|
||||||
|
if key == "LINK":
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
node.setValue("",translator.ugettext(node.value()))
|
node.setValue("", translator.ugettext(node.value()))
|
||||||
except UnicodeEncodeError, errMsg:
|
except UnicodeEncodeError, err_msg:
|
||||||
self.cbox.log.info("Failed unicode encoding for gettext: %s - %s" % (node.value(),errMsg))
|
self.cbox.log.info(
|
||||||
|
"Failed unicode encoding for gettext: %s - %s" \
|
||||||
|
% (node.value(),err_msg))
|
||||||
## fallback to default encoding
|
## fallback to default encoding
|
||||||
node.setValue("",translator.gettext(node.value()))
|
node.setValue("", translator.gettext(node.value()))
|
||||||
while hdf_node:
|
while hdf_node:
|
||||||
translate_node(hdf_node)
|
translate_node(hdf_node)
|
||||||
walk_tree(hdf_node.child())
|
walk_tree(hdf_node.child())
|
||||||
|
@ -439,86 +523,95 @@ class WebInterfaceSites:
|
||||||
walk_tree(hdf)
|
walk_tree(hdf)
|
||||||
|
|
||||||
|
|
||||||
def __getLanguageData(self):
|
def __get_language_data(self):
|
||||||
"""return the hdf dataset of the main interface and all plugins
|
"""return the hdf dataset of the main interface and all plugins
|
||||||
translations are done according to self.langOrder
|
translations are done according to self.lang_order
|
||||||
"""
|
"""
|
||||||
## check if the language setting was changed - use cached data if possible
|
## check if the language setting has changed - use cache if possible
|
||||||
try:
|
if self.__cached_language_data and \
|
||||||
if self.cachedLanguageData["langOrder"] == self.langOrder:
|
self.__cached_language_data["lang_order"] == self.lang_order:
|
||||||
self.cbox.log.debug("using cached language data: %s" % str(self.langOrder))
|
self.cbox.log.debug(
|
||||||
return self.cachedLanguageData["hdf"]
|
"using cached language data: %s" % str(self.lang_order))
|
||||||
except AttributeError:
|
return self.__cached_language_data["hdf"]
|
||||||
pass
|
|
||||||
self.cbox.log.debug("generating language data")
|
self.cbox.log.debug("generating language data")
|
||||||
hdf = neo_util.HDF()
|
hdf = neo_util.HDF()
|
||||||
hdf.readFile(os.path.join(self.prefs["Locations"]["TemplateDir"],"language.hdf"))
|
hdf.readFile(os.path.join(
|
||||||
self.__substituteGettext(self.langOrder, GETTEXT_DOMAIN, hdf)
|
self.cbox.prefs["Locations"]["TemplateDir"],"language.hdf"))
|
||||||
|
self.__substitute_gettext(self.lang_order, GETTEXT_DOMAIN, hdf)
|
||||||
## load the language data of all plugins
|
## load the language data of all plugins
|
||||||
for p in self.pluginList.getPlugins():
|
for plugin in self.__plugin_manager.get_plugins():
|
||||||
pl_lang = p.getLanguageData()
|
pl_lang = plugin.get_language_data()
|
||||||
self.__substituteGettext(self.langOrder, "%s-feature-%s" % (GETTEXT_DOMAIN, p.getName()), pl_lang)
|
self.__substitute_gettext(self.lang_order, "%s-feature-%s" % \
|
||||||
hdf.copy("Plugins.%s" % p.getName(), pl_lang)
|
(GETTEXT_DOMAIN, plugin.get_name()), pl_lang)
|
||||||
self.cbox.log.debug("language data for plugin loaded: %s" % p.getName())
|
hdf.copy("Plugins.%s" % plugin.get_name(), pl_lang)
|
||||||
|
self.cbox.log.debug(
|
||||||
|
"language data for plugin loaded: %s" % plugin.get_name())
|
||||||
## cache result for later retrieval
|
## cache result for later retrieval
|
||||||
self.cachedLanguageData = {"langOrder": self.langOrder, "hdf": hdf}
|
self.__cached_language_data = \
|
||||||
|
{"lang_order": self.lang_order, "hdf": hdf}
|
||||||
return hdf
|
return hdf
|
||||||
|
|
||||||
|
|
||||||
def __render(self, renderInfo, plugin=None):
|
def __render(self, render_info, plugin=None):
|
||||||
'''renders from clearsilver templates and returns the resulting html
|
'''renders from clearsilver templates and returns the resulting html
|
||||||
'''
|
'''
|
||||||
## is renderInfo a string (filename of the template) or a dictionary?
|
## is render_info a string (filename of the template) or a dictionary?
|
||||||
if type(renderInfo) == types.DictType:
|
if isinstance(render_info, dict):
|
||||||
template = renderInfo["template"]
|
template = render_info["template"]
|
||||||
if renderInfo.has_key("generator"):
|
if render_info.has_key("generator"):
|
||||||
generator = renderInfo["generator"]
|
generator = render_info["generator"]
|
||||||
else:
|
else:
|
||||||
generator = None
|
generator = None
|
||||||
else:
|
else:
|
||||||
(template, generator) = (renderInfo, None)
|
(template, generator) = (render_info, None)
|
||||||
|
|
||||||
## load the language data
|
## load the language data
|
||||||
hdf = neo_util.HDF()
|
hdf = neo_util.HDF()
|
||||||
hdf.copy("Lang", self.__getLanguageData())
|
hdf.copy("Lang", self.__get_language_data())
|
||||||
|
|
||||||
## first: assume, that the template file is in the global template directory
|
## first: assume, that the template file is in the global
|
||||||
self.dataset["Settings.TemplateFile"] = os.path.abspath(os.path.join(self.prefs["Locations"]["TemplateDir"], template + ".cs"))
|
## template directory
|
||||||
|
self.__dataset["Settings.TemplateFile"] = os.path.abspath(os.path.join(
|
||||||
|
self.cbox.prefs["Locations"]["TemplateDir"],
|
||||||
|
template + ".cs"))
|
||||||
|
|
||||||
if plugin:
|
if plugin:
|
||||||
## check, if the plugin provides the template file -> overriding
|
## check, if the plugin provides the template file -> overriding
|
||||||
plugin_cs_file = plugin.getTemplateFileName(template)
|
plugin_cs_file = plugin.get_template_filename(template)
|
||||||
if plugin_cs_file:
|
if plugin_cs_file:
|
||||||
self.dataset["Settings.TemplateFile"] = plugin_cs_file
|
self.__dataset["Settings.TemplateFile"] = plugin_cs_file
|
||||||
|
|
||||||
## add the current state of the plugins to the hdf dataset
|
## add the current state of the plugins to the hdf dataset
|
||||||
self.dataset["Data.Status.Plugins.%s" % plugin.getName()] = plugin.getStatus()
|
self.__dataset["Data.Status.Plugins.%s" % plugin.get_name()] = \
|
||||||
|
plugin.get_status()
|
||||||
## load the dataset of the plugin
|
## load the dataset of the plugin
|
||||||
plugin.loadDataSet(hdf)
|
plugin.load_dataset(hdf)
|
||||||
|
|
||||||
self.log.info("rendering site: " + template)
|
self.cbox.log.info("rendering site: " + template)
|
||||||
|
|
||||||
cs_path = os.path.abspath(os.path.join(self.prefs["Locations"]["TemplateDir"], "main.cs"))
|
cs_path = os.path.abspath(os.path.join(
|
||||||
|
self.cbox.prefs["Locations"]["TemplateDir"], "main.cs"))
|
||||||
if not os.access(cs_path, os.R_OK):
|
if not os.access(cs_path, os.R_OK):
|
||||||
log.error("Couldn't read clearsilver file: %s" % cs_path)
|
self.cbox.log.error(
|
||||||
|
"Couldn't read clearsilver file: %s" % cs_path)
|
||||||
yield "Couldn't read clearsilver file: %s" % cs_path
|
yield "Couldn't read clearsilver file: %s" % cs_path
|
||||||
return
|
return
|
||||||
|
|
||||||
self.log.debug(self.dataset)
|
self.cbox.log.debug(self.__dataset)
|
||||||
for key in self.dataset.keys():
|
for key in self.__dataset.keys():
|
||||||
hdf.setValue(key,str(self.dataset[key]))
|
hdf.setValue(key, str(self.__dataset[key]))
|
||||||
cs = neo_cs.CS(hdf)
|
cs_data = neo_cs.CS(hdf)
|
||||||
cs.parseFile(cs_path)
|
cs_data.parseFile(cs_path)
|
||||||
|
|
||||||
## is there a generator containing additional information?
|
## is there a generator containing additional information?
|
||||||
if not generator:
|
if not generator:
|
||||||
## all content in one flush
|
## all content in one flush
|
||||||
yield cs.render()
|
yield cs_data.render()
|
||||||
else:
|
else:
|
||||||
content_generate = generator()
|
content_generate = generator()
|
||||||
dummy_line = """<!-- CONTENT_DUMMY -->"""
|
dummy_line = """<!-- CONTENT_DUMMY -->"""
|
||||||
## now we do it linewise - checking for the content marker
|
## now we do it linewise - checking for the content marker
|
||||||
for line in cs.render().splitlines():
|
for line in cs_data.render().splitlines():
|
||||||
if line.find(dummy_line) != -1:
|
if line.find(dummy_line) != -1:
|
||||||
yield line.replace(dummy_line, content_generate.next())
|
yield line.replace(dummy_line, content_generate.next())
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -24,6 +24,8 @@ super class of all web interface unittests for the cryptobox
|
||||||
just inherit this class and add some test functions
|
just inherit this class and add some test functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import twill
|
import twill
|
||||||
import cherrypy
|
import cherrypy
|
||||||
|
@ -34,10 +36,12 @@ import os
|
||||||
## we do the following, for easy surfing
|
## we do the following, for easy surfing
|
||||||
## e.g. use: cbx.go(your_url)
|
## e.g. use: cbx.go(your_url)
|
||||||
## commands api: http://twill.idyll.org/commands.html
|
## commands api: http://twill.idyll.org/commands.html
|
||||||
CBXHOST="localhost"
|
CBXHOST = "localhost"
|
||||||
CBXPORT=8081
|
CBXPORT = 8081
|
||||||
CBX_URL="http://%s:%d/" % (CBXHOST, CBXPORT)
|
CBX_URL = "http://%s:%d/" % (CBXHOST, CBXPORT)
|
||||||
LOG_FILE="/tmp/twill.log"
|
LOG_FILE = "/tmp/cryptobox-twill.log"
|
||||||
|
WEBLOG_FILE = "/tmp/cryptobox-cherrypy.log"
|
||||||
|
|
||||||
|
|
||||||
class WebInterfaceTestClass(unittest.TestCase):
|
class WebInterfaceTestClass(unittest.TestCase):
|
||||||
'''this class checks the webserver, using "twill"
|
'''this class checks the webserver, using "twill"
|
||||||
|
@ -62,9 +66,12 @@ class WebInterfaceTestClass(unittest.TestCase):
|
||||||
'server.logToScreen' : False,
|
'server.logToScreen' : False,
|
||||||
'autoreload.on': False,
|
'autoreload.on': False,
|
||||||
'server.threadPool': 1,
|
'server.threadPool': 1,
|
||||||
'server.environment': 'production',
|
'server.environment': 'development',
|
||||||
|
'server.log_tracebacks': True,
|
||||||
|
'server.log_file': WEBLOG_FILE,
|
||||||
})
|
})
|
||||||
cherrypy.root = cryptobox.web.sites.WebInterfaceSites("cryptobox-unittests.conf")
|
cherrypy.root = cryptobox.web.sites.WebInterfaceSites(
|
||||||
|
"cryptobox-unittests.conf")
|
||||||
cherrypy.server.start(initOnly=True, serverClass=None)
|
cherrypy.server.start(initOnly=True, serverClass=None)
|
||||||
|
|
||||||
from cherrypy._cpwsgi import wsgiApp
|
from cherrypy._cpwsgi import wsgiApp
|
||||||
|
@ -74,19 +81,13 @@ class WebInterfaceTestClass(unittest.TestCase):
|
||||||
self.output = open(LOG_FILE,"a")
|
self.output = open(LOG_FILE,"a")
|
||||||
twill.set_output(self.output)
|
twill.set_output(self.output)
|
||||||
self.cmd = twill.commands
|
self.cmd = twill.commands
|
||||||
self.URL = CBX_URL
|
self.url = CBX_URL
|
||||||
self.cbox = cherrypy.root.cbox
|
self.cbox = cherrypy.root.cbox
|
||||||
self.globals, self.locals = twill.namespaces.get_twill_glocals()
|
self.globals, self.locals = twill.namespaces.get_twill_glocals()
|
||||||
## search for a usable block device
|
## search for a usable block device
|
||||||
## use /dev/ubd? if possible - otherwise /dev/hd?
|
## use /dev/ubd? if possible - otherwise /dev/hd?
|
||||||
## so it will be possible to use these tests inside of an uml
|
## so it will be possible to use these tests inside of an uml
|
||||||
for d in ["ubdb", "loop", "ubda", "udbc", "ubdd", "hdb", "hda", "hdc", "hdd"]:
|
self.blockdevice, self.device = self.__find_test_device()
|
||||||
if os.path.exists("/dev/%s1" % d):
|
|
||||||
device = d
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
device = "hda"
|
|
||||||
self.device = device
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,6 +104,34 @@ class WebInterfaceTestClass(unittest.TestCase):
|
||||||
browser = twill.commands.get_browser()
|
browser = twill.commands.get_browser()
|
||||||
soup = BeautifulSoup(browser.get_html())
|
soup = BeautifulSoup(browser.get_html())
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
|
||||||
|
def __find_test_device(self):
|
||||||
|
"""Search for a valid test device - the data will get lost ...
|
||||||
|
"""
|
||||||
|
for dev in ["ubdb", "loop", "ubda", "udbc", "ubdd"]:
|
||||||
|
if os.path.exists("/dev/%s1" % dev) \
|
||||||
|
and not self.__is_config_partition("/dev/%s1" % dev):
|
||||||
|
return (dev, dev + "1")
|
||||||
|
if os.path.exists("/dev/%s2" % dev) \
|
||||||
|
and not self.__is_config_partition("/dev/%s2" % dev):
|
||||||
|
return (dev, dev + "2")
|
||||||
|
else:
|
||||||
|
raise Exception, "no valid device for testing found"
|
||||||
|
|
||||||
|
|
||||||
|
def __is_config_partition(self, device):
|
||||||
|
"""Check if the device is a configuration partition.
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
shell = False,
|
||||||
|
stdout = subprocess.PIPE,
|
||||||
|
stderr = subprocess.PIPE,
|
||||||
|
args = [ '/sbin/e2label',
|
||||||
|
device ])
|
||||||
|
(stdout, stderr) = proc.communicate()
|
||||||
|
return stdout.strip() == "cbox_config"
|
||||||
|
|
||||||
|
|
||||||
def register_auth(self, url, user="admin", password="admin"):
|
def register_auth(self, url, user="admin", password="admin"):
|
||||||
|
|
44
src/pylintrc
Normal file
44
src/pylintrc
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# this is a local configuration file for pylint to be used for checking the
|
||||||
|
# quality of the CryptoBox code
|
||||||
|
#
|
||||||
|
# just run:
|
||||||
|
# bin/do_pylint.sh cryptobox.core.main
|
||||||
|
# to check the module cryptobox.core.main
|
||||||
|
|
||||||
|
|
||||||
|
[MASTER]
|
||||||
|
# Add <file or directory> to the black list. It should be a base name, not a
|
||||||
|
# path. You may set this option multiple times.
|
||||||
|
ignore=CVS
|
||||||
|
ignore=.svn
|
||||||
|
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
|
||||||
|
# Required attributes for module, separated by a comma
|
||||||
|
required-attributes=__revision__
|
||||||
|
|
||||||
|
# Good variable names which should always be accepted, separated by a comma
|
||||||
|
good-names=i,j,k,ex,Run,_
|
||||||
|
|
||||||
|
# Bad variable names which should always be refused, separated by a comma
|
||||||
|
bad-names=foo,bar,baz,toto,tutu,tata
|
||||||
|
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
|
||||||
|
# Maximum number of characters on a single line.
|
||||||
|
max-line-length=88
|
||||||
|
|
||||||
|
# Maximum number of lines in a module
|
||||||
|
max-module-lines=1000
|
||||||
|
|
||||||
|
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||||
|
# tab).
|
||||||
|
indent-string='\t'
|
||||||
|
|
||||||
|
|
||||||
|
[MISCELLANEOUS]
|
||||||
|
|
||||||
|
# List of note tags to take in consideration, separated by a comma.
|
||||||
|
notes=FIXME,XXX,TODO
|
Loading…
Reference in a new issue