plugin interface implemented
example plugins added: date and network moved "logs" to pluginsmaster
parent
5af79f90b6
commit
dba8ca79fd
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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))
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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>
|
Loading…
Reference in New Issue