URLs changed to new plugin addressing scheme

svn:keywords set
fixed: shutdown - delay reboot/poweroff by some seconds to finish the web page before
added: format_fs - show link to umount in case of active device
added: new plugin "language_selection"
fixed: recently introduced syntax error in 'network'
added: "volume_props" mentions encryption support via "format_fs" (including link)
updated: plugin-interface.txt
fixed: broken test case for date plugin (caused by twill, I guess)
added: "partition" plugin - better handling of config partition
This commit is contained in:
lars 2006-11-06 06:17:22 +00:00
parent 7905fe7051
commit 80337411ae
49 changed files with 259 additions and 116 deletions

View File

@ -7,7 +7,7 @@ class date(CryptoBoxPlugin.CryptoBoxPlugin):
requestAuth = False
rank = 10
def doAction(self, store=None, year=0, month=0, day=0, hour=0, minute=0):
def doAction(self, store=None, year=None, month=None, day=None, hour=None, minute=None):
import datetime
if store:
try:

View File

@ -4,10 +4,10 @@
<?cs call:handle_messages() ?>
<?cs call:print_form_header("set_date", "plugins/date") ?>
<?cs call:print_form_header("set_date", "date") ?>
<p><label for="date"><?cs var:html_escape(Lang.Plugins.date.Text.Date) ?>: </label><br/>
<select name="day" tabindex="1" size="0"><?cs
<select id="date" name="day" tabindex="1" size="0"><?cs
loop: x = #1, #31, #1 ?>
<?cs if:x == Data.Plugins.date.day ?><option selected="selected"><?cs
else ?><option><?cs /if ?><?cs var:x ?></option><?cs /loop ?>
@ -25,7 +25,7 @@
</select></p>
<p><label for="time"><?cs var:html_escape(Lang.Plugins.date.Text.Time) ?>: </label><br/>
<select name="hour" tabindex="4" size="0"><?cs
<select id="time" name="hour" tabindex="4" size="0"><?cs
loop: x = #0, #23, #1 ?>
<?cs if:x == Data.Plugins.date.hour ?><option selected="selected"><?cs
else ?><option><?cs /if ?><?cs if:x<10 ?>0<?cs /if ?><?cs var:x ?></option><?cs /loop ?>

View File

@ -23,7 +23,7 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def _getCurrentDate(self):
date_url = self.URL + "plugins/date"
date_url = self.URL + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.find("Data.Status.Plugins.date=([0-9]+/[0-9]+/[0-9]+/[0-9]+/[0-9]+/[0-9]+)$", "m")
@ -40,7 +40,15 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def _setDate(self, date):
date_url = self.URL + "plugins/date"
"""for now we have to use this function instead of the one below"""
date_url = self.URL + "date?store=1&year=%d&month=%d&day=%d&hour=%d&minute=%d" % (date["year"], date["month"], date["day"], date["hour"], date["minute"])
self.register_auth(date_url)
self.cmd.go(date_url)
def _setDateBroken(self, date):
"""this should work, but the parsing of twill seems to be broken"""
date_url = self.URL + "date"
self.register_auth(date_url)
self.cmd.go(date_url)
self.cmd.formvalue("set_date", "year", str(date["year"]))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -4,6 +4,6 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
'''display all devices'''
self.cmd.go(self.URL + "plugins/disks?weblang=en")
self.cmd.go(self.URL + "disks?weblang=en")
self.cmd.find("Disks")

View File

@ -7,12 +7,26 @@ Button.Format = Initialize filesystem
Text {
Confirm = Yes, I know what I am doing!
FormatWarning = All data of the selected filesystem will get lost!
FSType = Filesystem type
IsEncrypted = Encryption
Yes = Yes
No = No
UnmountBeforeInit = You must deactivate this volume before you may initialize it.
}
AdviceMessage {
FormatWarning {
Text = All data of the selected filesystem will get lost!
}
UnmountBeforeInit {
Text = You must deactivate this volume before you may initialize it.
Link.Text = Deactive volume now
Link.Rel = volume_mount
Link.Attr1.name = action
Link.Attr1.value = umount
Link.Attr2.name = redirect
Link.Attr2.value = format_fs
}
}
SuccessMessage {

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/format_fs?weblang=en&device=%2Fdev%2Floop1"
url = self.URL + "format_fs?weblang=en&device=%2Fdev%2Floop1"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Initializing filesystem')

View File

@ -7,13 +7,12 @@
<?cs call:handle_messages() ?>
<?cs if:Data.CurrentDisk.active ?>
<?cs call:hint(Lang.Plugins.format_fs.Text.UnmountBeforeInit) ?>
<?cs call:hint("Plugins.format_fs.UnmountBeforeInit") ?>
<?cs else ?>
<?cs call:print_form_header("set_type", "plugins/format_fs") ?>
<?cs call:hint(Lang.Plugins.format_fs.Text.FormatWarning) ?>
<?cs call:hint("Plugins.format_fs.FormatWarning") ?>
<?cs call:print_form_header("set_type", "format_fs") ?>
<p><label for="fs_type"><?cs var:html_escape(Lang.Plugins.format_fs.Text.FSType)
?>: </label><select name="fs_type" id="fs_type" size="0">
<?cs each:x = Data.Plugins.format_fs.fs_types ?>

View File

@ -7,13 +7,12 @@
<?cs call:handle_messages() ?>
<?cs if:Data.CurrentDisk.active ?>
<?cs call:hint(Lang.Plugins.format_fs.Text.UnmountBeforeInit) ?>
<?cs call:hint("Plugins.format_fs.UnmountBeforeInit") ?>
<?cs else ?>
<?cs call:print_form_header("set_luks", "plugins/format_fs") ?>
<?cs call:hint(Lang.Plugins.format_fs.Text.FormatWarning) ?>
<?cs call:hint("Plugins.format_fs.FormatWarning") ?>
<?cs call:print_form_header("set_luks", "format_fs") ?>
<p><?cs var:html_escape(Lang.Plugins.format_fs.Text.FSType) ?>: <?cs var:html_escape(Data.Plugins.format_fs.fs_type) ?></p>
<p><?cs var:html_escape(Lang.Plugins.format_fs.Text.IsEncrypted) ?>: <?cs if:Data.Plugins.format_fs.container_type == "luks" ?><?cs
var:html_escape(Lang.Plugins.format_fs.Text.Yes) ?><?cs else ?><?cs

View File

@ -4,7 +4,7 @@ class help(CryptoBoxPlugin.CryptoBoxPlugin):
pluginCapabilities = [ "menu" ]
requestAuth = False
rank = 50
rank = 80
def doAction(self, page=""):
'''prints the offline wikipage

View File

@ -7,23 +7,23 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
'''help pages should be available in different languages'''
## check english help pages
self.cmd.go(self.URL + "plugins/help?weblang=en")
self.cmd.go(self.URL + "help?weblang=en")
self.cmd.find("Table of Contents")
self.cmd.find("Getting started")
self.cmd.go(self.URL + "plugins/help?weblang=de")
self.cmd.go(self.URL + "help?weblang=de")
self.cmd.find("Table of Contents")
self.cmd.find("Wie geht es los")
self.cmd.go(self.URL + "plugins/help?weblang=si")
self.cmd.go(self.URL + "help?weblang=si")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
#TODO: add a slovene text here, as soon as the help is translated
self.cmd.go(self.URL + "plugins/help?weblang=fr")
self.cmd.go(self.URL + "help?weblang=fr")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")
#TODO: add a french text here, as soon as the help is translated
## test a random language - it should fall back to english
self.cmd.go(self.URL + "plugins/help?weblang=foobar")
self.cmd.go(self.URL + "help?weblang=foobar")
self.assertRaises(TwillAssertionError, self.cmd.notfind, "Table of Contents")

View File

@ -0,0 +1,5 @@
Name = Choose interface language
Link = Languages
Title.Language = Choose an interface language

View File

@ -0,0 +1,15 @@
<?cs # $Id$ ?>
<h1><?cs var:html_escape(Lang.Plugins.language_selection.Title.Language) ?></h1>
<?cs call:handle_messages() ?>
<div id="lang">
<ul>
<?cs loop:index = #0, subcount(Data.Languages)-1, #1 ?>
<li><a href="<?cs
call:link("disks", 'weblang', Data.Languages[index].name, '','') ?>" title="<?cs
var:html_escape(Data.Languages[index].link) ?>" /><?cs
var:html_escape(Data.Languages[index].link) ?></a></li><?cs /loop ?>
</ul>
</div>

View File

@ -0,0 +1,16 @@
import CryptoBoxPlugin
class language_selection(CryptoBoxPlugin.CryptoBoxPlugin):
pluginCapabilities = [ "system", "menu" ]
requestAuth = False
rank = 60
def doAction(self):
return "language_selection"
def getStatus(self):
return "TODO"

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,10 @@
import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "language_selection?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('hoose an interface language')

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_logs(self):
log_url = self.URL + "plugins/logs"
log_url = self.URL + "logs"
self.register_auth(log_url)
self.cmd.go(log_url)
self.cmd.find('class="console"')
@ -14,7 +14,7 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
## 2) the log message does not get lost in a possible stream of log messages
log_text = "unittest - just a marker - please ignore"
self.cbox.log.error(log_text)
log_url = self.URL + "plugins/logs"
log_url = self.URL + "logs"
self.register_auth(log_url)
self.cmd.go(log_url)
self.cmd.find(log_text)

View File

@ -8,7 +8,7 @@
<?cs call:handle_messages() ?>
<?cs call:print_form_header("set_ip", "plugins/network") ?>
<?cs call:print_form_header("set_ip", "network") ?>
<p><label for="ip"><?cs var:html_escape(Lang.Plugins.network.Text.IP) ?>: </label>
<input class="ipnum" type="text" tabindex="1" name="ip1" size="3" id="ip"

View File

@ -84,11 +84,11 @@ class network(CryptoBoxPlugin.CryptoBoxPlugin):
args = [
root_action_plug.IFCONFIG_BIN,
root_action_plug.IFACE])
proc.wait()
(stdout, stderr) = proc.communicate()
(output, error) = proc.communicate()
if proc.returncode != 0: return (0,0,0,0)
## this regex matches the four numbers of the IP
match = re.search(u'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s',output)
match = re.search(u'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s', stdout)
if match:
## use the previously matched numbers
return tuple([int(e) for e in match.groups()])

View File

@ -8,11 +8,11 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
'''change of network address'''
## the time module is necessary for the CHANGE_IP_DELAY
import time
self.register_auth(self.URL + "plugins/network")
self.cmd.go(self.URL + "plugins/network")
self.register_auth(self.URL + "network")
self.cmd.go(self.URL + "network")
## extract the current IP from the network plugin output
def getCurrentIP():
self.cmd.go(self.URL + "plugins/network")
self.cmd.go(self.URL + "network")
self.cmd.show()
self.cmd.find(u'Data.Status.Plugins.network=([0-9\.]*)$', "m")
return self.locals["__match__"]
@ -23,7 +23,7 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
self.cmd.echo(origIPocts)
wrongIP = "192.168.123.321"
def setIP((ip1, ip2, ip3, ip4)):
self.cmd.go(self.URL + "plugins/network")
self.cmd.go(self.URL + "network")
self.cmd.formvalue("set_ip", "ip1", str(ip1))
self.cmd.formvalue("set_ip", "ip2", str(ip2))
self.cmd.formvalue("set_ip", "ip3", str(ip3))

View File

@ -1,5 +1,5 @@
Name = Disk partitioning
Link = Disk partitioning
Link = Partition a disk
Title.Partition = Disk partitions
@ -24,9 +24,15 @@ Text {
PartType = Type
Size = Size (MB)
SelectDevice = Choose a disk for partitioning
WarningMessage = If you continue, you will destroy all data on the choosen disk. Please be VERY careful!
ProgressInfo = Progress of formatting:
CreateConfigPartition = create config partition
CreateConfigPartition = Automatically creating a configuration partition.
RemovalContainers = These disks will be destroyed, if you continue
}
AdviceMessage {
DeviceDataIsLost {
Text = If you continue, you will destroy all data on the choosen disk. Please be VERY careful!
}
}
SuccessMessage {
@ -61,6 +67,8 @@ WarningMessage {
DiskIsBusy {
Title = This disk is busy
Text = Please deactivate all containers of this disk before partitioning.
Link.Text = Show all disks
Link.Rel = disks
}
PartitionTooBig {

View File

@ -24,8 +24,8 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
## load default hdf values
self.__prepareDataset()
## retrieve some values from 'args' - defaults are empty
self.withConfigPartition = self.__isWithConfigPartition(args)
self.device = self.__getSelectedDevice(args)
self.withConfigPartition = self.__isWithConfigPartition()
self.cbox.log.debug("partition plugin: selected device=%s" % str(self.device))
self.deviceSize = self.__getAvailableDeviceSize(self.device)
try:
@ -86,7 +86,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
def __isDeviceBusy(self, device):
"""check if the device (or one of its partitions) is mounted"""
# TODO: the config partition is ignored, as it is not part of the container list - that is not good
# the config partition is ignored, as it will get unmounted if necessary
import re
for c in self.cbox.getContainerList():
if re.match(device + "\d*$", c.getDevice()):
@ -142,6 +142,8 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
parts = self.__getPartitionsFromArgs(args)
if parts:
self.__setPartitionData(parts)
if CryptoBoxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
self.cbox.prefs.umountPartition()
if not self.__runFDisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
return self.__actionAddPartition(args)
@ -162,8 +164,12 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
result = formatPart_gen.next()
## after the first partiton, we can reRead the containerList (as the possible config partition was already created)
if self.withConfigPartition and (counter == 1):
## important: reRead the containerList
self.cbox.reReadContainerList()
## important: reRead the containerList - but somehow it breaks the flow (hanging process)
#self.cbox.reReadContainerList()
## write config data
self.cbox.prefs.mountPartition()
self.cbox.prefs.write()
self.cbox.log.info("settings stored on config partition")
## return the result
if result:
yield "OK"
@ -180,22 +186,30 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
import types
## we do not have to take special care for a possible config partition
parts = [ { "size": self.deviceSize, "type": "windows" } ]
## doe
## umount partition if necessary
if CryptoBoxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
self.cbox.prefs.umountPartition()
## partition it
if not self.__runFDisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
return None
result = [e for e in self.__formatPartitions(parts) if type(e) == types.BooleanType] # it is a generator, returning device names and bolean values
## "formatPartitions" is a generator, returning device names and bolean values
result = [e for e in self.__formatPartitions(parts) if type(e) == types.BooleanType]
if self.withConfigPartition:
self.cbox.prefs.mountPartition()
self.cbox.prefs.write()
## check if there is a "False" return value
if False in result:
## operation failed
self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
self.cbox.log.info("easy partitioning failed")
return None
return "select_partitions"
else:
## operation was successful
self.hdf["Data.Success"] = "Plugins.partition.EasySetup"
self.cbox.log.info("easy partitioning succeeded")
return None
## do not show the disk overview immediately - it does not get updated that fast
return { "plugin":"system_preferences", "values":[] }
def __setPartitionData(self, parts):
@ -212,6 +226,12 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
self.hdf[self.hdf_prefix + "CreateConfigPartition"] = "1"
for t in self.PartTypes.keys():
self.hdf[self.hdf_prefix + "Types.%s" % t] = t
## store the currently existing partitions of the choosen block device
current_containers = [ e for e in self.cbox.getContainerList() if CryptoBoxTools.isPartOfBlockDevice(self.device, e.getDevice()) ]
## additionally store the uuids (to be removed after partitioning)
for (index, t) in enumerate(current_containers):
self.hdf[self.hdf_prefix + "ExistingContainers.%d.name" % index] = t.getName()
self.hdf[self.hdf_prefix + "ExistingContainers.%d.size" % index] = CryptoBoxTools.getBlockDeviceSizeHumanly(t.getDevice())
def __getPartitionsFromArgs(self, args):
@ -251,15 +271,15 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
return deviceSize
def __isWithConfigPartition(self, args):
try:
if args["create_config_partition"]:
createConfig = True
else:
createConfig = False
except KeyError:
createConfig = False
return createConfig
def __isWithConfigPartition(self):
"""check if we have to create a configuration partition"""
if self.cbox.prefs.requiresPartition():
active = self.cbox.prefs.getActivePartition()
## we need a partition, if there is no active one
if not active: return True
## check if the active one is part of the current device
return CryptoBoxTools.isPartOfBlockDevice(self.device, active)
return False
def __runFDisk(self, parts):
@ -350,6 +370,9 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
def __formatOnePartition(self, dev_name, type):
## first: retrieve UUID - it can be removed from the database afterwards
prev_uuid = [self.cbox.getUUIDForName(e.getName()) for e in self.cbox.getContainerList() if e.getDevice() == dev_name ]
## call "mkfs"
proc = subprocess.Popen(
shell = False,
args = [
@ -365,6 +388,9 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
self.cbox.log.warn("failed to create filesystem on %s: %s" % (dev_name, error))
return False
else:
## remove unused uuid
if prev_uuid:
self.cbox.removeUUID(prev_uuid[0])
return True

View File

@ -42,6 +42,9 @@ def __formatPartition(device, type):
## TODO: very ugly way of communication: it assumes, that failures are fast - success is slow
if proc.returncode == 0:
time.sleep(1)
return True
else:
return False
thread = threading.Thread()
thread.setDaemon(True)
thread.run = formatting

View File

@ -8,9 +8,9 @@
<?cs if:subcount(Data.Plugins.partition.BlockDevices) > 0 ?>
<?cs call:print_form_header("select_device", "plugins/partition") ?>
<?cs call:print_form_header("select_device", "partition") ?>
<?cs call:hint(Lang.Plugins.partition.Text.WarningMessage) ?>
<?cs call:hint("Plugins.partition.DeviceDataIsLost") ?>
<p><label for="block_device"><?cs var:html_escape(Lang.Plugins.partition.Text.SelectDevice) ?>: </label><br/>
<select name="block_device" id="block_device" tabindex="1" size="0">
@ -20,8 +20,8 @@
<?cs /each ?>
</select></p>
<p><input type="checkbox" name="create_config_partition" value="1" tabindex="2" id="create_config_partition" /><label for="create_config_partition"><?cs var:html_escape(Lang.Plugins.partition.Text.CreateConfigPartition) ?></label></p>
<!--
<p><input type="checkbox" name="create_config_partition" value="1" tabindex="2" id="create_config_partition" /><label for="create_config_partition"><?cs var:html_escape(Lang.Plugins.partition.Text.CreateConfigPartition) ?></label></p>
<?cs if:Data.Plugins.partition.CreateConfigPartition ?>
<input type="hidden" name="create_config_partition" value="1" />
<?cs /if ?>

View File

@ -24,7 +24,7 @@
<td><?cs var:Data.Plugins.partition.Parts[x].Size ?></td>
<td><?cs var:Data.Plugins.partition.Parts[x].Type ?></td>
<td>
<?cs call:print_form_header("part_del_" + x, "plugins/partition") ?>
<?cs call:print_form_header("part_del_" + x, "partition") ?>
<?cs include:Settings.PluginDir + "/partition/current_partition_info.cs" ?>
<input type="hidden" name="step" value="del_partition" />
<input type="hidden" name="del_num" value="<?cs var:x ?>" />
@ -37,7 +37,7 @@
<?cs # new partition input if space is available ?>
<?cs if:Data.Plugins.partition.availSize > 0 ?>
<tr>
<?cs call:print_form_header("part_add", "plugins/partition") ?>
<?cs call:print_form_header("part_add", "partition") ?>
<?cs include:Settings.PluginDir + "/partition/current_partition_info.cs" ?>
<input type="hidden" name="step" value="add_partition" />
<?cs set: x = subcount(Data.Plugins.partition.Parts) ?>
@ -55,10 +55,21 @@
</div>
<?cs if:subcount(Data.Plugins.partition.Parts) > 0 ?>
<?cs call:hint(Lang.Plugins.partition.Text.WarningMessage) ?>
<?cs if:Data.Plugins.partition.CreateConfigPartition ?><p><?cs var:html_escape(Lang.Plugins.partition.Text.CreateConfigPartition) ?></p><?cs /if ?>
<?cs call:print_form_header("part_finish", "plugins/partition") ?>
<?cs if:subcount(Data.Plugins.partition.ExistingContainers) ?>
<p align="left"><?cs var:html_escape(Lang.Plugins.partition.Text.RemovalContainers) ?>:
<ul>
<?cs each:item = Data.Plugins.partition.ExistingContainers ?>
<li><?cs var:html_escape(item.name) ?> (<?cs var:html_escape(item.size) ?>)</li>
<?cs /each ?>
</ul></p>
<?cs /if ?>
<?cs if:subcount(Data.Plugins.partition.Parts) > 0 ?>
<?cs call:hint("Plugins.partition.DeviceDataIsLost") ?>
<?cs call:print_form_header("part_finish", "partition") ?>
<?cs include:Settings.PluginDir + "/partition/current_partition_info.cs" ?>
<input type="hidden" name="step" value="finish" />
<button type="submit"><?cs var:html_escape(Lang.Plugins.partition.Button.SavePartitions) ?></button>

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/partition?weblang=en"
url = self.URL + "partition?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('VERY careful')

View File

@ -11,9 +11,10 @@ Python code interface:
- this function will get called whenever this plugins is involved in a request
- all arguments should be optional (e.g. for displaying a form without previous input values)
- the argument "store" should be used to process a form submission (just a recommendation)
- if the processing failed for some reason (invalid input, ...), it should manually set the
"Data.Warning" (resp. "Data.Error" or "Data.Success") to a value of your choice (preferably
you may want to use messages of your namespace (e.g. "Plugins.PLUGINNAME.InvalidInput"))
- if the processing failed for some reason (invalid input, ...), it should manually set
"Data.Warning" or "Data.Success") to a value of your choice (preferably
you may want to use messages of the namespace of your plugin
(e.g. "Data.Plugins.PLUGINNAME.WarningMessage.InvalidInput"))
- the return value should be the name of the template that should be displayed after processing
(a template file in the plugin directory takes precedence over global template files)
- the return value may also be a dictionary with the following elements:
@ -56,7 +57,7 @@ Language file structure:
Clearsilver template:
- should start with a "<h1>" tag (volume plugins: "h2")
- links to the plugin (e.g. in form headers) could look like the following:
<?cs call:link("plugins/PLUGINNAME",'','','','') ?>
<?cs call:link("PLUGINNAME",'','','','') ?>
- volume plugins must include "show_volume_[header|footer]" (see examples)

View File

@ -1,5 +1,5 @@
Name = Plugin Manager
Link = Plugin Manager
Link = Manage plugins
Title.PluginManager = Plugin Manager

View File

@ -17,7 +17,7 @@
<?cs call:handle_messages() ?>
<?cs call:print_form_header("manage_plugins", "plugins/plugin_manager") ?>
<?cs call:print_form_header("manage_plugins", "plugin_manager") ?>
<h2><?cs var:html_escape(Lang.Plugins.plugin_manager.Text.SystemPlugins) ?></h2>
<p>

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/plugin_manager?weblang=en"
url = self.URL + "plugin_manager?weblang=en"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Plugin Manager')

View File

@ -4,19 +4,12 @@
<?cs call:handle_messages() ?>
<!--
<p style="text-align: center">
<?cs var:html_escape(Lang.Plugins.shutdown.Text.ShutdownInfo) ?>
</p>
-->
<div class="plugin_system">
<a href="<?cs call:link('plugins/shutdown','type','shutdown','','') ?>">
<img src="<?cs call:link('icons/plugins/shutdown','image','gnome-shutdown.png','','')
<a href="<?cs call:link('shutdown','type','shutdown','','') ?>">
<img src="<?cs call:link('icons/shutdown','image','gnome-shutdown.png','','')
?>" alt="icon: shutdown" /><br/><?cs var:html_escape(Lang.Plugins.shutdown.Button.Shutdown) ?></a></div>
<div class="plugin_system">
<a href="<?cs call:link('plugins/shutdown','type','reboot','','') ?>">
<img src="<?cs call:link('icons/plugins/shutdown','image','gnome-reboot.png','','')
<a href="<?cs call:link('shutdown','type','reboot','','') ?>">
<img src="<?cs call:link('icons/shutdown','image','gnome-reboot.png','','')
?>" alt="icon: reboot" /><br/><?cs var:html_escape(Lang.Plugins.shutdown.Button.Reboot) ?></a></div>

View File

@ -2,11 +2,12 @@ Name = Shutdown or reboot the computer
Link = Shutdown
Title.Shutdown = Shutdown computer
Title.ProgressShutdown = The CryptoBox is shutting down
Title.ProgressReboot = The CryptoBox is rebooting
Button.Shutdown = Poweroff
Button.Reboot = Reboot
Text.ShutdownInfo = You may turn off or reboot your CryptoBox here.
SuccessMessage {
Shutdown {

View File

@ -0,0 +1,6 @@
<?cs # $Id$ ?>
<h1><?cs var:html_escape(Lang.Plugins.shutdown.Title.ProgressReboot) ?></h1>
<?cs call:handle_messages() ?>

View File

@ -0,0 +1,6 @@
<?cs # $Id$ ?>
<h1><?cs var:html_escape(Lang.Plugins.shutdown.Title.ProgressShutdown) ?></h1>
<?cs call:handle_messages() ?>

View File

@ -3,20 +3,20 @@
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
PLUGIN_TYPE = "cryptobox"
POWEROFF_BIN = "/sbin/poweroff"
REBOOT_BIN = "/sbin/reboot"
SHUTDOWN_BIN = "/sbin/shutdown"
## delay (in seconds) before shutdown
SHUTDOWN_DELAY = 3
import subprocess
import re
import sys
import os
def call_prog(progy):
proc = subprocess.Popen(
shell = False,
args = [progy])
proc.wait()
shell = False,
args = progy)
proc.communicate()
return proc.returncode == 0
@ -34,9 +34,9 @@ if __name__ == "__main__":
sys.exit(1)
if args[0] == "reboot":
result = call_prog(REBOOT_BIN)
result = call_prog([SHUTDOWN_BIN, "-t", str(SHUTDOWN_DELAY), "-r", "now"])
elif args[0] == "shutdown":
result = call_prog(POWEROFF_BIN)
result = call_prog([SHUTDOWN_BIN, "-t", str(SHUTDOWN_DELAY), "-h", "now"])
else:
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
sys.exit(1)

View File

@ -6,7 +6,7 @@ class shutdown(CryptoBoxPlugin.CryptoBoxPlugin):
pluginCapabilities = [ "system", "menu" ]
requestAuth = False
rank = 70
rank = 90
def doAction(self, type=None):
if not type:
@ -14,7 +14,7 @@ class shutdown(CryptoBoxPlugin.CryptoBoxPlugin):
elif type == "shutdown":
if self.__doShutdown("shutdown"):
self.hdf["Data.Success"] = "Plugins.shutdown.Shutdown"
return None
return "progress_shutdown"
else:
self.hdf["Data.Warning"] = "Plugins.shutdown.ShutdownFailed"
return "form_shutdown"
@ -23,7 +23,7 @@ class shutdown(CryptoBoxPlugin.CryptoBoxPlugin):
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
self.hdf["Data.Redirect.URL"] = ""
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
return None
return "progress_reboot"
else:
self.hdf["Data.Warning"] = "Plugins.shutdown.RebootFailed"
return "form_shutdown"

View File

@ -3,9 +3,9 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/shutdown"
url = self.URL + "shutdown"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('plugins/shutdown\?type=reboot')
self.cmd.find('plugins/shutdown\?type=shutdown')
self.cmd.find('shutdown\?type=reboot')
self.cmd.find('shutdown\?type=shutdown')

View File

@ -3,6 +3,6 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_preferences_overview(self):
self.cmd.go(self.URL + "plugins/system_preferences?weblang=en")
self.cmd.go(self.URL + "system_preferences?weblang=en")
self.cmd.find("Preferences")

View File

@ -1,5 +1,5 @@
Name = User Manager
Link = User Manager
Link = Manage users
Title {
UserManager = Manage users

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -16,7 +16,7 @@ class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def _gotoPage(self):
url = self.URL + "plugins/user_manager"
url = self.URL + "user_manager"
self.register_auth(url)
self.cmd.go(url)

View File

@ -17,7 +17,7 @@
<h2><?cs var:html_escape(Lang.Plugins.user_manager.Title.AddUser) ?></h2>
<p>
<?cs call:print_form_header("add_user", "plugins/user_manager") ?>
<?cs call:print_form_header("add_user", "user_manager") ?>
<table>
<tr><td class="left_column">
<label for="new_user"><?cs var:html_escape(Lang.Plugins.user_manager.Text.NewUser) ?>:</label></td>
@ -40,7 +40,7 @@
<h2><?cs var:html_escape(Lang.Plugins.user_manager.Title.ChangePassword) ?></h2>
<p>
<?cs call:print_form_header("change_password", "plugins/user_manager") ?>
<?cs call:print_form_header("change_password", "user_manager") ?>
<table>
<tr><td class="left_column">
<label for="chpw_user"><?cs var:html_escape(Lang.Plugins.user_manager.Text.ChangePasswordUser) ?>:</label></td>
@ -68,7 +68,7 @@
<h2><?cs var:html_escape(Lang.Plugins.user_manager.Title.DelUser) ?></h2>
<p>
<table><tr><td class="left_column">
<?cs call:print_form_header("del_user", "plugins/user_manager") ?>
<?cs call:print_form_header("del_user", "user_manager") ?>
<label for="user"><?cs var:html_escape(Lang.Plugins.user_manager.Text.DelUser) ?>: </label><select id="user" name="user" size="0">
<?cs each:x=Data.Plugins.user_manager.Users ?><?cs if:x != "admin" ?>
<option><?cs var:html_escape(x) ?></option>

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/volume_details?weblang=en&device=%2Fdev%2Floop1"
url = self.URL + "volume_details?weblang=en&device=%2Fdev%2Floop1"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Technical details')

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/volume_mount?weblang=en&device=%2Fdev%2Floop1"
url = self.URL + "volume_mount?weblang=en&device=%2Fdev%2Floop1"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('ctivate volume')

View File

@ -2,7 +2,7 @@
<?cs call:handle_messages() ?>
<p><?cs call:print_form_header("mount", "plugins/volume_mount") ?>
<p><?cs call:print_form_header("mount", "volume_mount") ?>
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<?cs if:Data.CurrentDisk.encryption ?>
<input type="hidden" name="action" value="mount_luks" />

View File

@ -2,7 +2,7 @@
<?cs call:handle_messages() ?>
<?cs call:print_form_header("umount", "plugins/volume_mount") ?>
<?cs call:print_form_header("umount", "volume_mount") ?>
<p><input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="umount" />
<button type="submit" tabindex="2"><?cs var:html_escape(Lang.Button.Umount) ?></button></p>

View File

@ -5,17 +5,30 @@ Title {
Properties = Properties
ChangeVolumeName = Change the name of this volume
ChangePassword = Change the password of this volume
Encryption = Encryption
}
Button {
ContainerNameSet = Change name
ChangePassword = Change password
FormatContainer = Format volume
}
Text {
UmountBeforeProps = You must deactivate a volume, if you want to change its properties.
Text.FormatForEncryptionSupport = This volume is not encrypted. If you want to turn on encryption, then you have to format the volume. Beware: this will destroy all data of this container.
AdviceMessage {
UmountBeforeProps {
Text = You must deactivate a volume, if you want to change its properties.
Link.Text = Deactive volume now
Link.Rel = volume_mount
Link.Attr1.name = action
Link.Attr1.value = umount
Link.Attr2.name = redirect
Link.Attr2.value = volume_props
}
}

View File

@ -3,7 +3,7 @@ import WebInterfaceTestClass
class unittests(WebInterfaceTestClass.WebInterfaceTestClass):
def test_read_form(self):
url = self.URL + "plugins/volume_props?weblang=en&device=%2Fdev%2Floop1"
url = self.URL + "volume_props?weblang=en&device=%2Fdev%2Floop1"
self.register_auth(url)
self.cmd.go(url)
self.cmd.find('Properties')

View File

@ -8,7 +8,7 @@
<?cs if:Data.CurrentDisk.active ?>
<?cs call:hint(Lang.Plugins.volume_props.Text.UmountBeforeProps) ?>
<?cs call:hint("Plugins.volume_props.UmountBeforeProps") ?>
<?cs else ?>
<table>
@ -17,10 +17,10 @@
<tr><td colspan="3">
<h3><?cs var:html_escape(Lang.Plugins.volume_props.Title.ChangeVolumeName) ?></h3>
</td></tr>
<?cs call:print_form_header("set_name", "plugins/volume_props") ?><tr>
<?cs call:print_form_header("set_name", "volume_props") ?><tr>
<td align="right"><label for="vol_name"><?cs var:html_escape(Lang.Text.ContainerName) ?>: </label></td>
<td><input type="text" name="vol_name" tabindex="10" size="15" id="vol_name" value="<?cs var:html_escape(Data.CurrentDisk.name) ?>" /></td>
<td align="right">
<td>
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="store" value="set_name" />
<button type="submit" tabindex="11"><?cs var:html_escape(Lang.Plugins.volume_props.Button.ContainerNameSet) ?></button>
@ -35,7 +35,7 @@
<tr><td colspan="3">
<h3><?cs var:html_escape(Lang.Plugins.volume_props.Title.ChangePassword) ?></h3>
</td></tr>
<?cs call:print_form_header("set_password", "plugins/volume_props") ?>
<?cs call:print_form_header("set_password", "volume_props") ?>
<tr>
<td align="right"><label for="old_pw"><?cs var:html_escape(Lang.Text.EnterCurrentPassword) ?>: </label></td>
<td><input type="password" name="old_pw" tabindex="20" size="15" id="old_pw" /></td>
@ -49,14 +49,23 @@
<tr>
<td align="right"><label for="new_pw2"><?cs var:html_escape(Lang.Text.EnterSamePassword) ?>: </label></td>
<td><input type="password" name="new_pw2" tabindex="22" size="15" id="new_pw2" /></td>
<td align="right">
<td>
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="store" value="change_pw" />
<button type="submit" tabindex="23"><?cs var:html_escape(Lang.Plugins.volume_props.Button.ChangePassword) ?></button></p>
<button type="submit" tabindex="23"><?cs var:html_escape(Lang.Plugins.volume_props.Button.ChangePassword) ?></button>
</td>
</tr>
</form>
<tr><td></td><td></td><td></td></tr>
<?cs else ?>
<tr><td colspan="3">
<h3><?cs var:html_escape(Lang.Plugins.volume_props.Title.Encryption) ?></h3>
</td></tr>
<tr><td colspan="2" align="left"><?cs var:html_escape(Lang.Plugins.volume_props.Text.FormatForEncryptionSupport) ?></td>
<td>
<?cs call:print_form_header("enable_encryption", "format_fs") ?>
<button type="submit" tabindex="30"><?cs var:html_escape(Lang.Plugins.volume_props.Button.FormatContainer) ?></button>
</td></tr>
<?cs /if ?>
</table>