removed setting "DocLanguage" (replaced by general "Language")
plugins are now classes inherited from CryptoBoxPlugin language detection added (via request header "Accept-Language")
This commit is contained in:
parent
56e954d1c4
commit
90efd72b8b
11 changed files with 287 additions and 164 deletions
|
@ -8,11 +8,15 @@ from CryptoBoxExceptions import *
|
|||
class WebInterfacePlugins:
|
||||
|
||||
def __init__(self, log, plugins, handler_func):
|
||||
for plname in plugins.allPlugins():
|
||||
for plugin in plugins.getPlugins():
|
||||
if not plugin: continue
|
||||
plname = plugin.getName()
|
||||
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(self, plname, handler_func(plugin))
|
||||
setattr(getattr(self, plname), "exposed", True)
|
||||
# TODO: check, if this really works - for now the "stream_response" feature seems to be broken
|
||||
#setattr(getattr(self, plname), "stream_respones", True)
|
||||
|
||||
|
||||
|
||||
|
@ -28,22 +32,19 @@ class WebInterfaceSites:
|
|||
self.log = logging.getLogger("CryptoBox")
|
||||
self.prefs = self.cbox.prefs
|
||||
self.__resetDataset()
|
||||
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 __resetDataset(self):
|
||||
"""this method has to be called at the beginning of every "site" action
|
||||
important: only at the beginning of an action (to not loose information)
|
||||
important: for _every_ "site" action (cherrypy is stateful)
|
||||
also take care for the plugins, as they also contain datasets
|
||||
"""
|
||||
self.dataset = WebInterfaceDataset.WebInterfaceDataset(self.cbox, self.prefs)
|
||||
|
||||
|
||||
def __isHDAvailable(self):
|
||||
#TODO: implement this
|
||||
return True
|
||||
self.pluginList = Plugins.PluginManager(self.cbox, self.prefs["Locations"]["PluginDir"])
|
||||
self.plugins = WebInterfacePlugins(self.log, self.pluginList, self.return_plugin_action)
|
||||
## publish the url "/system" as an alias for "/plugins"
|
||||
self.plugins.index = self.system
|
||||
self.dataset = WebInterfaceDataset.WebInterfaceDataset(self.cbox, self.prefs, self.pluginList.getPlugins())
|
||||
|
||||
|
||||
def __check_config(self):
|
||||
|
@ -274,9 +275,14 @@ class WebInterfaceSites:
|
|||
|
||||
|
||||
def test(self, weblang=""):
|
||||
import cherrypy
|
||||
self.__resetDataset()
|
||||
self.__setWebLang(weblang)
|
||||
return "test passed"
|
||||
for x in pref_langs:
|
||||
yield "Lang: %s<br/>" % x
|
||||
for (key,value) in headers.items():
|
||||
yield "%s: %s<br/>" % (key,value)
|
||||
#return "test passed"
|
||||
|
||||
|
||||
def umount_do(self, device, weblang=""):
|
||||
|
@ -315,7 +321,7 @@ class WebInterfaceSites:
|
|||
return self.__render("show_volume")
|
||||
|
||||
|
||||
def return_plugin_action(self, plugin_name):
|
||||
def return_plugin_action(self, plugin):
|
||||
def handler(**args):
|
||||
self.__resetDataset()
|
||||
try:
|
||||
|
@ -323,9 +329,10 @@ class WebInterfaceSites:
|
|||
del args["weblang"]
|
||||
except KeyError:
|
||||
pass
|
||||
plugin = self.pluginList.getPlugin(plugin_name)
|
||||
nextTemplate = plugin.doAction(self.dataset, self.cbox, **args)
|
||||
return self.__render(nextTemplate, plugin_name)
|
||||
nextTemplate = plugin.doAction(**args)
|
||||
## set the default template
|
||||
if not nextTemplate: nextTemplate = "form_system"
|
||||
return self.__render(nextTemplate, plugin)
|
||||
return handler
|
||||
|
||||
|
||||
|
@ -384,18 +391,54 @@ class WebInterfaceSites:
|
|||
## TODO: add some code to evaluate the language setting of the browser
|
||||
guess = value
|
||||
availLangs = self.cbox.getAvailableLanguages()
|
||||
## TODO: add some warnings for an invalid choosen language
|
||||
if not guess:
|
||||
guess = self.__getPreferredBrowserLanguage(availLangs)
|
||||
if not guess or \
|
||||
not guess in availLangs or \
|
||||
re.search(u'\W', guess):
|
||||
guess = self.prefs["WebSettings"]["Language"]
|
||||
not guess in availLangs or \
|
||||
re.search(u'\W', guess):
|
||||
self.cbox.log.info("invalid language choosen: %s" % guess)
|
||||
guess = self.prefs["WebSettings"]["Language"]
|
||||
## TODO: extract the current "browser-language" - this should be the first guess
|
||||
## maybe the language is still not valid
|
||||
if not guess in availLangs:
|
||||
self.log.warn("the configured language is invalid: %s" % guess)
|
||||
guess = "en"
|
||||
## maybe there is no english dataset???
|
||||
if not guess in availLangs:
|
||||
self.log.warn("couldn't find the english dataset")
|
||||
guess = availLangs[0]
|
||||
self.dataset["Settings.Language"] = guess
|
||||
self.dataset["Settings.DocLang"] = guess
|
||||
self.dataset["Settings.LinkAttrs.weblang"] = guess
|
||||
## we only have to save it, if it was specified correctly and explicitly
|
||||
if value == guess:
|
||||
self.dataset["Settings.LinkAttrs.weblang"] = guess
|
||||
|
||||
|
||||
def __getPreferredBrowserLanguage(self, availLangs):
|
||||
"""guess the preferred language of the user (as sent by the browser)
|
||||
take the first language, that is part of 'availLangs'
|
||||
"""
|
||||
import cherrypy
|
||||
try:
|
||||
pref_lang_header = cherrypy.request.headers["Accept-Language"]
|
||||
except KeyError:
|
||||
## no language header was specified
|
||||
return None
|
||||
## this could be a typical 'Accept-Language' header:
|
||||
## de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
|
||||
regex = re.compile(u"\w+(-\w+)?(;q=[\d\.]+)?$")
|
||||
pref_langs = [e.split(";",1)[0]
|
||||
for e in pref_lang_header.split(",")
|
||||
if regex.match(e)]
|
||||
## is one of these preferred languages available?
|
||||
for lang in pref_langs:
|
||||
if lang in availLangs: return lang
|
||||
## we try to be nice: also look for "de" if "de-de" was specified ...
|
||||
for lang in pref_langs:
|
||||
## use only the first part of the language
|
||||
short_lang = lang.split("-",1)[0]
|
||||
if short_lang in availLangs: return short_lang
|
||||
## we give up
|
||||
return None
|
||||
|
||||
|
||||
def __setDevice(self, device):
|
||||
|
@ -415,16 +458,34 @@ class WebInterfaceSites:
|
|||
else:
|
||||
return False
|
||||
|
||||
|
||||
def __render(self, template, plugin=None):
|
||||
'''renders from clearsilver templates and returns the resulting html
|
||||
|
||||
Gets a dictionary with all settings, nessessary for rendering.
|
||||
In fact the dictionary is a copy of the CryptoBoxWerbserverSite
|
||||
object, that calls this render method. This might be bloat but
|
||||
this way the render method has always a complete, actual set of values.
|
||||
def __getLanguageData(self, web_lang="en"):
|
||||
import neo_cgi, neo_util, os
|
||||
default_lang = "en"
|
||||
conf_lang = self.prefs["WebSettings"]["Language"]
|
||||
hdf = neo_util.HDF()
|
||||
langDir = os.path.abspath(self.prefs["Locations"]["LangDir"])
|
||||
langFiles = []
|
||||
## first: read default language (en)
|
||||
if (default_lang != conf_lang) and (default_lang != web_lang):
|
||||
langFiles.append(os.path.join(langDir, default_lang + ".hdf"))
|
||||
## second: read language as defined in the config file
|
||||
if (conf_lang != web_lang):
|
||||
langFiles.append(os.path.join(langDir, conf_lang + ".hdf"))
|
||||
## third: read language as configured via web interface
|
||||
langFiles.append(os.path.join(langDir, web_lang + ".hdf"))
|
||||
for langFile in langFiles:
|
||||
if os.access(langFile, os.R_OK):
|
||||
hdf.readFile(langFile)
|
||||
else:
|
||||
log.warn("Couldn't read language file: %s" % langFile)
|
||||
return hdf
|
||||
|
||||
|
||||
def __render(self, renderInfo, plugin=None):
|
||||
'''renders from clearsilver templates and returns the resulting html
|
||||
'''
|
||||
import os
|
||||
import os, types
|
||||
try:
|
||||
import neo_cgi, neo_util, neo_cs
|
||||
except ImportError:
|
||||
|
@ -433,40 +494,78 @@ class WebInterfaceSites:
|
|||
sys.stderr.write(errorMsg)
|
||||
raise ImportError, errorMsg
|
||||
|
||||
plugin_cs_file = False
|
||||
## is renderInfo a string (filename of the template) or a dictionary?
|
||||
if type(renderInfo) == types.DictType:
|
||||
template = renderInfo["template"]
|
||||
if renderInfo.has_key("generator"):
|
||||
generator = renderInfo["generator"]
|
||||
else:
|
||||
generator = False
|
||||
else:
|
||||
(template, generator) = (renderInfo, None)
|
||||
|
||||
## load the language data
|
||||
hdf = neo_util.HDF()
|
||||
hdf.copy("Lang", self.__getLanguageData(self.dataset["Settings.Language"]))
|
||||
|
||||
## first: assume, that the template file is in the global template directory
|
||||
self.dataset["Settings.TemplateFile"] = os.path.abspath(os.path.join(self.prefs["Locations"]["TemplateDir"], template + ".cs"))
|
||||
|
||||
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"] = plugin_cs_file or default_cs_file
|
||||
## check, if the plugin provides the template file -> overriding
|
||||
plugin_cs_file = plugin.getTemplateFileName(template)
|
||||
if plugin_cs_file:
|
||||
self.dataset["Settings.TemplateFile"] = plugin_cs_file
|
||||
## add the current state of the plugins to the hdf dataset
|
||||
self.dataset["Data.Status.Plugins.%s" % plugin.getName()] = plugin.getStatus()
|
||||
## load the language data
|
||||
pl_lang = plugin.getLanguageData(self.dataset["Settings.Language"])
|
||||
if pl_lang:
|
||||
hdf.copy("Lang.Plugins.%s" % plugin.getName(), pl_lang)
|
||||
## load the dataset of the plugin
|
||||
plugin.loadDataSet(hdf)
|
||||
|
||||
self.log.info("rendering site: " + template)
|
||||
|
||||
cs_path = os.path.join(self.prefs["Locations"]["TemplateDir"], "main.cs")
|
||||
cs_path = os.path.abspath(os.path.join(self.prefs["Locations"]["TemplateDir"], "main.cs"))
|
||||
if not os.access(cs_path, os.R_OK):
|
||||
log.error("Couldn't read clearsilver file: %s" % cs_path)
|
||||
return "Couldn't read clearsilver file: %s" % cs_path
|
||||
yield "Couldn't read clearsilver file: %s" % cs_path
|
||||
return
|
||||
|
||||
# use the user selected language instead of the configured
|
||||
hdf_path = os.path.join(self.prefs["Locations"]["LangDir"], self.dataset["Settings.Language"] + ".hdf")
|
||||
if not os.access(hdf_path, os.R_OK):
|
||||
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.pluginList)
|
||||
|
||||
## update the container information
|
||||
## update the container hdf-dataset (necessary if a plugin changed the state of a container)
|
||||
self.dataset.setContainersState()
|
||||
|
||||
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.pluginList.loadLanguageData(hdf, lang=self.dataset["Settings.Language"])
|
||||
cs = neo_cs.CS(hdf)
|
||||
cs.parseFile(cs_path)
|
||||
return cs.render()
|
||||
|
||||
## is there a generator containing additional information?
|
||||
if generator is None:
|
||||
## all content in one flush
|
||||
yield cs.render()
|
||||
else:
|
||||
content_generate = generator()
|
||||
dummy_line = """<!-- CONTENT_DUMMY -->"""
|
||||
## now we do it linewise - checking for the content marker
|
||||
for line in cs.render().splitlines():
|
||||
if line.find(dummy_line) != -1:
|
||||
yield line.replace(dummy_line, content_generate.next())
|
||||
else:
|
||||
yield line + "\n"
|
||||
|
||||
|
||||
def test_stream(self):
|
||||
"""just for testing purposes - to check if the "stream_response" feature
|
||||
actually works - for now (September 02006) it does not seem to be ok"""
|
||||
import time
|
||||
yield "<html><head><title>neu</title></head><body><p><ul>"
|
||||
for a in range(10):
|
||||
yield "<li>yes: %d - %s</li>" % (a, str(time.time()))
|
||||
time.sleep(1)
|
||||
yield "</ul></p></html>"
|
||||
|
||||
|
||||
############################################################################
|
||||
|
@ -484,12 +583,6 @@ class WebInterfaceSites:
|
|||
umount_do.exposed = True
|
||||
show_volumes.exposed = True
|
||||
test.exposed = True
|
||||
test_stream.exposed = True
|
||||
|
||||
|
||||
|
||||
"""
|
||||
## TODO: check this before anything else
|
||||
if self.cbox.getAvailableDocLanguages():
|
||||
self.dataset["Data.Error"] = "NoDocumentation"
|
||||
return self.__render("show_status")
|
||||
"""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue