plugin interface implemented
example plugins added: date and network moved "logs" to plugins
This commit is contained in:
parent
5af79f90b6
commit
dba8ca79fd
27 changed files with 483 additions and 174 deletions
|
@ -26,6 +26,9 @@ class CryptoBox:
|
|||
|
||||
put things like logging, conf and oter stuff in here,
|
||||
that might be used by more classes, it will be passed on to them'''
|
||||
|
||||
VERSION = "0.3~1"
|
||||
|
||||
def __init__(self, config_file=None):
|
||||
import CryptoBoxSettings
|
||||
self.log = self.__getStartupLogger()
|
||||
|
@ -141,13 +144,14 @@ class CryptoBoxProps(CryptoBox):
|
|||
return []
|
||||
try:
|
||||
fd = open(log_file, "r")
|
||||
if maxSize: content = fd.readlines(maxSize)
|
||||
else: content = fd.readlines()
|
||||
if maxSize: fd.seek(-maxSize, 2) # seek relative to the end of the file
|
||||
content = fd.readlines()
|
||||
fd.close()
|
||||
except IOError:
|
||||
self.log.warn("failed to read the log file (%s)" % log_file)
|
||||
return []
|
||||
if lines: content = content[-lines:]
|
||||
content.reverse()
|
||||
return content
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,15 @@ class CryptoBoxError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class CBPluginError(CryptoBoxError):
|
||||
"""should be raised for plugin specific problems"""
|
||||
|
||||
|
||||
class CBPluginActionError(CBPluginError):
|
||||
"""should be raised when a plugin action failed"""
|
||||
pass
|
||||
|
||||
|
||||
class CBConfigError(CryptoBoxError):
|
||||
"""any kind of error related to the configuration of a cryptobox"""
|
||||
pass
|
||||
|
|
|
@ -171,6 +171,7 @@ NameDatabase = fileWriteable(default="/var/cache/cryptobox/volumen_names.db")
|
|||
TemplateDir = directoryExists(default="/usr/share/cryptobox/template")
|
||||
LangDir = directoryExists(default="/usr/share/cryptobox/lang")
|
||||
DocDir = directoryExists(default="/usr/share/doc/cryptobox/html")
|
||||
PluginDir = directoryExists(default="/usr/share/cryptobox/plugins")
|
||||
|
||||
[Log]
|
||||
Level = option("debug", "info", "warn", "error", default="warn")
|
||||
|
|
76
pythonrewrite/bin2/Plugins.py
Normal file
76
pythonrewrite/bin2/Plugins.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
# $Id$
|
||||
|
||||
import imp
|
||||
import os
|
||||
import logging
|
||||
|
||||
|
||||
class PluginManager:
|
||||
"""manage available plugins"""
|
||||
|
||||
def __init__(self, plugin_dirs=None):
|
||||
self.log = logging.getLogger("CryptoBox")
|
||||
if hasattr(plugin_dirs, "__iter__"):
|
||||
self.plugin_dirs = [os.path.abspath(dir) for dir in plugin_dirs]
|
||||
else:
|
||||
self.plugin_dirs = [os.path.abspath(plugin_dirs)]
|
||||
|
||||
|
||||
def allPlugins(self):
|
||||
for plfile in self.__getPluginFiles():
|
||||
yield os.path.basename(plfile)[:-3]
|
||||
|
||||
|
||||
def getPlugin(self, name):
|
||||
for plfile in self.__getPluginFiles():
|
||||
if name == os.path.basename(plfile)[:-3]:
|
||||
return imp.load_source(name, plfile)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def getTemplateFileName(self, plname, template_name):
|
||||
"""return the name of the template file, if it is part of the mentioned plugin
|
||||
"""
|
||||
result = [os.path.join(os.path.dirname(cur_file), template_name + ".cs")
|
||||
for cur_file in self.__getPluginFiles()
|
||||
if plname == os.path.basename(cur_file)[:-3]]
|
||||
for templ_file in result:
|
||||
if os.access(templ_file, os.R_OK) and os.path.isfile(templ_file):
|
||||
return templ_file
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def loadLanguageData(self, hdf, lang="en"):
|
||||
for plfile in self.__getPluginFiles():
|
||||
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)
|
||||
break
|
||||
else:
|
||||
self.log.debug("Couldn't find a plugin language file (%s)" % default_langfile)
|
||||
|
||||
|
||||
def __getPluginFiles(self):
|
||||
result = []
|
||||
for dir in [os.path.abspath(e) for e in self.plugin_dirs if os.access(e, os.R_OK) and os.path.isdir(e)]:
|
||||
for plname in [f for f in os.listdir(dir)]:
|
||||
pldir = os.path.join(dir, plname)
|
||||
plfile = os.path.join(pldir, plname + ".py")
|
||||
if os.path.isfile(plfile) and os.access(plfile, os.R_OK):
|
||||
result.append(plfile)
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
x = PluginManager("../plugins")
|
||||
for a in x.allPlugins():
|
||||
print "Plugin: %s" % a
|
||||
print x.getPlugin(a).getStatus()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
import CryptoBoxContainer
|
||||
|
||||
## useful constant for many functions
|
||||
## useful constant for some functions
|
||||
CONT_TYPES = CryptoBoxContainer.CryptoBoxContainer.Types
|
||||
|
||||
class WebInterfaceDataset(dict):
|
||||
|
@ -16,6 +16,31 @@ class WebInterfaceDataset(dict):
|
|||
self.__setCryptoBoxState()
|
||||
|
||||
|
||||
def setPluginState(self, plugins):
|
||||
for pl in plugins.allPlugins():
|
||||
self["Data.Status.Modules." + pl] = plugins.getPlugin(pl).getStatus(self.cbox)
|
||||
|
||||
|
||||
def setCurrentDiskState(self, device):
|
||||
for container in self.cbox.getContainerList():
|
||||
if container.getDevice() == device:
|
||||
isEncrypted = (container.getType() == CONT_TYPES["luks"]) and 1 or 0
|
||||
isPlain = (container.getType() == CONT_TYPES["plain"]) and 1 or 0
|
||||
isMounted = container.isMounted() and 1 or 0
|
||||
self["Data.CurrentDisk.device"] = container.getDevice()
|
||||
self["Data.CurrentDisk.name"] = container.getName()
|
||||
self["Data.CurrentDisk.encryption"] = isEncrypted
|
||||
self["Data.CurrentDisk.plaintext"] = isPlain
|
||||
self["Data.CurrentDisk.active"] = isMounted
|
||||
if isMounted:
|
||||
(size, avail, used) = container.getCapacity()
|
||||
percent = used / size
|
||||
self["Data.CurrentDisk.capacity.used"] = used
|
||||
self["Data.CurrentDisk.capacity.free"] = avail
|
||||
self["Data.CurrentDisk.capacity.size"] = size
|
||||
self["Data.CurrentDisk.capacity.percent"] = percent
|
||||
|
||||
|
||||
def __setConfigValues(self):
|
||||
self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"])
|
||||
self["Settings.LanguageDir"] = os.path.abspath(self.prefs["Locations"]["LangDir"])
|
||||
|
@ -26,6 +51,7 @@ class WebInterfaceDataset(dict):
|
|||
|
||||
|
||||
def __setCryptoBoxState(self):
|
||||
self["Data.Version"] = self.cbox.VERSION
|
||||
avail_counter = 0
|
||||
active_counter = 0
|
||||
for container in self.cbox.getContainerList():
|
||||
|
@ -45,26 +71,6 @@ class WebInterfaceDataset(dict):
|
|||
## TODO: open issues: Data.Config.AdminPasswordIsSet
|
||||
|
||||
|
||||
def setCurrentDiskState(self, device):
|
||||
for container in self.cbox.getContainerList():
|
||||
if container.getDevice() == device:
|
||||
isEncrypted = (container.getType() == CONT_TYPES["luks"]) and 1 or 0
|
||||
isPlain = (container.getType() == CONT_TYPES["plain"]) and 1 or 0
|
||||
isMounted = container.isMounted() and 1 or 0
|
||||
self["Data.CurrentDisk.device"] = container.getDevice()
|
||||
self["Data.CurrentDisk.name"] = container.getName()
|
||||
self["Data.CurrentDisk.encryption"] = isEncrypted
|
||||
self["Data.CurrentDisk.plaintext"] = isPlain
|
||||
self["Data.CurrentDisk.active"] = isMounted
|
||||
|
||||
if isMounted:
|
||||
(size, avail, used) = container.getCapacity()
|
||||
percent = used / size
|
||||
self["Data.CurrentDisk.capacity.used"] = used
|
||||
self["Data.CurrentDisk.capacity.free"] = avail
|
||||
self["Data.CurrentDisk.capacity.size"] = size
|
||||
self["Data.CurrentDisk.capacity.percent"] = percent
|
||||
|
||||
def __getLanguageName(self, lang):
|
||||
import neo_cgi, neo_util, neo_cs
|
||||
hdf_path = os.path.join(self.prefs["Locations"]["LangDir"], lang + ".hdf")
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import CryptoBox
|
||||
import WebInterfaceDataset
|
||||
import re
|
||||
from Plugins import PluginManager
|
||||
from CryptoBoxExceptions import *
|
||||
|
||||
class WebInterfaceSites:
|
||||
'''
|
||||
|
@ -14,6 +16,16 @@ class WebInterfaceSites:
|
|||
self.log = logging.getLogger("CryptoBox")
|
||||
self.prefs = self.cbox.prefs
|
||||
self.__resetDataset()
|
||||
self.plugins = PluginManager(self.prefs["Locations"]["PluginDir"])
|
||||
self.__exposePlugins()
|
||||
|
||||
|
||||
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):
|
||||
|
@ -65,12 +77,6 @@ class WebInterfaceSites:
|
|||
return self.__render("show_status")
|
||||
|
||||
|
||||
def config(self,weblang=""):
|
||||
self.__resetDataset()
|
||||
self.__setWebLang(weblang)
|
||||
pass
|
||||
|
||||
|
||||
def doc(self,page="",weblang=""):
|
||||
'''prints the offline wikipage
|
||||
'''
|
||||
|
@ -88,20 +94,9 @@ class WebInterfaceSites:
|
|||
return self.__render("show_doc")
|
||||
|
||||
|
||||
def system(self, shutdowntype="", weblang=""):
|
||||
# TODO: check weblang
|
||||
def system(self, weblang=""):
|
||||
self.__resetDataset()
|
||||
self.__setWebLang(weblang)
|
||||
if shutdowntype == "reboot":
|
||||
self.dataset["Data.Success"] = "ReBoot"
|
||||
self.dataset["Data.Redirect.Action"] = "show_status"
|
||||
self.dataset["Data.Redirect.Delay"] = "180"
|
||||
self.log.info("TODO: call function for system reboot")
|
||||
elif shutdowntype == "poweroff":
|
||||
self.dataset["Data.Success"] = "PowerOff"
|
||||
self.log.info("TODO: call function for system shutdown")
|
||||
else:
|
||||
self.log.warn("This shutdown-mode (%s) is not supported." % shutdowntype)
|
||||
return self.__render("form_system")
|
||||
|
||||
|
||||
|
@ -316,6 +311,26 @@ class WebInterfaceSites:
|
|||
return self.__render("show_volume")
|
||||
|
||||
|
||||
def return_module_action(self, module):
|
||||
def handler(**args):
|
||||
self.__resetDataset()
|
||||
try:
|
||||
self.__setWebLang(args["weblang"])
|
||||
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)
|
||||
return handler
|
||||
|
||||
|
||||
'''
|
||||
## DONE: these functions are pythonized
|
||||
#################### show_log #######################
|
||||
|
@ -403,7 +418,7 @@ class WebInterfaceSites:
|
|||
return False
|
||||
|
||||
|
||||
def __render(self, template):
|
||||
def __render(self, template, module=None):
|
||||
'''renders from clearsilver templates and returns the resulting html
|
||||
|
||||
Gets a dictionary with all settings, nessessary for rendering.
|
||||
|
@ -411,7 +426,6 @@ class WebInterfaceSites:
|
|||
object, that calls this render method. This might be bloat but
|
||||
this way the render method has always a complete, actual set of values.
|
||||
'''
|
||||
|
||||
import os
|
||||
try:
|
||||
import neo_cgi, neo_util, neo_cs
|
||||
|
@ -421,7 +435,11 @@ class WebInterfaceSites:
|
|||
sys.stderr.write(errorMsg)
|
||||
raise ImportError, errorMsg
|
||||
|
||||
self.dataset["Data.Action"] = template
|
||||
module_cs_file = False
|
||||
if module:
|
||||
module_cs_file = self.plugins.getTemplateFileName(module, 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.log.info("rendering site: " + template)
|
||||
|
||||
cs_path = os.path.join(self.prefs["Locations"]["TemplateDir"], "main.cs")
|
||||
|
@ -435,11 +453,16 @@ class WebInterfaceSites:
|
|||
log.error("Couldn't read language file: %s" % hdf_path)
|
||||
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)
|
||||
|
||||
hdf = neo_util.HDF()
|
||||
hdf.readFile(hdf_path)
|
||||
self.log.debug(self.dataset)
|
||||
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"])
|
||||
cs = neo_cs.CS(hdf)
|
||||
cs.parseFile(cs_path)
|
||||
return cs.render()
|
||||
|
@ -462,6 +485,7 @@ class WebInterfaceSites:
|
|||
test.exposed = True
|
||||
|
||||
|
||||
|
||||
"""
|
||||
## TODO: check this before anything else
|
||||
if self.cbox.getAvailableDocLanguages():
|
||||
|
|
|
@ -32,6 +32,11 @@ LangDir = ../lang
|
|||
#DocDir = /usr/share/doc/cryptobox/html
|
||||
DocDir = ../doc/html
|
||||
|
||||
# path to the plugin directory
|
||||
#PluginDir = /usr/share/cryptobox/plugins
|
||||
PluginDir = ../plugins
|
||||
|
||||
|
||||
|
||||
[Log]
|
||||
# possible values are "debug", "info", "warn" and "error" or numbers from
|
||||
|
|
|
@ -48,6 +48,7 @@ MountParentDir = %s
|
|||
TemplateDir = ../templates
|
||||
LangDir = ../lang
|
||||
DocDir = ../doc/html
|
||||
PluginDir = ../plugins
|
||||
[Log]
|
||||
Level = debug
|
||||
Destination = file
|
||||
|
|
|
@ -134,36 +134,11 @@ Lang {
|
|||
Text = Die ausgewählte Sprache ist nicht verfügbar!
|
||||
}
|
||||
|
||||
InvalidIP {
|
||||
Title = Ungültige IP
|
||||
Text = Die ausgewählte Netzwerkadresse ist nicht gültig!
|
||||
}
|
||||
|
||||
InvalidTimeOut {
|
||||
Title = Ungültige Zeitabschaltung
|
||||
Text = Der ausgewählte Wert der Zeitabschaltung ist nicht gültig!
|
||||
}
|
||||
|
||||
ConfigTimeOutFailed {
|
||||
Title = Fehler beim Ändern der Zeitabschaltung
|
||||
Text = Der Wert der Zeitabschaltung konnte nicht geändert werden!
|
||||
}
|
||||
|
||||
ConfigLanguageFailed {
|
||||
Title = Fehler beim Ändern der Spracheinstellung
|
||||
Text = Die Spracheinstellung konnte nicht geändert werden!
|
||||
}
|
||||
|
||||
ConfigIPFailed {
|
||||
Title = Fehler beim Ändern der Netzwerkadresse
|
||||
Text = Die Netzwerkadresse konnte nicht geändert werden!
|
||||
}
|
||||
|
||||
IPAddressChanged {
|
||||
Title = Änderung der Netzwerk-Adresse
|
||||
Text = Die Netzwerk-Adresse der CryptoBox wurde verändert. In wenigen Sekunden werden sie zu der neuen Adresse umgeleitet.
|
||||
}
|
||||
|
||||
NoDiskAvailableForMount {
|
||||
Title = Kein Daten-Container verfügbar
|
||||
Text = Es ist kein inaktiver Daten-Container verfügbar. Vielleicht sind bereits alle Container aktiv?
|
||||
|
|
|
@ -11,7 +11,6 @@ Lang {
|
|||
Mount = Activation of encrypted data
|
||||
Umount = Deactivation of encrypted data
|
||||
Config = CryptoBox configuration
|
||||
Log = CryptoBox logfiles
|
||||
System = System
|
||||
Status = Status
|
||||
Volume = Properties of
|
||||
|
@ -31,7 +30,6 @@ Lang {
|
|||
PartitionInfo = Current partioning of the disk:
|
||||
IPAddress = Network address (IP) of the CryptoBox:
|
||||
TimeOut = Timeout for deactivation of the encrypted filesystem (in minutes):
|
||||
EmptyLog = The logfiles of the CryptoBox are empty.
|
||||
SelectLanguage = Language preferences:
|
||||
RedirectNote = Click here if your browser does not support automatic redirection.
|
||||
ProjectHomePage = Website of project
|
||||
|
@ -59,7 +57,6 @@ Lang {
|
|||
Config = Configuration
|
||||
PowerOff = Shutdown
|
||||
ReBoot = Reboot
|
||||
Protocol = Show logfiles
|
||||
Documentation = Help
|
||||
Status = Status
|
||||
System = System
|
||||
|
@ -134,35 +131,12 @@ Lang {
|
|||
Text = The selected language is not available!
|
||||
}
|
||||
|
||||
InvalidIP {
|
||||
Title = Invalid IP address
|
||||
Text = The selected network address is not valid!
|
||||
}
|
||||
|
||||
InvalidTimeOut {
|
||||
Title = Invalid timeout
|
||||
Text = The selected timeout is not valid!
|
||||
}
|
||||
|
||||
ConfigTimeOutFailed {
|
||||
Title = Error during change of timeout
|
||||
Text = The timeout value could not be changed!
|
||||
}
|
||||
|
||||
ConfigLanguageFailed {
|
||||
Title = Error during change of language preferences
|
||||
Text = The language preferences could not be changed!
|
||||
}
|
||||
|
||||
ConfigIPFailed {
|
||||
Title = Error during change of network address
|
||||
Text = The network address could not be changed!
|
||||
}
|
||||
|
||||
IPAddressChanged {
|
||||
Title = Change of network address
|
||||
Text = The network address has been changed. In a few seconds you will get redirected to the new address.
|
||||
}
|
||||
|
||||
NoDiskAvailableForMount {
|
||||
Title = No partition available
|
||||
|
|
|
@ -125,35 +125,10 @@ Lang {
|
|||
Text = Izbrani jezik ni na voljo!
|
||||
}
|
||||
|
||||
InvalidIP {
|
||||
Title = Napačen IP naslov
|
||||
Text = Izbran omrežni naslov ni veljaven!
|
||||
}
|
||||
|
||||
InvalidTimeOut {
|
||||
Title = Nepravilen čas preklica
|
||||
Text = Izbran čas preklica ni veljaven!
|
||||
}
|
||||
|
||||
ConfigTimeOutFailed {
|
||||
Title = Napaka med spremembo časa preklica
|
||||
Text = Časa preklica ne morete spremeniti!
|
||||
}
|
||||
|
||||
ConfigLanguageFailed {
|
||||
Title = Napaka med spremembo jezikovnih nastavitev
|
||||
Text = Spreminjanje jezikovnih nastavitev ni mogoče.
|
||||
}
|
||||
|
||||
ConfigIPFailed {
|
||||
Title = Napaka med spreminjanjem omrežnega naslova.
|
||||
Text = Spreminjanje omrežnega naslova ni mogoče.
|
||||
}
|
||||
|
||||
IPAddressChanged {
|
||||
Title = Sprememba omrežnega naslova
|
||||
Text = Omrežni naslov je spremenjen. V nekaj sekundah boste preusmerjeni na nov naslov.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
36
pythonrewrite/plugins/date/date.py
Normal file
36
pythonrewrite/plugins/date/date.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from CryptoBoxExceptions import CBPluginActionError
|
||||
|
||||
|
||||
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):
|
||||
import datetime
|
||||
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"
|
||||
# TODO: how to set the current time? (and how to become root?)
|
||||
## we will continue with the system menue
|
||||
return "form_system"
|
||||
else:
|
||||
return "form_date"
|
||||
|
||||
|
||||
def getStatus(cbox):
|
||||
return str(__getCurrentDate())
|
||||
|
||||
|
||||
def __getCurrentDate():
|
||||
import datetime
|
||||
return datetime.datetime(2000,1,1).now()
|
||||
|
42
pythonrewrite/plugins/date/form_date.cs
Normal file
42
pythonrewrite/plugins/date/form_date.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<h1><?cs var:html_escape(Lang.Title.ConfigDate) ?></h1>
|
||||
|
||||
<?cs call:print_form_header("module_date") ?>
|
||||
|
||||
<p><label for="date"><?cs var:html_escape(Lang.Text.Date) ?>: </label><br/>
|
||||
<select name="day" size="0"><?cs
|
||||
loop: x = #1, #31, #1 ?>
|
||||
<?cs if:x == Data.Modules.date.day ?><option selected="selected"><?cs
|
||||
else ?><option><?cs /if ?><?cs var:x ?></option><?cs /loop ?>
|
||||
</select>
|
||||
<select name="month" size="0"><?cs
|
||||
loop: x = #1, #12, #1 ?>
|
||||
<?cs if:x == Data.Modules.date.month ?><option selected="selected" <?cs
|
||||
else ?><option <?cs /if ?>value="<?cs var:x ?>"><?cs
|
||||
var:html_escape(Lang.Text.Months[x]) ?></option><?cs /loop ?>
|
||||
</select>
|
||||
<select name="year" size="0"><?cs
|
||||
loop: x = #2006, #2025, #1 ?>
|
||||
<?cs if:x == Data.Modules.date.year ?><option selected="selected"><?cs
|
||||
else ?><option><?cs /if ?><?cs var:x ?></option><?cs /loop ?>
|
||||
</select></p>
|
||||
|
||||
<p><label for="time"><?cs var:html_escape(Lang.Text.Time) ?>: </label><br/>
|
||||
<select name="hour" size="0"><?cs
|
||||
loop: x = #0, #23, #1 ?>
|
||||
<?cs if:x == Data.Modules.date.hour ?><option selected="selected"><?cs
|
||||
else ?><option><?cs /if ?><?cs if:x<10 ?>0<?cs /if ?><?cs var:x ?></option><?cs /loop ?>
|
||||
</select> :
|
||||
<select name="minute" size="0"><?cs
|
||||
loop: x = #0, #59, #1 ?>
|
||||
<?cs if:x == Data.Modules.date.minute ?><option selected="selected"><?cs
|
||||
else ?><option><?cs /if ?><?cs if:x<10 ?>0<?cs /if ?><?cs var:x ?></option><?cs /loop ?>
|
||||
</select></p>
|
||||
|
||||
<input type="hidden" name="store" value="yes" />
|
||||
|
||||
<button type="submit"><?cs var:html_escape(Lang.Button.ConfigDate) ?></button>
|
||||
|
||||
</form>
|
||||
|
35
pythonrewrite/plugins/date/lang/en.hdf
Normal file
35
pythonrewrite/plugins/date/lang/en.hdf
Normal file
|
@ -0,0 +1,35 @@
|
|||
Lang {
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
}
|
13
pythonrewrite/plugins/logs/lang/en.hdf
Normal file
13
pythonrewrite/plugins/logs/lang/en.hdf
Normal file
|
@ -0,0 +1,13 @@
|
|||
Lang {
|
||||
|
||||
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 the log file
|
||||
Rank = 90
|
||||
}
|
||||
|
||||
}
|
21
pythonrewrite/plugins/logs/logs.py
Normal file
21
pythonrewrite/plugins/logs/logs.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from CryptoBoxExceptions import CBPluginActionError
|
||||
|
||||
|
||||
def prepareForm(hdf, cbox):
|
||||
hdf["Data.Modules.logs.Content"] = __getLogContent(cbox)
|
||||
|
||||
|
||||
def doAction(cbox):
|
||||
return "show_log"
|
||||
|
||||
|
||||
def getStatus(cbox):
|
||||
return "%s:%s:%s" % (
|
||||
cbox.prefs["Log"]["Level"],
|
||||
cbox.prefs["Log"]["Destination"],
|
||||
cbox.prefs["Log"]["Details"])
|
||||
|
||||
|
||||
def __getLogContent(cbox, lines=30, maxSize=2000):
|
||||
return "<br/>".join(cbox.getLogData(lines, maxSize))
|
||||
|
13
pythonrewrite/plugins/logs/show_log.cs
Normal file
13
pythonrewrite/plugins/logs/show_log.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?cs # $Id: show_log.cs 374 2006-05-30 18:47:34Z lars $ ?>
|
||||
|
||||
<div id="log">
|
||||
|
||||
<h1><?cs var:html_escape(Lang.Title.Log) ?></h1>
|
||||
|
||||
<?cs if:Data.Modules.logs.Content ?>
|
||||
<p class="console"><?cs var:Data.Modules.logs.Content ?></p>
|
||||
<?cs else ?>
|
||||
<p><?cs var:html_escape(Lang.Text.EmptyLog) ?></p>
|
||||
<?cs /if ?>
|
||||
|
||||
</div>
|
22
pythonrewrite/plugins/network/form_network.cs
Normal file
22
pythonrewrite/plugins/network/form_network.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<h1><?cs var:html_escape(Lang.Title.Network) ?></h1>
|
||||
|
||||
<?cs call:print_form_header("module_network") ?>
|
||||
|
||||
<p><label for="ip"><?cs var:html_escape(Lang.Text.IP) ?>: </label><br/>
|
||||
<input type="text" name="ip1" size="3" id="ip" value="<?cs
|
||||
var:Data.Modules.network.ip.oc1 ?>" />.
|
||||
<input type="text" name="ip2" size="3" value="<?cs
|
||||
var:Data.Modules.network.ip.oc2 ?>" />.
|
||||
<input type="text" name="ip3" size="3" value="<?cs
|
||||
var:Data.Modules.network.ip.oc3 ?>" />.
|
||||
<input type="text" name="ip4" size="3" value="<?cs
|
||||
var:Data.Modules.network.ip.oc4 ?>" /></p>
|
||||
|
||||
<input type="hidden" name="store" value="yes" />
|
||||
|
||||
<button type="submit"><?cs var:html_escape(Lang.Button.Network) ?></button>
|
||||
|
||||
</form>
|
||||
|
20
pythonrewrite/plugins/network/lang/en.hdf
Normal file
20
pythonrewrite/plugins/network/lang/en.hdf
Normal file
|
@ -0,0 +1,20 @@
|
|||
Lang {
|
||||
|
||||
Title.Network = Network settings
|
||||
|
||||
Button.Network = Update settings
|
||||
|
||||
Text.IP = Network address
|
||||
|
||||
Modules.network {
|
||||
Name = Configure network
|
||||
Link = Configure network
|
||||
Rank = 30
|
||||
}
|
||||
|
||||
Warning.InvalidIP {
|
||||
Title = Invalid value
|
||||
Text = An invalid network address (IP) was supplied. Please try again.
|
||||
}
|
||||
|
||||
}
|
33
pythonrewrite/plugins/network/network.py
Normal file
33
pythonrewrite/plugins/network/network.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
from CryptoBoxExceptions import CBPluginActionError
|
||||
|
||||
|
||||
def prepareForm(hdf, cbox):
|
||||
(oc1, oc2, oc3, oc4) = __getCurrentIP()
|
||||
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=""):
|
||||
if store:
|
||||
try:
|
||||
# TODO: check the IP here
|
||||
pass
|
||||
except ValueError:
|
||||
raise CBPluginActionError, "InvalidIP"
|
||||
# TODO: how to set the new IP? (and how to become root?)
|
||||
## we will continue with the system menue
|
||||
return "form_system"
|
||||
else:
|
||||
return "form_network"
|
||||
|
||||
|
||||
def getStatus(cbox):
|
||||
return "%d.%d.%d.%d" % __getCurrentIP()
|
||||
|
||||
|
||||
def __getCurrentIP():
|
||||
# TODO: for now we only provide a dummy
|
||||
return (192,168,0,23)
|
||||
|
36
pythonrewrite/plugins/plugin-interface.txt
Normal file
36
pythonrewrite/plugins/plugin-interface.txt
Normal file
|
@ -0,0 +1,36 @@
|
|||
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 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
|
||||
- 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)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
Language file structure:
|
||||
- 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
|
||||
|
||||
|
||||
Clearsilver template:
|
||||
- should start with a "<h1>" tag
|
||||
- links to the module (e.g. in form headers) could look like the following:
|
||||
<?cs call:link("module_MODULENAME",'','','','') ?>
|
||||
- a hidden input field called "store" should be used to indicate a form submission
|
||||
|
|
@ -7,29 +7,31 @@
|
|||
</div><!-- end of 'words' -->
|
||||
|
||||
<div id="footer">
|
||||
<?cs # Development or not ?>
|
||||
<?cs if:(Data.Status.DevelopmentMode == 1) ?>
|
||||
<div id="development">!Development Mode!</div>
|
||||
<?cs /if ?>
|
||||
<?cs # Version ?>
|
||||
v<?cs var:Data.Version ?>
|
||||
<a href="http://cryptobox.org" title="<?cs var:html_escape(Lang.Text.ProjectHomePage) ?>">CryptoBox-Home</a> <?cs var:html_escape(Lang.Text.ProjectNote) ?> <a href="https://systemausfall.org/senselab" title="systemausfall.org">sense.lab</a>
|
||||
<?cs # Development or not ?><?cs
|
||||
if:(Data.Status.DevelopmentMode == 1) ?>
|
||||
<div id="development">!Development Mode!</div><?cs /if ?>
|
||||
<?cs var:Data.Version ?>
|
||||
<a href="http://cryptobox.org" title="<?cs var:html_escape(Lang.Text.ProjectHomePage) ?>">CryptoBox-Home</a> <?cs var:html_escape(Lang.Text.ProjectNote) ?> <a href="https://systemausfall.org/senselab" title="systemausfall.org">sense.lab</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- end of 'content' -->
|
||||
</div><!-- end of 'main' -->
|
||||
|
||||
<?cs # TODO: update these status settings - most are outdated ... ?>
|
||||
<!-- CBOX-STATUS-begin - used for validation - do not touch!
|
||||
Data.Config.IP=<?cs var:Data.Config.IP ?>
|
||||
Data.Config.Language=<?cs var:Data.Config.Language ?>
|
||||
Data.Config.TimeOut=<?cs var:Data.Config.TimeOut ?>
|
||||
Data.Status.Config=<?cs var:Data.Status.Config ?>
|
||||
Data.Status.InitRunning=<?cs var:Data.Status.InitRunning ?>
|
||||
Data.Status.IP=<?cs var:Data.Status.IP ?>
|
||||
Data.Status.Mounted=<?cs var:Data.Status.Mounted ?>
|
||||
CBOX-STATUS-end -->
|
||||
Data.Config.IP=<?cs var:html_escape(Data.Config.IP) ?>
|
||||
Data.Config.Language=<?cs var:html_escape(Data.Config.Language) ?>
|
||||
Data.Config.TimeOut=<?cs var:html_escape(Data.Config.TimeOut) ?>
|
||||
Data.Status.Config=<?cs var:html_escape(Data.Status.Config) ?>
|
||||
Data.Status.InitRunning=<?cs var:html_escape(Data.Status.InitRunning) ?>
|
||||
Data.Status.IP=<?cs var:html_escape(Data.Status.IP) ?>
|
||||
Data.Status.Mounted=<?cs var:html_escape(Data.Status.Mounted) ?>
|
||||
<?cs each:x = Data.Status.Modules ?>Data.Status.Modules.<?cs
|
||||
var:name(x) ?>=<?cs var: html_escape(x) ?>
|
||||
<?cs /each
|
||||
?>CBOX-STATUS-end -->
|
||||
|
||||
<?cs # $Revision$ ?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -4,25 +4,24 @@
|
|||
|
||||
<p><ul>
|
||||
|
||||
<?cs # poweroff ?>
|
||||
<li><a href="<?cs call:link('system','type','poweroff','','') ?>" title="<?cs var:html_escape(Lang.Button.PowerOff) ?>">
|
||||
<?cs var:html_escape(Lang.Button.PowerOff) ?></a></li>
|
||||
<?cs # sort the Plugins - using the most stupid way :) ?>
|
||||
<?cs loop: order = #0, #100, #1
|
||||
?><?cs # plugins ?><?cs each:x = Lang.Modules
|
||||
?><?cs if:x.Rank == order ?>
|
||||
<li><a href="<?cs call:link('module_' + name(x),'','','','') ?>" title="<?cs
|
||||
var:html_escape(x.Link) ?>"><?cs var:html_escape(x.Link) ?></a></li><?cs
|
||||
/if ?><?cs
|
||||
/each ?><?cs
|
||||
/loop ?>
|
||||
<?cs # maybe someone forgot to set the rank of a module: we try to catch them ?>
|
||||
|
||||
<?cs # reboot ?>
|
||||
<li><a href="<?cs call:link('system','type','reboot','','') ?>" title="<?cs
|
||||
var:html_escape(Lang.Button.ReBoot) ?>"><?cs var:html_escape(Lang.Button.ReBoot) ?></a></li>
|
||||
<?cs # plugins ?><?cs each:x = Lang.Modules ?><?cs
|
||||
if:!x.Rank || !(x.Rank >= 0 && x.Rank <= 100) ?>
|
||||
<li><a href="<?cs call:link('module_' + name(x),'','','','') ?>" title="<?cs
|
||||
var:html_escape(x.Link) ?>"><?cs var:html_escape(x.Link) ?></a></li><?cs
|
||||
/if ?><?cs
|
||||
/each ?>
|
||||
|
||||
<?cs # config ?>
|
||||
<li><a href="<?cs call:link('config_ask','','','','') ?>" title="<?cs
|
||||
var:html_escape(Lang.Button.Config) ?>"><?cs var:html_escape(Lang.Button.Config) ?></a></li>
|
||||
|
||||
<?cs # initialize ?>
|
||||
<li><a href="<?cs call:link('init_ask','','','','') ?>" title="<?cs
|
||||
var:html_escape(Lang.Button.DoInit) ?>"><?cs var:html_escape(Lang.Button.DoInit) ?></a></li>
|
||||
|
||||
<?cs # show log files ?>
|
||||
<li><a href="<?cs call:link('logs','','','','') ?>" title="<?cs var:html_escape(Lang.Button.Protocol) ?>"><?cs var:html_escape(Lang.Button.Protocol) ?></a></li>
|
||||
|
||||
</ul></p>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
<?cs include:Settings.TemplateDir + '/macros.cs' ?>
|
||||
<?cs include:Settings.TemplateDir + '/header.cs' ?>
|
||||
|
||||
<!-- chosen cryptobox template: <?cs var:Data.Action ?> -->
|
||||
<!-- chosen cryptobox template: <?cs var:Data.TemplateFile ?> -->
|
||||
|
||||
<?cs if:Data.Error ?>
|
||||
<?cs include:Settings.TemplateDir + '/error.cs' ?>
|
||||
<?cs else ?>
|
||||
<?cs if:Data.Warning ?><?cs call:warning(Data.Warning) ?><?cs /if ?>
|
||||
<?cs if:Data.Success ?><?cs call:success(Data.Success) ?><?cs /if ?>
|
||||
<?cs include:Settings.TemplateDir + '/' + Data.Action + '.cs' ?>
|
||||
<?cs include:Data.TemplateFile ?>
|
||||
<?cs /if ?>
|
||||
|
||||
<?cs include:Settings.TemplateDir + '/footer.cs' ?>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<div id="log">
|
||||
|
||||
<h1><?cs var:html_escape(Lang.Title.Log) ?></h1>
|
||||
|
||||
<?cs if:Data.Log ?>
|
||||
<p class="console"><?cs var:Data.Log ?></p>
|
||||
<?cs else ?>
|
||||
<p><?cs var:html_escape(Lang.Text.EmptyLog) ?></p>
|
||||
<?cs /if ?>
|
||||
|
||||
</div>
|
|
@ -21,7 +21,7 @@
|
|||
?>"><?cs var:partition.name ?></a></li><?cs /if ?><?cs /each ?></ul><?cs /if ?>
|
||||
<?cs if:Data.activeDisksCount < subcount(Data.Disks) ?>
|
||||
<p><?cs var:html_escape(Lang.Text.PassivePartitions) ?>:
|
||||
<ul><?cs each:partition = Data.Disks ?><?cs if:partition.active ?>
|
||||
<ul><?cs each:partition = Data.Disks ?><?cs if:!partition.active ?>
|
||||
<li><a href="<?cs call:link('show_volume','device',partition.device,'','')
|
||||
?>"><?cs var:partition.name ?></a></li><?cs /if ?><?cs /each ?></ul><?cs /if ?>
|
||||
<?cs /if ?>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<?cs if:!Data.CurrentDisk.active ?>
|
||||
<h2>Change the name of the container</h2>
|
||||
<?cs call:print_form_header("volume_name_set") ?>
|
||||
<p><label for="vol_name"><?cs var:html_escape(Lang.Text.ContainerName) ?></label>
|
||||
<p><label for="volume_name"><?cs var:html_escape(Lang.Text.ContainerName) ?></label>
|
||||
<input type="text" name="volume_name" size="20" id="volume_name" value="<?cs var:html_escape(Data.CurrentDisk.name) ?>" />
|
||||
<input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
|
||||
<button type="submit"><?cs var:html_escape(Lang.Button.ContainerNameSet) ?></button></p>
|
||||
|
|
Loading…
Reference in a new issue