diff --git a/pythonrewrite/bin/CryptoBox.py b/pythonrewrite/bin/CryptoBox.py index daf75da..ac74e63 100755 --- a/pythonrewrite/bin/CryptoBox.py +++ b/pythonrewrite/bin/CryptoBox.py @@ -18,6 +18,7 @@ import CryptoBoxContainer from CryptoBoxExceptions import * import re import os +import CryptoBoxTools @@ -112,10 +113,16 @@ class CryptoBoxProps(CryptoBox): def __init__(self, config_file=None): '''read config and fill class variables''' CryptoBox.__init__(self, config_file) + self.__reReadContainerList() + + + def __reReadContainerList(self): self.containers = [] - for device in self.__getAvailablePartitions(): + for device in CryptoBoxTools.getAvailablePartitions(): if self.isDeviceAllowed(device): self.containers.append(CryptoBoxContainer.CryptoBoxContainer(device, self)) + ## sort by container name + self.containers.sort(cmp = lambda x,y: x.getName() < y.getName() and -1 or 1) def isDeviceAllowed(self, devicename): @@ -185,9 +192,22 @@ class CryptoBoxProps(CryptoBox): "assign a name to a uuid in the ContainerNameDatabase" used_uuid = self.getUUIDForName(name) "first remove potential conflicting uuid/name combination" - if used_uuid: del self.prefs.nameDB[used_uuid] + if used_uuid: + ## remember the container which name was overriden + for e in self.containers: + if e.getName() == name: + forcedRename = e + break + del self.prefs.nameDB[used_uuid] self.prefs.nameDB[uuid] = name self.prefs.nameDB.write() + ## rename the container that lost its name (necessary while we use cherrypy) + if used_uuid: + ## this is surely not the best way to regenerate the name + dev = e.getDevice() + old_index = self.containers.index(e) + self.containers.remove(e) + self.containers.insert(old_index, CryptoBoxContainer.CryptoBoxContainer(dev,self)) def getNameForUUID(self, uuid): @@ -244,102 +264,6 @@ class CryptoBoxProps(CryptoBox): return [] - """ ************ internal stuff starts here *********** """ - - def __getAvailablePartitions(self): - "retrieve a list of all available containers" - ret_list = [] - try: - "the following reads all lines of /proc/partitions and adds the mentioned devices" - fpart = open("/proc/partitions", "r") - try: - line = fpart.readline() - while line: - p_details = line.split() - if (len(p_details) == 4): - "the following code prevents double entries like /dev/hda and /dev/hda1" - (p_major, p_minor, p_size, p_device) = p_details - if re.search('^[0-9]*$', p_major) and re.search('^[0-9]*$', p_minor): - p_parent = re.sub('[1-9]?[0-9]$', '', p_device) - if p_parent == p_device: - if [e for e in ret_list if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]: - "major partition - its children are already in the list" - pass - else: - "major partition - but there are no children for now" - ret_list.append(p_device) - else: - "minor partition - remove parent if necessary" - if p_parent in ret_list: ret_list.remove(p_parent) - ret_list.append(p_device) - line = fpart.readline() - finally: - fpart.close() - return [self.__getAbsoluteDeviceName(e) for e in ret_list] - except IOError: - self.log.warning("Could not read /proc/partitions") - return [] - - - def __getAbsoluteDeviceName(self, shortname): - """ returns the absolute file name of a device (e.g.: "hda1" -> "/dev/hda1") - this does also work for device mapper devices - if the result is non-unique, one arbitrary value is returned""" - if re.search('^/', shortname): return shortname - default = os.path.join("/dev", shortname) - if os.path.exists(default): return default - result = self.__findMajorMinorOfDevice(shortname) - "if no valid major/minor was found -> exit" - if not result: return default - (major, minor) = result - "for device-mapper devices (major == 254) ..." - if major == 254: - result = self.__findMajorMinorDeviceName("/dev/mapper", major, minor) - if result: return result[0] - "now check all files in /dev" - result = self.__findMajorMinorDeviceName("/dev", major, minor) - if result: return result[0] - return default - - - def __findMajorMinorOfDevice(self, device): - "return the major/minor numbers of a block device by querying /sys/block/?/dev" - if not os.path.exists(os.path.join("/sys/block", device)): return None - blockdev_info_file = os.path.join(os.path.join("/sys/block", device), "dev") - try: - f_blockdev_info = open(blockdev_info_file, "r") - blockdev_info = f_blockdev_info.read() - f_blockdev_info.close() - (str_major, str_minor) = blockdev_info.split(":") - "numeric conversion" - try: - major = int(str_major) - minor = int(str_minor) - return (major, minor) - except ValueError: - "unknown device numbers -> stop guessing" - return None - except IOError: - pass - - - def __findMajorMinorDeviceName(self, dir, major, minor): - "returns the names of devices with the specified major and minor number" - collected = [] - try: - subdirs = [os.path.join(dir, e) for e in os.listdir(dir) if (not os.path.islink(os.path.join(dir, e))) and os.path.isdir(os.path.join(dir, e))] - "do a recursive call to parse the directory tree" - for dirs in subdirs: - collected.extend(self.__findMajorMinorDeviceName(dirs, major, minor)) - "filter all device inodes in this directory" - collected.extend([os.path.realpath(os.path.join(dir, e)) for e in os.listdir(dir) if (os.major(os.stat(os.path.join(dir, e)).st_rdev) == major) and (os.minor(os.stat(os.path.join(dir, e)).st_rdev) == minor)]) - result = [] - for e in collected: - if e not in result: result.append(e) - return collected - except OSError: - return [] - if __name__ == "__main__": cb = CryptoBox() diff --git a/pythonrewrite/bin/CryptoBoxContainer.py b/pythonrewrite/bin/CryptoBoxContainer.py index 8e1e334..90ea84a 100755 --- a/pythonrewrite/bin/CryptoBoxContainer.py +++ b/pythonrewrite/bin/CryptoBoxContainer.py @@ -205,6 +205,7 @@ class CryptoBoxContainer: def __getUUID(self): """return UUID for luks partitions, ext2/3 and vfat filesystems""" + emergency_default = self.device.replace(os.path.sep, "_") devnull = None try: devnull = open(os.devnull, "w") @@ -214,7 +215,7 @@ class CryptoBoxContainer: shell=False, stdin=None, stdout=subprocess.PIPE, - stderr=devnull, + stderr=subprocess.PIPE, args=[self.Progs["blkid"], "-s", "UUID", "-o", "value", @@ -225,10 +226,10 @@ class CryptoBoxContainer: result = proc.stdout.read().strip() if proc.returncode != 0: self.log.warn("retrieving of partition type via 'blkid' failed: %s" % (proc.stderr.read().strip(), )) - return None + return emergency_default devnull.close() if result: return result - return self.device.replace(os.path.sep, "_") + return emergency_default def __getTypeOfPartition(self): diff --git a/pythonrewrite/bin/CryptoBoxTools.py b/pythonrewrite/bin/CryptoBoxTools.py new file mode 100644 index 0000000..a73a659 --- /dev/null +++ b/pythonrewrite/bin/CryptoBoxTools.py @@ -0,0 +1,117 @@ +import logging +import os +import re + +logger = logging.getLogger("CryptoBox") + + +def getAvailablePartitions(): + "retrieve a list of all available containers" + ret_list = [] + try: + "the following reads all lines of /proc/partitions and adds the mentioned devices" + fpart = open("/proc/partitions", "r") + try: + line = fpart.readline() + while line: + p_details = line.split() + if (len(p_details) == 4): + "the following code prevents double entries like /dev/hda and /dev/hda1" + (p_major, p_minor, p_size, p_device) = p_details + if re.search('^[0-9]*$', p_major) and re.search('^[0-9]*$', p_minor): + p_parent = re.sub('[1-9]?[0-9]$', '', p_device) + if p_parent == p_device: + if [e for e in ret_list if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]: + "major partition - its children are already in the list" + pass + else: + "major partition - but there are no children for now" + ret_list.append(p_device) + else: + "minor partition - remove parent if necessary" + if p_parent in ret_list: ret_list.remove(p_parent) + ret_list.append(p_device) + line = fpart.readline() + finally: + fpart.close() + return map(getAbsoluteDeviceName, ret_list) + except IOError: + logger.warning("Could not read /proc/partitions") + return [] + + +def getAbsoluteDeviceName(shortname): + """ returns the absolute file name of a device (e.g.: "hda1" -> "/dev/hda1") + this does also work for device mapper devices + if the result is non-unique, one arbitrary value is returned""" + if re.search('^/', shortname): return shortname + default = os.path.join("/dev", shortname) + if os.path.exists(default): return default + result = findMajorMinorOfDevice(shortname) + "if no valid major/minor was found -> exit" + if not result: return default + (major, minor) = result + "for device-mapper devices (major == 254) ..." + if major == 254: + result = findMajorMinorDeviceName("/dev/mapper", major, minor) + if result: return result[0] + "now check all files in /dev" + result = findMajorMinorDeviceName("/dev", major, minor) + if result: return result[0] + return default + + +def findMajorMinorOfDevice(device): + "return the major/minor numbers of a block device by querying /sys/block/?/dev" + if not os.path.exists(os.path.join(os.path.sep,"sys","block",device)): return None + blockdev_info_file = os.path.join(os.path.join(os.path.sep,"sys","block", device), "dev") + try: + f_blockdev_info = open(blockdev_info_file, "r") + blockdev_info = f_blockdev_info.read() + f_blockdev_info.close() + (str_major, str_minor) = blockdev_info.split(":") + "numeric conversion" + try: + major = int(str_major) + minor = int(str_minor) + return (major, minor) + except ValueError: + "unknown device numbers -> stop guessing" + return None + except IOError: + pass + + +def findMajorMinorDeviceName(dir, major, minor): + "returns the names of devices with the specified major and minor number" + collected = [] + try: + subdirs = [os.path.join(dir, e) for e in os.listdir(dir) if (not os.path.islink(os.path.join(dir, e))) and os.path.isdir(os.path.join(dir, e))] + "do a recursive call to parse the directory tree" + for dirs in subdirs: + collected.extend(findMajorMinorDeviceName(dirs, major, minor)) + "filter all device inodes in this directory" + collected.extend([os.path.realpath(os.path.join(dir, e)) for e in os.listdir(dir) if (os.major(os.stat(os.path.join(dir, e)).st_rdev) == major) and (os.minor(os.stat(os.path.join(dir, e)).st_rdev) == minor)]) + ## remove double entries + result = [] + for e in collected: + if e not in result: result.append(e) + return result + except OSError: + return [] + + +def getParentBlockDevices(): + devs = [] + for line in file("/proc/partitions"): + p_details = line.split() + ## we expect four values - otherwise continue with next iteration + if len(p_details) != 4: continue + (p_major, p_minor, p_size, p_device) = p_details + ## we expect numeric values in the first two columns + if re.search(u'\D',p_major) or re.search(u'\D',p_minor): continue + ## now let us check, if it is a (parent) block device or a partition + if not os.path.isdir(os.path.join(os.path.sep, "sys", "block", p_device)): continue + devs.append(p_device) + return map(getAbsoluteDeviceName, devs) + diff --git a/pythonrewrite/bin/Plugins.py b/pythonrewrite/bin/Plugins.py index 1d87df6..368ce40 100644 --- a/pythonrewrite/bin/Plugins.py +++ b/pythonrewrite/bin/Plugins.py @@ -44,14 +44,19 @@ class PluginManager: def loadLanguageData(self, hdf, lang="en"): + import neo_cgi, neo_util for plfile in self.__getPluginFiles(): + plname = os.path.basename(plfile)[:-3] langdir = os.path.join(os.path.dirname(plfile), "lang") selected_langfile = os.path.join(langdir, lang + ".hdf") default_langfile = os.path.join(langdir, "en.hdf") for langfile in (selected_langfile, default_langfile): if os.access(langfile, os.R_OK): self.log.debug("Loading plugin language file: %s" % langfile) - hdf.readFile(langfile) + lang_hdf = neo_util.HDF() + lang_hdf.readFile(langfile) + ## add the language data below "Lang.Plugins.PLUGINNAME" + hdf.copy("Lang.Plugins." + plname, lang_hdf) break else: self.log.debug("Couldn't find a plugin language file (%s)" % default_langfile) diff --git a/pythonrewrite/bin/WebInterfaceDataset.py b/pythonrewrite/bin/WebInterfaceDataset.py index a91e7be..fb770a1 100644 --- a/pythonrewrite/bin/WebInterfaceDataset.py +++ b/pythonrewrite/bin/WebInterfaceDataset.py @@ -18,7 +18,7 @@ class WebInterfaceDataset(dict): def setPluginState(self, plugins): for pl in plugins.allPlugins(): - self["Data.Status.Modules." + pl] = plugins.getPlugin(pl).getStatus(self.cbox) + self["Data.Status.Plugins." + pl] = plugins.getPlugin(pl).getStatus(self.cbox) def setCurrentDiskState(self, device): @@ -48,6 +48,7 @@ class WebInterfaceDataset(dict): self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"] self["Settings.Language"] = self.prefs["WebSettings"]["Language"] self["Settings.DocLang"] = self.prefs["WebSettings"]["DocLanguage"] + self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"] def __setCryptoBoxState(self): diff --git a/pythonrewrite/bin/WebInterfaceSites.py b/pythonrewrite/bin/WebInterfaceSites.py index 7534ac6..04a6e17 100755 --- a/pythonrewrite/bin/WebInterfaceSites.py +++ b/pythonrewrite/bin/WebInterfaceSites.py @@ -1,9 +1,21 @@ import CryptoBox import WebInterfaceDataset import re -from Plugins import PluginManager +import Plugins from CryptoBoxExceptions import * + +class WebInterfacePlugins: + + def __init__(self, log, plugins, handler_func): + for plname in plugins.allPlugins(): + log.info("Plugin '%s' loaded" % plname) + ## this should be the "easiest" way to expose all plugins as URLs + setattr(self, plname, handler_func(plname)) + setattr(getattr(self, plname), "exposed", True) + + + class WebInterfaceSites: ''' url2func = {'index':'show_status','doc':'show_doc','logs':'show_log'} @@ -16,17 +28,10 @@ class WebInterfaceSites: self.log = logging.getLogger("CryptoBox") self.prefs = self.cbox.prefs self.__resetDataset() - self.plugins = PluginManager(self.prefs["Locations"]["PluginDir"]) - self.__exposePlugins() - + self.pluginList = Plugins.PluginManager(self.prefs["Locations"]["PluginDir"]) + self.plugins = WebInterfacePlugins(self.log, self.pluginList, self.return_plugin_action) + self.plugins.index = self.system - def __exposePlugins(self): - for plname in self.plugins.allPlugins(): - self.log.info("Plugin '%s' loaded" % plname) - ## this should be the "easiest" way to expose all modules as URLs - setattr(self, "module_" + plname, self.return_module_action(plname)) - setattr(getattr(self, "module_" + plname), "exposed", True) - def __resetDataset(self): self.dataset = WebInterfaceDataset.WebInterfaceDataset(self.cbox, self.prefs) @@ -134,8 +139,8 @@ class WebInterfaceSites: try: container.setName(volume_name) # TODO: specify the possible exceptions - except Exception: - self.log.warn("failed to rename the volume '%s' to '%s'" % (device, volume_name)) + except Exception, errMsg: + self.log.warn("failed to rename the volume '%s' to '%s: %s'" % (device, volume_name, errMsg)) self.dataset["Data.Warning"] = "SetVolumeNameFailed" else: self.log.info("successfully renamed volume '%s' to '%s'" % (device, volume_name)) @@ -311,7 +316,7 @@ class WebInterfaceSites: return self.__render("show_volume") - def return_module_action(self, module): + def return_plugin_action(self, plugin_name): def handler(**args): self.__resetDataset() try: @@ -319,15 +324,9 @@ class WebInterfaceSites: del args["weblang"] except KeyError: pass - plugin = self.plugins.getPlugin(module) - try: - nextTemplate = plugin.doAction(self.cbox, **args) - except CBPluginActionError, errMsg: - self.log.debug(errMsg) - self.dataset["Data.Warning"] = errMsg - nextTemplate = "empty" - plugin.prepareForm(self.dataset, self.cbox) - return self.__render(nextTemplate, module) + plugin = self.pluginList.getPlugin(plugin_name) + nextTemplate = plugin.doAction(self.dataset, self.cbox, **args) + return self.__render(nextTemplate, plugin_name) return handler @@ -418,7 +417,7 @@ class WebInterfaceSites: return False - def __render(self, template, module=None): + def __render(self, template, plugin=None): '''renders from clearsilver templates and returns the resulting html Gets a dictionary with all settings, nessessary for rendering. @@ -430,16 +429,16 @@ class WebInterfaceSites: try: import neo_cgi, neo_util, neo_cs except ImportError: - errorMsg = "Could not import clearsilver modules. Try 'apt-get install python-clearsilver'." + errorMsg = "Could not import clearsilver module. Try 'apt-get install python-clearsilver'." self.log.error(errorMsg) sys.stderr.write(errorMsg) raise ImportError, errorMsg - module_cs_file = False - if module: - module_cs_file = self.plugins.getTemplateFileName(module, template) + plugin_cs_file = False + if plugin: + plugin_cs_file = self.pluginList.getTemplateFileName(plugin, template) default_cs_file = os.path.join(self.prefs["Locations"]["TemplateDir"], template + ".cs") - self.dataset["Data.TemplateFile"] = module_cs_file or default_cs_file + self.dataset["Data.TemplateFile"] = plugin_cs_file or default_cs_file self.log.info("rendering site: " + template) cs_path = os.path.join(self.prefs["Locations"]["TemplateDir"], "main.cs") @@ -454,7 +453,7 @@ class WebInterfaceSites: return "Couldn't read language file: %s" % hdf_path ## add the current state of the plugins to the hdf dataset - self.dataset.setPluginState(self.plugins) + self.dataset.setPluginState(self.pluginList) hdf = neo_util.HDF() hdf.readFile(hdf_path) @@ -462,7 +461,7 @@ class WebInterfaceSites: for key in self.dataset.keys(): hdf.setValue(key,str(self.dataset[key])) ## load languaga data of plugins - self.plugins.loadLanguageData(hdf, lang=self.dataset["Settings.Language"]) + self.pluginList.loadLanguageData(hdf, lang=self.dataset["Settings.Language"]) cs = neo_cs.CS(hdf) cs.parseFile(cs_path) return cs.render() diff --git a/pythonrewrite/plugins/date/date.py b/pythonrewrite/plugins/date/date.py index 5f70e0b..2502075 100644 --- a/pythonrewrite/plugins/date/date.py +++ b/pythonrewrite/plugins/date/date.py @@ -1,26 +1,17 @@ -from CryptoBoxExceptions import CBPluginActionError import subprocess import os -def prepareForm(hdf, cbox): - date = __getCurrentDate() - hdf["Data.Modules.date.year"] = date.year - hdf["Data.Modules.date.month"] = date.month - hdf["Data.Modules.date.day"] = date.day - hdf["Data.Modules.date.hour"] = date.hour - hdf["Data.Modules.date.minute"] = date.minute - - -def doAction(cbox, store=None, year=0, month=0, day=0, hour=0, minute=0): +def doAction(hdf, cbox, store=None, year=0, month=0, day=0, hour=0, minute=0): import datetime + __prepareFormData(hdf, cbox) if store: try: year, month, day = int(year), int(month), int(day) hour, minute = int(hour), int(minute) new_date = datetime.datetime(year, month, day, hour, minute) except ValueError: - raise CBPluginActionError, "InvalidDate" + hdf["Data.Warning"] = "Plugins.date.InvalidDate" proc = subprocess.Popen( shell = False, args = [ @@ -33,7 +24,8 @@ def doAction(cbox, store=None, year=0, month=0, day=0, hour=0, minute=0): if proc.returncode == 0: return "form_system" else: - raise CBPluginActionError, "InvalidDate" + hdf["Data.Warning"] = "Plugins.date.InvalidDate" + return "form_date" else: return "form_date" @@ -42,6 +34,15 @@ def getStatus(cbox): return str(__getCurrentDate()) +def __prepareFormData(hdf, cbox): + date = __getCurrentDate() + hdf["Data.Plugins.date.year"] = date.year + hdf["Data.Plugins.date.month"] = date.month + hdf["Data.Plugins.date.day"] = date.day + hdf["Data.Plugins.date.hour"] = date.hour + hdf["Data.Plugins.date.minute"] = date.minute + + def __getCurrentDate(): import datetime return datetime.datetime(2000,1,1).now() diff --git a/pythonrewrite/plugins/date/form_date.cs b/pythonrewrite/plugins/date/form_date.cs index 838db44..451f96d 100644 --- a/pythonrewrite/plugins/date/form_date.cs +++ b/pythonrewrite/plugins/date/form_date.cs @@ -1,42 +1,42 @@ -

+

- + -


+


-


+


 : 

- + diff --git a/pythonrewrite/plugins/date/lang/en.hdf b/pythonrewrite/plugins/date/lang/en.hdf index 44824b5..17d2b02 100644 --- a/pythonrewrite/plugins/date/lang/en.hdf +++ b/pythonrewrite/plugins/date/lang/en.hdf @@ -1,35 +1,29 @@ -Lang { +Name = Change date and time +Link = Set date/time +Rank = 10 - Title.ConfigDate = Date and time setting +Title.ConfigDate = Date and time setting - Button.ConfigDate = Set date and time - - Text.Date = Date - Text.Time = Time - Text.Months { - 1 = January - 2 = February - 3 = March - 4 = April - 5 = May - 6 = June - 7 = July - 8 = August - 9 = September - 10 = October - 11 = November - 12 = December - } - - Modules.date { - Name = Change date and time - Link = Set date/time - Rank = 10 - } - - WarningMessage.InvalidDate { - Title = Invalid value - Text = An invalid value for date or time was supplied. Please try again. - } +Button.ConfigDate = Set date and time +Text.Date = Date +Text.Time = Time +Text.Months { + 1 = January + 2 = February + 3 = March + 4 = April + 5 = May + 6 = June + 7 = July + 8 = August + 9 = September + 10 = October + 11 = November + 12 = December +} + +WarningMessage.InvalidDate { + Title = Invalid value + Text = An invalid value for date or time was supplied. Please try again. } diff --git a/pythonrewrite/plugins/logs/lang/en.hdf b/pythonrewrite/plugins/logs/lang/en.hdf index cc74717..58e8d50 100644 --- a/pythonrewrite/plugins/logs/lang/en.hdf +++ b/pythonrewrite/plugins/logs/lang/en.hdf @@ -1,13 +1,7 @@ -Lang { +Name = Show the content of the log file +Link = Show log file +Rank = 90 - Title.Log = CryptoBox logfiles +Title.Log = CryptoBox logfiles - Text.EmptyLog = The logfile of the CryptoBox is empty. - - Modules.logs { - Name = Show the content of the log file - Link = Show log file - Rank = 90 - } - -} +Text.EmptyLog = The logfile of the CryptoBox is empty. diff --git a/pythonrewrite/plugins/logs/logs.py b/pythonrewrite/plugins/logs/logs.py index 81a09d7..ff40e46 100644 --- a/pythonrewrite/plugins/logs/logs.py +++ b/pythonrewrite/plugins/logs/logs.py @@ -1,11 +1,6 @@ -from CryptoBoxExceptions import CBPluginActionError - -def prepareForm(hdf, cbox): - hdf["Data.Modules.logs.Content"] = __getLogContent(cbox) - - -def doAction(cbox): +def doAction(hdf, cbox): + __prepareFormData(hdf,cbox) return "show_log" @@ -16,6 +11,10 @@ def getStatus(cbox): cbox.prefs["Log"]["Details"]) +def __prepareFormData(hdf, cbox): + hdf["Data.Plugins.logs.Content"] = __getLogContent(cbox) + + def __getLogContent(cbox, lines=30, maxSize=2000): return "
".join(cbox.getLogData(lines, maxSize)) diff --git a/pythonrewrite/plugins/logs/show_log.cs b/pythonrewrite/plugins/logs/show_log.cs index 91d910f..223ece9 100644 --- a/pythonrewrite/plugins/logs/show_log.cs +++ b/pythonrewrite/plugins/logs/show_log.cs @@ -1,13 +1,13 @@ - +
-

+

- -

+ +

-

+

diff --git a/pythonrewrite/plugins/network/form_network.cs b/pythonrewrite/plugins/network/form_network.cs index 072ceae..4ca71f8 100644 --- a/pythonrewrite/plugins/network/form_network.cs +++ b/pythonrewrite/plugins/network/form_network.cs @@ -1,22 +1,22 @@ -

+

- + -


+


. + var:Data.Plugins.network.ip.oc1 ?>" />. . + var:Data.Plugins.network.ip.oc2 ?>" />. . + var:Data.Plugins.network.ip.oc3 ?>" />.

+ var:Data.Plugins.network.ip.oc4 ?>" />

- + diff --git a/pythonrewrite/plugins/network/lang/en.hdf b/pythonrewrite/plugins/network/lang/en.hdf index 5c1cac8..bd60bf7 100644 --- a/pythonrewrite/plugins/network/lang/en.hdf +++ b/pythonrewrite/plugins/network/lang/en.hdf @@ -1,20 +1,24 @@ -Lang { +Name = Configure network +Link = Configure network +Rank = 30 - Title.Network = Network settings +Title.Network = Network settings - Button.Network = Update settings +Button.Network = Update settings - Text.IP = Network address +Text.IP = Network address - Modules.network { - Name = Configure network - Link = Configure network - Rank = 30 - } - WarningMessage.InvalidIP { +WarningMessage { + InvalidIP { Title = Invalid value Text = An invalid network address (IP) was supplied. Please try again. } - +} + +SuccessMessage { + IPChanged { + Title = Network address changed + Text = The network address has been changed. In a few seconds you will get redirected to the new address. + } } diff --git a/pythonrewrite/plugins/network/network.py b/pythonrewrite/plugins/network/network.py index 67652da..82a4e5b 100644 --- a/pythonrewrite/plugins/network/network.py +++ b/pythonrewrite/plugins/network/network.py @@ -1,19 +1,11 @@ -from CryptoBoxExceptions import CBPluginActionError import re import subprocess import imp import os -def prepareForm(hdf, cbox): - (oc1, oc2, oc3, oc4) = __getCurrentIP(cbox) - hdf["Data.Modules.network.ip.oc1"] = oc1 - hdf["Data.Modules.network.ip.oc2"] = oc2 - hdf["Data.Modules.network.ip.oc3"] = oc3 - hdf["Data.Modules.network.ip.oc4"] = oc4 - - -def doAction(cbox, store=None, ip1="", ip2="", ip3="", ip4=""): +def doAction(hdf, cbox, store=None, ip1="", ip2="", ip3="", ip4=""): + __prepareFormData(hdf, cbox) if store: try: for ip_in in (ip1, ip2, ip3, ip4): @@ -22,11 +14,16 @@ def doAction(cbox, store=None, ip1="", ip2="", ip3="", ip4=""): raise ValueError ip = "%d.%d.%d.%d" % (int(ip1), int(ip2), int(ip3), int(ip4)) except ValueError: - raise CBPluginActionError, "InvalidIP" + hdf["Data.Warning"] = "Plugins.network.InvalidIP" + return "form_system" if __setIP(cbox, ip): + hdf["Data.Success"] = "Plugins.network.IPChanged" + hdf["Data.Redirect.URL"] = "" + hdf["Data.Redirect.Delay"] = 30 return "form_system" else: - raise CBPluginActionError, "InvalidIP" + hdf["Data.Warning"] = "Plugins.network.InvalidIP" + return "form_network" else: return "form_network" @@ -35,14 +32,22 @@ def getStatus(cbox): return "%d.%d.%d.%d" % __getCurrentIP(cbox) +def __prepareFormData(hdf, cbox): + (oc1, oc2, oc3, oc4) = __getCurrentIP(cbox) + hdf["Data.Plugins.network.ip.oc1"] = oc1 + hdf["Data.Plugins.network.ip.oc2"] = oc2 + hdf["Data.Plugins.network.ip.oc3"] = oc3 + hdf["Data.Plugins.network.ip.oc4"] = oc4 + + def __getCurrentIP(cbox): - root_action_mod = imp.load_source("root_action", os.path.join(os.path.dirname(__file__), "root_action.py")) + root_action_plug = imp.load_source("root_action", os.path.join(os.path.dirname(__file__), "root_action.py")) proc = subprocess.Popen( shell = False, stdout = subprocess.PIPE, args = [ - root_action_mod.IFCONFIG_BIN, - root_action_mod.IFACE]) + root_action_plug.IFCONFIG_BIN, + root_action_plug.IFACE]) (output, error) = proc.communicate() if proc.returncode != 0: return (0,0,0,0) match = re.search(u'inet [\w]+:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s',output) diff --git a/pythonrewrite/plugins/partition/current_partition_info.cs b/pythonrewrite/plugins/partition/current_partition_info.cs new file mode 100644 index 0000000..e896e23 --- /dev/null +++ b/pythonrewrite/plugins/partition/current_partition_info.cs @@ -0,0 +1,8 @@ + + + + + + + diff --git a/pythonrewrite/plugins/partition/lang/en.hdf b/pythonrewrite/plugins/partition/lang/en.hdf new file mode 100644 index 0000000..f790621 --- /dev/null +++ b/pythonrewrite/plugins/partition/lang/en.hdf @@ -0,0 +1,33 @@ +Name = Disk partitioning +Link = Disk partitioning +Rank = 80 + +Title.Partition = Disk partitions + +Button { + SelectDevice = Repartition disk + AddPartition = Add another partition + Back = Back + SavePartitions = Save changes + AbortPartitions = Cancel +} + +Text { + FS { + Type = Filesystem type + Fat = FAT (Windows) + Ext2 = Ext2 + Ext3 = Ext3 + Reiser = Reiser + } + Size = Size (MB) + SelectDevice = Choose a disk for partitioning + NoDevicesAvailable = No suitable disks found - please check your configuration and hardware setup. + + +WarningMessage { + InvalidInput { + Title = Invalid input + Text = You entered an invalid value. + } +} diff --git a/pythonrewrite/plugins/partition/partition.py b/pythonrewrite/plugins/partition/partition.py new file mode 100644 index 0000000..8987d31 --- /dev/null +++ b/pythonrewrite/plugins/partition/partition.py @@ -0,0 +1,132 @@ +import re +import subprocess +import imp +import os +import logging +import CryptoBoxTools + +PartTypes = { + "linux" : "L", + "windows" : "0xC"} + +logger = logging.getLogger("CryptoBox") + +def doAction(hdf, cbox, **args): + try: + step = args["step"] + del args["step"] + except KeyError: + step = "select_device" + if step == "add_partition": + return __actionAddPartition(hdf, cbox, args) + if step == "del_partition": + return __actionDelPartition(hdf, cbox, args) + elif step == "finish": + return __actionFinish(hdf, cbox, args) + else: # for "select_device" and for invalid targets + return __actionSelectDevice(hdf, cbox, args) + + +def getStatus(cbox): + return "%d.%d.%d.%d" % __getCurrentIP(cbox) + + +def __isDeviceValid(device, cbox): + if not cbox.isDeviceAllowed(device): + return False + if not device in CryptoBoxTools.getParentBlockDevices(): + return False + + +def __actionSelectDevice(hdf, cbox, args): + block_devices = [e + for e in CryptoBoxTools.getParentBlockDevices() + if cbox.isDeviceAllowed(e)] + counter = 0 + for a in block_devices: + hdf["Data.Plugins.partition.BlockDevices.%d" % counter] = a + cbox.log.debug("found a suitable block device: %s" % a) + counter += 1 + return "select_device" + + +def __actionAddPartition(hdf, cbox, args): + try: + device = args["block_device"] + except KeyError: + return __actionSelectDevice(hdf, cbox, args) + #FIXME: the following check should obviuosly get reversed + if __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) + size = __getDeviceSize(device) + hdf["Data.Plugins.partition.Device"] = device + hdf["Data.Plugins.partition.Device.Size"] = size + parts = __getPartitionsFromArgs(args, size) + __setPartitionData(hdf, parts, size) + return "set_partitions" + + +def __actionDelPartition(hdf, cbox, args): + try: + device = args["block_device"] + except KeyError: + return __actionSelectDevice(hdf, cbox, args) + #FIXME: the following check should obviuosly get reversed + if __isDeviceValid(device, cbox): return __actionSelectDevice(hdf, cbox, args) + size = __getDeviceSize(device) + hdf["Data.Plugins.partition.Device"] = device + hdf["Data.Plugins.partition.Device.Size"] = size + parts = __getPartitionsFromArgs(args, size) + __setPartitionData(hdf, parts[:-1], size) + return "set_partitions" + + +def __setPartitionData(hdf, parts, size): + availSize = size + i = 0 + for part in parts: + logger.debug(part) + hdf["Data.Plugins.partition.Parts.%d.Size" % i] = part["size"] + hdf["Data.Plugins.partition.Parts.%d.Type" % i] = part["type"] + availSize -= part["size"] + i += 1 + hdf["Data.Plugins.partition.availSize"] = availSize + for t in PartTypes.keys(): + hdf["Data.Plugins.partition.Types.%s" % t] = t + + +def __getPartitionsFromArgs(args, maxSize): + parts = [] + done = False + availSize = maxSize + i = -1 + while not done: + i += 1 + try: + size = int(args["part%d_size" % i]) + partType = args["part%d_type" % i] + if int(size) > availSize: continue + if int(size) <= 0: continue + if not partType in PartTypes.keys(): continue + parts.append({"size":size, "type":partType}) + availSize -= size + except TypeError: + pass + except KeyError: + done = True + return parts + + +def __getDeviceSize(device): + rdev = os.stat(device).st_rdev + minor = os.minor(rdev) + major = os.major(rdev) + for f in file("/proc/partitions"): + try: + elements = f.split() + if len(elements) != 4: continue + if (int(elements[0]) == major) and (int(elements[1]) == minor): + return int(elements[2]) + except ValueError: + pass + return 0 + diff --git a/pythonrewrite/plugins/partition/root_action.py b/pythonrewrite/plugins/partition/root_action.py new file mode 100755 index 0000000..1b23a91 --- /dev/null +++ b/pythonrewrite/plugins/partition/root_action.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python2.4 + +#TODO: add netmask and gateway + +## necessary: otherwise CryptoBoxRootActions.py will refuse to execute this script +PLUGIN_TYPE = "cryptobox" + + +import subprocess +import re +import sys +import os + + +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) + + proc = subprocess.Popen( + shell = False, + args = [IFCONFIG_BIN, IFACE, args[0]]) + proc.communicate() + sys.exit(proc.returncode) + diff --git a/pythonrewrite/plugins/partition/select_device.cs b/pythonrewrite/plugins/partition/select_device.cs new file mode 100644 index 0000000..9b982a9 --- /dev/null +++ b/pythonrewrite/plugins/partition/select_device.cs @@ -0,0 +1,27 @@ + + +

+ + 0 ?> + + + +


+

+ + + + + + + + + +

+ + + diff --git a/pythonrewrite/plugins/partition/set_partitions.cs b/pythonrewrite/plugins/partition/set_partitions.cs new file mode 100644 index 0000000..ad2dc96 --- /dev/null +++ b/pythonrewrite/plugins/partition/set_partitions.cs @@ -0,0 +1,37 @@ + + +

+ +

+

- -

+ + + + +

- -

+ + + + + + + 0 ?> + + + + + + + + 0 ?> + + + + + + + diff --git a/pythonrewrite/plugins/plugin-interface.txt b/pythonrewrite/plugins/plugin-interface.txt index 97ff779..a801d5f 100644 --- a/pythonrewrite/plugins/plugin-interface.txt +++ b/pythonrewrite/plugins/plugin-interface.txt @@ -1,36 +1,33 @@ The following directory structure is required: - - python code: plugins/MODULENAME/MODULENAME.py (all lower case is recommended) - - language files: plugins/MODULENAME/lang/(en|de|??).hdf - - clearsilver templates: plugins/MODULENAME/*.cs + - python code: plugins/PLUGINNAME/PLUGINNAME.py (all lower case is recommended) + - language files: plugins/PLUGINNAME/lang/(en|de|??).hdf + - clearsilver templates: plugins/PLUGINNAME/*.cs Python code interface: - def prepareForm(hdf, cbox): - - here you may add some items to the hdf dataset used by the templates - - the recommended namespace is Data.Modules.MODULENAME.??? - - def doAction(cbox, store=None, ???): - - this function will get called whenever this module is involved in a request + def doAction(hdf, cbox, store=None, ???): + - 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 raise a CBPluginException (e.g. CBPluginActionError) - the error message should be the name of a warning message (maybe defined in the plugin specific language file) - e.g. "InvalidDate" for Lang.WarningMessage.InvalidDate - - the return value should be the name of the template that should be displayed after processing (a template file in the module 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) def def getStatus(cbox): - - returns a string, that described a state connected to this module (e.g. the current date and time (for the "date" plugin) + - returns a string, that described a state connected to this plugin (e.g. the current date and time (for the "date" plugin) 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 following values _must_ be defined: - Lang.Modules.MODULENAME.Name (a short description) - Lang.Modules.MODULENAME.Link (the visible text for links to this module) - Lang.Modules.MODULENAME.Rank (defines the order of the plugins displayed) - - all other elements should follow the usual structure of language files + 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) Clearsilver template: - should start with a "

" tag - - links to the module (e.g. in form headers) could look like the following: - + - 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 diff --git a/pythonrewrite/templates/footer.cs b/pythonrewrite/templates/footer.cs index 508216c..7f3e30b 100644 --- a/pythonrewrite/templates/footer.cs +++ b/pythonrewrite/templates/footer.cs @@ -26,7 +26,7 @@ Data.Status.Config= Data.Status.InitRunning= Data.Status.IP= Data.Status.Mounted= -Data.Status.Modules.Data.Status.Plugins.= CBOX-STATUS-end --> diff --git a/pythonrewrite/templates/form_system.cs b/pythonrewrite/templates/form_system.cs index 2563dd7..7269960 100644 --- a/pythonrewrite/templates/form_system.cs +++ b/pythonrewrite/templates/form_system.cs @@ -6,18 +6,18 @@ -
  • " title="">
  • - + -= 0 && x.Rank <= 100) ?> -
  • " title="">
  • diff --git a/pythonrewrite/templates/macros.cs b/pythonrewrite/templates/macros.cs index e094019..5183f50 100644 --- a/pythonrewrite/templates/macros.cs +++ b/pythonrewrite/templates/macros.cs @@ -1,41 +1,45 @@
    -

    -

    - -

    unknown warning message

    -

    could not find warning message: ''

    +# the following macro is as ugly as possible - but somehow we have to manage + to use 'normal' and 'plugin' messages in a clean way: + Lang.WarningMessage.??? - used by core functions + Lang.Plugins.PLUGINNAME.WarningMessage.??? - used by plugins ?>
    +

    +

    + +

    +

    + +

    unknown message

    +

    could not find message: ''

    -

    -

    - -

    unknown error message

    -

    could not find error message: ''

    -
    -

    -

    - -

    unknown success message

    -

    could not find success message: ''

    -
    - + + - - - + -
    -

    +
    +

    - - +