do not forget previous selections during en-/disable help

use png instead of gif for en-/disable help icons
download of complete log file is possible
prevent the "plugin_manager" from disabling itself
This commit is contained in:
lars 2007-02-06 10:08:55 +00:00
parent 00ebd07293
commit 11fba98cda
8 changed files with 79 additions and 18 deletions

View file

@ -7,6 +7,7 @@ Text {
ShowAll = Show all messages ShowAll = Show all messages
AtLeastWarnings = Show warnings and errors AtLeastWarnings = Show warnings and errors
OnlyErrors = Show errors only OnlyErrors = Show errors only
DownloadLogFile = Download complete log
AgeOfEvent = Time passed AgeOfEvent = Time passed
EventText = Description EventText = Description
TimeUnits { TimeUnits {

View file

@ -27,6 +27,7 @@ __revision__ = "$Id"
import cryptobox.plugins.base import cryptobox.plugins.base
import re import re
import datetime import datetime
import cherrypy
LOG_LEVELS = [ 'DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR' ] LOG_LEVELS = [ 'DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR' ]
@ -68,10 +69,24 @@ class logs(cryptobox.plugins.base.CryptoBoxPlugin):
level = None level = None
for (index, line) in enumerate(self.__filter_log_content(lines, size, level)): for (index, line) in enumerate(self.__filter_log_content(lines, size, level)):
self.__set_line_hdf_data(self.hdf_prefix + "Content.%d" % index, line) self.__set_line_hdf_data(self.hdf_prefix + "Content.%d" % index, line)
self.hdf[self.hdf_prefix + "Destination"] = self.cbox.prefs["Log"]["Destination"].lower() self.hdf[self.hdf_prefix + "Destination"] = \
self.cbox.prefs["Log"]["Destination"].lower()
return "show_log" return "show_log"
@cherrypy.expose
def download(self, **kargs):
"""Download the complete log file
**kargs are necessary - we have to ignore 'weblang' and so on ...
"""
log_file = self.__get_log_destination_file()
if log_file is None:
return ""
else:
return cherrypy.lib.cptools.serveFile(log_file, disposition="attachment", name="cryptobox_logfile.txt")
def get_status(self): def get_status(self):
"""The current status includes the log configuration details. """The current status includes the log configuration details.
""" """
@ -79,7 +94,7 @@ class logs(cryptobox.plugins.base.CryptoBoxPlugin):
self.cbox.prefs["Log"]["Level"], self.cbox.prefs["Log"]["Level"],
self.cbox.prefs["Log"]["Destination"], self.cbox.prefs["Log"]["Destination"],
self.cbox.prefs["Log"]["Details"]) self.cbox.prefs["Log"]["Details"])
def __filter_log_content(self, lines, max_size, level): def __filter_log_content(self, lines, max_size, level):
"""Filter, sort and shorten the log content. """Filter, sort and shorten the log content.
@ -122,7 +137,7 @@ class logs(cryptobox.plugins.base.CryptoBoxPlugin):
if not match: if not match:
## we could not parse the line - just return the text without meta info ## we could not parse the line - just return the text without meta info
return return
## matching was successfully - we can parse the line for details ## matching was successful - we can parse the line for details
## calculate time difference of log line (aka: age of event) ## calculate time difference of log line (aka: age of event)
try: try:
(year, month, day, hour, minute) = match.group( (year, month, day, hour, minute) = match.group(
@ -159,21 +174,31 @@ class logs(cryptobox.plugins.base.CryptoBoxPlugin):
pass pass
def __get_log_destination_file(self):
"""For non-file log destinations return 'None' and output a warning
"""
try:
if self.cbox.prefs["Log"]["Destination"].upper() == "FILE":
import os
return os.path.abspath(self.cbox.prefs["Log"]["Details"])
else:
return None
except KeyError:
self.cbox.log.error(
"could not evaluate one of the following config settings: "
+ "[Log]->Destination or [Log]->Details")
return None
def __get_log_data(self, lines=None, max_size=None): def __get_log_data(self, lines=None, max_size=None):
"""get the most recent log entries of the log file """get the most recent log entries of the log file
the maximum number and size of these entries can be limited by the maximum number and size of these entries can be limited by
'lines' and 'max_size' 'lines' and 'max_size'
""" """
# return nothing if the currently selected log output is not a file log_file = self.__get_log_destination_file()
try: ## return nothing if the currently selected log output is not a file
if self.cbox.prefs["Log"]["Destination"].upper() != "FILE": if log_file is None:
return []
log_file = self.cbox.prefs["Log"]["Details"]
except KeyError:
self.cbox.log.error(
"could not evaluate one of the following config settings: "
+ "[Log]->Destination or [Log]->Details")
return [] return []
try: try:
fdesc = open(log_file, "r") fdesc = open(log_file, "r")

View file

@ -64,6 +64,10 @@
/with ?><?cs /loop ?><?cs /with ?><?cs /loop ?><?cs
/if ?> /if ?>
</table> </table>
<?cs call:print_form_header("download-log", "downloads/logs") ?>
<button type="submit" value="refresh"><?cs
var:html_escape(Lang.Plugins.logs.Text.DownloadLogFile) ?></button>
</form>
<?cs else ?> <?cs else ?>
<?cs call:hint("Plugins.logs.EmptyLog") ?> <?cs call:hint("Plugins.logs.EmptyLog") ?>
<?cs /if ?> <?cs /if ?>

View file

@ -56,6 +56,7 @@ Python code interface:
never get called with an invalid device) never get called with an invalid device)
- the python module which contains the plugin's class should also contain a class called - the python module which contains the plugin's class should also contain a class called
'unittests' - it should inherit WebInterfaceTestClass.WebInterfaceTestClass 'unittests' - it should inherit WebInterfaceTestClass.WebInterfaceTestClass
- method "download" is exposed as "downloads/PLUGINNAME"
Language file structure: Language file structure:

View file

@ -139,6 +139,10 @@ class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
(vis_type, ) = pattern.match(key).groups() (vis_type, ) = pattern.match(key).groups()
if vis_type: if vis_type:
setting["visibility"].append(vis_type) setting["visibility"].append(vis_type)
## the plugin_manager _must_ always be visible
if (self.get_name() == name) and (not setting["visibility"]):
## reset to default
setting["visibility"] = self.plugin_visibility[:]
if args.has_key("%s_auth" % name): if args.has_key("%s_auth" % name):
setting["requestAuth"] = True setting["requestAuth"] = True
else: else:

View file

@ -147,6 +147,13 @@ class CryptoBoxPlugin:
return [] return []
@cherrypy.expose
def download(self, **kargs):
"""Deliver a downloadable file - by default return nothing
"""
return ""
@cherrypy.expose @cherrypy.expose
def get_icon(self, image=None, **kargs): def get_icon(self, image=None, **kargs):
"""return the image data of the icon of the plugin """return the image data of the icon of the plugin

View file

@ -58,6 +58,22 @@ class PluginIconHandler:
class PluginDownloadHandler:
"""deliver downloadable files of available plugins via cherrypy
the state (enabled/disabled) and the require-auth setting is ignored
"""
def __init__(self, plugins):
for plugin in plugins.get_plugins():
if not plugin:
continue
plname = plugin.get_name()
## expose the get_icon function of this plugin
setattr(self, plname, plugin.download)
class WebInterfaceSites: class WebInterfaceSites:
"""handle all http requests and render pages """handle all http requests and render pages
@ -91,6 +107,9 @@ class WebInterfaceSites:
## publish plugin icons ## publish plugin icons
self.icons = PluginIconHandler(self.__plugin_manager) self.icons = PluginIconHandler(self.__plugin_manager)
self.icons.exposed = True self.icons.exposed = True
## publish plugin downloads
self.downloads = PluginDownloadHandler(self.__plugin_manager)
self.downloads.exposed = True
## announce that the server started up ## announce that the server started up
self.setup() self.setup()
@ -206,7 +225,7 @@ class WebInterfaceSites:
## invalid base64 string ## invalid base64 string
pass pass
except AttributeError: except AttributeError:
## no cherrypy response header defined ## no cherrypy request header defined
pass pass
auth_dict = self.cbox.prefs.user_db["admins"] auth_dict = self.cbox.prefs.user_db["admins"]
if user in auth_dict.keys(): if user in auth_dict.keys():
@ -245,6 +264,7 @@ class WebInterfaceSites:
return self.return_plugin_action( return self.return_plugin_action(
self.__plugin_manager.get_plugin("disks"))(**param_dict) self.__plugin_manager.get_plugin("disks"))(**param_dict)
def new_http_error_handler(self, error_code, message): def new_http_error_handler(self, error_code, message):
"""handle http errors gracefully """handle http errors gracefully
@ -387,7 +407,7 @@ class WebInterfaceSites:
else: else:
return lambda **args: handler(self, **args) return lambda **args: handler(self, **args)
@cherrypy.expose @cherrypy.expose
def test(self, weblang="", help="0", device=None): def test(self, weblang="", help="0", device=None):
"""test authentication - this function may be safely removed """test authentication - this function may be safely removed

View file

@ -175,8 +175,7 @@ def:reload_link(attr, value) ?><?cs
?><?cs # do not keep _all_ params - just the necessary ones ?><?cs # do not keep _all_ params - just the necessary ones
otherwise it could happen, that a previous action is repeated otherwise it could happen, that a previous action is repeated
accidently by reloading - or given passwords can be exposed in the url accidently by reloading - or given passwords can be exposed in the url
?><?cs if:(name(attrs) == "weblang") || (name(attrs) == "device") || ?><?cs if:(name(attrs) != "action") && (name(attrs) != "store") ?><?cs
(name(attrs) == "help") ?><?cs
set:Temp[name(attrs)] = attrs ?><?cs /if set:Temp[name(attrs)] = attrs ?><?cs /if
?><?cs /each ?><?cs /each
?><?cs if:attr != "" ?><?cs set:Temp[attr] = value ?><?cs /if ?><?cs if:attr != "" ?><?cs set:Temp[attr] = value ?><?cs /if
@ -201,12 +200,12 @@ def:help_link() ?><?cs
<a href="<?cs call:reload_link("help","0") ?>" <a href="<?cs call:reload_link("help","0") ?>"
title="<?cs var:html_escape(Lang.Button.DisableHelp) ?>"> title="<?cs var:html_escape(Lang.Button.DisableHelp) ?>">
<?cs var:html_escape(Lang.Button.DisableHelp) ?><?cs <?cs var:html_escape(Lang.Button.DisableHelp) ?><?cs
set:icon_file = "icon_get_help_disable.gif" ?><?cs set:icon_file = "icon_get_help_disable.png" ?><?cs
else ?> else ?>
<a href="<?cs call:reload_link("help","1") ?>" <a href="<?cs call:reload_link("help","1") ?>"
title="<?cs var:html_escape(Lang.Button.EnableHelp) ?>"> title="<?cs var:html_escape(Lang.Button.EnableHelp) ?>">
<?cs var:html_escape(Lang.Button.EnableHelp) ?><?cs <?cs var:html_escape(Lang.Button.EnableHelp) ?><?cs
set:icon_file = "icon_get_help.gif" ?><?cs set:icon_file = "icon_get_help.png" ?><?cs
/if ?> /if ?>
<img class="message_symbol" src="cryptobox-misc/<?cs var:icon_file ?>" alt="icon: help" /> <img class="message_symbol" src="cryptobox-misc/<?cs var:icon_file ?>" alt="icon: help" />
</a></div><?cs </a></div><?cs