From ca13aebdc8c0c258b1c9d1de376e4bc6513027b0 Mon Sep 17 00:00:00 2001 From: lars Date: Mon, 9 Oct 2006 16:43:14 +0000 Subject: [PATCH] new plugins: 'format_fs', 'volume_mount', 'volume_props', 'shutdown' and 'volume_details' new plugin attribute: "requestAuth" --- pythonrewrite/plugins/date/date.py | 3 + pythonrewrite/plugins/format_fs/format_fs.py | 93 ++++++++++++++++ pythonrewrite/plugins/format_fs/lang/en.hdf | 36 +++++++ .../plugins/format_fs/volume_format.cs | 37 +++++++ .../plugins/format_fs/volume_format_luks.cs | 33 ++++++ pythonrewrite/plugins/logs/logs.py | 3 + pythonrewrite/plugins/network/form_network.cs | 22 ++-- pythonrewrite/plugins/network/network.py | 3 + pythonrewrite/plugins/partition/lang/en.hdf | 12 ++- pythonrewrite/plugins/partition/partition.py | 72 +++++++++---- .../plugins/partition/select_device.cs | 10 +- pythonrewrite/plugins/plugin-interface.txt | 39 ++++--- .../plugins/shutdown/form_shutdown.cs | 27 +++++ pythonrewrite/plugins/shutdown/lang/en.hdf | 34 ++++++ pythonrewrite/plugins/shutdown/root_action.py | 48 +++++++++ pythonrewrite/plugins/shutdown/shutdown.py | 50 +++++++++ .../plugins/volume_details/lang/en.hdf | 21 ++++ .../plugins/volume_details/volume_details.cs | 19 ++++ .../plugins/volume_details/volume_details.py | 17 +++ .../plugins/volume_mount/lang/en.hdf | 57 ++++++++++ .../plugins/volume_mount/volume_mount.cs | 16 +++ .../plugins/volume_mount/volume_mount.py | 102 ++++++++++++++++++ .../plugins/volume_mount/volume_status.cs | 9 ++ .../plugins/volume_mount/volume_umount.cs | 8 ++ .../plugins/volume_props/lang/en.hdf | 51 +++++++++ .../plugins/volume_props/volume_properties.cs | 63 +++++++++++ .../plugins/volume_props/volume_props.py | 80 ++++++++++++++ 27 files changed, 920 insertions(+), 45 deletions(-) create mode 100644 pythonrewrite/plugins/format_fs/format_fs.py create mode 100644 pythonrewrite/plugins/format_fs/lang/en.hdf create mode 100644 pythonrewrite/plugins/format_fs/volume_format.cs create mode 100644 pythonrewrite/plugins/format_fs/volume_format_luks.cs create mode 100644 pythonrewrite/plugins/shutdown/form_shutdown.cs create mode 100644 pythonrewrite/plugins/shutdown/lang/en.hdf create mode 100755 pythonrewrite/plugins/shutdown/root_action.py create mode 100644 pythonrewrite/plugins/shutdown/shutdown.py create mode 100644 pythonrewrite/plugins/volume_details/lang/en.hdf create mode 100644 pythonrewrite/plugins/volume_details/volume_details.cs create mode 100644 pythonrewrite/plugins/volume_details/volume_details.py create mode 100644 pythonrewrite/plugins/volume_mount/lang/en.hdf create mode 100644 pythonrewrite/plugins/volume_mount/volume_mount.cs create mode 100644 pythonrewrite/plugins/volume_mount/volume_mount.py create mode 100644 pythonrewrite/plugins/volume_mount/volume_status.cs create mode 100644 pythonrewrite/plugins/volume_mount/volume_umount.cs create mode 100644 pythonrewrite/plugins/volume_props/lang/en.hdf create mode 100644 pythonrewrite/plugins/volume_props/volume_properties.cs create mode 100644 pythonrewrite/plugins/volume_props/volume_props.py diff --git a/pythonrewrite/plugins/date/date.py b/pythonrewrite/plugins/date/date.py index 99f705a..a44ed0d 100644 --- a/pythonrewrite/plugins/date/date.py +++ b/pythonrewrite/plugins/date/date.py @@ -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: diff --git a/pythonrewrite/plugins/format_fs/format_fs.py b/pythonrewrite/plugins/format_fs/format_fs.py new file mode 100644 index 0000000..cd32640 --- /dev/null +++ b/pythonrewrite/plugins/format_fs/format_fs.py @@ -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 + diff --git a/pythonrewrite/plugins/format_fs/lang/en.hdf b/pythonrewrite/plugins/format_fs/lang/en.hdf new file mode 100644 index 0000000..a9c8822 --- /dev/null +++ b/pythonrewrite/plugins/format_fs/lang/en.hdf @@ -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! + } +} diff --git a/pythonrewrite/plugins/format_fs/volume_format.cs b/pythonrewrite/plugins/format_fs/volume_format.cs new file mode 100644 index 0000000..fcdb219 --- /dev/null +++ b/pythonrewrite/plugins/format_fs/volume_format.cs @@ -0,0 +1,37 @@ + + + + +

+ + +
+ +
+ + + + +

+ +

+ +

+

+ + + + + + + + + diff --git a/pythonrewrite/plugins/format_fs/volume_format_luks.cs b/pythonrewrite/plugins/format_fs/volume_format_luks.cs new file mode 100644 index 0000000..c610e71 --- /dev/null +++ b/pythonrewrite/plugins/format_fs/volume_format_luks.cs @@ -0,0 +1,33 @@ + + + + +

+ + +
+ +
+ + + + +

+ +

:

+

:

+ +

+

+ + + + + + + + + + diff --git a/pythonrewrite/plugins/logs/logs.py b/pythonrewrite/plugins/logs/logs.py index b629e0d..cb4d76d 100644 --- a/pythonrewrite/plugins/logs/logs.py +++ b/pythonrewrite/plugins/logs/logs.py @@ -3,6 +3,9 @@ import os class logs(CryptoBoxPlugin.CryptoBoxPlugin): + pluginCapabilities = [ "system" ] + requestAuth = False + def doAction(self): self.__prepareFormData() return "show_log" diff --git a/pythonrewrite/plugins/network/form_network.cs b/pythonrewrite/plugins/network/form_network.cs index 14d1179..d2946e7 100644 --- a/pythonrewrite/plugins/network/form_network.cs +++ b/pythonrewrite/plugins/network/form_network.cs @@ -1,18 +1,22 @@ + +

-


- . - . - . -

+

+ ...

diff --git a/pythonrewrite/plugins/network/network.py b/pythonrewrite/plugins/network/network.py index 55001b4..02478b2 100644 --- a/pythonrewrite/plugins/network/network.py +++ b/pythonrewrite/plugins/network/network.py @@ -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": diff --git a/pythonrewrite/plugins/partition/lang/en.hdf b/pythonrewrite/plugins/partition/lang/en.hdf index 25f8c82..07222d5 100644 --- a/pythonrewrite/plugins/partition/lang/en.hdf +++ b/pythonrewrite/plugins/partition/lang/en.hdf @@ -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 { diff --git a/pythonrewrite/plugins/partition/partition.py b/pythonrewrite/plugins/partition/partition.py index 8067c27..5e2ce03 100644 --- a/pythonrewrite/plugins/partition/partition.py +++ b/pythonrewrite/plugins/partition/partition.py @@ -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) @@ -105,7 +116,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin): parts = self.__getPartitionsFromArgs(args) self.__setPartitionData(parts) return "set_partitions" - + def __actionDelPartition(self, args): try: @@ -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 "Error" 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,13 +295,19 @@ 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 - yield ",%d,%s,*" % (parts[0]["size"], self.PartTypes[parts[0]["type"]][0]) + 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 if not parts: return @@ -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 "Failed!" + 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 "Failed!" + 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]) diff --git a/pythonrewrite/plugins/partition/select_device.cs b/pythonrewrite/plugins/partition/select_device.cs index f90a660..9d26d1b 100644 --- a/pythonrewrite/plugins/partition/select_device.cs +++ b/pythonrewrite/plugins/partition/select_device.cs @@ -15,7 +15,7 @@

-

+

+ + + diff --git a/pythonrewrite/plugins/plugin-interface.txt b/pythonrewrite/plugins/plugin-interface.txt index 0c69667..50cec84 100644 --- a/pythonrewrite/plugins/plugin-interface.txt +++ b/pythonrewrite/plugins/plugin-interface.txt @@ -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 "" 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 - - - function "getStatus": - - returns a string, that describes a state connected to this plugin (e.g. the current date and time (for the "date" plugin)) + * generator: a generator object ("yield") - its content will replace every + occurrence of "" 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)) + - 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 "

" tag + - should start with a "

" tag (volume plugins: "h2") - links to the plugin (e.g. in form headers) could look like the following: - - a hidden input field called "store" should be used to indicate a form submission + - volume plugins must include "show_volume_[header|footer]" (see examples) + diff --git a/pythonrewrite/plugins/shutdown/form_shutdown.cs b/pythonrewrite/plugins/shutdown/form_shutdown.cs new file mode 100644 index 0000000..23065c5 --- /dev/null +++ b/pythonrewrite/plugins/shutdown/form_shutdown.cs @@ -0,0 +1,27 @@ + + +

+ +

+ +

+ + + + + + + + +
+ + + + + + + + + +
+ diff --git a/pythonrewrite/plugins/shutdown/lang/en.hdf b/pythonrewrite/plugins/shutdown/lang/en.hdf new file mode 100644 index 0000000..0a9efe2 --- /dev/null +++ b/pythonrewrite/plugins/shutdown/lang/en.hdf @@ -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! + } +} diff --git a/pythonrewrite/plugins/shutdown/root_action.py b/pythonrewrite/plugins/shutdown/root_action.py new file mode 100755 index 0000000..ca98a47 --- /dev/null +++ b/pythonrewrite/plugins/shutdown/root_action.py @@ -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) + diff --git a/pythonrewrite/plugins/shutdown/shutdown.py b/pythonrewrite/plugins/shutdown/shutdown.py new file mode 100644 index 0000000..bd40e38 --- /dev/null +++ b/pythonrewrite/plugins/shutdown/shutdown.py @@ -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 + diff --git a/pythonrewrite/plugins/volume_details/lang/en.hdf b/pythonrewrite/plugins/volume_details/lang/en.hdf new file mode 100644 index 0000000..f6c81ac --- /dev/null +++ b/pythonrewrite/plugins/volume_details/lang/en.hdf @@ -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 + } +} + diff --git a/pythonrewrite/plugins/volume_details/volume_details.cs b/pythonrewrite/plugins/volume_details/volume_details.cs new file mode 100644 index 0000000..0022d14 --- /dev/null +++ b/pythonrewrite/plugins/volume_details/volume_details.cs @@ -0,0 +1,19 @@ + + + + +

+ +

+ + diff --git a/pythonrewrite/plugins/volume_details/volume_details.py b/pythonrewrite/plugins/volume_details/volume_details.py new file mode 100644 index 0000000..7354639 --- /dev/null +++ b/pythonrewrite/plugins/volume_details/volume_details.py @@ -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" + diff --git a/pythonrewrite/plugins/volume_mount/lang/en.hdf b/pythonrewrite/plugins/volume_mount/lang/en.hdf new file mode 100644 index 0000000..4cc9c87 --- /dev/null +++ b/pythonrewrite/plugins/volume_mount/lang/en.hdf @@ -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. + } + +} diff --git a/pythonrewrite/plugins/volume_mount/volume_mount.cs b/pythonrewrite/plugins/volume_mount/volume_mount.cs new file mode 100644 index 0000000..03ffad0 --- /dev/null +++ b/pythonrewrite/plugins/volume_mount/volume_mount.cs @@ -0,0 +1,16 @@ +

+ +

+ + + + + + + + + + + +

+ diff --git a/pythonrewrite/plugins/volume_mount/volume_mount.py b/pythonrewrite/plugins/volume_mount/volume_mount.py new file mode 100644 index 0000000..1774274 --- /dev/null +++ b/pythonrewrite/plugins/volume_mount/volume_mount.py @@ -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" + diff --git a/pythonrewrite/plugins/volume_mount/volume_status.cs b/pythonrewrite/plugins/volume_mount/volume_status.cs new file mode 100644 index 0000000..724af1a --- /dev/null +++ b/pythonrewrite/plugins/volume_mount/volume_status.cs @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/pythonrewrite/plugins/volume_mount/volume_umount.cs b/pythonrewrite/plugins/volume_mount/volume_umount.cs new file mode 100644 index 0000000..8019291 --- /dev/null +++ b/pythonrewrite/plugins/volume_mount/volume_umount.cs @@ -0,0 +1,8 @@ +

+ + +

+ +

+ + diff --git a/pythonrewrite/plugins/volume_props/lang/en.hdf b/pythonrewrite/plugins/volume_props/lang/en.hdf new file mode 100644 index 0000000..fbcd1d8 --- /dev/null +++ b/pythonrewrite/plugins/volume_props/lang/en.hdf @@ -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! + } +} diff --git a/pythonrewrite/plugins/volume_props/volume_properties.cs b/pythonrewrite/plugins/volume_props/volume_properties.cs new file mode 100644 index 0000000..b6f3d71 --- /dev/null +++ b/pythonrewrite/plugins/volume_props/volume_properties.cs @@ -0,0 +1,63 @@ + + + + +

+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+
+ + + +
+

+
+ + +

+
+ + + + diff --git a/pythonrewrite/plugins/volume_props/volume_props.py b/pythonrewrite/plugins/volume_props/volume_props.py new file mode 100644 index 0000000..e99ef16 --- /dev/null +++ b/pythonrewrite/plugins/volume_props/volume_props.py @@ -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"