new plugins: 'format_fs', 'volume_mount', 'volume_props', 'shutdown' and 'volume_details'
new plugin attribute: "requestAuth"
This commit is contained in:
parent
0e8a5daa73
commit
ca13aebdc8
27 changed files with 920 additions and 45 deletions
|
@ -3,6 +3,9 @@ import CryptoBoxPlugin
|
|||
|
||||
class date(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "system" ]
|
||||
requestAuth = False
|
||||
|
||||
def doAction(self, store=None, year=0, month=0, day=0, hour=0, minute=0):
|
||||
import datetime
|
||||
if store:
|
||||
|
|
93
pythonrewrite/plugins/format_fs/format_fs.py
Normal file
93
pythonrewrite/plugins/format_fs/format_fs.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
import CryptoBoxPlugin
|
||||
|
||||
class format_fs(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "volume" ]
|
||||
requestAuth = True
|
||||
|
||||
## map filesystem types to the appropriate arguments for 'mkfs'
|
||||
fsTypes = {
|
||||
"windows": "vfat",
|
||||
"linux": "ext3" }
|
||||
|
||||
containerTypes = [ "luks", "plain" ]
|
||||
|
||||
|
||||
def doAction(self, store=None, fs_type="windows", container_type="luks", crypto_password=None, crypto_password2=None, confirm=None):
|
||||
if not fs_type in self.fsTypes.keys():
|
||||
self.cbox.info
|
||||
return "format_volume"
|
||||
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
|
||||
self.hdf[self.hdf_prefix + "container_type"] = container_type
|
||||
for t in self.fsTypes.keys():
|
||||
self.hdf[self.hdf_prefix + "fs_types." + t] = t
|
||||
if store == "step1":
|
||||
if not confirm:
|
||||
self.cbox.log.warn("missing confirmation for formatting of filesystem: %s" % self.device)
|
||||
self.hdf["Data.Warning"] = "Plugins.format_fs.FormatNotConfirmed"
|
||||
return "volume_format"
|
||||
if container_type == "luks":
|
||||
return "volume_format_luks"
|
||||
elif container_type == "plain":
|
||||
return self.__format_plain(fs_type)
|
||||
elif store == "step2":
|
||||
if container_type == "luks":
|
||||
return self.__format_luks(fs_type, crypto_password, crypto_password2)
|
||||
else:
|
||||
self.cbox.log.info("invalid input value for 'container_type': %s" % container_type)
|
||||
return "volume_format"
|
||||
elif store:
|
||||
self.cbox.log.info("invalid input value for 'store': %s" % store)
|
||||
return "volume_format"
|
||||
else:
|
||||
return "volume_format"
|
||||
|
||||
|
||||
def getStatus(self):
|
||||
return "no status"
|
||||
|
||||
|
||||
def __format_plain(self, fsType):
|
||||
try:
|
||||
container = self.cbox.getContainer(self.device)
|
||||
container.create(container.Types["plain"])
|
||||
except CBVolumeIsActive:
|
||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
||||
return None
|
||||
except CBContainerError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.format_fs.FormatFailed"
|
||||
self.cbox.log.warn("initialization of device '%s' failed" % self.device)
|
||||
self.cbox.log.warn("reason: %s" % errMsg)
|
||||
return "volume_format"
|
||||
else:
|
||||
self.cbox.log.info("successfully initialized device '%s'" % self.device)
|
||||
return None
|
||||
|
||||
|
||||
def __format_luks(self, fsType, pw, pw2):
|
||||
if not pw:
|
||||
self.hdf["Data.Warning"] = "EmptyCryptoPassword"
|
||||
self.cbox.log.warn("no crypto password was supplied for initialization of device '%s'" % self.device)
|
||||
return "volume_format"
|
||||
if pw != pw2:
|
||||
self.hdf["Data.Warning"] = "DifferentCryptoPasswords"
|
||||
self.cbox.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % self.device)
|
||||
return "volume_format"
|
||||
container = self.cbox.getContainer(self.device)
|
||||
try:
|
||||
container.create(container.Types["luks"], pw)
|
||||
except CBVolumeIsActive:
|
||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
||||
return None
|
||||
except CBContainerError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.format_fs.FormatFailed"
|
||||
self.cbox.log.warn("initialization of device '%s' failed" % self.device)
|
||||
self.cbox.log.warn("reason: %s" % errMsg)
|
||||
return "volume_format"
|
||||
else:
|
||||
self.hdf["Data.Success"] = "Plugins.format_fs.FormatSuccess"
|
||||
self.cbox.log.info("successfully initialized device '%s'" % self.device)
|
||||
return None
|
||||
|
36
pythonrewrite/plugins/format_fs/lang/en.hdf
Normal file
36
pythonrewrite/plugins/format_fs/lang/en.hdf
Normal file
|
@ -0,0 +1,36 @@
|
|||
Name = Create filesystems
|
||||
Link = Format
|
||||
Rank = 60
|
||||
|
||||
Title.Format = Initializing filesystem
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
SuccessMessage {
|
||||
FormatSuccess {
|
||||
Title = Formatting successful
|
||||
Text = The selected filesystem was successfully formatted.
|
||||
}
|
||||
}
|
||||
|
||||
WarningMessage {
|
||||
FormatNotConfirmed {
|
||||
Title = Confirmation missing
|
||||
Text = You did not confirm this action by activating the checkbox.
|
||||
}
|
||||
|
||||
FormatFailed {
|
||||
Title = Formatting failed
|
||||
Text = Formatting of the selected filesystem failed for unknown reasons - sorry!
|
||||
}
|
||||
}
|
37
pythonrewrite/plugins/format_fs/volume_format.cs
Normal file
37
pythonrewrite/plugins/format_fs/volume_format.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_header.cs" ?>
|
||||
|
||||
<h2><?cs var:html_escape(Lang.Plugins.format_fs.Title.Format) ?></h2>
|
||||
|
||||
<?cs if:Data.CurrentDisk.active ?>
|
||||
<div class="unavailable_action">
|
||||
<?cs var:html_escape(Lang.Plugins.format_fs.Text.UnmountBeforeInit) ?>
|
||||
</div>
|
||||
<?cs else ?>
|
||||
|
||||
<?cs call:print_form_header("plugins/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 ?>
|
||||
<option <?cs if:x == "windows" ?>selected="selected"<?cs /if ?>><?cs var:html_escape(x) ?></option><?cs /each ?>
|
||||
</select></p>
|
||||
|
||||
<p><label for="container_type"><?cs var:html_escape(Lang.Plugins.format_fs.Text.IsEncrypted)
|
||||
?>: <select name="container_type" id="container_type">
|
||||
<option value="luks" <?cs if:Data.Plugins.format_fs.container_type != "plain" ?>selected="selected"<?cs /if ?>><?cs var:html_escape(Lang.Plugins.format_fs.Text.Yes) ?></option> -->
|
||||
<option value="plain" <?cs if:Data.Plugins.format_fs.container_type == "plain" ?>selected="selected"<?cs /if ?>><?cs var:html_escape(Lang.Plugins.format_fs.Text.No) ?></option>
|
||||
</select></p>
|
||||
|
||||
<p class="note"><?cs var:html_escape(Lang.Plugins.format_fs.Text.FormatWarning) ?></p>
|
||||
<p><input type="checkbox" name="confirm" value="1" id="confirm"><label for="confirm"><?cs var:html_escape(Lang.Plugins.format_fs.Text.Confirm) ?><p/>
|
||||
|
||||
<input type="hidden" name="device" value="<?cs var:Data.CurrentDisk.device ?>" />
|
||||
<input type="hidden" name="store" value="step1" />
|
||||
<button type="submit"><?cs var:html_escape(Lang.Plugins.format_fs.Button.Format) ?></button>
|
||||
</form>
|
||||
|
||||
<?cs /if ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_footer.cs" ?>
|
33
pythonrewrite/plugins/format_fs/volume_format_luks.cs
Normal file
33
pythonrewrite/plugins/format_fs/volume_format_luks.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_header.cs" ?>
|
||||
|
||||
<h2><?cs var:html_escape(Lang.Plugins.format_fs.Title.Format) ?></h2>
|
||||
|
||||
<?cs if:Data.CurrentDisk.active ?>
|
||||
<div class="unavailable_action">
|
||||
<?cs var:html_escape(Lang.Plugins.format_fs.Text.UnmountBeforeInit) ?>
|
||||
</div>
|
||||
<?cs else ?>
|
||||
|
||||
<?cs call:print_form_header("plugins/format_fs") ?>
|
||||
|
||||
<p class="note"><?cs var:html_escape(Lang.Plugins.format_fs.Text.FormatWarning) ?></p>
|
||||
|
||||
<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
|
||||
var:html_escape(Lang.Plugins.format_fs.Text.No) ?><?cs /if ?></p>
|
||||
|
||||
<p><label for="crypto_password"><?cs var:html_escape(Lang.Text.EnterNewCryptoPassword) ?></label> <input type="password" id="crypto_password" name="crypto_password" /></p>
|
||||
<p><label for="crypto_password2"><?cs var:html_escape(Lang.Text.EnterSameCryptoPassword) ?></label> <input type="password" id="crypto_password2" name="crypto_password2" /></p>
|
||||
<input type="hidden" name="device" value="<?cs var:Data.CurrentDisk.device ?>" />
|
||||
<input type="hidden" name="fs_type" value="<?cs var:html_escape(Data.Plugins.format_fs.fs_type) ?>" />
|
||||
<input type="hidden" name="container_type" value="<?cs var:html_escape(Data.Plugins.format_fs.container_type) ?>" />
|
||||
<input type="hidden" name="store" value="step2" />
|
||||
<button type="submit"><?cs var:html_escape(Lang.Plugins.format_fs.Button.Format) ?></button>
|
||||
</form>
|
||||
|
||||
<?cs /if ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_footer.cs" ?>
|
|
@ -3,6 +3,9 @@ import os
|
|||
|
||||
class logs(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "system" ]
|
||||
requestAuth = False
|
||||
|
||||
def doAction(self):
|
||||
self.__prepareFormData()
|
||||
return "show_log"
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<style type="text/css">
|
||||
input.ipnum { text-align: center }
|
||||
</style>
|
||||
|
||||
<h1><?cs var:html_escape(Lang.Plugins.network.Title.Network) ?></h1>
|
||||
|
||||
<?cs call:print_form_header("plugins/network") ?>
|
||||
|
||||
<p><label for="ip"><?cs var:html_escape(Lang.Plugins.network.Text.IP) ?>: </label><br/>
|
||||
<input type="text" tabindex="1" name="ip1" size="3" id="ip" value="<?cs
|
||||
var:Data.Plugins.network.ip.oc1 ?>" />.
|
||||
<input type="text" tabindex="1" name="ip2" size="3" value="<?cs
|
||||
var:Data.Plugins.network.ip.oc2 ?>" />.
|
||||
<input type="text" tabindex="2" name="ip3" size="3" value="<?cs
|
||||
var:Data.Plugins.network.3p.oc3 ?>" />.
|
||||
<input type="text" tabindex="4" name="ip4" size="3" value="<?cs
|
||||
var:Data.Plugins.network.ip.oc4 ?>" /></p>
|
||||
<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"
|
||||
value="<?cs var:Data.Plugins.network.ip.oc1
|
||||
?>" />.<input class="ipnum" type="text" tabindex="2" name="ip2" size="3"
|
||||
value="<?cs var:Data.Plugins.network.ip.oc2
|
||||
?>" />.<input class="ipnum" type="text" tabindex="3" name="ip3" size="3"
|
||||
value="<?cs var:Data.Plugins.network.ip.oc3
|
||||
?>" />.<input class="ipnum" type="text" tabindex="4" name="ip4" size="3"
|
||||
value="<?cs var:Data.Plugins.network.ip.oc4 ?>" /></p>
|
||||
|
||||
<input type="hidden" tabindex="5" name="store" value="yes" />
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ CHANGE_IP_DELAY=5
|
|||
|
||||
class network(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "system" ]
|
||||
requestAuth = True
|
||||
|
||||
def doAction(self, store=None, redirected="", ip1="", ip2="", ip3="", ip4=""):
|
||||
## if we were redirected, then we should display the default page
|
||||
if redirected == "1":
|
||||
|
|
|
@ -5,7 +5,8 @@ Rank = 80
|
|||
Title.Partition = Disk partitions
|
||||
|
||||
Button {
|
||||
SelectDevice = Repartition disk
|
||||
SelectDevice = Manual partitioning
|
||||
EasySetup = Automatic setup
|
||||
AddPartition = Add
|
||||
DelPartition = Remove
|
||||
SavePartitions = Write new partition table
|
||||
|
@ -24,8 +25,9 @@ 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 careful!
|
||||
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
|
||||
}
|
||||
|
||||
SuccessMessage {
|
||||
|
@ -33,6 +35,12 @@ SuccessMessage {
|
|||
Title = Partitioning complete
|
||||
Text = The disk was partitioned successfully.
|
||||
}
|
||||
|
||||
EasySetup {
|
||||
Title = Initialization completed
|
||||
Text = Automatic initialization was finished successfully.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
WarningMessage {
|
||||
|
|
|
@ -6,6 +6,9 @@ import CryptoBoxPlugin
|
|||
|
||||
class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "system" ]
|
||||
requestAuth = True
|
||||
|
||||
PartTypes = {
|
||||
"windows" : ["0xC", "vfat"],
|
||||
"linux" : ["L", "ext3"]}
|
||||
|
@ -22,21 +25,29 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
## retrieve some values from 'args' - defaults are empty
|
||||
self.withConfigPartition = self.__isWithConfigPartition(args)
|
||||
self.device = self.__getSelectedDevice(args)
|
||||
self.cbox.log.debug("partition plugin: selected device=%s" % str(self.device))
|
||||
self.deviceSize = self.__getAvailableDeviceSize(self.device)
|
||||
try:
|
||||
step = args["step"]
|
||||
del args["step"]
|
||||
except KeyError:
|
||||
step = "select_device"
|
||||
try:
|
||||
## this way of selecting the easy setup is necessary: see select_device.py for details
|
||||
if args["easy"]: step = "easy"
|
||||
except KeyError:
|
||||
pass
|
||||
## no (or invalid) device was supplied
|
||||
if not self.device:
|
||||
step == "select_device"
|
||||
if step == "add_partition":
|
||||
return self.__actionAddPartition(args)
|
||||
if step == "del_partition":
|
||||
elif step == "del_partition":
|
||||
return self.__actionDelPartition(args)
|
||||
elif step == "finish":
|
||||
return self.__actionFinish(args)
|
||||
elif step == "easy":
|
||||
return self.__actionEasySetup(args)
|
||||
else: # for "select_device" and for invalid targets
|
||||
return self.__actionSelectDevice(args)
|
||||
|
||||
|
@ -132,11 +143,6 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
|
||||
return self.__actionAddPartition(args)
|
||||
else:
|
||||
# TODO: will we use the "yield"-style? If yes, then remove these messages (success and warning)
|
||||
#if self.__formatPartitions(parts):
|
||||
# self.hdf["Data.Success"] = "Plugins.partition.Partitioned"
|
||||
#else:
|
||||
# self.hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
|
||||
"""
|
||||
tricky problem: if the device was partitioned, then a created config partition is still part of the containerlist, as the label is not checked again - very ugly!!! So we will call reReadContainerList after formatting the last partition - see below
|
||||
"""
|
||||
|
@ -156,7 +162,10 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
## important: reRead the containerList
|
||||
self.cbox.reReadContainerList()
|
||||
## return the result
|
||||
yield result
|
||||
if result:
|
||||
yield "OK"
|
||||
else:
|
||||
yield "<b>Error</b>"
|
||||
return {
|
||||
"template": "show_format_progress",
|
||||
"generator": result_generator}
|
||||
|
@ -164,6 +173,28 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
return self.__actionAddPartition(args)
|
||||
|
||||
|
||||
def __actionEasySetup(self, args):
|
||||
import types
|
||||
## we do not have to take special care for a possible config partition
|
||||
parts = [ { "size": self.deviceSize, "type": "windows" } ]
|
||||
## doe
|
||||
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
|
||||
## 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
|
||||
else:
|
||||
## operation was successful
|
||||
self.hdf["Data.Success"] = "Plugins.partition.EasySetup"
|
||||
self.cbox.log.info("easy partitioning succeeded")
|
||||
return None
|
||||
|
||||
|
||||
def __setPartitionData(self, parts):
|
||||
availSize = self.deviceSize
|
||||
i = 0
|
||||
|
@ -242,6 +273,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
## check if the device is completely filled (to avoid some empty last blocks)
|
||||
avail_size = self.deviceSize
|
||||
for d in parts: avail_size -= d["size"]
|
||||
self.cbox.log.debug("remaining size: %d" % avail_size)
|
||||
isFilled = avail_size == 0
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
|
@ -252,7 +284,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"plugin",
|
||||
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
||||
os.path.join(self.pluginDir, "root_action.py"),
|
||||
"partition",
|
||||
self.device])
|
||||
for line in self.__getSFDiskLayout(parts, isFilled):
|
||||
|
@ -263,12 +295,18 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
|
||||
|
||||
def __getSFDiskLayout(self, paramParts, isFilled):
|
||||
"""this generator returns the input lines for sfdisk"""
|
||||
parts = paramParts[:]
|
||||
## first a (possible) configuration partition - so it will be reusable
|
||||
if self.withConfigPartition:
|
||||
## fill the main table (including a config partition)
|
||||
yield ",%d,%s" % (self.ConfigPartition["size"], self.ConfigPartition["type"])
|
||||
## one primary partition
|
||||
if isFilled and (len(parts) == 1):
|
||||
## fill the rest of the device
|
||||
yield ",,%s,*" % self.PartTypes[parts[0]["type"]][0]
|
||||
else:
|
||||
## only use the specified size
|
||||
yield ",%d,%s,*" % (parts[0]["size"], self.PartTypes[parts[0]["type"]][0])
|
||||
del parts[0]
|
||||
## no extended partition, if there is only one disk
|
||||
|
@ -303,10 +341,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
partType = self.PartTypes[parts[0]["type"]][1]
|
||||
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
||||
yield dev_name
|
||||
if self.__formatOnePartition(dev_name, partType):
|
||||
yield "OK"
|
||||
else:
|
||||
yield "<b>Failed!</b>"
|
||||
yield self.__formatOnePartition(dev_name, partType)
|
||||
del parts[0]
|
||||
## other data partitions
|
||||
part_num = 5
|
||||
|
@ -315,10 +350,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
partType = self.PartTypes[parts[0]["type"]][1]
|
||||
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, partType))
|
||||
yield dev_name
|
||||
if self.__formatOnePartition(dev_name, partType):
|
||||
yield "OK"
|
||||
else:
|
||||
yield "<b>Failed!</b>"
|
||||
yield self.__formatOnePartition(dev_name, partType)
|
||||
part_num += 1
|
||||
del parts[0]
|
||||
return
|
||||
|
@ -331,7 +363,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"plugin",
|
||||
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
||||
os.path.join(self.pluginDir, "root_action.py"),
|
||||
"format",
|
||||
dev_name,
|
||||
type])
|
||||
|
@ -352,7 +384,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
|
|||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"plugin",
|
||||
os.path.join(os.path.dirname(__file__), "root_action.py"),
|
||||
os.path.join(self.pluginDir, "root_action.py"),
|
||||
"label",
|
||||
dev_name,
|
||||
label])
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<?cs /each ?>
|
||||
</select></p>
|
||||
|
||||
<p><label for="create_config_partition">Create configuration partition?</label><input type="checkbox" name="create_config_partition" value="1" tabindex="2" id="create_config_partition" /></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" />
|
||||
|
@ -28,7 +28,13 @@
|
|||
|
||||
<input type="hidden" name="step" value="add_partition" />
|
||||
|
||||
<button type="submit" tabindex="3"><?cs var:html_escape(Lang.Plugins.partition.Button.SelectDevice) ?></button>
|
||||
<div align="center"><table><tr>
|
||||
<!-- we have to avoid an ugly IE bug, that ignores the "value" attribute
|
||||
of "button" elements: if a variable called 'easy' is set, then this
|
||||
button was choosen - uuuuuugly! -->
|
||||
<td><button type="submit" name="easy" value="1" tabindex="3"><?cs var:html_escape(Lang.Plugins.partition.Button.EasySetup) ?></button></td>
|
||||
<td><button type="submit" name="normal" value="1" tabindex="4"><?cs var:html_escape(Lang.Plugins.partition.Button.SelectDevice) ?></button></td>
|
||||
</tr></table></div>
|
||||
|
||||
</form>
|
||||
|
||||
|
|
|
@ -5,34 +5,49 @@ The following directory structure is required:
|
|||
|
||||
|
||||
Python code interface:
|
||||
- create a class with the same name as the plugin - it has to inherit CryptoBoxPlugin
|
||||
- create a class with the same name as the plugin - it must inherit CryptoBoxPlugin
|
||||
- function "doAction":
|
||||
- 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"))
|
||||
- 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)
|
||||
- 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"))
|
||||
- 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:
|
||||
* template: the name of the template file (mandatory)
|
||||
* generator: a generator object ("yield") - its content will replace every occourence of "<!-- CONTENT_DUMMY -->" in the template (useful for pages that are displayed step by step (as for formatting of filesystems))
|
||||
- an empty (e.g. None) return value can be used to go return to the plugin page
|
||||
|
||||
* generator: a generator object ("yield") - its content will replace every
|
||||
occurrence of "<!-- CONTENT_DUMMY -->" in the template (useful for pages that
|
||||
are displayed step by step (as for formatting of filesystems))
|
||||
- an empty (e.g. None) return value can be used to go to the default page (now: the
|
||||
plugin overview)
|
||||
- function "getStatus":
|
||||
- returns a string, that describes a state connected to this plugin (e.g. the current date and time (for the "date" plugin))
|
||||
- returns a string, that describes a state connected to this plugin (e.g. the current date and
|
||||
time (for the "date" plugin))
|
||||
- the class variable "pluginCapabilities" must be an array of strings (supported: "system" and
|
||||
"volume")
|
||||
- the class variable "requestAuth" is boolean and defines, if admin authentication is necessary
|
||||
for this plugin
|
||||
- volume plugins contain the attribute "device" (you may trust this value - a volume plugin will
|
||||
never get called with an invalid device)
|
||||
|
||||
|
||||
Language file structure:
|
||||
- the content of the language file will be added to the hdf dataset below "Lang.Plugins.PLUGINNAME" (this avoids namespace conflicts)
|
||||
- the content of the language file will be added to the hdf dataset below "Lang.Plugins.PLUGINNAME"
|
||||
(this avoids namespace conflicts)
|
||||
- the following values _must_ be defined:
|
||||
Name (a short description)
|
||||
Link (the visible text for links to this plugin)
|
||||
Rank (defines the order of the plugins displayed (0..100))
|
||||
- all warnings, error and success messages should be stored below WarningMessage.??? (resp. ErrorMessage or SuccessMessage)
|
||||
- all warnings, error and success messages should be stored below WarningMessage.???
|
||||
(resp. ErrorMessage or SuccessMessage)
|
||||
|
||||
|
||||
Clearsilver template:
|
||||
- should start with a "<h1>" tag
|
||||
- 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",'','','','') ?>
|
||||
- a hidden input field called "store" should be used to indicate a form submission
|
||||
- volume plugins must include "show_volume_[header|footer]" (see examples)
|
||||
|
||||
|
||||
|
|
27
pythonrewrite/plugins/shutdown/form_shutdown.cs
Normal file
27
pythonrewrite/plugins/shutdown/form_shutdown.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<h1><?cs var:html_escape(Lang.Plugins.shutdown.Title.Shutdown) ?></h1>
|
||||
|
||||
<p style="text-align: center">
|
||||
<?cs var:html_escape(Lang.Plugins.shutdown.Text.ShutdownInfo) ?>
|
||||
</p>
|
||||
|
||||
|
||||
<table style="text-align:center; width:100%">
|
||||
<tr>
|
||||
<td style="text-align: right">
|
||||
<?cs call:print_form_header("plugins/shutdown") ?>
|
||||
<input type="hidden" name="type" value="reboot" />
|
||||
<button type="submit" tabindex="2"><?cs var:html_escape(Lang.Plugins.shutdown.Button.Reboot) ?></button>
|
||||
</form>
|
||||
</td>
|
||||
<td style="width:5%"></td>
|
||||
<td style="text-align: left">
|
||||
<?cs call:print_form_header("plugins/shutdown") ?>
|
||||
<input type="hidden" name="type" value="shutdown" />
|
||||
<button type="submit" tabindex="1"><?cs var:html_escape(Lang.Plugins.shutdown.Button.Shutdown) ?></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
34
pythonrewrite/plugins/shutdown/lang/en.hdf
Normal file
34
pythonrewrite/plugins/shutdown/lang/en.hdf
Normal file
|
@ -0,0 +1,34 @@
|
|||
Name = Shutdown or reboot the computer
|
||||
Link = Shutdown/Reboot
|
||||
Rank = 70
|
||||
|
||||
Title.Shutdown = Shutdown computer
|
||||
|
||||
Button.Shutdown = Poweroff
|
||||
Button.Reboot = Reboot
|
||||
|
||||
Text.ShutdownInfo = You may turn off or reboot your CryptoBox here.
|
||||
|
||||
SuccessMessage {
|
||||
Shutdown {
|
||||
Title = Shutting down the system
|
||||
Text = If the computer does not turn off itself within a minute, then you should plug it off manually.
|
||||
}
|
||||
|
||||
Reboot {
|
||||
Title = Rebooting the system
|
||||
Text = This may take a while (depending on your hardware) ...
|
||||
}
|
||||
}
|
||||
|
||||
WarningMessage {
|
||||
ShutdownFailed {
|
||||
Title = Shutdown failed
|
||||
Text = Shutting down of the system failed for some reason - sorry!
|
||||
}
|
||||
|
||||
RebootFailed {
|
||||
Title = Reboot failed
|
||||
Text = Reboot of the system failed for some reason - sorry!
|
||||
}
|
||||
}
|
48
pythonrewrite/plugins/shutdown/root_action.py
Executable file
48
pythonrewrite/plugins/shutdown/root_action.py
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python2.4
|
||||
|
||||
## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script
|
||||
PLUGIN_TYPE = "cryptobox"
|
||||
|
||||
POWEROFF_BIN = "/sbin/poweroff"
|
||||
REBOOT_BIN = "/sbin/reboot"
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def call_prog(progy):
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
args = [progy])
|
||||
proc.communicate()
|
||||
return proc.returncode == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = sys.argv[1:]
|
||||
|
||||
self_bin = sys.argv[0]
|
||||
|
||||
if len(args) > 1:
|
||||
sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args))
|
||||
sys.exit(1)
|
||||
|
||||
if len(args) == 0:
|
||||
sys.stderr.write("%s: no argument supplied\n" % self_bin)
|
||||
sys.exit(1)
|
||||
|
||||
if args[0] == "reboot":
|
||||
result = call_prog(REBOOT_BIN)
|
||||
elif args[0] == "shutdown":
|
||||
result = call_prog(POWEROFF_BIN)
|
||||
else:
|
||||
sys.stderr.write("%s: illegal argument (%s)\n" % (self_bin, args[0]))
|
||||
sys.exit(1)
|
||||
|
||||
if result:
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
50
pythonrewrite/plugins/shutdown/shutdown.py
Normal file
50
pythonrewrite/plugins/shutdown/shutdown.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
import CryptoBoxPlugin
|
||||
|
||||
REDIRECT_DELAY = 180
|
||||
|
||||
class shutdown(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "system" ]
|
||||
requestAuth = False
|
||||
|
||||
def doAction(self, type=None):
|
||||
if not type:
|
||||
return "form_shutdown"
|
||||
elif type == "shutdown":
|
||||
if self.__doShutdown("shutdown"):
|
||||
self.hdf["Data.Success"] = "Plugins.shutdown.Shutdown"
|
||||
return None
|
||||
else:
|
||||
self.hdf["Data.Warning"] = "Plugins.shutdown.ShutdownFailed"
|
||||
return "form_shutdown"
|
||||
elif type == "reboot":
|
||||
if self.__doShutdown("reboot"):
|
||||
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
|
||||
self.hdf["Data.Redirect.URL"] = ""
|
||||
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
|
||||
return None
|
||||
else:
|
||||
self.hdf["Data.Warning"] = "Plugins.shutdown.RebootFailed"
|
||||
return "form_shutdown"
|
||||
else:
|
||||
return "form_shutdown"
|
||||
|
||||
|
||||
def getStatus(self):
|
||||
return "the box is up'n'running"
|
||||
|
||||
|
||||
def __doShutdown(self, action):
|
||||
import subprocess
|
||||
import os
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"plugin",
|
||||
os.path.join(self.pluginDir, "root_action.py"),
|
||||
action])
|
||||
proc.communicate()
|
||||
return proc.returncode == 0
|
||||
|
21
pythonrewrite/plugins/volume_details/lang/en.hdf
Normal file
21
pythonrewrite/plugins/volume_details/lang/en.hdf
Normal file
|
@ -0,0 +1,21 @@
|
|||
Name = Technical details of a volume
|
||||
Link = Details
|
||||
Rank = 100
|
||||
|
||||
Title.Details = Technical details
|
||||
|
||||
Text {
|
||||
DeviceName = Name of device
|
||||
Status = Status
|
||||
StatusActive = active
|
||||
StatusPassive = passive
|
||||
EncryptionStatus = Encryption
|
||||
Yes = Yes
|
||||
No = No
|
||||
Size {
|
||||
All = Space of volume
|
||||
Avail = Available space of volume
|
||||
Used = Used space of volume
|
||||
}
|
||||
}
|
||||
|
19
pythonrewrite/plugins/volume_details/volume_details.cs
Normal file
19
pythonrewrite/plugins/volume_details/volume_details.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_header.cs" ?>
|
||||
|
||||
<h2><?cs var:html_escape(Lang.Plugins.volume_details.Title.Details) ?></h2>
|
||||
|
||||
<p><ul>
|
||||
<li><?cs var:html_escape(Lang.Text.ContainerName) ?>: <?cs var:html_escape(Data.CurrentDisk.name) ?></li>
|
||||
<li><?cs var:html_escape(Lang.Plugins.volume_details.Text.DeviceName) ?>: <?cs var:html_escape(Data.CurrentDisk.device) ?></li>
|
||||
<li><?cs var:html_escape(Lang.Plugins.volume_details.Text.Status) ?>: <?cs if:Data.CurrentDisk.active ?><?cs var:html_escape(Lang.Plugins.volume_details.Text.StatusActive) ?><?cs else ?><?cs var:html_escape(Lang.Plugins.volume_details.Text.StatusPassive) ?><?cs /if ?></li>
|
||||
<li><?cs var:html_escape(Lang.Plugins.volume_details.Text.EncryptionStatus) ?>: <?cs if:Data.CurrentDisk.encryption ?><?cs var:html_escape(Lang.Plugins.volume_details.Text.Yes) ?><?cs else ?><?cs var:html_escape(Lang.Plugins.volume_details.Text.Yes) ?><?cs /if ?></li>
|
||||
<?cs if:Data.CurrentDisk.active ?>
|
||||
<li><?cs var:html_escape(Lang.Plugins.volume_details.Text.Size.All) ?>: <?cs var:html_escape(Data.CurrentDisk.capacity.size) ?></li>
|
||||
<li><?cs var:html_escape(Lang.Plugins.volume_details.Text.Size.Avail) ?>: <?cs var:html_escape(Data.CurrentDisk.capacity.free) ?></li>
|
||||
<li><?cs var:html_escape(Lang.Plugins.volume_details.Text.Size.Used) ?>: <?cs var:html_escape(Data.CurrentDisk.capacity.percent) ?>%</li>
|
||||
<?cs /if ?>
|
||||
</ul></p>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_footer.cs" ?>
|
17
pythonrewrite/plugins/volume_details/volume_details.py
Normal file
17
pythonrewrite/plugins/volume_details/volume_details.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
import CryptoBoxPlugin
|
||||
|
||||
|
||||
class volume_details(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "volume" ]
|
||||
requestAuth = False
|
||||
|
||||
|
||||
def doAction(self):
|
||||
## all variables are already set somewhere else
|
||||
return "volume_details"
|
||||
|
||||
|
||||
def getStatus(self):
|
||||
return "no status"
|
||||
|
57
pythonrewrite/plugins/volume_mount/lang/en.hdf
Normal file
57
pythonrewrite/plugins/volume_mount/lang/en.hdf
Normal file
|
@ -0,0 +1,57 @@
|
|||
Name = Mount and umount volumes
|
||||
Link = Main
|
||||
Rank = 0
|
||||
|
||||
|
||||
Title {
|
||||
Mount = Activate volume
|
||||
Umount = Deactivate volume
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
Mount = Activate volume
|
||||
Umount = Deactivate volume
|
||||
}
|
||||
|
||||
|
||||
SuccessMessage {
|
||||
MountDone {
|
||||
Title = Encrypted filesystem activated
|
||||
Text = The encrypted filesystem is now available.
|
||||
}
|
||||
|
||||
UmountDone {
|
||||
Title = Encrypted filesystem deactivated
|
||||
Text = The encrypted filesystem is now secured from all forms of access.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WarningMessage {
|
||||
MountFailed {
|
||||
Title = Activation failed
|
||||
Text = The encrypted filesystem could not be activated. Probably the given password was wrong. Please try again.
|
||||
}
|
||||
|
||||
MountCryptoFailed {
|
||||
Title = Activation failed
|
||||
Text = Maybe you entered the wrong password?
|
||||
}
|
||||
|
||||
UmountFailed {
|
||||
Title = Deactivation failed
|
||||
Text = The encrypted filesystem could not be deactivated. Probably some files are still in use. Close all unclean programs (for example that widely used word processor). In case of emergency just shut down the CryptoBox!
|
||||
}
|
||||
|
||||
IsAlreadyMounted {
|
||||
Title = Already active
|
||||
Text = The volume is already active.
|
||||
}
|
||||
|
||||
IsNotMounted {
|
||||
Title = Inactive
|
||||
Text = The volume is currently not active.
|
||||
}
|
||||
|
||||
}
|
16
pythonrewrite/plugins/volume_mount/volume_mount.cs
Normal file
16
pythonrewrite/plugins/volume_mount/volume_mount.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
<h2><?cs var:html_escape(Lang.Plugins.volume_mount.Title.Mount) ?></h2>
|
||||
|
||||
<p><?cs call:print_form_header("plugins/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" />
|
||||
<?cs else ?>
|
||||
<input type="hidden" name="action" value="mount_plain" />
|
||||
<?cs /if ?>
|
||||
<?cs if:Data.CurrentDisk.encryption ?>
|
||||
<label for="pw"><?cs var:html_escape(Lang.Text.EnterCurrentCryptoPassword) ?>: </label>
|
||||
<input type="password" tabindex="1" id="pw" name="pw" size="20" maxlength="60" />
|
||||
<?cs /if ?>
|
||||
<button type="submit" tabindex="2"><?cs var:html_escape(Lang.Plugins.volume_mount.Button.Mount) ?></button>
|
||||
</form></p>
|
||||
|
102
pythonrewrite/plugins/volume_mount/volume_mount.py
Normal file
102
pythonrewrite/plugins/volume_mount/volume_mount.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
import CryptoBoxPlugin
|
||||
from CryptoBoxExceptions import *
|
||||
|
||||
|
||||
class volume_mount(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "volume" ]
|
||||
requestAuth = False
|
||||
|
||||
|
||||
def doAction(self, action=None, pw=None):
|
||||
self.container = self.cbox.getContainer(self.device)
|
||||
if action == "mount_plain":
|
||||
return self.__doMountPlain()
|
||||
elif action == "mount_luks":
|
||||
return self.__doMountLuks(pw)
|
||||
elif action == "umount":
|
||||
return self.__doUmount()
|
||||
elif not action:
|
||||
return "volume_status"
|
||||
else:
|
||||
self.cbox.log.info("plugin 'volume_mount' - unknown action: %s" % action)
|
||||
return None
|
||||
|
||||
|
||||
def getStatus(self):
|
||||
container = self.cbox.getContainer(self.device)
|
||||
if not self.container:
|
||||
return "invalid device"
|
||||
if container.isMounted():
|
||||
return "active"
|
||||
else:
|
||||
return "passive"
|
||||
|
||||
|
||||
def __doMountPlain(self):
|
||||
if self.container.isMounted():
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
|
||||
self.cbox.log.info("the device (%s) is already mounted" % device)
|
||||
return "volume_status"
|
||||
if self.container.getType() != self.container.Types["plain"]:
|
||||
## not a plain container - fail silently
|
||||
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
|
||||
return "volume_status"
|
||||
try:
|
||||
self.container.mount()
|
||||
except CBMountError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
|
||||
self.cbox.log.warn("failed to mount the device (%s): %s" % (self.device, errMsg))
|
||||
return "volume_status"
|
||||
except CBContainerError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountFailed"
|
||||
self.cbox.log.warn("failed to mount the device (%s): %s" % (self.device, errMsg))
|
||||
return "volume_status"
|
||||
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
|
||||
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
|
||||
return "volume_status"
|
||||
|
||||
|
||||
def __doMountLuks(self, pw):
|
||||
if self.container.isMounted():
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsAlreadyMounted"
|
||||
self.cbox.log.info("the device (%s) is already mounted" % device)
|
||||
return "volume_status"
|
||||
if not pw:
|
||||
self.dataset["Data.Warning"] = "EmptyCryptoPassword"
|
||||
self.log.info("no password was supplied for mounting of device: '%s'" % device)
|
||||
return "volume_status"
|
||||
if self.container.getType() != self.container.Types["luks"]:
|
||||
## not a luks container - fail silently
|
||||
self.cbox.log.info("plugin 'volume_mount' - invalid container type")
|
||||
return "volume_status"
|
||||
try:
|
||||
self.container.mount(pw)
|
||||
except CBMountError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
|
||||
self.cbox.log.warn("failed to mount the device (%s): %s" % (self.device, errMsg))
|
||||
return "volume_status"
|
||||
except CBContainerError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.MountCryptoFailed"
|
||||
self.cbox.log.warn("failed to mount the device (%s): %s" % (self.device, errMsg))
|
||||
return "volume_status"
|
||||
self.cbox.log.info("successfully mounted the volume: %s" % self.device)
|
||||
self.hdf["Data.Success"] = "Plugins.volume_mount.MountDone"
|
||||
return "volume_status"
|
||||
|
||||
|
||||
def __doUmount(self):
|
||||
if not self.container.isMounted():
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_mount.IsNotMounted"
|
||||
self.cbox.log.info("the device (%s) is currently not mounted" % self.device)
|
||||
return "volume_status"
|
||||
try:
|
||||
self.container.umount()
|
||||
except CBUmountError, errMsg:
|
||||
self.hdf["Data.Warning"] = "InvalidType"
|
||||
self.cbox.log.warn("could not umount the volume (%s): %s" % (self.device, errMsg))
|
||||
return "volume_status"
|
||||
self.cbox.log.info("successfully unmounted the container: %s" % self.device)
|
||||
self.hdf["Data.Success"] = "Plugins.volume_mount.UmountDone"
|
||||
return "volume_status"
|
||||
|
9
pythonrewrite/plugins/volume_mount/volume_status.cs
Normal file
9
pythonrewrite/plugins/volume_mount/volume_status.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?cs include:Settings.TemplateDir + "/show_volume_header.cs" ?>
|
||||
|
||||
<?cs if:Data.CurrentDisk.active ?>
|
||||
<?cs include:Settings.PluginDir + "/volume_mount/volume_umount.cs" ?>
|
||||
<?cs else ?>
|
||||
<?cs include:Settings.PluginDir + "/volume_mount/volume_mount.cs" ?>
|
||||
<?cs /if ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_footer.cs" ?>
|
8
pythonrewrite/plugins/volume_mount/volume_umount.cs
Normal file
8
pythonrewrite/plugins/volume_mount/volume_umount.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
<h2><?cs var:html_escape(Lang.Plugins.volume_mount.Title.Umount) ?></h2>
|
||||
|
||||
<?cs call:print_form_header("plugins/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>
|
||||
</form>
|
||||
|
51
pythonrewrite/plugins/volume_props/lang/en.hdf
Normal file
51
pythonrewrite/plugins/volume_props/lang/en.hdf
Normal file
|
@ -0,0 +1,51 @@
|
|||
Name = Volume properties
|
||||
Link = Properties
|
||||
Rank = 40
|
||||
|
||||
Title {
|
||||
Properties = Properties
|
||||
ChangeVolumeName = Change the name of this volume
|
||||
ChangePassword = Change the password of this volume
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
ContainerNameSet = Change name
|
||||
ChangePassword = Change password
|
||||
}
|
||||
|
||||
|
||||
Text {
|
||||
UmountBeforeProps = You must deactivate a volume, if you want to change its properties.
|
||||
}
|
||||
|
||||
|
||||
SuccessMessage {
|
||||
PasswordChange {
|
||||
Title = Password changed
|
||||
Text = The password of this volume was changed successfully.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WarningMessage {
|
||||
InvalidVolumeName {
|
||||
Title = Changing of container's name failed
|
||||
Text = The supplied new name of the container was invalid. Please try again!
|
||||
}
|
||||
|
||||
SetVolumeNameFailed {
|
||||
Title = Changing of container's name failed
|
||||
Text = Could not change the name of the container. Take a look at the log files for details.
|
||||
}
|
||||
|
||||
VolumeNameIsInUse {
|
||||
Title = Volume name is in use
|
||||
Text = Another volume with the same name is active.
|
||||
}
|
||||
|
||||
PasswordChange {
|
||||
Title = Could not change password
|
||||
Text = The password of this volume could not be changed - sorry!
|
||||
}
|
||||
}
|
63
pythonrewrite/plugins/volume_props/volume_properties.cs
Normal file
63
pythonrewrite/plugins/volume_props/volume_properties.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_header.cs" ?>
|
||||
|
||||
<h2><?cs var:html_escape(Lang.Plugins.volume_props.Title.Properties) ?></h2>
|
||||
|
||||
<?cs if:Data.CurrentDisk.active ?>
|
||||
|
||||
<div class="unavailable_action">
|
||||
<?cs var:html_escape(Lang.Plugins.volume_props.Text.UmountBeforeProps) ?>
|
||||
</div>
|
||||
|
||||
<?cs else ?>
|
||||
<table>
|
||||
|
||||
<?cs # name change is only possible if the volume is not mounted ?>
|
||||
<tr><td colspan="3">
|
||||
<h3><?cs var:html_escape(Lang.Plugins.volume_props.Title.ChangeVolumeName) ?></h3>
|
||||
</td></tr>
|
||||
<?cs call:print_form_header("plugins/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">
|
||||
<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>
|
||||
</td>
|
||||
</tr></form>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
|
||||
|
||||
<?cs # password change is only possible if the volume is not mounted ?>
|
||||
<tr><td colspan="3">
|
||||
<h3><?cs var:html_escape(Lang.Plugins.volume_props.Title.ChangePassword) ?></h3>
|
||||
</td></tr>
|
||||
<?cs call:print_form_header("plugins/volume_props") ?>
|
||||
<tr>
|
||||
<td align="right"><label for="old_pw"><?cs var:html_escape(Lang.Text.EnterCurrentCryptoPassword) ?>: </label></td>
|
||||
<td><input type="password" name="old_pw" tabindex="20" size="15" id="old_pw" /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right"><label for="new_pw"><?cs var:html_escape(Lang.Text.EnterNewCryptoPassword) ?>: </label></td>
|
||||
<td><input type="password" name="new_pw" tabindex="21" size="15" id="new_pw" /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right"><label for="new_pw2"><?cs var:html_escape(Lang.Text.EnterSameCryptoPassword) ?>: </label></td>
|
||||
<td><input type="password" name="new_pw2" tabindex="22" size="15" id="new_pw2" /></td>
|
||||
<td align="right">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<?cs /if ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + "/show_volume_footer.cs" ?>
|
80
pythonrewrite/plugins/volume_props/volume_props.py
Normal file
80
pythonrewrite/plugins/volume_props/volume_props.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
import CryptoBoxPlugin
|
||||
from CryptoBoxExceptions import *
|
||||
|
||||
|
||||
class volume_props(CryptoBoxPlugin.CryptoBoxPlugin):
|
||||
|
||||
pluginCapabilities = [ "volume" ]
|
||||
requestAuth = False
|
||||
|
||||
|
||||
def doAction(self, store=None, vol_name=None, old_pw=None, new_pw=None, new_pw2=None):
|
||||
self.container = self.cbox.getContainer(self.device)
|
||||
if not self.container:
|
||||
return None
|
||||
self.__prepareHDF()
|
||||
if store == "set_name":
|
||||
return self.__setVolumeName(vol_name)
|
||||
elif store == "change_pw":
|
||||
return self.__changePassword(old_pw, new_pw, new_pw2)
|
||||
elif not store:
|
||||
return "volume_properties"
|
||||
else:
|
||||
self.cbox.log.info("plugin 'volume_props' - unknown action: %s" % store)
|
||||
return "volume_properties"
|
||||
|
||||
|
||||
def getStatus(self):
|
||||
self.container = self.cbox.getContainer(self.device)
|
||||
if not self.container:
|
||||
return "invalid device"
|
||||
return "name=%s" % self.container.getName()
|
||||
|
||||
|
||||
def __prepareHDF(self):
|
||||
self.hdf[self.hdf_prefix + "vol_name"] = self.container.getName()
|
||||
|
||||
|
||||
def __setVolumeName(self, vol_name):
|
||||
if not vol_name:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_props.InvalidVolumeName"
|
||||
return "volume_properties"
|
||||
if vol_name == self.container.getName():
|
||||
## nothing has to be done
|
||||
return "volume_properties"
|
||||
try:
|
||||
self.container.setName(vol_name)
|
||||
except CBInvalidName:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_props.InvalidVolumeName"
|
||||
except CBNameActivelyUsed:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_props.VolumeNameIsInUse"
|
||||
except CBContainerError:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_props.SetVolumeNameFailed"
|
||||
## reread the volume name
|
||||
self.__prepareHDF()
|
||||
return "volume_properties"
|
||||
|
||||
|
||||
def __changePassword(self, old_pw, new_pw, new_pw2):
|
||||
if not old_pw:
|
||||
self.hdf["Data.Warning"] = "EmptyCryptoPassword"
|
||||
elif not new_pw:
|
||||
self.hdf["Data.Warning"] = "EmptyNewCryptoPassword"
|
||||
elif new_pw != new_pw2:
|
||||
self.hdf["Data.Warning"] = "DifferentCryptoPasswords"
|
||||
elif old_pw == new_pw:
|
||||
## do nothing
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
self.container.changePassword(old_pw, new_pw)
|
||||
except CBInvalidType, errMsg:
|
||||
self.cbox.log.info("plugin 'volume_props' - cannot change passphrase for non-encrypted container (%s): %s" % (self.device, errMsg))
|
||||
except CBVolumeIsActive:
|
||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||
except CBChangePasswordError, errMsg:
|
||||
self.cbox.log.warn("plugin 'volume_props' - cannot change password for device (%s): %s" % (self.device, errMsg))
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_props.PasswordChange"
|
||||
else:
|
||||
self.hdf["Data.Success"] = "Plugins.volume_props.PasswordChange"
|
||||
return "volume_properties"
|
Loading…
Reference in a new issue