added minor parts of slovene translation
fixed samba integration script added syslog support replaced 'pattern' with 'level' for 'logs' plugin improved fetch_po_files script improved output of log plugin recursively storing setting files fixed umask set to 022 defining bootup and shutdown handler for the server implementing volume_automount mounting simplified the output preperation of the partition plugin "busy" flag handling moved from core/container to core/main
12
README.samba
|
@ -19,7 +19,6 @@ Reload the new samba configuration by calling:
|
||||||
invoke-rc.d samba reload
|
invoke-rc.d samba reload
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
B) one share for each volume
|
B) one share for each volume
|
||||||
|
|
||||||
Copy the example event script /usr/share/doc/cryptobox-server/event-script/samba
|
Copy the example event script /usr/share/doc/cryptobox-server/event-script/samba
|
||||||
|
@ -27,14 +26,5 @@ to /etc/cryptobox-server/events.d/samba. This event handler will add and remove
|
||||||
shares whenever a volume is mounted or unmounted via the CryptoBox webinterface.
|
shares whenever a volume is mounted or unmounted via the CryptoBox webinterface.
|
||||||
|
|
||||||
Add the following line to your /etc/samba/smb.conf:
|
Add the following line to your /etc/samba/smb.conf:
|
||||||
include = /var/cache/cryptobox-server/samba-include.conf
|
include = /var/cache/cryptobox-server/settings/misc/samba-include.conf
|
||||||
|
|
||||||
Create this file:
|
|
||||||
touch /var/cache/cryptobox-server/samba-include.conf
|
|
||||||
|
|
||||||
Chown it to the cryptobox user:
|
|
||||||
chown cryptobox /var/cache/cryptobox-server/samba-include.conf
|
|
||||||
|
|
||||||
Reload the new samba configuration by calling:
|
|
||||||
invoke-rc.d samba reload
|
|
||||||
|
|
||||||
|
|
|
@ -106,10 +106,24 @@ class CryptoBoxWebserver:
|
||||||
"staticFilter.file": os.path.realpath(os.path.join(opts.datadir, 'favicon.ico'))}
|
"staticFilter.file": os.path.realpath(os.path.join(opts.datadir, 'favicon.ico'))}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
self.define_exit_handlers(cherrypy.root)
|
||||||
|
|
||||||
|
|
||||||
|
def define_exit_handlers(self, cbw):
|
||||||
|
import atexit
|
||||||
|
import signal
|
||||||
|
atexit.register(cbw.cleanup)
|
||||||
|
def kill_signal_handler(signum, frame):
|
||||||
|
cbw.cbox.log.info("Kill signal handler called: %d" % signum)
|
||||||
|
sys.exit(1)
|
||||||
|
signal.signal(signal.SIGTERM, kill_signal_handler)
|
||||||
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
cherrypy.server.start()
|
cherrypy.server.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def fork_to_background():
|
def fork_to_background():
|
||||||
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
|
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
|
||||||
|
@ -221,6 +235,8 @@ def parseOptions():
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
## process arguments
|
## process arguments
|
||||||
options = parseOptions()
|
options = parseOptions()
|
||||||
|
## set umask to 022 (aka 755) - octal value
|
||||||
|
os.umask(022)
|
||||||
## run the webserver as a daemon process
|
## run the webserver as a daemon process
|
||||||
if options.background: fork_to_background()
|
if options.background: fork_to_background()
|
||||||
## write pid file
|
## write pid file
|
||||||
|
|
|
@ -76,7 +76,8 @@ Languages = en, de, sl, fr
|
||||||
|
|
||||||
[Programs]
|
[Programs]
|
||||||
cryptsetup = /sbin/cryptsetup
|
cryptsetup = /sbin/cryptsetup
|
||||||
mkfs-data = /sbin/mkfs.ext3
|
mkfs = /sbin/mkfs
|
||||||
|
nice = /usr/bin/nice
|
||||||
blkid = /sbin/blkid
|
blkid = /sbin/blkid
|
||||||
blockdev = /sbin/blockdev
|
blockdev = /sbin/blockdev
|
||||||
mount = /bin/mount
|
mount = /bin/mount
|
||||||
|
|
|
@ -64,6 +64,7 @@ Destination = file
|
||||||
# syslog: $LOG_FACILITY
|
# syslog: $LOG_FACILITY
|
||||||
#Details = /var/log/cryptobox.log
|
#Details = /var/log/cryptobox.log
|
||||||
Details = ./cryptobox.log
|
Details = ./cryptobox.log
|
||||||
|
#Details = SYSLOG
|
||||||
|
|
||||||
|
|
||||||
[WebSettings]
|
[WebSettings]
|
||||||
|
|
|
@ -27,5 +27,6 @@ if [ ! -e "$TEST_IMG" ]
|
||||||
dd if=/dev/zero of="$TEST_IMG" bs=1M count=$TEST_SIZE
|
dd if=/dev/zero of="$TEST_IMG" bs=1M count=$TEST_SIZE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
linux ubd0="$ROOT_IMG" ubd1="$TEST_IMG" con=xterm hostfs=$PROJ_DIR fakehd eth0=daemon mem=$MEM_SIZE
|
# "aio=2.4" is necessary, as otherwise sfdiks hangs at "nanosleep({3,0})"
|
||||||
|
linux ubd0="$ROOT_IMG" ubd1="$TEST_IMG" con=xterm hostfs=$PROJ_DIR fakehd eth0=daemon mem=$MEM_SIZE aio=2.4
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<IfModule mod_dav_fs.c>
|
<IfModule mod_dav_fs.c>
|
||||||
# include the dynamically managed configuration directory - IT MUST EXIST
|
# include the dynamically managed configuration directory - IT MUST EXIST
|
||||||
Include /var/cache/cryptobox-server/settings/apache2_dav.conf.d/
|
Include /var/cache/cryptobox-server/settings/misc/apache2_dav.conf.d/
|
||||||
# lock database - should be writeable for www-data
|
# lock database - should be writeable for www-data
|
||||||
DavLockDB /tmp/dav_lock.db
|
DavLockDB /tmp/dav_lock.db
|
||||||
# a longer value than the default (120) help for high-latency networks
|
# a longer value than the default (120) help for high-latency networks
|
||||||
|
|
|
@ -49,14 +49,14 @@ EventDir = /etc/cryptobox-server/events.d
|
||||||
Level = debug
|
Level = debug
|
||||||
|
|
||||||
# where to write the log messages to?
|
# where to write the log messages to?
|
||||||
# possible values are: file
|
# possible values are 'file' and 'syslog'
|
||||||
# syslog support will be added later
|
|
||||||
Destination = file
|
Destination = file
|
||||||
|
|
||||||
# depending on the choosen destination (see above) you may select
|
# depending on the choosen destination (see above) you may select
|
||||||
# details. Possible values for the different destinations are:
|
# details. Possible values for the different destinations are:
|
||||||
# file: $FILENAME
|
# file: $FILENAME
|
||||||
# syslog: $LOG_FACILITY
|
# syslog: KERN | USER | MAIL | DAEMON | AUTH | SYSLOG | LPR | NEWS | UUCP
|
||||||
|
# | CRON | AUTHPRIV | LOCAL0 .. LOCAL7
|
||||||
Details = /var/log/cryptobox-server/cryptobox.log
|
Details = /var/log/cryptobox-server/cryptobox.log
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ Stylesheet = /cryptobox-misc/cryptobox.css
|
||||||
# see /usr/share/locale for a list of possible language codes
|
# see /usr/share/locale for a list of possible language codes
|
||||||
# if a translated string is not available, then the english original is displayed
|
# if a translated string is not available, then the english original is displayed
|
||||||
# available languages: cs, da, de, en, es, fi, fr, hu, it, ja, nl, pl, pt, ru, sl, sv
|
# available languages: cs, da, de, en, es, fi, fr, hu, it, ja, nl, pl, pt, ru, sl, sv
|
||||||
Languages = de, en, fr
|
Languages = de, en, fr, es, sl
|
||||||
|
|
||||||
|
|
||||||
[Programs]
|
[Programs]
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
# DO NOT REMOVE OR EDIT THIS FILE
|
|
||||||
# the file was automatically generated by the cryptobox package
|
|
10
debian/changelog
vendored
|
@ -1,3 +1,13 @@
|
||||||
|
cryptobox (0.2.54-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* log plugin improved
|
||||||
|
* samba plugin fixed
|
||||||
|
* syslog support added
|
||||||
|
* improved output of 'logs' plugin
|
||||||
|
* finished 'volume_automount' plugin
|
||||||
|
|
||||||
|
-- Lars Kruse <devel@sumpfralle.de> Mon, 11 Dec 2006 11:52:38 +0100
|
||||||
|
|
||||||
cryptobox (0.2.53-1) unstable; urgency=low
|
cryptobox (0.2.53-1) unstable; urgency=low
|
||||||
|
|
||||||
* constant screen width
|
* constant screen width
|
||||||
|
|
2
debian/control
vendored
|
@ -9,7 +9,7 @@ Standards-Version: 3.7.2
|
||||||
Package: cryptobox-server
|
Package: cryptobox-server
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${python:Depends}, cryptsetup (>=20050111), e2fsprogs (>= 1.27), adduser, python (>=2.4), python-clearsilver, super, dosfstools, python-cherrypy, python-configobj
|
Depends: ${python:Depends}, cryptsetup (>=20050111), e2fsprogs (>= 1.27), adduser, python (>=2.4), python-clearsilver, super, dosfstools, python-cherrypy, python-configobj
|
||||||
Suggests: samba, apache, stunnel
|
Suggests: samba, apache2, stunnel
|
||||||
Replaces: cryptobox
|
Replaces: cryptobox
|
||||||
XB-Python-Version: ${python:Versions}
|
XB-Python-Version: ${python:Versions}
|
||||||
Description: Web interface for an encrypting fileserver
|
Description: Web interface for an encrypting fileserver
|
||||||
|
|
2
debian/cryptobox-server.postrm
vendored
|
@ -15,7 +15,7 @@ remove_super_lines()
|
||||||
## do nothing, if there is no CryptoBox line
|
## do nothing, if there is no CryptoBox line
|
||||||
grep -q "CRYPTOBOX_MARKER" "$SUPER_FILE" || return 0
|
grep -q "CRYPTOBOX_MARKER" "$SUPER_FILE" || return 0
|
||||||
sed -i /CRYPTOBOX_MARKER/d "$SUPER_FILE"
|
sed -i /CRYPTOBOX_MARKER/d "$SUPER_FILE"
|
||||||
sed -i /CryptoBoxRootActions/d "$SUPER_FILE"
|
sed -i /^CryptoBoxRootActions/d "$SUPER_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,13 @@ Event scripts for CryptoBox events
|
||||||
|
|
||||||
If you want to execute specific actions according to changes of the cryptobox,
|
If you want to execute specific actions according to changes of the cryptobox,
|
||||||
then you can just add your own scripts to this directory.
|
then you can just add your own scripts to this directory.
|
||||||
For every supported event of the CryptoBox, all scripts are called with root user
|
These scripts are called with root user permissions.
|
||||||
permissions.
|
|
||||||
|
|
||||||
The common synopsis for all event scripts is:
|
The common synopsis for all event scripts is:
|
||||||
SCRIPTNAME EVENT [[EVENT_INFOS]...]
|
SCRIPTNAME EVENT [[EVENT_INFOS]...]
|
||||||
|
|
||||||
|
|
||||||
|
1) Possible events
|
||||||
Supported events:
|
Supported events:
|
||||||
premount|postmount|preumount|postumount:
|
premount|postmount|preumount|postumount:
|
||||||
called before and after (u)mounting of a volume
|
called before and after (u)mounting of a volume
|
||||||
|
@ -18,9 +19,17 @@ Supported events:
|
||||||
- mount_dir: mountpoint of the volume
|
- mount_dir: mountpoint of the volume
|
||||||
|
|
||||||
|
|
||||||
|
2) Preperation of event scripts
|
||||||
Every event script has to fulfill the following conditions:
|
Every event script has to fulfill the following conditions:
|
||||||
- be executable (for the cryptobox user and for root)
|
- be executable (for the cryptobox user and for root)
|
||||||
- be writeable for root only
|
- be writeable for root only
|
||||||
- its parent directories must be writeable for root only
|
- its parent directories must be writeable for root only
|
||||||
- the directory of the script must contain a file called '_event_scripts_' (to prevent abuse)
|
- the directory of the script must contain a file called '_event_scripts_' (to prevent abuse)
|
||||||
|
|
||||||
|
|
||||||
|
3) Storing settings
|
||||||
|
If your custom event script needs to write information to a file, then it
|
||||||
|
should create this file below /var/cache/cryptobox-server/settings/misc/.
|
||||||
|
(adapt this directory to your setup, if you changed the default settings of
|
||||||
|
[Locations]->SettingsDir)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
# (e.g. /etc/apache2/conf.d)
|
# (e.g. /etc/apache2/conf.d)
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Params: $event $volume_name $volume_type $mount_dir
|
# Params: $event $device $volume_name $volume_type $mount_dir
|
||||||
#
|
#
|
||||||
# event: premount | postmount | preumount | postumount
|
# event: premount | postmount | preumount | postumount
|
||||||
# device: name of the device
|
# device: name of the device
|
||||||
|
@ -24,7 +24,7 @@ set -eu
|
||||||
# adapt this part of the file to your setup
|
# adapt this part of the file to your setup
|
||||||
|
|
||||||
APACHE_SCRIPT=/etc/init.d/apache2
|
APACHE_SCRIPT=/etc/init.d/apache2
|
||||||
APACHE_CONF_DIR=/var/cache/cryptobox/apache2_dav.conf.d
|
APACHE_CONF_DIR=/var/cache/cryptobox/settings/misc/apache2_dav.conf.d
|
||||||
|
|
||||||
# this apache config snippet is used for every published volume
|
# this apache config snippet is used for every published volume
|
||||||
# _VOLUME_NAME_ and _SHARE_DIR_ are replaced by their actual values
|
# _VOLUME_NAME_ and _SHARE_DIR_ are replaced by their actual values
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
# The following line _must_ be added to your /etc/samba/smb.conf:
|
# The following line _must_ be added to your /etc/samba/smb.conf:
|
||||||
# include = /var/cache/cryptobox-server/samba-include.conf
|
# include = /var/cache/cryptobox-server/samba-include.conf
|
||||||
# and you should create this file and chown it to the cryptobox user:
|
# and you should create this file and chown it to the cryptobox user:
|
||||||
# touch /var/cache/cryptobox-server/samba-include.conf
|
# touch /var/cache/cryptobox-server/settings/misc/samba-include.conf
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Params: $event $volume_name $volume_type $mount_dir
|
# Params: $event $device $volume_name $volume_type $mount_dir
|
||||||
#
|
#
|
||||||
# event: premount | postmount | preumount | postumount
|
# event: premount | postmount | preumount | postumount
|
||||||
# device: name of the device
|
# device: name of the device
|
||||||
|
@ -25,17 +25,15 @@ set -eu
|
||||||
# adapt this part of the file to your needs
|
# adapt this part of the file to your needs
|
||||||
|
|
||||||
SAMBA_CONTROL=smbcontrol
|
SAMBA_CONTROL=smbcontrol
|
||||||
SAMBA_CONF_DIR=/var/cache/cryptobox-server/samba.conf.d
|
SAMBA_CONF_DIR=/var/cache/cryptobox-server/settings/misc/samba.conf.d
|
||||||
MAIN_SAMBA_CONF_FILE=/var/cache/cryptobox-server/samba-include.conf
|
MAIN_SAMBA_CONF_FILE=/var/cache/cryptobox-server/settings/misc/samba-include.conf
|
||||||
|
|
||||||
# this smb.conf snippet will get used for every published share
|
# this smb.conf snippet will get used for every published share
|
||||||
# _VOLUME_NAME and _SHARE_DIR_ are replaced by their actual values
|
# _VOLUME_NAME and _SHARE_DIR_ are replaced by their actual values
|
||||||
# TODO: improve the later parsing of _SHARE_DIR_ in update_include_conf_file
|
|
||||||
# for now it depends on non existing whitespaces around the dirname
|
|
||||||
SAMBA_SHARE_TEMPLATE=$(cat - <<-"EOF"
|
SAMBA_SHARE_TEMPLATE=$(cat - <<-"EOF"
|
||||||
[_VOLUME_NAME_]
|
[_VOLUME_NAME_]
|
||||||
comment = CryptoBox share
|
comment = CryptoBox share
|
||||||
path =_SHARE_DIR_
|
path = _SHARE_DIR_
|
||||||
read only = no
|
read only = no
|
||||||
guest ok = yes
|
guest ok = yes
|
||||||
EOF
|
EOF
|
||||||
|
@ -71,7 +69,7 @@ update_include_conf_file()
|
||||||
( echo "# this file was automatically generated by the CryptoBox"
|
( echo "# this file was automatically generated by the CryptoBox"
|
||||||
echo "# DO NOT EDIT - all changes will get lost!"
|
echo "# DO NOT EDIT - all changes will get lost!"
|
||||||
find "$SAMBA_CONF_DIR" -type f -name "*.conf" | while read fname
|
find "$SAMBA_CONF_DIR" -type f -name "*.conf" | while read fname
|
||||||
do mdir=$(cat "$fname" | grep "path.*=" | cut -f 2 -d "=")
|
do mdir=$(grep "path.*=" "$fname" | cut -f 2 -d "=" | sed 's/^[ \t]*//')
|
||||||
# check if the mount directory still exists
|
# check if the mount directory still exists
|
||||||
if test -d "$mdir"
|
if test -d "$mdir"
|
||||||
then echo "include = $fname"
|
then echo "include = $fname"
|
||||||
|
|
|
@ -3,14 +3,14 @@ msgstr ""
|
||||||
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
||||||
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
||||||
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
||||||
"PO-Revision-Date: 2006-11-30 08:49+0100\n"
|
"PO-Revision-Date: 2006-12-11 01:40+0100\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||||
"X-Generator: Translate Toolkit 0.10.1\n"
|
"X-Generator: Pootle 0.10.1\n"
|
||||||
|
|
||||||
#: Name
|
#: Name
|
||||||
msgid "English"
|
msgid "English"
|
||||||
|
@ -18,11 +18,11 @@ msgstr ""
|
||||||
|
|
||||||
#: Title.Top
|
#: Title.Top
|
||||||
msgid "The CryptoBox"
|
msgid "The CryptoBox"
|
||||||
msgstr "Privatnost v vsako vas"
|
msgstr ""
|
||||||
|
|
||||||
#: Title.Slogan
|
#: Title.Slogan
|
||||||
msgid "Privacy for the rest of us."
|
msgid "Privacy for the rest of us."
|
||||||
msgstr ""
|
msgstr "Privatnost v vsako vas"
|
||||||
|
|
||||||
#: Title.Volume
|
#: Title.Volume
|
||||||
msgid "Volume"
|
msgid "Volume"
|
||||||
|
|
|
@ -47,22 +47,17 @@ class date(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
datetime.datetime(year, month, day, hour, minute)
|
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.__prepare_form_data()
|
|
||||||
return "form_date"
|
|
||||||
date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
|
|
||||||
if self.__set_date(date):
|
|
||||||
self.cbox.log.info("changed date to: %s" % date)
|
|
||||||
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
|
|
||||||
return "form_date"
|
|
||||||
else:
|
else:
|
||||||
## a failure should usually be an invalid date (we do not check it really)
|
date = "%02d%02d%02d%02d%d" % (month, day, hour, minute, year)
|
||||||
self.cbox.log.info("failed to set date: %s" % date)
|
if self.__set_date(date):
|
||||||
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
self.cbox.log.info("changed date to: %s" % date)
|
||||||
self.__prepare_form_data()
|
self.hdf["Data.Success"] = "Plugins.date.DateChanged"
|
||||||
return "form_date"
|
else:
|
||||||
else:
|
## a failure should usually be an invalid date (we do not check it really)
|
||||||
self.__prepare_form_data()
|
self.cbox.log.info("failed to set date: %s" % date)
|
||||||
return "form_date"
|
self.hdf["Data.Warning"] = "Plugins.date.InvalidDate"
|
||||||
|
self.__prepare_form_data()
|
||||||
|
return "form_date"
|
||||||
|
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
|
|
|
@ -1,102 +1,101 @@
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
||||||
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
||||||
"POT-Creation-Date: 2006-11-28 05:04+0100\n"
|
"POT-Creation-Date: 2006-11-28 05:04+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: 2006-12-09 17:00+0100\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||||
"X-Generator: Translate Toolkit 0.10.1\n"
|
"X-Generator: Pootle 0.10.1\n"
|
||||||
|
|
||||||
#: Name
|
#: Name
|
||||||
msgid "Change date and time"
|
msgid "Change date and time"
|
||||||
msgstr ""
|
msgstr "Spremeni datum in čas"
|
||||||
|
|
||||||
#: Link
|
#: Link
|
||||||
msgid "Set date/time"
|
msgid "Set date/time"
|
||||||
msgstr ""
|
msgstr "Nastavi datum in čas"
|
||||||
|
|
||||||
#: Title.ConfigDate
|
#: Title.ConfigDate
|
||||||
msgid "Date and time setting"
|
msgid "Date and time setting"
|
||||||
msgstr ""
|
msgstr "Nastavitve datum/čas"
|
||||||
|
|
||||||
#: Button.ConfigDate
|
#: Button.ConfigDate
|
||||||
msgid "Set date and time"
|
msgid "Set date and time"
|
||||||
msgstr ""
|
msgstr "Nastavi datum/čas"
|
||||||
|
|
||||||
#: Text.Date
|
#: Text.Date
|
||||||
msgid "Date"
|
msgid "Date"
|
||||||
msgstr ""
|
msgstr "Datum"
|
||||||
|
|
||||||
#: Text.Time
|
#: Text.Time
|
||||||
msgid "Time"
|
msgid "Time"
|
||||||
msgstr ""
|
msgstr "Čas"
|
||||||
|
|
||||||
#: Text.Months.1
|
#: Text.Months.1
|
||||||
msgid "January"
|
msgid "January"
|
||||||
msgstr ""
|
msgstr "Januar"
|
||||||
|
|
||||||
#: Text.Months.2
|
#: Text.Months.2
|
||||||
msgid "February"
|
msgid "February"
|
||||||
msgstr ""
|
msgstr "Februar"
|
||||||
|
|
||||||
#: Text.Months.3
|
#: Text.Months.3
|
||||||
msgid "March"
|
msgid "March"
|
||||||
msgstr ""
|
msgstr "Marec"
|
||||||
|
|
||||||
#: Text.Months.4
|
#: Text.Months.4
|
||||||
msgid "April"
|
msgid "April"
|
||||||
msgstr ""
|
msgstr "April"
|
||||||
|
|
||||||
#: Text.Months.5
|
#: Text.Months.5
|
||||||
msgid "May"
|
msgid "May"
|
||||||
msgstr ""
|
msgstr "Maj"
|
||||||
|
|
||||||
#: Text.Months.6
|
#: Text.Months.6
|
||||||
msgid "June"
|
msgid "June"
|
||||||
msgstr ""
|
msgstr "Junij"
|
||||||
|
|
||||||
#: Text.Months.7
|
#: Text.Months.7
|
||||||
msgid "July"
|
msgid "July"
|
||||||
msgstr ""
|
msgstr "Julij"
|
||||||
|
|
||||||
#: Text.Months.8
|
#: Text.Months.8
|
||||||
msgid "August"
|
msgid "August"
|
||||||
msgstr ""
|
msgstr "Avgust"
|
||||||
|
|
||||||
#: Text.Months.9
|
#: Text.Months.9
|
||||||
msgid "September"
|
msgid "September"
|
||||||
msgstr ""
|
msgstr "September"
|
||||||
|
|
||||||
#: Text.Months.10
|
#: Text.Months.10
|
||||||
msgid "October"
|
msgid "October"
|
||||||
msgstr ""
|
msgstr "Oktober"
|
||||||
|
|
||||||
#: Text.Months.11
|
#: Text.Months.11
|
||||||
msgid "November"
|
msgid "November"
|
||||||
msgstr ""
|
msgstr "November"
|
||||||
|
|
||||||
#: Text.Months.12
|
#: Text.Months.12
|
||||||
msgid "December"
|
msgid "December"
|
||||||
msgstr ""
|
msgstr "December"
|
||||||
|
|
||||||
#: SuccessMessage.DateChanged.Title
|
#: SuccessMessage.DateChanged.Title
|
||||||
msgid "Date changed"
|
msgid "Date changed"
|
||||||
msgstr ""
|
msgstr "Datum je spremenjen"
|
||||||
|
|
||||||
#: SuccessMessage.DateChanged.Text
|
#: SuccessMessage.DateChanged.Text
|
||||||
msgid "The date was changed successfully."
|
msgid "The date was changed successfully."
|
||||||
msgstr ""
|
msgstr "Datum je bil uspešno spremenjen"
|
||||||
|
|
||||||
#: WarningMessage.InvalidDate.Title
|
#: WarningMessage.InvalidDate.Title
|
||||||
msgid "Invalid value"
|
msgid "Invalid value"
|
||||||
msgstr ""
|
msgstr "Neveljavna vrednost"
|
||||||
|
|
||||||
#: WarningMessage.InvalidDate.Text
|
#: WarningMessage.InvalidDate.Text
|
||||||
msgid "An invalid value for date or time was supplied. Please try again."
|
msgid "An invalid value for date or time was supplied. Please try again."
|
||||||
msgstr ""
|
msgstr "Nepravilen vnos datuma ali časa. Prosimo poskusite ponovno."
|
||||||
|
|
|
@ -45,7 +45,7 @@ if __name__ == "__main__":
|
||||||
sys.stderr.write("%s: no argument supplied\n" % self_bin)
|
sys.stderr.write("%s: no argument supplied\n" % self_bin)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if re.search(u'\D', args[0]):
|
if re.search(r'\D', args[0]):
|
||||||
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
|
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
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(r'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/%s" % self.device in devices)
|
self.assertTrue("/dev/%s" % self.device in devices)
|
||||||
|
|
|
@ -43,7 +43,7 @@ class help(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
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(r'\W', page) and \
|
||||||
os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
|
os.path.isfile(os.path.join(self.cbox.prefs["Locations"]["DocDir"],
|
||||||
self.default_lang, page + '.html')):
|
self.default_lang, page + '.html')):
|
||||||
## everything is ok
|
## everything is ok
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
||||||
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
||||||
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: 2006-12-09 16:28+0100\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||||
"X-Generator: Translate Toolkit 0.10.1\n"
|
"X-Generator: Pootle 0.10.1\n"
|
||||||
|
|
||||||
#: Name
|
#: Name
|
||||||
msgid "User manual"
|
msgid "User manual"
|
||||||
msgstr ""
|
msgstr "Uporabniški priročnik"
|
||||||
|
|
||||||
#: Link
|
#: Link
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr ""
|
msgstr "Pomoč"
|
||||||
|
|
|
@ -89,6 +89,6 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
|
|
||||||
def _getHelpStatus(self):
|
def _getHelpStatus(self):
|
||||||
self.cmd.find(u'Data.Status.Plugins.help=(.*)$', "m")
|
self.cmd.find(r'Data.Status.Plugins.help=(.*)$', "m")
|
||||||
return tuple(self.locals["__match__"].split(":"))
|
return tuple(self.locals["__match__"].split(":"))
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,25 @@
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
||||||
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
||||||
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: 2006-12-09 16:33+0100\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||||
"X-Generator: Translate Toolkit 0.10.1\n"
|
"X-Generator: Pootle 0.10.1\n"
|
||||||
|
|
||||||
#: Name
|
#: Name
|
||||||
msgid "Choose interface language"
|
msgid "Choose interface language"
|
||||||
msgstr ""
|
msgstr "Izberite jezik"
|
||||||
|
|
||||||
#: Link
|
#: Link
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr ""
|
msgstr "Jezik"
|
||||||
|
|
||||||
#: Title.Language
|
#: Title.Language
|
||||||
msgid "Choose an interface language"
|
msgid "Choose an interface language"
|
||||||
msgstr ""
|
msgstr "Izberite Jezik"
|
||||||
|
|
|
@ -35,7 +35,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
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(r'Data.Status.Plugins.language_selection=(.*)$', "m")
|
||||||
langs = self.locals["__match__"].split(":")
|
langs = self.locals["__match__"].split(":")
|
||||||
self.assertTrue(len(langs)>1)
|
self.assertTrue(len(langs)>1)
|
||||||
self.assertTrue(langs[0] == "en")
|
self.assertTrue(langs[0] == "en")
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
Name = Show the content of the log file
|
Name = Show event log
|
||||||
Link = Show log file
|
Link = Event log
|
||||||
|
|
||||||
Title.Log = CryptoBox logfiles
|
Title.Log = CryptoBox event log
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
EmptyLog = The logfile of the CryptoBox is empty.
|
ShowAll = Show all messages
|
||||||
Refresh = Refresh
|
AtLeastWarnings = Show warnings and errors
|
||||||
|
OnlyErrors = Show errors only
|
||||||
|
AgeOfEvent = Time passed
|
||||||
|
EventText = Description
|
||||||
|
TimeUnits {
|
||||||
|
Days = days
|
||||||
|
Hours = hours
|
||||||
|
Minutes = minutes
|
||||||
|
Seconds = seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AdviceMessage {
|
||||||
|
EmptyLog.Text = There are no messages available.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
#log p.console {
|
#log table.log td.level img {
|
||||||
margin-left: 10%;
|
width: 24px;
|
||||||
margin-right: 10%;
|
height: 24px;
|
||||||
font-family: monospace;
|
vertical-align: middle;
|
||||||
text-align: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#log table.log td.time {
|
||||||
|
padding: 0 5px 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#log table.log td.text {
|
||||||
|
font-size: 0.8em;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,14 @@ __revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
LOG_LEVELS = [ 'DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR' ]
|
||||||
|
|
||||||
|
LINE_REGEX = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}) " \
|
||||||
|
+ r"(?P<hour>\d{2}):(?P<minute>\d{2}):\d{2},\d{3} (?P<level>" \
|
||||||
|
+ "|".join([ "(?:%s)" % e for e in LOG_LEVELS]) + r"): (?P<text>.*)$")
|
||||||
|
|
||||||
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
|
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
"""The logs feature of the CryptoBox.
|
"""The logs feature of the CryptoBox.
|
||||||
|
@ -36,29 +44,31 @@ class logs(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
request_auth = False
|
request_auth = False
|
||||||
rank = 90
|
rank = 90
|
||||||
|
|
||||||
def do_action(self, lines=50, size=3000, pattern=None):
|
def do_action(self, lines=50, size=3000, level=None):
|
||||||
"""Show the latest part of the log file.
|
"""Show the latest part of the log file.
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
## filter input
|
## filter input
|
||||||
try:
|
try:
|
||||||
lines = int(lines)
|
lines = int(lines)
|
||||||
if lines <= 0:
|
if lines <= 0:
|
||||||
raise(ValueError)
|
raise(ValueError)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
self.cbox.log.info("[logs] invalid line number: %s" % str(lines))
|
||||||
lines = 50
|
lines = 50
|
||||||
try:
|
try:
|
||||||
size = int(size)
|
size = int(size)
|
||||||
if size <= 0:
|
if size <= 0:
|
||||||
raise(ValueError)
|
raise(ValueError)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
self.cbox.log.info("[logs] invalid log size: %s" % str(size))
|
||||||
size = 3000
|
size = 3000
|
||||||
if not pattern is None:
|
if not level is None:
|
||||||
pattern = str(pattern)
|
level = str(level)
|
||||||
if re.search(u'\W', pattern):
|
if not level in LOG_LEVELS:
|
||||||
pattern = None
|
self.cbox.log.info("[logs] invalid log level: %s" % str(level))
|
||||||
self.hdf[self.hdf_prefix + "Content"] = self.__get_log_content(
|
level = None
|
||||||
lines, size, pattern)
|
for (index, line) in enumerate(self.__get_log_content(lines, size, level)):
|
||||||
|
self.__set_line_hdf_data(self.hdf_prefix + "Content.%d" % index, line)
|
||||||
self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.abspath(os.path.join(
|
self.hdf[self.hdf_prefix + "StyleSheetFile"] = os.path.abspath(os.path.join(
|
||||||
self.plugin_dir, "logs.css"))
|
self.plugin_dir, "logs.css"))
|
||||||
return "show_log"
|
return "show_log"
|
||||||
|
@ -73,21 +83,79 @@ class logs(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.cbox.prefs["Log"]["Details"])
|
self.cbox.prefs["Log"]["Details"])
|
||||||
|
|
||||||
|
|
||||||
def __get_log_content(self, lines, max_size, pattern):
|
def __get_log_content(self, lines, max_size, level):
|
||||||
"""Filter, sort and shorten the log content.
|
"""Filter, sort and shorten the log content.
|
||||||
"""
|
"""
|
||||||
if pattern:
|
if level and level in LOG_LEVELS:
|
||||||
|
filtered_levels = LOG_LEVELS[:]
|
||||||
|
## only the given and higher levels are accepted
|
||||||
|
while filtered_levels[0] != level:
|
||||||
|
del filtered_levels[0]
|
||||||
content = []
|
content = []
|
||||||
current_length = 0
|
current_length = 0
|
||||||
for line in self.cbox.get_log_data():
|
for line in self.cbox.get_log_data():
|
||||||
if line.find(pattern) != -1:
|
for one_level in filtered_levels:
|
||||||
content.append(line)
|
if line.find(one_level) != -1:
|
||||||
current_length += len(line)
|
|
||||||
if lines and len(content) >= lines:
|
|
||||||
break
|
|
||||||
if max_size and current_length >= max_size:
|
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
## the line does not contain an appropriate level name
|
||||||
|
continue
|
||||||
|
## we found a line that fits
|
||||||
|
content.append(line)
|
||||||
|
current_length += len(line)
|
||||||
|
if lines and len(content) >= lines:
|
||||||
|
break
|
||||||
|
if max_size and current_length >= max_size:
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
content = self.cbox.get_log_data(lines, max_size)
|
content = self.cbox.get_log_data(lines, max_size)
|
||||||
return "<br/>".join(content)
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def __set_line_hdf_data(self, hdf_prefix, line):
|
||||||
|
"""Parse the log line for time and log level.
|
||||||
|
|
||||||
|
If parsing fails, then the output line is simply displayed without
|
||||||
|
meta information.
|
||||||
|
"""
|
||||||
|
self.hdf[hdf_prefix + ".Text"] = line.strip()
|
||||||
|
match = LINE_REGEX.match(line)
|
||||||
|
if not match:
|
||||||
|
## we could not parse the line - just return the text without meta info
|
||||||
|
return
|
||||||
|
## matching was successfully - we can parse the line for details
|
||||||
|
## calculate time difference of log line (aka: age of event)
|
||||||
|
try:
|
||||||
|
(year, month, day, hour, minute) = match.group(
|
||||||
|
'year', 'month', 'day', 'hour', 'minute')
|
||||||
|
(year, month, day, hour, minute) = \
|
||||||
|
(int(year), int(month), int(day), int(hour), int(minute))
|
||||||
|
## timediff is a timedelta object
|
||||||
|
timediff = datetime.datetime.today() - \
|
||||||
|
datetime.datetime(year, month, day, hour, minute)
|
||||||
|
## the time units (see below) correspond to the names within the language
|
||||||
|
## file: Text.TimeUnits.Days ...
|
||||||
|
if timediff.days >= 1:
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Days'
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.days
|
||||||
|
elif timediff.seconds >= 3600:
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Hours'
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds / 3600
|
||||||
|
elif timediff.seconds >= 60:
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Minutes'
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds / 60
|
||||||
|
else:
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Unit"] = 'Seconds'
|
||||||
|
self.hdf[hdf_prefix + ".TimeDiff.Value"] = timediff.seconds
|
||||||
|
except (OverflowError, TypeError, ValueError, IndexError), err_msg:
|
||||||
|
pass
|
||||||
|
## retrieve the level
|
||||||
|
try:
|
||||||
|
self.hdf[hdf_prefix + ".Level"] = match.group('level')
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
self.hdf[hdf_prefix + ".Text"] = match.group('text').strip()
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
|
@ -6,21 +6,63 @@
|
||||||
|
|
||||||
<h1><?cs var:html_escape(Lang.Plugins.logs.Title.Log) ?></h1>
|
<h1><?cs var:html_escape(Lang.Plugins.logs.Title.Log) ?></h1>
|
||||||
|
|
||||||
<div align="center">
|
<table border="0" align="center"><tr>
|
||||||
<?cs call:print_form_header("log-form", "logs") ?>
|
<td><?cs call:print_form_header("log-all", "logs") ?>
|
||||||
<button type="submit" value="refresh"><?cs
|
<button type="submit" value="refresh"><?cs
|
||||||
var:html_escape(Lang.Plugins.logs.Text.Refresh) ?></button>
|
var:html_escape(Lang.Plugins.logs.Text.ShowAll) ?></button>
|
||||||
</form>
|
</form></td>
|
||||||
</div>
|
<td><?cs call:print_form_header("log-warnings", "logs") ?>
|
||||||
|
<input type="hidden" name="level" value="WARNING" />
|
||||||
|
<button type="submit" value="refresh"><?cs
|
||||||
|
var:html_escape(Lang.Plugins.logs.Text.AtLeastWarnings) ?></button>
|
||||||
|
</form></td>
|
||||||
|
<td><?cs call:print_form_header("log-only-error", "logs") ?>
|
||||||
|
<input type="hidden" name="level" value="ERROR" />
|
||||||
|
<button type="submit" value="refresh"><?cs
|
||||||
|
var:html_escape(Lang.Plugins.logs.Text.OnlyErrors) ?></button>
|
||||||
|
</form></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
<?cs call:handle_messages() ?>
|
<?cs call:handle_messages() ?>
|
||||||
|
|
||||||
<div id="log">
|
<div id="log">
|
||||||
|
|
||||||
<?cs if:Data.Plugins.logs.Content ?>
|
<?cs if:subcount(Data.Plugins.logs.Content) > 0 ?>
|
||||||
<p class="console"><?cs var:Data.Plugins.logs.Content ?></p>
|
<table class="log"><?cs # the first line dictates if we show meta info or not
|
||||||
|
?><?cs if:Data.Plugins.logs.Content.0.Level ?>
|
||||||
|
<tr><th></th>
|
||||||
|
<th><?cs var:html_escape(Lang.Plugins.logs.Text.AgeOfEvent) ?></th>
|
||||||
|
<th><?cs var:html_escape(Lang.Plugins.logs.Text.EventText) ?></th>
|
||||||
|
</tr>
|
||||||
|
<?cs loop:index = #0, subcount(Data.Plugins.logs.Content)-1, #1 ?><?cs
|
||||||
|
with:x=Data.Plugins.logs.Content[index] ?><?cs
|
||||||
|
if:x.Text ?><?cs
|
||||||
|
if:x.Level == "ERROR" ?><?cs
|
||||||
|
set:meta_file="dialog-error_tango.gif" ?><?cs
|
||||||
|
elif:x.Level == "WARNING" ?><?cs
|
||||||
|
set:meta_file="dialog-warning_tango.gif" ?><?cs
|
||||||
|
else ?><?cs
|
||||||
|
set:meta_file="dialog-information_tango.gif" ?><?cs
|
||||||
|
/if ?>
|
||||||
|
<tr><td class="level"><img src="<?cs
|
||||||
|
call:link("cryptobox-misc/" + meta_file, "", "", "", "") ?>"
|
||||||
|
alt="symbol: <?cs var:html_escape(x.Level) ?>" /></td>
|
||||||
|
<td class="time"><?cs if:x.TimeDiff.Value ?><?cs
|
||||||
|
var:html_escape(x.TimeDiff.Value) ?> <?cs
|
||||||
|
var:html_escape(Lang.Plugins.logs.Text.TimeUnits[
|
||||||
|
x.TimeDiff.Unit]) ?><?cs
|
||||||
|
/if ?></td>
|
||||||
|
<td class="text"><?cs var:html_escape(x.Text) ?></td></tr><?cs
|
||||||
|
/if ?><?cs /with ?><?cs /loop ?><?cs
|
||||||
|
else ?><?cs
|
||||||
|
loop:index = #0, subcount(Data.Plugins.logs.Content)-1, #1 ?><?cs
|
||||||
|
with:x=Data.Plugins.logs.Content[index] ?>
|
||||||
|
<tr><td><?cs var:html_escape(x.Text) ?></td></tr><?cs
|
||||||
|
/with ?><?cs /loop ?><?cs
|
||||||
|
/if ?>
|
||||||
|
</table>
|
||||||
<?cs else ?>
|
<?cs else ?>
|
||||||
<p><?cs var:html_escape(Lang.Plugins.logs.Text.EmptyLog) ?></p>
|
<?cs call:hint("Plugins.logs.EmptyLog") ?>
|
||||||
<?cs /if ?>
|
<?cs /if ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,32 +28,32 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
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('<table class="log">')
|
||||||
|
|
||||||
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 + "?level=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('<table class="log">')
|
||||||
self.cmd.go(log_url + "?lines=0")
|
self.cmd.go(log_url + "?lines=0")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
self.cmd.go(log_url + "?lines=x")
|
self.cmd.go(log_url + "?lines=x")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
self.cmd.go(log_url + "?size=1000")
|
self.cmd.go(log_url + "?size=1000")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
self.cmd.go(log_url + "?size=0")
|
self.cmd.go(log_url + "?size=0")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
self.cmd.go(log_url + "?size=x")
|
self.cmd.go(log_url + "?size=x")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
self.cmd.go(log_url + "?pattern=foobar")
|
self.cmd.go(log_url + "?level=foobar")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
self.cmd.go(log_url + u"?pattern=kfj!^(]")
|
self.cmd.go(log_url + r"?level=kfj!^(]")
|
||||||
self.cmd.find('class="console"')
|
self.cmd.find('<table class="log">')
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ class network(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
return (0,0,0,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(r'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()])
|
||||||
|
|
|
@ -50,7 +50,7 @@ if __name__ == "__main__":
|
||||||
sys.stderr.write("%s: no argument supplied\n" % self_bin)
|
sys.stderr.write("%s: no argument supplied\n" % self_bin)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
match = re.search(u'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$', args[0])
|
match = re.search(r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$', args[0])
|
||||||
## did we match? If yes, then: are there wrong values inside?
|
## did we match? If yes, then: are there wrong values inside?
|
||||||
if not match or [e for e in match.groups() if int(e) > 255]:
|
if not match or [e for e in match.groups() if int(e) > 255]:
|
||||||
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
|
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
|
||||||
|
|
|
@ -38,7 +38,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
def get_current_ip():
|
def get_current_ip():
|
||||||
self.register_auth(self.url + "network")
|
self.register_auth(self.url + "network")
|
||||||
self.cmd.go(self.url + "network")
|
self.cmd.go(self.url + "network")
|
||||||
self.cmd.find(u'Data.Status.Plugins.network=([0-9\.]*)$', "m")
|
self.cmd.find(r'Data.Status.Plugins.network=([0-9\.]*)$', "m")
|
||||||
return self.locals["__match__"]
|
return self.locals["__match__"]
|
||||||
orig_ip_text = get_current_ip()
|
orig_ip_text = get_current_ip()
|
||||||
orig_ip_octs = orig_ip_text.split(".")
|
orig_ip_octs = orig_ip_text.split(".")
|
||||||
|
|
|
@ -57,16 +57,18 @@ WarningMessage {
|
||||||
PartitioningFailed {
|
PartitioningFailed {
|
||||||
Title = Partitioning failed
|
Title = Partitioning failed
|
||||||
Text = The partitioning of the device failed for some reason - sorry!
|
Text = The partitioning of the device failed for some reason - sorry!
|
||||||
Link.Text = Show log messages
|
Link.Text = Show log messages
|
||||||
Link.Attr1.name = pattern
|
Link.Rel = logs
|
||||||
|
Link.Attr1.name = level
|
||||||
Link.Attr1.value = ERROR
|
Link.Attr1.value = ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
FormattingFailed {
|
FormattingFailed {
|
||||||
Title = Formatting failed
|
Title = Formatting failed
|
||||||
Text = The formatting of the filesystems of the device failed - sorry!
|
Text = Formatting of at least one volume failed - sorry!
|
||||||
Link.Text = Show log messages
|
Link.Text = Show log messages
|
||||||
Link.Attr1.name = pattern
|
Link.Rel = logs
|
||||||
|
Link.Attr1.name = level
|
||||||
Link.Attr1.value = ERROR
|
Link.Attr1.value = ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -209,37 +209,34 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
## partition is still part of the containerlist, as the label is not
|
## partition is still part of the containerlist, as the label is not
|
||||||
## checked again - very ugly!!! So we will call reReadContainerList
|
## checked again - very ugly!!! So we will call reReadContainerList
|
||||||
## after formatting the last partition - see below
|
## after formatting the last partition - see below
|
||||||
self.cbox.reread_container_list()
|
#self.cbox.reread_container_list()
|
||||||
def result_generator():
|
format_ok = True
|
||||||
"""Generate the results of formatting - may be threaded.
|
counter = 0
|
||||||
"""
|
## initialize the generator
|
||||||
counter = 0
|
format_part_gen = self.__format_partitions(parts)
|
||||||
## initialize the generator
|
while counter < len(parts):
|
||||||
format_part_gen = self.__format_partitions(parts)
|
## first part: get the device name
|
||||||
while counter < len(parts):
|
counter += 1
|
||||||
## first part: get the device name
|
## second part: do the real formatting of a partition
|
||||||
yield format_part_gen.next()
|
result = format_part_gen.next()
|
||||||
counter += 1
|
## after the first partiton, we can reRead the containerList
|
||||||
## second part: do the real formatting of a partition
|
## (as the possible config partition was already created)
|
||||||
result = format_part_gen.next()
|
if self.with_config_partition and (counter == 1):
|
||||||
## after the first partiton, we can reRead the containerList
|
## important: reRead the containerList - but somehow it
|
||||||
## (as the possible config partition was already created)
|
## breaks the flow (hanging process)
|
||||||
if self.with_config_partition and (counter == 1):
|
#self.cbox.reReadContainerList()
|
||||||
## important: reRead the containerList - but somehow it
|
## write config data
|
||||||
## breaks the flow (hanging process)
|
self.cbox.prefs.mount_partition()
|
||||||
#self.cbox.reReadContainerList()
|
self.cbox.prefs.write()
|
||||||
## write config data
|
self.cbox.log.info("settings stored on config partition")
|
||||||
self.cbox.prefs.mount_partition()
|
## return the result
|
||||||
self.cbox.prefs.write()
|
if not result:
|
||||||
self.cbox.log.info("settings stored on config partition")
|
format_ok = False
|
||||||
## return the result
|
if format_ok:
|
||||||
if result:
|
self.hdf["Data.Success"] = "Plugins.partition.Partitioned"
|
||||||
yield "OK"
|
else:
|
||||||
else:
|
self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
|
||||||
yield "<b>Error</b>"
|
return "empty"
|
||||||
return {
|
|
||||||
"template": "show_format_progress",
|
|
||||||
"generator": result_generator}
|
|
||||||
else:
|
else:
|
||||||
return self.__action_add_partition(args)
|
return self.__action_add_partition(args)
|
||||||
|
|
||||||
|
@ -382,6 +379,9 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
self.device])
|
self.device])
|
||||||
for line in self.__get_sfdisk_layout(parts, is_filled):
|
for line in self.__get_sfdisk_layout(parts, is_filled):
|
||||||
proc.stdin.write(line + "\n")
|
proc.stdin.write(line + "\n")
|
||||||
|
#TODO: if running inside of an uml, then sfdisk hangs at "nanosleep({3,0})"
|
||||||
|
# very ugly - maybe a uml bug?
|
||||||
|
# it seems, like this can be avoided by running uml with the param "aio=2.4"
|
||||||
(output, error) = proc.communicate()
|
(output, error) = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
self.cbox.log.debug("partitioning failed: %s" % error)
|
self.cbox.log.debug("partitioning failed: %s" % error)
|
||||||
|
@ -439,7 +439,6 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
dev_name = self.device + str(part_num)
|
dev_name = self.device + str(part_num)
|
||||||
part_type = PARTTYPES[parts[0]["type"]][1]
|
part_type = PARTTYPES[parts[0]["type"]][1]
|
||||||
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
|
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
|
||||||
yield dev_name
|
|
||||||
yield self.__format_one_partition(dev_name, part_type)
|
yield self.__format_one_partition(dev_name, part_type)
|
||||||
del parts[0]
|
del parts[0]
|
||||||
## other data partitions
|
## other data partitions
|
||||||
|
@ -449,7 +448,6 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
part_type = PARTTYPES[parts[0]["type"]][1]
|
part_type = PARTTYPES[parts[0]["type"]][1]
|
||||||
self.cbox.log.info("formatting partition (%s) as '%s'" % \
|
self.cbox.log.info("formatting partition (%s) as '%s'" % \
|
||||||
(dev_name, part_type))
|
(dev_name, part_type))
|
||||||
yield dev_name
|
|
||||||
yield self.__format_one_partition(dev_name, part_type)
|
yield self.__format_one_partition(dev_name, part_type)
|
||||||
part_num += 1
|
part_num += 1
|
||||||
del parts[0]
|
del parts[0]
|
||||||
|
@ -476,34 +474,6 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def __old_format_one_partition(self, dev_name, fs_type):
|
|
||||||
"""Format a single partition
|
|
||||||
"""
|
|
||||||
## first: retrieve UUID - it can be removed from the database afterwards
|
|
||||||
prev_name = [e.get_name() for e in self.cbox.get_container_list()
|
|
||||||
if e.get_device() == dev_name]
|
|
||||||
## call "mkfs"
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
shell = False,
|
|
||||||
args = [
|
|
||||||
self.cbox.prefs["Programs"]["super"],
|
|
||||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
|
||||||
"plugin",
|
|
||||||
os.path.join(self.plugin_dir, "root_action.py"),
|
|
||||||
"format",
|
|
||||||
dev_name,
|
|
||||||
fs_type])
|
|
||||||
(output, error) = proc.communicate()
|
|
||||||
if proc.returncode != 0:
|
|
||||||
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
## remove unused volume entry
|
|
||||||
if prev_name:
|
|
||||||
del self.cbox.prefs.volumes_db[prev_name[0]]
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def __set_label_of_partition(self, dev_name, label):
|
def __set_label_of_partition(self, dev_name, label):
|
||||||
"""Set the label of a partition - useful for the config partition.
|
"""Set the label of a partition - useful for the config partition.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -30,6 +30,10 @@ Python code interface:
|
||||||
- function "get_status":
|
- 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))
|
||||||
|
- function "setup":
|
||||||
|
- may be overridden to specify bootup behaviour
|
||||||
|
- function "cleanup":
|
||||||
|
- may be overridden to specify shutdown behaviour
|
||||||
- the class variable "plugin_capabilities" 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 "plugin_visibility" may contain one or more of the following items:
|
- the class variable "plugin_visibility" may contain one or more of the following items:
|
||||||
|
|
|
@ -35,7 +35,7 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
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(r'\W', plugin_name): return "plugin_list"
|
||||||
plugin_manager = cryptobox.plugins.manage.PluginManager(
|
plugin_manager = cryptobox.plugins.manage.PluginManager(
|
||||||
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
|
self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
|
||||||
plugin = plugin_manager.get_plugin(plugin_name)
|
plugin = plugin_manager.get_plugin(plugin_name)
|
||||||
|
@ -51,7 +51,7 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
elif store:
|
elif store:
|
||||||
for key in args.keys():
|
for key in args.keys():
|
||||||
if key.endswith("_listed"):
|
if key.endswith("_listed"):
|
||||||
if not re.search(u'\W',key):
|
if not re.search(r'\W',key):
|
||||||
self.__setConfig(key[:-7], args)
|
self.__setConfig(key[:-7], args)
|
||||||
else:
|
else:
|
||||||
self.cbox.log.info("plugin_manager: invalid plugin name (%s)" % \
|
self.cbox.log.info("plugin_manager: invalid plugin name (%s)" % \
|
||||||
|
@ -129,7 +129,7 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
setting = {}
|
setting = {}
|
||||||
setting["visibility"] = []
|
setting["visibility"] = []
|
||||||
## look for "_visible_" values and apply them
|
## look for "_visible_" values and apply them
|
||||||
pattern = re.compile(u'%s_visible_([\w]+)$' % name)
|
pattern = re.compile(r'%s_visible_([\w]+)$' % name)
|
||||||
for key in args.keys():
|
for key in args.keys():
|
||||||
if key.startswith(name + "_visible_"):
|
if key.startswith(name + "_visible_"):
|
||||||
(vis_type, ) = pattern.match(key).groups()
|
(vis_type, ) = pattern.match(key).groups()
|
||||||
|
|
|
@ -34,25 +34,25 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
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 + r"?plugin_name=t/-!")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?plugin_name=foobar")
|
self.cmd.go(url + r"?plugin_name=foobar")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?plugin_name=disks&action=up")
|
self.cmd.go(url + r"?plugin_name=disks&action=up")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?plugin_name=disks&action=down")
|
self.cmd.go(url + r"?plugin_name=disks&action=down")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&dis/ks_listed")
|
self.cmd.go(url + r"?store=1&dis/ks_listed")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu=1&disks_rank=x")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=x")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu=1&disks_auth=1")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_auth=1")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50&disks_auth=1")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=50&disks_auth=1")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,11 +60,11 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
#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 + r"?plugin_name=disks&action=up")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu=1&disks_rank=0")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=0")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?plugin_name=disks&action=up")
|
self.cmd.go(url + r"?plugin_name=disks&action=up")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,11 +72,11 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
## 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 + r"?plugin_name=disks&action=down")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?store=1&disks_listed&disks_visible_menu=1&disks_rank=100")
|
self.cmd.go(url + r"?store=1&disks_listed&disks_visible_menu=1&disks_rank=100")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
self.cmd.go(url + u"?plugin_name=disks&action=down")
|
self.cmd.go(url + r"?plugin_name=disks&action=down")
|
||||||
self.cmd.find('Plugin Manager')
|
self.cmd.find('Plugin Manager')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
|
|
||||||
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(r'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)
|
||||||
self.assertTrue("disks" in plugins)
|
self.assertTrue("disks" in plugins)
|
||||||
|
|
|
@ -38,7 +38,7 @@ class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
if store is None:
|
if store is None:
|
||||||
pass
|
pass
|
||||||
elif store == "add_user":
|
elif store == "add_user":
|
||||||
if (user is None) or (re.search(u'\W', user)):
|
if (user is None) or (re.search(r'\W', user)):
|
||||||
self.hdf["Data.Warning"] = "Plugins.user_manager.InvalidUserName"
|
self.hdf["Data.Warning"] = "Plugins.user_manager.InvalidUserName"
|
||||||
elif not new_pw:
|
elif not new_pw:
|
||||||
self.hdf["Data.Warning"] = "EmptyNewPassword"
|
self.hdf["Data.Warning"] = "EmptyNewPassword"
|
||||||
|
|
|
@ -28,8 +28,10 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
"""try to read automount form"""
|
"""try to read automount form"""
|
||||||
url = self.url + "volume_automount?weblang=en&device=%2Fdev%2F" + self.device
|
url = self.url + "volume_automount?weblang=en&device=%2Fdev%2F" + self.device
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
|
## first: turn it off
|
||||||
|
self.cmd.go(url + "&action=disable")
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
self.cmd.find('Opening during startup')
|
self.cmd.find('is disabled')
|
||||||
|
|
||||||
|
|
||||||
def test_toggle(self):
|
def test_toggle(self):
|
||||||
|
@ -37,11 +39,11 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
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%s&action=disable" % self.device)
|
self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=disable" % self.device)
|
||||||
self.cmd.find("Automatic opening disabled")
|
self.cmd.find("Automatic activation disabled")
|
||||||
self.cmd.find("is disabled")
|
self.cmd.find("is disabled")
|
||||||
self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=enable" % self.device)
|
self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=enable" % self.device)
|
||||||
self.cmd.find("Automatic opening enabled")
|
self.cmd.find("Automatic activation enabled")
|
||||||
self.cmd.notfind("is disabled")
|
self.cmd.find("is enabled")
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_input(self):
|
def test_invalid_input(self):
|
||||||
|
@ -49,6 +51,6 @@ class unittests(cryptobox.web.testclass.WebInterfaceTestClass):
|
||||||
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%s&action=foobar" % self.device)
|
self.cmd.go(url + "?device=%%2Fdev%%2F%s&action=foobar" % self.device)
|
||||||
self.cmd.notfind("Automatic opening disabled")
|
self.cmd.notfind("Automatic activation disabled")
|
||||||
self.cmd.notfind("Automatic opening enabled")
|
self.cmd.notfind("Automatic activation enabled")
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
__revision__ = "$Id"
|
__revision__ = "$Id"
|
||||||
|
|
||||||
import cryptobox.plugins.base
|
import cryptobox.plugins.base
|
||||||
|
import cryptobox.core.container
|
||||||
from cryptobox.core.exceptions import *
|
from cryptobox.core.exceptions import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,21 +56,34 @@ class volume_automount(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||||
return "volume_automount"
|
return "volume_automount"
|
||||||
|
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
"""Override bootup behaviour.
|
||||||
|
|
||||||
|
Mount all volumes marked as 'automount'.
|
||||||
|
"""
|
||||||
|
cryptobox.plugins.base.CryptoBoxPlugin.setup(self)
|
||||||
|
for cont in self.cbox.get_container_list():
|
||||||
|
if self.__is_auto_mount(cont) and not cont.is_mounted():
|
||||||
|
cont.mount()
|
||||||
|
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
return str(self.__is_auto_mount())
|
return str(self.__is_auto_mount(self.cbox.get_container(self.device)))
|
||||||
|
|
||||||
|
|
||||||
def __prepare_hdf(self):
|
def __prepare_hdf(self):
|
||||||
if self.__is_auto_mount():
|
if self.__is_auto_mount(self.cbox.get_container(self.device)):
|
||||||
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 __is_auto_mount(self):
|
def __is_auto_mount(self, container):
|
||||||
container = self.cbox.get_container(self.device)
|
|
||||||
if not container:
|
if not container:
|
||||||
return False
|
return False
|
||||||
|
## only valid for plain volumes
|
||||||
|
if container.get_type() != cryptobox.core.container.CONTAINERTYPES["plain"]:
|
||||||
|
return False
|
||||||
if container.attributes.has_key("automount"):
|
if container.attributes.has_key("automount"):
|
||||||
return container.attributes["automount"] == self.true_string
|
return container.attributes["automount"] == self.true_string
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -47,7 +47,7 @@ WarningMessage {
|
||||||
Text = Formatting of the selected filesystem failed for unknown reasons - sorry!
|
Text = Formatting of the selected filesystem failed for unknown reasons - sorry!
|
||||||
Link.Text = View log messages
|
Link.Text = View log messages
|
||||||
Link.Rel = logs
|
Link.Rel = logs
|
||||||
Link.Attr1.name = pattern
|
Link.Attr1.name = level
|
||||||
Link.Attr1.value = ERROR
|
Link.Attr1.value = ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ Link = Activation
|
||||||
|
|
||||||
|
|
||||||
Title {
|
Title {
|
||||||
Mount = Open volume
|
Mount = Opening a volume
|
||||||
Umount = Turn on the volume
|
Umount = Closing a volume
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@ SuccessMessage {
|
||||||
|
|
||||||
WarningMessage {
|
WarningMessage {
|
||||||
MountFailed {
|
MountFailed {
|
||||||
Title = Activation failed
|
Title = Opening failed
|
||||||
Text = The volume could not be activated for some reason. Sorry!
|
Text = The volume could not be activated for some reason. Sorry!
|
||||||
}
|
}
|
||||||
|
|
||||||
MountCryptoFailed {
|
MountCryptoFailed {
|
||||||
Title = Activation failed
|
Title = Opening failed
|
||||||
Text = Maybe you entered the wrong password?
|
Text = Maybe you entered the wrong password?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,10 @@ 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
|
url = self.url + "volume_mount?weblang=en&device=%2Fdev%2F" + self.device
|
||||||
self.register_auth(url)
|
self.register_auth(url)
|
||||||
|
## first: umount if necessary
|
||||||
|
self.cmd.go(url + "&action=umount")
|
||||||
|
## now we can start
|
||||||
self.cmd.go(url)
|
self.cmd.go(url)
|
||||||
|
#TODO: make sure, that device is closed before
|
||||||
self.cmd.find('Open volume')
|
self.cmd.find('Open volume')
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,88 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# this script symlinks all cbx po files to thorax' pootle dir
|
# this script symlinks all cbx po files to a language directory structure, as
|
||||||
# it is useful to be root for this - otherwise chown and the pootle restart will fail
|
# it is used by the pootle translation server
|
||||||
#
|
#
|
||||||
|
# all language files are chgrp'ed to the 'pootle' group and group write
|
||||||
|
# permissions are added
|
||||||
|
#
|
||||||
|
# call this script whenever you add _new_ languages to your translation server
|
||||||
|
#
|
||||||
|
# it is useful to be root while calling it - otherwise chgrp will fail
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Copyright 2006 sense.lab e.V.
|
||||||
|
#
|
||||||
|
# This file is part of the CryptoBox.
|
||||||
|
#
|
||||||
|
# The CryptoBox is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# The CryptoBox is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with the CryptoBox; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
test $# -ne 1 && echo "Usage: $(basename $0) TARGET_DIR" && exit 1
|
test $# -ne 1 && echo "Usage: $(basename $0) TARGET_DIR" && exit 1
|
||||||
|
|
||||||
test ! -d "$1" && echo "target directory does not exist: '$1'" && exit 1
|
test ! -d "$1" && echo "target directory does not exist: '$1'" && exit 1
|
||||||
|
|
||||||
TARGETPATH=$1
|
if test "$(id -u)" == 0
|
||||||
|
then is_root=1
|
||||||
|
else is_root=0
|
||||||
|
echo "$(basename $0) not running as root: the language files will not be writeable for pootle" >&2
|
||||||
|
echo " run this script as root to change the permissions of the language files appropriately" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEST_GROUP=pootle
|
||||||
|
TARGETPATH=${1%/}
|
||||||
BASEPATH=$(cd $(dirname "$0")/..; pwd)
|
BASEPATH=$(cd $(dirname "$0")/..; pwd)
|
||||||
|
|
||||||
mkdir -p ${TARGETPATH}/templates
|
############# functions ###############
|
||||||
|
|
||||||
for language in `ls ${BASEPATH}/intl/` ; do
|
# symlink a language file and chgrp if possible
|
||||||
|
# Paramters: LANG_FILE LANGUAGE
|
||||||
|
process_language_file()
|
||||||
|
{
|
||||||
|
test ! -d "${TARGETPATH}/$2" && mkdir -p "${TARGETPATH}/$2"
|
||||||
|
ln -sfn "$1" "${TARGETPATH}/$2/"
|
||||||
|
if test "$is_root" == 1
|
||||||
|
then chgrp "$DEST_GROUP" "$1" "$TARGETPATH/$2"
|
||||||
|
chmod g+w "$1" "$TARGETPATH/$2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
############# main #################
|
||||||
|
|
||||||
|
|
||||||
|
for language in $(ls ${BASEPATH}/intl/) ; do
|
||||||
test ! -d "${BASEPATH}/intl/${language}" && continue
|
test ! -d "${BASEPATH}/intl/${language}" && continue
|
||||||
echo "Processing $language ..."
|
echo "Processing $language ..."
|
||||||
[ ! -d ${TARGETPATH}/${language} ] && mkdir -p ${TARGETPATH}/${language}
|
[ ! -d ${TARGETPATH}/${language} ] && mkdir -p ${TARGETPATH}/${language}
|
||||||
## base translation
|
## base translation
|
||||||
find ${BASEPATH}/intl/${language} -name \*.po -exec ln -sfn '{}' ${TARGETPATH}/${language}/ \;
|
find "${BASEPATH}/intl/${language}" -name \*.po | while read fname
|
||||||
|
do process_language_file "$fname" "$language"
|
||||||
|
done
|
||||||
## plugin translations
|
## plugin translations
|
||||||
for plugin in $(ls ${BASEPATH}/plugins/); do
|
find "${BASEPATH}/plugins/" -name \*.po | \
|
||||||
test ! -d "${BASEPATH}/plugins/${plugin}" && continue
|
grep "/intl/$language/" | while read fname
|
||||||
find ${BASEPATH}/plugins/${plugin}/intl/${language} -name \*.po -exec ln -sfn '{}' ${TARGETPATH}/${language}/ \;
|
do process_language_file "$fname" "$language"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "Processing template files ..."
|
echo "Processing template files ..."
|
||||||
find ${BASEPATH}/intl ${BASEPATH}/plugins -type f -name \*.pot | while read fname
|
find ${BASEPATH}/intl ${BASEPATH}/plugins -type f -name \*.pot | while read fname
|
||||||
do ln -sfn $fname ${TARGETPATH}/templates/
|
do process_language_file "$fname" "template"
|
||||||
done
|
done
|
||||||
|
|
||||||
chown -R pootle. ${TARGETPATH}
|
|
||||||
/etc/init.d/pootle restart
|
|
||||||
|
|
||||||
|
|
|
@ -10,5 +10,5 @@ __all__ = ['core', 'web', 'plugins', 'tests']
|
||||||
__revision__ = "$Id$"
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.2.53"
|
__version__ = "0.2.54"
|
||||||
|
|
||||||
|
|
|
@ -208,41 +208,6 @@ class CryptoBoxContainer:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def set_busy(self, new_state, time_limit=300):
|
|
||||||
"""Set the current busy state.
|
|
||||||
|
|
||||||
The timelimit is specified in seconds.
|
|
||||||
"""
|
|
||||||
if new_state:
|
|
||||||
self.cbox.busy_devices[self.device] = int(time.time() + time_limit)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
if self.cbox.busy_devices[self.device]:
|
|
||||||
del self.cbox.busy_devices[self.device]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def is_busy(self):
|
|
||||||
"""Check the busy state of the container.
|
|
||||||
"""
|
|
||||||
if not self.cbox.busy_devices.has_key(self.device):
|
|
||||||
self.cbox.log.debug("no 'busy' attribute for '%s'" % self.get_name())
|
|
||||||
return False
|
|
||||||
## invalid value - can happen after saving and loading the database
|
|
||||||
if not isinstance(self.cbox.busy_devices[self.device], int):
|
|
||||||
self.cbox.log.debug("invalid 'busy' attribute for '%s'" % self.get_name())
|
|
||||||
del db_entry["busy"]
|
|
||||||
return False
|
|
||||||
if time.time() >= self.cbox.busy_devices[self.device]:
|
|
||||||
self.cbox.log.debug("expired 'busy' attribute for '%s'" % self.get_name())
|
|
||||||
del db_entry["busy"]
|
|
||||||
return False
|
|
||||||
## lock is still active
|
|
||||||
self.cbox.log.debug("active 'busy' attribute for '%s'" % self.get_name())
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def change_password(self, oldpw, newpw):
|
def change_password(self, oldpw, newpw):
|
||||||
"""Change the password of an encrypted container.
|
"""Change the password of an encrypted container.
|
||||||
|
|
||||||
|
@ -311,6 +276,23 @@ class CryptoBoxContainer:
|
||||||
raise CBChangePasswordError(error_msg)
|
raise CBChangePasswordError(error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def is_busy(self):
|
||||||
|
"""Return the current state of the busy flag of this device.
|
||||||
|
|
||||||
|
The busy flag is mainly used to indicate that the device may not be used
|
||||||
|
while it is being formatted or similar.
|
||||||
|
"""
|
||||||
|
return self.cbox.get_device_busy_state(self.device)
|
||||||
|
|
||||||
|
|
||||||
|
def set_busy(self, new_state, timeout=300):
|
||||||
|
"""Set the busy state of this device.
|
||||||
|
|
||||||
|
Either set or remove this flag.
|
||||||
|
The timeout is optional and defaults to five minutes.
|
||||||
|
"""
|
||||||
|
self.cbox.set_device_busy_state(self.device, new_state, timeout)
|
||||||
|
|
||||||
|
|
||||||
## ****************** internal stuff *********************
|
## ****************** internal stuff *********************
|
||||||
|
|
||||||
|
@ -424,7 +406,7 @@ class CryptoBoxContainer:
|
||||||
"-c", os.devnull,
|
"-c", os.devnull,
|
||||||
"-w", os.devnull,
|
"-w", os.devnull,
|
||||||
self.device ])
|
self.device ])
|
||||||
(stdout, stder) = proc.communicate()
|
(stdout, stderr) = proc.communicate()
|
||||||
if proc.returncode == 0:
|
if proc.returncode == 0:
|
||||||
## we found a uuid
|
## we found a uuid
|
||||||
return stdout.strip()
|
return stdout.strip()
|
||||||
|
@ -644,14 +626,20 @@ class CryptoBoxContainer:
|
||||||
raise CBVolumeIsActive(
|
raise CBVolumeIsActive(
|
||||||
"deactivate the partition before filesystem initialization")
|
"deactivate the partition before filesystem initialization")
|
||||||
def format():
|
def format():
|
||||||
import os
|
"""This function will get called as a seperate thread.
|
||||||
old_name = self.get_name()
|
|
||||||
|
To avoid the non-sharing cpu distribution between the formatting thread
|
||||||
|
and the main interface, we fork and let the parent wait for the child.
|
||||||
|
This should be handled using the kernel's threading features.
|
||||||
|
"""
|
||||||
|
## create a local object - to store different values for each thread
|
||||||
|
loc_data = threading.local()
|
||||||
|
loc_data.old_name = self.get_name()
|
||||||
self.set_busy(True, 600)
|
self.set_busy(True, 600)
|
||||||
self.cbox.log.debug("Turn the busy flag on: %s" % self.device)
|
|
||||||
## give the main thread a chance to continue
|
## give the main thread a chance to continue
|
||||||
child_pid = os.fork()
|
loc_data.child_pid = os.fork()
|
||||||
if child_pid == 0:
|
if loc_data.child_pid == 0:
|
||||||
proc = subprocess.Popen(
|
loc_data.proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
|
@ -660,17 +648,19 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["nice"],
|
self.cbox.prefs["Programs"]["nice"],
|
||||||
self.cbox.prefs["Programs"]["mkfs"],
|
self.cbox.prefs["Programs"]["mkfs"],
|
||||||
"-t", fs_type, self.device])
|
"-t", fs_type, self.device])
|
||||||
(stdout, sterr) = proc.communicate()
|
loc_data.proc.wait()
|
||||||
## for to allow error detection
|
## for to allow error detection
|
||||||
if proc.returncode == 0:
|
if loc_data.proc.returncode == 0:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
## skip cleanup stuff (as common for sys.exit)
|
## skip cleanup stuff (as common for sys.exit)
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
else:
|
else:
|
||||||
os.waitpid(child_pid, 0)
|
os.waitpid(loc_data.child_pid, 0)
|
||||||
self.set_name(old_name)
|
try:
|
||||||
|
self.set_name(loc_data.old_name)
|
||||||
|
except CBNameIsInUse:
|
||||||
|
pass
|
||||||
self.set_busy(False)
|
self.set_busy(False)
|
||||||
self.cbox.log.debug("Turn the busy flag off: %s" % self.device)
|
|
||||||
bg_task = threading.Thread(target=format)
|
bg_task = threading.Thread(target=format)
|
||||||
bg_task.start()
|
bg_task.start()
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
@ -731,14 +721,20 @@ class CryptoBoxContainer:
|
||||||
self.cbox.log.error(err_msg)
|
self.cbox.log.error(err_msg)
|
||||||
raise CBCreateError(err_msg)
|
raise CBCreateError(err_msg)
|
||||||
def format_luks():
|
def format_luks():
|
||||||
import os
|
"""This function will get called as a seperate thread.
|
||||||
old_name = self.get_name()
|
|
||||||
|
To avoid the non-sharing cpu distribution between the formatting thread
|
||||||
|
and the main interface, we fork and let the parent wait for the child.
|
||||||
|
This should be handled using the kernel's threading features.
|
||||||
|
"""
|
||||||
|
## create a local object - to store different values for each thread
|
||||||
|
loc_data = threading.local()
|
||||||
|
loc_data.old_name = self.get_name()
|
||||||
self.set_busy(True, 600)
|
self.set_busy(True, 600)
|
||||||
self.cbox.log.debug("Turn the busy flag on: %s" % self.device)
|
loc_data.child_pid = os.fork()
|
||||||
child_pid = os.fork()
|
if loc_data.child_pid == 0:
|
||||||
if child_pid == 0:
|
|
||||||
## make the filesystem
|
## make the filesystem
|
||||||
proc = subprocess.Popen(
|
loc_data.proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdin = None,
|
stdin = None,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
|
@ -748,17 +744,16 @@ class CryptoBoxContainer:
|
||||||
self.cbox.prefs["Programs"]["mkfs"],
|
self.cbox.prefs["Programs"]["mkfs"],
|
||||||
"-t", fs_type,
|
"-t", fs_type,
|
||||||
os.path.join(self.__dmDir, self.name)])
|
os.path.join(self.__dmDir, self.name)])
|
||||||
(stdou, stderr) = proc.communicate()
|
loc_data.proc.wait()
|
||||||
## wait to allow error detection
|
## wait to allow error detection
|
||||||
if proc.returncode == 0:
|
if loc_data.proc.returncode == 0:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
## skip cleanup stuff (as common for sys.exit)
|
## skip cleanup stuff (as common for sys.exit)
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
else:
|
else:
|
||||||
os.waitpid(child_pid, 0)
|
os.waitpid(loc_data.child_pid, 0)
|
||||||
self.set_name(old_name)
|
self.set_name(loc_data.old_name)
|
||||||
self.set_busy(False)
|
self.set_busy(False)
|
||||||
self.cbox.log.debug("Turn the busy flag off: %s" % self.device)
|
|
||||||
## remove the mapping - for every exit status
|
## remove the mapping - for every exit status
|
||||||
self.__umount_luks()
|
self.__umount_luks()
|
||||||
bg_task = threading.Thread(target=format_luks)
|
bg_task = threading.Thread(target=format_luks)
|
||||||
|
|
|
@ -31,6 +31,7 @@ import re
|
||||||
import os
|
import os
|
||||||
import cryptobox.core.tools as cbxTools
|
import cryptobox.core.tools as cbxTools
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
class CryptoBox:
|
class CryptoBox:
|
||||||
|
@ -46,10 +47,40 @@ class CryptoBox:
|
||||||
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
|
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
|
||||||
self.__run_tests()
|
self.__run_tests()
|
||||||
self.__containers = []
|
self.__containers = []
|
||||||
self.busy_devices = {}
|
self.__busy_devices = {}
|
||||||
|
self.__busy_devices_sema = threading.BoundedSemaphore()
|
||||||
self.reread_container_list()
|
self.reread_container_list()
|
||||||
|
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
"""Initialize the cryptobox.
|
||||||
|
"""
|
||||||
|
self.log.info("Starting up the CryptoBox ...")
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""Umount all containers and shutdown everything safely.
|
||||||
|
"""
|
||||||
|
self.log.info("Shutting down the CryptoBox ...")
|
||||||
|
## umount all containers
|
||||||
|
self.log.info("Umounting all volumes ...")
|
||||||
|
self.reread_container_list()
|
||||||
|
for cont in self.get_container_list():
|
||||||
|
cont.umount()
|
||||||
|
## save all settings
|
||||||
|
self.log.info("Storing local settings ...")
|
||||||
|
self.prefs.write()
|
||||||
|
if self.prefs.get_active_partition:
|
||||||
|
self.prefs.umount_partition()
|
||||||
|
## shutdown logging as the last step
|
||||||
|
try:
|
||||||
|
self.log.info("Turning off logging ...")
|
||||||
|
self.log.close()
|
||||||
|
except AttributeError:
|
||||||
|
## there should be 'close' action - but it may fail silently
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __get_startup_logger(self):
|
def __get_startup_logger(self):
|
||||||
"""Initialize the configured logging facility of the CryptoBox.
|
"""Initialize the configured logging facility of the CryptoBox.
|
||||||
|
|
||||||
|
@ -128,6 +159,44 @@ class CryptoBox:
|
||||||
self.__containers.sort(cmp = lambda x, y: x.get_name() < y.get_name() and -1 or 1)
|
self.__containers.sort(cmp = lambda x, y: x.get_name() < y.get_name() and -1 or 1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_device_busy_state(self, device):
|
||||||
|
"""Return whether a device is currently marked as busy or not.
|
||||||
|
|
||||||
|
The busy flag can be turned off manually (recommended) or the timeout
|
||||||
|
can expire.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
self.__busy_devices_sema.acquire()
|
||||||
|
## not marked as busy
|
||||||
|
if not self.__busy_devices.has_key(device):
|
||||||
|
self.__busy_devices_sema.release()
|
||||||
|
return False
|
||||||
|
## timer is expired
|
||||||
|
if time.time() > self.__busy_devices[device]:
|
||||||
|
del self.__busy_devices[device]
|
||||||
|
self.__busy_devices_sema.release()
|
||||||
|
return False
|
||||||
|
self.__busy_devices_sema.release()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def set_device_busy_state(self, device, new_state, timeout=300):
|
||||||
|
"""Mark a device as busy.
|
||||||
|
|
||||||
|
This is especially useful during formatting, as this may take a long time.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
self.__busy_devices_sema.acquire()
|
||||||
|
self.log.debug("Turn busy flag %s: %s" % (new_state and "on" or "off", device))
|
||||||
|
if new_state:
|
||||||
|
self.__busy_devices[device] = time.time() + timeout
|
||||||
|
else:
|
||||||
|
if self.__busy_devices.has_key(device):
|
||||||
|
del self.__busy_devices[device]
|
||||||
|
self.log.debug("Current busy flags: %s" % str(self.__busy_devices))
|
||||||
|
self.__busy_devices_sema.release()
|
||||||
|
|
||||||
|
|
||||||
def is_config_partition(self, device):
|
def is_config_partition(self, device):
|
||||||
"""Check if a given partition contains configuration informations.
|
"""Check if a given partition contains configuration informations.
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import configobj, validate
|
import configobj, validate
|
||||||
|
import syslog
|
||||||
|
|
||||||
|
|
||||||
class CryptoBoxSettings:
|
class CryptoBoxSettings:
|
||||||
|
@ -56,6 +57,11 @@ class CryptoBoxSettings:
|
||||||
self.volumes_db = self.__get_volumes_database()
|
self.volumes_db = self.__get_volumes_database()
|
||||||
self.plugin_conf = self.__get_plugin_config()
|
self.plugin_conf = self.__get_plugin_config()
|
||||||
self.user_db = self.__get_user_db()
|
self.user_db = self.__get_user_db()
|
||||||
|
self.misc_files = []
|
||||||
|
self.__read_misc_files()
|
||||||
|
|
||||||
|
|
||||||
|
def __read_misc_files(self):
|
||||||
self.misc_files = self.__get_misc_files()
|
self.misc_files = self.__get_misc_files()
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,6 +156,7 @@ class CryptoBoxSettings:
|
||||||
if not self.get_active_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
|
||||||
|
self.__read_misc_files()
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
|
@ -363,9 +370,10 @@ class CryptoBoxSettings:
|
||||||
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 []
|
||||||
return [MiscConfigFile(os.path.join(misc_dir, f), self.log)
|
misc_files = []
|
||||||
for f in os.listdir(misc_dir)
|
for root, dirs, files in os.walk(misc_dir):
|
||||||
if os.path.isfile(os.path.join(misc_dir, f))]
|
misc_files.extend([os.path.join(root, e) for e in files])
|
||||||
|
return [MiscConfigFile(os.path.join(misc_dir, f), self.log) for f in misc_files]
|
||||||
|
|
||||||
|
|
||||||
def __get_config_filename(self, config_file):
|
def __get_config_filename(self, config_file):
|
||||||
|
@ -395,28 +403,46 @@ class CryptoBoxSettings:
|
||||||
def __configure_log_handler(self):
|
def __configure_log_handler(self):
|
||||||
"""Configure the log handler of the CryptoBox according to the config.
|
"""Configure the log handler of the CryptoBox according to the config.
|
||||||
"""
|
"""
|
||||||
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"]
|
if not log_level in log_level_avail:
|
||||||
if not log_level in log_level_avail:
|
|
||||||
raise TypeError
|
|
||||||
except KeyError:
|
|
||||||
raise CBConfigUndefinedError("Log", "Level")
|
|
||||||
except TypeError:
|
|
||||||
raise CBConfigInvalidValueError("Log", "Level", log_level,
|
raise CBConfigInvalidValueError("Log", "Level", log_level,
|
||||||
"invalid log level: only %s are allowed" % log_level_avail)
|
"invalid log level: only %s are allowed" % str(log_level_avail))
|
||||||
try:
|
log_destination = self.prefs["Log"]["Destination"].lower()
|
||||||
|
## keep this in sync with the spec and the log_destination branches below
|
||||||
|
log_dest_avail = ['file', 'syslog']
|
||||||
|
if not log_destination in log_dest_avail:
|
||||||
|
raise CBConfigInvalidValueError("Log", "Destination", log_destination,
|
||||||
|
"invalid log destination: only %s are allowed" % str(log_dest_avail))
|
||||||
|
if log_destination == 'file':
|
||||||
try:
|
try:
|
||||||
log_handler = logging.FileHandler(self.prefs["Log"]["Details"])
|
log_handler = logging.FileHandler(self.prefs["Log"]["Details"])
|
||||||
except KeyError:
|
except IOError:
|
||||||
raise CBConfigUndefinedError("Log", "Details")
|
raise CBEnvironmentError("could not write to log file (%s)" % \
|
||||||
except IOError:
|
self.prefs["Log"]["Details"])
|
||||||
raise CBEnvironmentError("could not write to log file (%s)" % \
|
log_handler.setFormatter(
|
||||||
self.prefs["Log"]["Details"])
|
logging.Formatter('%(asctime)s %(levelname)s: %(message)s'))
|
||||||
log_handler.setFormatter(
|
elif log_destination == 'syslog':
|
||||||
logging.Formatter('%(asctime)s CryptoBox %(levelname)s: %(message)s'))
|
log_facility = self.prefs["Log"]["Details"].upper()
|
||||||
|
log_facil_avail = ['KERN', 'USER', 'MAIL', 'DAEMON', 'AUTH', 'SYSLOG',
|
||||||
|
'LPR', 'NEWS', 'UUCP', 'CRON', 'AUTHPRIV', 'LOCAL0', 'LOCAL1',
|
||||||
|
'LOCAL2', 'LOCAL3', 'LOCAL4', 'LOCAL5', 'LOCAL6', 'LOCAL7']
|
||||||
|
if not log_facility in log_facil_avail:
|
||||||
|
raise CBConfigInvalidValueError("Log", "Details", log_facility,
|
||||||
|
"invalid log details for 'syslog': only %s are allowed" % \
|
||||||
|
str(log_facil_avail))
|
||||||
|
## retrive the log priority from the syslog module
|
||||||
|
log_handler = LocalSysLogHandler("CryptoBox",
|
||||||
|
getattr(syslog, 'LOG_%s' % log_facility))
|
||||||
|
log_handler.setFormatter(
|
||||||
|
logging.Formatter('%(asctime)s CryptoBox %(levelname)s: %(message)s'))
|
||||||
|
else:
|
||||||
|
## this should never happen - we just have it in case someone forgets
|
||||||
|
## to update the spec, the 'log_dest_avail' or the above branches
|
||||||
|
raise CBConfigInvalidValueError("Log", "Destination", log_destination,
|
||||||
|
"invalid log destination: only %s are allowed" % str(log_dest_avail))
|
||||||
cbox_log = logging.getLogger("CryptoBox")
|
cbox_log = logging.getLogger("CryptoBox")
|
||||||
## remove previous handlers
|
## remove previous handlers (from 'basicConfig')
|
||||||
cbox_log.handlers = []
|
cbox_log.handlers = []
|
||||||
## add new one
|
## add new one
|
||||||
cbox_log.addHandler(log_handler)
|
cbox_log.addHandler(log_handler)
|
||||||
|
@ -446,8 +472,8 @@ EventDir = string(default="/etc/cryptobox-server/events.d")
|
||||||
|
|
||||||
[Log]
|
[Log]
|
||||||
Level = option("debug", "info", "warn", "error", default="warn")
|
Level = option("debug", "info", "warn", "error", default="warn")
|
||||||
Destination = option("file", default="file")
|
Destination = option("file", "syslog", default="file")
|
||||||
Details = string(min=1)
|
Details = string(min=1, default="/var/log/cryptobox-server/cryptobox.log")
|
||||||
|
|
||||||
[WebSettings]
|
[WebSettings]
|
||||||
Stylesheet = string(min=1)
|
Stylesheet = string(min=1)
|
||||||
|
@ -595,3 +621,34 @@ class MiscConfigFile:
|
||||||
fdesc.close()
|
fdesc.close()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class LocalSysLogHandler(logging.Handler):
|
||||||
|
"""Pass logging messages to a local syslog server without unix sockets.
|
||||||
|
|
||||||
|
derived from: logging.SysLogHandler
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, prepend='CryptoBox', facility=syslog.LOG_USER):
|
||||||
|
logging.Handler.__init__(self)
|
||||||
|
self.formatter = None
|
||||||
|
self.facility = facility
|
||||||
|
syslog.openlog(prepend, 0, facility)
|
||||||
|
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""close the syslog connection
|
||||||
|
"""
|
||||||
|
syslog.closelog()
|
||||||
|
logging.Handler.close(self)
|
||||||
|
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
"""format and send the log message
|
||||||
|
"""
|
||||||
|
msg = "%s: %s" % (record.levelname, record.getMessage())
|
||||||
|
try:
|
||||||
|
syslog.syslog(record.levelno, msg)
|
||||||
|
except:
|
||||||
|
self.handleError(record)
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ def get_parent_blockdevices():
|
||||||
continue
|
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):
|
if re.search(r'\D', p_major) or re.search(r'\D', p_minor):
|
||||||
continue
|
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)):
|
if not os.path.isdir(os.path.join(os.path.sep, "sys", "block", p_device)):
|
||||||
|
|
|
@ -83,6 +83,18 @@ class CryptoBoxPlugin:
|
||||||
return self.__module__
|
return self.__module__
|
||||||
|
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
"""Any plugin that wants to define bootup actions may override this.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""Any plugin that wants to define shutdown actions may override this.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def get_icon(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
|
||||||
|
@ -92,7 +104,7 @@ class CryptoBoxPlugin:
|
||||||
'**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 re
|
import re
|
||||||
if (image is None) or (not re.match(u'[\w\-\.]*$', image)):
|
if (image is None) or (not re.match(r'[\w\-\.]*$', image)):
|
||||||
plugin_icon_file = os.path.join(self.plugin_dir, self.default_icon_filename)
|
plugin_icon_file = os.path.join(self.plugin_dir, self.default_icon_filename)
|
||||||
else:
|
else:
|
||||||
plugin_icon_file = os.path.join(self.plugin_dir, image)
|
plugin_icon_file = os.path.join(self.plugin_dir, image)
|
||||||
|
|
|
@ -144,7 +144,7 @@ CryptoBoxRootActions = CryptoBoxRootActions
|
||||||
filename=self.filenames["configFileBroken"])
|
filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
|
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
|
||||||
self.filenames["configFileBroken"])
|
self.filenames["configFileBroken"])
|
||||||
self.write_config("Details", "#out",
|
self.write_config("Destination", "Destination = foobar",
|
||||||
filename=self.filenames["configFileBroken"])
|
filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
|
self.assertRaises(CBConfigError, cryptobox.core.main.CryptoBox,
|
||||||
self.filenames["configFileBroken"])
|
self.filenames["configFileBroken"])
|
||||||
|
|
|
@ -83,6 +83,25 @@ class WebInterfaceSites:
|
||||||
self._cp_on_http_error = self.new_http_error_handler
|
self._cp_on_http_error = self.new_http_error_handler
|
||||||
## set initial language order
|
## set initial language order
|
||||||
self.lang_order = self.cbox.prefs["WebSettings"]["Languages"][:]
|
self.lang_order = self.cbox.prefs["WebSettings"]["Languages"][:]
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
"""Prepare the webinterface.
|
||||||
|
"""
|
||||||
|
self.cbox.setup()
|
||||||
|
for plugin in self.__plugin_manager.get_plugins():
|
||||||
|
if plugin:
|
||||||
|
plugin.setup()
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""Shutdown the webinterface safely.
|
||||||
|
"""
|
||||||
|
for plugin in self.__plugin_manager.get_plugins():
|
||||||
|
if plugin:
|
||||||
|
plugin.cleanup()
|
||||||
|
self.cbox.cleanup()
|
||||||
|
|
||||||
|
|
||||||
def __reset_dataset(self):
|
def __reset_dataset(self):
|
||||||
|
@ -421,7 +440,7 @@ class WebInterfaceSites:
|
||||||
self.cbox.log.debug(
|
self.cbox.log.debug(
|
||||||
"raised priority of preferred browser language: %s" % guess)
|
"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 lang_order) and (not re.search(u'\W', value)):
|
if value and (value in lang_order) and (not re.search(r'\W', value)):
|
||||||
lang_order.remove(value)
|
lang_order.remove(value)
|
||||||
lang_order.insert(0, value)
|
lang_order.insert(0, value)
|
||||||
self.cbox.log.debug(
|
self.cbox.log.debug(
|
||||||
|
@ -447,7 +466,7 @@ class WebInterfaceSites:
|
||||||
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(r"\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)]
|
||||||
|
@ -468,7 +487,7 @@ class WebInterfaceSites:
|
||||||
def __set_device(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) \
|
if device and re.match(r'[\w /\-]+$', device) \
|
||||||
and self.cbox.get_container(device):
|
and self.cbox.get_container(device):
|
||||||
self.cbox.log.debug("select device: %s" % device)
|
self.cbox.log.debug("select device: %s" % device)
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -64,9 +64,9 @@ WarningMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeMayNotBeMounted {
|
VolumeMayNotBeMounted {
|
||||||
Title = The container is mounted
|
Title = The volume is open
|
||||||
Text = This action is not available while the container is active. Please turn it off first.
|
Text = This action is not available while the container is active. Please close it first.
|
||||||
Link.Text = Deactivate volume
|
Link.Text = Close volume
|
||||||
Link.Rel = volume_mount
|
Link.Rel = volume_mount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ WarningMessage {
|
||||||
Text = We (the developer of the CryptoBox) would like to fix this problem for you and others. Please send the most recent part of the CryptoBox log to info@cryptobox.org. Thanks for your contribution!
|
Text = We (the developer of the CryptoBox) would like to fix this problem for you and others. Please send the most recent part of the CryptoBox log to info@cryptobox.org. Thanks for your contribution!
|
||||||
Link.Text = View log
|
Link.Text = View log
|
||||||
Link.Rel = logs
|
Link.Rel = logs
|
||||||
Link.Attr1.name = pattern
|
Link.Attr1.name = level
|
||||||
Link.Attr1.value = ERROR
|
Link.Attr1.value = ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,13 +62,13 @@ def:message_dispatch(mname, type, category)
|
||||||
?><?cs set:plugSuffix = string.slice(mname,savedX+1,string.length(mname))
|
?><?cs set:plugSuffix = string.slice(mname,savedX+1,string.length(mname))
|
||||||
?><?cs # choose the appropriate symbol file
|
?><?cs # choose the appropriate symbol file
|
||||||
?><?cs if:type == "success" ?><?cs
|
?><?cs if:type == "success" ?><?cs
|
||||||
set:symbolFile = "dialog-information_tango.png"
|
set:symbolFile = "dialog-information_tango.gif"
|
||||||
?><?cs elif:type == "warning" ?><?cs
|
?><?cs elif:type == "warning" ?><?cs
|
||||||
set:symbolFile = "dialog-error_tango.png"
|
set:symbolFile = "dialog-error_tango.gif"
|
||||||
?><?cs elif type == "environment_warning" ?><?cs
|
?><?cs elif type == "environment_warning" ?><?cs
|
||||||
set:symbolFile = "dialog-error_tango.png"
|
set:symbolFile = "dialog-error_tango.gif"
|
||||||
?><?cs elif type == "hint" ?><?cs
|
?><?cs elif type == "hint" ?><?cs
|
||||||
set:symbolFile = "dialog-warning_tango.png"
|
set:symbolFile = "dialog-warning_tango.gif"
|
||||||
?><?cs /if
|
?><?cs /if
|
||||||
?><?cs # preparations are done - now start writing
|
?><?cs # preparations are done - now start writing
|
||||||
?><div class="message"><table><tr><td class="message_symbol"><img src="<?cs
|
?><div class="message"><table><tr><td class="message_symbol"><img src="<?cs
|
||||||
|
|
BIN
www-data/dialog-error_tango.gif
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
www-data/dialog-information_tango.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
www-data/dialog-warning_tango.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 1.5 KiB |