german language file updated

WebInterfaceDataset replaces CryptoBoxWebserverSettings
WebInterfaceSites replaces CryptoBoxWebserverSites
input validation rewritten
clearsiler macro 'print_form_header' now expects the 'action' as a parameter
This commit is contained in:
lars 2006-09-07 11:21:56 +00:00
parent 0835144ad1
commit 0aa1f9f74b
23 changed files with 644 additions and 392 deletions

View file

@ -262,6 +262,16 @@ class CryptoBoxProps(CryptoBox):
return []
def getContainer(self, device):
"retrieve the container element for this device"
all = [e for e in self.getContainerList() if e.device == device]
if all:
return all[0]
else:
return None
def setNameForUUID(self, uuid, name):
"assign a name to a uuid in the ContainerNameDatabase"
used_uuid = self.getUUIDForName(name)

View file

@ -508,7 +508,7 @@ class CryptoBoxContainer:
"luksFormat",
self.device,
"--batch-mode",
"--cipher", self.cbox.cbxPrefs["System"]["DefaultCipher"],
"--cipher", self.cbox.cbxPrefs["Main"]["DefaultCipher"],
"--iter-time", "2000"])
proc.stdin.write(password)
(output, errout) = proc.communicate()

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python2.4
import os
import CryptoBoxWebserverSites
import WebInterfaceSites
try:
import cherrypy
@ -12,7 +12,7 @@ class CryptoBoxWebserver:
'''this class starts the cherryp webserver and serves the single sites'''
def __init__(self):
cherrypy.root = CryptoBoxWebserverSites.CryptoBoxWebserverSites()
cherrypy.root = WebInterfaceSites.WebInterfaceSites()
#expose static content:
#I currently have no idea how to cleanly extract the stylesheet path from
#the config object without an extra CryptoBox.CryptoBoxProps instance.

View file

@ -1,42 +0,0 @@
import os
try:
import neo_cgi, neo_util, neo_cs
except ImportError:
raise ImportError("could not import clearsilver modules! Try apt-get install python-clearsilver.")
class CryptoBoxWebserverRender:
'''renders the site with clearsilver template and languagefile
'''
def render(self, website):
'''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.
'''
website.log.info("rendering site: "+website.settings["Data.Action"])
cs_path = website.cbxPrefs["Locations"]["TemplateDir"]+"/main.cs"
if not os.access(cs_path, os.R_OK):
website.log.error("Couldn't read cs file: %s" % cs_path)
return "Couldn't read cs file: %s" % cs_path
#hdf_path = website.cbxPrefs["Locations"]["LangDir"]+"/"+website.cbxPrefs["WebSettings"]["Language"]+".hdf"
# use the user selected language ('Settings.Language') instead of the configured
hdf_path = website.cbxPrefs["Locations"]["LangDir"]+"/"+website.settings["Settings.Language"]+".hdf"
if not os.access(hdf_path, os.R_OK):
website.log.error("Couldn't read hdf file: %s" % hdf_path)
return "Couldn't read hdf file: %s" % hdf_path
hdf = neo_util.HDF()
hdf.readFile(hdf_path)
website.log.debug(website.settings)
for key in website.settings.keys():
hdf.setValue(key,str(website.settings[key]))
cs = neo_cs.CS(hdf)
cs.parseFile(cs_path)
return cs.render()

View file

@ -1,42 +0,0 @@
class CryptoBoxWebserverSettings:
'''this is the motherclass of all cbx site settings
put the stuff in here, that every site will need access to'''
def setSettings(self, website):
'''fills a dictionary with values from the configfile
There may also be set some useful standards here.'''
website.settings={}
#TODO: this is nessessary since the last config split in different sections
## put all found WebSettings values in the dictionary
## RFC: arbitrarily importing all available keys does not sound very secure [l]
## RFC: settings with the same names in different sections (Log, Main, ...) will collide silently - right? [l]
## yep, we'll have to divide between settings for clearsilver and settings we need for other webstuff [a]
## I think it would be better to expose only the necessary settings (manually - not just everything) [l]
for key in self.cbxPrefs["WebSettings"].keys():
website.settings["Settings."+key] = self.cbxPrefs["WebSettings"][key]
## also all Log values
for key in self.cbxPrefs["Log"].keys():
website.settings["Log."+key] = self.cbxPrefs["Log"][key]
## also Main
for key in self.cbxPrefs["Main"].keys():
website.settings["Settings."+key] = self.cbxPrefs["Main"][key]
## Locations dito
for key in self.cbxPrefs["Locations"].keys():
website.settings["Settings."+key] = self.cbxPrefs["Locations"][key]
## put available languages also in the dictionary
website.settings["Settings.AvailableLanguages"] = self.getAvailableLanguages()
website.settings["Settings.AvailableDocLanguages"] = self.getAvailableDocLanguages()
#self.log.info(self.settings)
def print_foo(self):
'''a stupid demo method
if there are methods necessary for more than one site,
put them in here like this stupid demo'''
self.log.info("'print_foo' was called by some site and triggerd an inheritated method")
self.cbx_inheritance_test("fooooooooooooobaaaaaaaaaaaaaaaaaaaar")

View file

@ -1,258 +0,0 @@
import CryptoBox
import CryptoBoxWebserverSettings
import CryptoBoxWebserverRender
# RFC: is this global variable necessary? [l]
website = CryptoBoxWebserverRender.CryptoBoxWebserverRender()
# RFC: where should we put the information gathering? (available harddisks, current volume info, ...) - selectively for every "site" or always (as before)? [l]
# RFC: is it necessary to inherit these both classes?
# for clarity they should be just instanciated - or not? [l]
class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettings.CryptoBoxWebserverSettings):
'''
url2func = {'index':'show_status','doc':'show_doc','logs':'show_log'}
'''
def __prepare(self, action="show_status"):
'''handles stuff that all sites need as preparation
The default site to render is 'show_status'.
Self.settings is filled by the following methodcall
thus every rendered site will get actual values from the configfile.
After that the corresponding site-method (e.g. doc) may set individual values.
'''
# RFC: the following line somehow implicitly calls 'setSettings(self, self)'
# should it be that way? [l]
self.setSettings(self)
#self.settings
self.settings["Data.Action"] = action
#TODO: check ssl status
def __sanitize_input(self, evilparams):
'''mistrusts every given parameter and wipes crap out
Every single site method has to call this before even looking
at url-given parameters.
This has to be called manually, since I don't see any other way of
sanitizing input automatically for all sites.
To take full effect it is good style not to use any given
parameter for any website. Instead use "settings.["..." if it
isn't already defined. Then define it in here, after carefully
checking.
# RFC: why shouldn't it be called in __init__? [l]
there is no such thing like __init__ in cherrypy sites [a]
what about the unnamed place, where 'exposed' attributes are set? [l]
'''
# RFC: this dictionary is not sufficient for arbitrary text inputs (e.g.: names) or numbers [l]
# what way would we sanizite such input? just exclude forbidden elements? [a]
# I would prefer a seperate function for each possible setting [l]
niceparams = {
'weblang': ["Settings.Language", self.settings["Settings.AvailableLanguages"]],
'loglevel': ["Log.Level", ('','info', 'warn', 'debug', 'error')],
'type': ["Data.Type", ('reboot', 'poweroff')]
}
## check all given evil parameters against the nice ones
## set them to self.settings if accepted, otherwise do nothing
for evilkey in evilparams.keys():
# TODO: should be easier without the following for-loop
for nicekey in niceparams.keys():
if evilkey == nicekey:
#self.log.warn(niceparams[nicekey][0])
#self.log.warn(niceparams[nicekey][1])
if evilparams[nicekey] and evilparams[nicekey] in niceparams[nicekey][1]:
# RFC: isn't "self.settings" a non-obvious name for user input? [l]
# self.settings is used by clearsilver [a]
# yes, but why should clearsilver have access to the user input? [l]
self.settings[niceparams[nicekey][0]] = evilparams[nicekey]
#self.log.warn(niceparams[nicekey][0])
#self.log.warn(evilparams[nicekey])
'''
## e.g. do this manually
if evilkey == "weblang":
if evilparams["weblang"] and evilparams["weblang"] in niceparams["weblang"]:
self.settings["Settings.Language"] = evilparams["weblang"]
if evilkey == "loglevel":
if evilparams["loglevel"] and evilparams["loglevel"] in niceparams["loglevel"]:
self.settings["Log.Level"] = evilparams["loglevel"]
if evilkey == "type":
if evilparams["type"] and evilparams["type"] in niceparams["type"]:
self.settings["Data.Type"] = evilparams["type"]
'''
return
def __isHDAvailable(self):
#TODO: implement this
return True
def __check_config(self):
#TODO: from now on a cryptobox is always configured
return True
def __check_init_running(self):
#TODO: implement this check (is mkfs still running?)
return False
######################################################################
## put real sites down here and don't forget to expose them at the end
def logs(self, loglevel=""):
'''displays a HTML version of the logfile
The loglevel has to be set and nothing else, as we just log in english.
RFC: what does this mean? We still have to save the current language - or not? [l]
Be aware not to name this method just "log" as it seems to be a
reserved word.
# RFC: maybe it conflicts with CryptoBoxProps.log - which we inherited? [l]
'''
self.__prepare("show_log")
self.__sanitize_input({"loglevel":loglevel})
self.settings["Data.Log"] = "<br/>".join(self.getLogData(lines=30, maxSize=2000))
return website.render(self)
def status(self, weblang=""):
'''shows the current status of the box
'''
self.__prepare("show_status")
self.__sanitize_input({"weblang":weblang})
if not self.__check_config():
self.settings["Data.Warning"] = "NotInitialized"
self.settings["Data.Action"] = "form_init"
elif self.__check_init_running():
self.settings["Data.Warning"] = "InitNotFinished"
self.settings["Data.Action"] = "empty"
self.settings["Data.Redirect.Action"] = "form_config"
self.settings["Data.Redirect.Delay"] = "30"
else:
self.settings["Data.Action"] = "show_status"
self.settings["Data.Redirect.Delay"] = "60"
return website.render(self)
def config(self,weblang=""):
pass
# TODO: add "doclang" - it is selected by each link in the doc pages
# according to scripts/docexport it's weblang [a]
def doc(self,page="",weblang=""):
'''prints the offline wikipage
'''
self.__prepare("show_doc")
# TODO: single pagenames should be sanitized
self.__sanitize_input({"weblang":weblang})
# TODO: check the supplied page name for validity (is it text? pattern match?)
if page:
self.settings["Data.Doc.Page"] = page
else:
## display this site as default helpsite
self.settings["Data.Doc.Page"] ="CryptoBoxUser"
if len(self.settings["Settings.AvailableDocLanguages"]) < 1:
self.settings["Data.Error"] = "NoDocumentation"
# TODO: what should be done, if there is an error?
# do you mean this is not an error? [a]
# it is, but the current action is still "show_doc" - despite the error - maybe "blank" would be better? [l]
## set doclang to weblang, otherwise the default weblang from the config will be used for doclang
elif self.settings["Settings.Language"] in self.settings["Settings.AvailableDocLanguages"]:
self.settings["Settings.DocLang"] = self.settings["Settings.Language"]
# TODO: missing 'else'?
return website.render(self)
def system(self, type="", weblang=""):
self.__prepare("form_system")
self.__sanitize_input({"type":type,"weblang":weblang})
if type == "reboot":
self.settings["Data.Success"] = "ReBoot"
self.settings["Data.Redirect.Action"] = "show_status"
self.settings["Data.Redirect.Delay"] = "180"
self.log.info("TODO: call function for system reboot")
elif type == "poweroff":
self.settings["Data.Success"] = "PowerOff"
self.log.info("TODO: call function for system shutdown")
else:
self.log.warn("This shutdown-mode (%s) is not supplied." % type)
return website.render(self)
def index(self):
self.__prepare("show_status")
return website.render(self)
def test(self):
return "test passed"
def umount_do(self):
if not __isHDAvailable():
pass
else:
pass
'''
## DONE: these functions are pythonized
#################### show_log #######################
##################### doc ############################
##################### poweroff ######################
##################### reboot ########################
## but there are even more TODO
#-------------------------------------------------------#
# here you may define all cases that require a harddisk #
#-------------------------------------------------------#
################ umount_do #######################
elif action == "unmount_do":
if not device:
self.log.debug("invalid device chosen: %s" device
settings["Data.Warning"] = "InvalidDevice"
settings["Data.Action"] = "empty"
elif not True: #TODO: replace True with check_config()
settings["Data.Warning"] = "NotInitialized"
settings["Data.Action"] = "form_init"
elif True: #TODO: replace True with check_init_running()
settings["Data.Warning"] = "InitNotFinished"
settings["Data.Action"] = "empty"
settings["Data.Redirect.Action"] = "form_config"
settings["Data.Redirect.Delay"] = "30"
elif not True: #TODO: replace True with check_mounted(device)
settings["Data.Warning"] = "NotMounted"
settings["Data.Action"] = "show_volume"
else: #unmount
#TODO: replace this line with umount_vol(device)
if True: #TODO: replace True with check_mounted(device)
settings["Data.Warning"] = "UmountFailed"
settings["Data.Action"] = "show_volume"
else:
settings["Data.Action"] = "show_volume"
################ mount_do ########################
elif action == "mount_do":
if device:
pass #TODO: is_encrypted = check_device_encryption(device)
else:
self.log.debug("invalid device chosen: %s" device
settings["Data.Warning"] = "InvalidDevice"
settings["Data.Action"] = "empty"
elif not True: #TODO: replace True with check_config()
settings["Data.Warning"] = "NotInitialized"
settings["Data.Action"] = "form_init"
#at cryptobox.pl line 568
'''
############################################################################
## to make the sites visible through the webserver they must be exposed here
index.exposed = True
doc.exposed = True
logs.exposed = True
system.exposed = True
status.exposed = True
test.exposed = True

View file

@ -0,0 +1,74 @@
import os
import CryptoBoxContainer
## useful constant for many functions
CONT_TYPES = CryptoBoxContainer.CryptoBoxContainer.Types
class WebInterfaceDataset(dict):
"""this class contains all data that should be available for the clearsilver
templates
"""
def __init__(self, cbox, prefs):
self.prefs = prefs
self.cbox = cbox
self.__setConfigValues()
self.__setCryptoBoxState()
def __setConfigValues(self):
self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"])
self["Settings.LanguageDir"] = os.path.abspath(self.prefs["Locations"]["LangDir"])
self["Settings.DocDir"] = os.path.abspath(self.prefs["Locations"]["DocDir"])
self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"]
self["Settings.Language"] = self.prefs["WebSettings"]["Language"]
self["Settings.DocLang"] = self.prefs["WebSettings"]["DocLanguage"]
def __setCryptoBoxState(self):
avail_counter = 0
active_counter = 0
for container in self.cbox.getContainerList():
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.Disks.%d.device" % avail_counter] = container.getDevice()
self["Data.Disks.%d.name" % avail_counter] = container.getName()
self["Data.Disks.%d.encryption" % avail_counter] = isEncrypted
self["Data.Disks.%d.plaintext" % avail_counter] = isPlain
self["Data.Disks.%d.active" % avail_counter] = isMounted
if isMounted: active_counter += 1
avail_counter += 1
self["Data.activeDisksCount"] = active_counter
for lang in self.cbox.getAvailableLanguages():
self["Data.Languages." + lang] = self.__getLanguageName(lang)
## 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")
hdf = neo_util.HDF()
hdf.readFile(hdf_path)
return hdf.getValue("Lang.Name",lang)

View file

@ -0,0 +1,470 @@
import CryptoBox
import WebInterfaceDataset
import re
class WebInterfaceSites:
'''
url2func = {'index':'show_status','doc':'show_doc','logs':'show_log'}
'''
def __init__(self):
import logging
self.cbox = CryptoBox.CryptoBoxProps()
self.log = logging.getLogger("CryptoBox")
self.prefs = self.cbox.cbxPrefs
self.__resetDataset()
def __resetDataset(self):
self.dataset = WebInterfaceDataset.WebInterfaceDataset(self.cbox, self.prefs)
def __isHDAvailable(self):
#TODO: implement this
return True
def __check_config(self):
#TODO: from now on a cryptobox is always configured
return True
def __check_init_running(self):
#TODO: implement this check (is mkfs still running?)
return False
######################################################################
## put real sites down here and don't forget to expose them at the end
def logs(self, weblang=""):
'''displays a HTML version of the logfile
'''
self.__resetDataset()
self.__setWebLang(weblang)
self.dataset["Data.Log"] = "<br/>".join(self.cbox.getLogData(lines=30, maxSize=2000))
return self.__render("show_log")
def status(self, weblang=""):
'''shows the current status of the box
'''
self.__resetDataset()
self.__setWebLang(weblang)
if not self.__check_config():
self.dataset["Data.Warning"] = "NotInitialized"
return self.__render("form_init")
elif self.__check_init_running():
self.dataset["Data.Warning"] = "InitNotFinished"
self.dataset["Data.Redirect.Action"] = "form_config"
self.dataset["Data.Redirect.Delay"] = "30"
return self.__render("empty")
else:
self.dataset["Data.Redirect.Delay"] = "60"
return self.__render("show_status")
def config(self,weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
pass
def doc(self,page="",weblang=""):
'''prints the offline wikipage
'''
import re
self.__resetDataset()
self.__setWebLang(weblang)
## check for invalid characters
if page and not re.search(u'\W', page):
self.dataset["Data.Doc.Page"] = page
else:
## display this page as default help page
self.dataset["Data.Doc.Page"] ="CryptoBoxUser"
return self.__render("show_doc")
def system(self, shutdowntype="", weblang=""):
# TODO: check 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")
def index(self, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
return self.__render("show_status")
def show_volume(self, device="", weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if self.__setDevice(device):
return self.__render("show_volume")
else:
if self.cbox.getContainerList():
return self.__render("show_volumes")
else:
return self.__render("show_status")
def show_volumes(self, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
return self.__render("show_volumes")
def volume_name_set(self, device="", volume_name="", weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if self.__setDevice(device):
volume_name = volume_name.strip()
if self.__checkVolumeName(volume_name):
container = self.cbox.getContainer(device)
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))
self.dataset["Data.Warning"] = "SetVolumeNameFailed"
else:
self.log.info("successfully renamed volume '%s' to '%s'" % (device, volume_name))
# reread the dataset
self.__resetDataset()
self.dataset.setCurrentDiskState(device)
else:
self.dataset["Data.Warning"] = "InvalidVolumeName"
return self.__render("show_volume")
else:
if self.cbox.getContainerList():
return self.__render("show_volumes")
else:
return self.__render("show_status")
def mount_do(self, device, crypto_password=None, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if self.__setDevice(device):
container = self.cbox.getContainer(device)
if container.isMounted():
self.dataset["Data.Warning"] = "IsMounted"
self.log.warn("the device (%s) is already mounted" % device)
else:
try:
if container.getType() == container.Types["luks"]:
## encrypted luks container
if not crypto_password:
self.dataset["Data.Warning"] = "EmptyCryptoPassword"
self.log.warn("no password was supplied for mounting of device '%s'" % device)
return self.__render("show_volume")
else:
container.mount(crypto_password)
elif container.getType() == container.Types["plain"]:
## plain container
container.mount()
else:
## mounting is not possible
# TODO: wrong warning message - replace it
self.dataset["Data.Warning"] = "MountFailed"
self.log.warn("this type of container (%s) cannot be mounted - sorry!" % device)
except (Exception, "MountError"):
self.dataset["Data.Warning"] = "MountFailed"
self.log.warn("failed to mount the device (%s)" % device)
else:
self.log.info("successfully mounted the container (%s)" % device)
# reread the dataset
self.__resetDataset()
self.dataset.setCurrentDiskState(device)
else:
if self.cbox.getContainerList():
return self.__render("show_volumes")
else:
return self.__render("show_status")
return self.__render("show_volume")
def volume_init_ask(self, device, encryption=None, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if self.__setDevice(device):
container = self.cbox.getContainer(device)
if container.isMounted():
self.dataset["Data.Warning"] = "VolumeMayNotBeMounted"
self.log.warn("initialization is not possible as long as the device (%s) is mounted" % device)
return self.__render("show_volume")
else:
if encryption is None:
self.dataset["Data.Init.isCrypto"] = 0
else:
self.dataset["Data.Init.isCrypto"] = 1
return self.__render("form_init")
else:
if self.cbox.getContainerList():
return self.__render("show_volumes")
else:
return self.__render("show_status")
def init_do(self, device, confirm, crypto_password=None, crypto_password2=None, encryption=None, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if self.__setDevice(device):
container = self.cbox.getContainer(device)
## set 'Data.Init.isCrypto' - just in case, we have to show the same form again
if encryption is None:
self.dataset["Data.Init.isCrypto"] = 0
else:
self.dataset["Data.Init.isCrypto"] = 1
if container.isMounted():
self.dataset["Data.Warning"] = "VolumeMayNotBeMounted"
self.log.warn("initialization is not possible as long as the device (%s) is mounted" % device)
return self.__render("form_init")
else:
# TODO: we have to compare 'confirm' with the value in the language file - IMPORTANT!
if not confirm:
self.dataset["Data.Warning"] = "InitNotConfirmed"
self.log.warn("the confirmation sentence for initialization of the device '%s' was wrong" % device)
return self.__render("form_init")
try:
if not encryption is None:
if not crypto_password:
self.dataset["Data.Warning"] = "EmptyCryptoPassword"
self.log.warn("no crypto password was supplied for initialization of device '%s'" % device)
return self.__render("form_init")
if crypto_password != crypto_password2:
self.dataset["Data.Warning"] = "DifferentCryptoPasswords"
self.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % device)
return self.__render("form_init")
container.create(container.Types["luks"], crypto_password)
else:
container.create(container.Types["plain"])
# TODO: specify the exception
except Exception, errMsg:
# TODO: wrong error/warning message - change it
self.dataset["Data.Error"] = "InitFailed"
self.log.warn("initialization of device '%s' failed" % device)
self.log.warn("reason: %s" % errMsg)
return self.__render("form_init")
else:
self.log.info("successfully initialized device '%s'" % device)
# reread the dataset
self.__resetDataset()
self.dataset.setCurrentDiskState(device)
return self.__render("show_volume")
else:
if self.cbox.getContainerList():
return self.__render("show_volumes")
else:
return self.__render("show_status")
def test(self):
self.__resetDataset()
return "test passed"
def umount_do(self, device, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if self.__setDevice(device):
container = self.cbox.getContainer(device)
if not container.isMounted():
self.dataset["Data.Warning"] = "NotMounted"
self.log.warn("the device (%s) is currently not mounted" % device)
else:
try:
if container.getType() == container.Types["luks"]:
## encrypted luks container
container.umount()
elif container.getType() == container.Types["plain"]:
## plain container
container.umount()
else:
## mounting is not possible
# TODO: wrong warning message - replace it
self.dataset["Data.Warning"] = "UmountFailed"
self.log.warn("this type of container (%s) cannot be umounted - sorry!" % device)
except (Exception, "UmountError"):
self.dataset["Data.Warning"] = "UmountFailed"
self.log.warn("failed to unmount the device (%s)" % device)
else:
self.log.info("successfully unmounted the container (%s)" % device)
# reread the dataset
self.__resetDataset()
self.dataset.setCurrentDiskState(device)
else:
if self.cbox.getContainerList():
return self.__render("show_volumes")
else:
return self.__render("show_status")
return self.__render("show_volume")
'''
## DONE: these functions are pythonized
#################### show_log #######################
##################### doc ############################
##################### poweroff ######################
##################### reboot ########################
## but there are even more TODO
#-------------------------------------------------------#
# here you may define all cases that require a harddisk #
#-------------------------------------------------------#
################ umount_do #######################
elif action == "unmount_do":
if not device:
self.log.debug("invalid device chosen: %s" device
settings["Data.Warning"] = "InvalidDevice"
settings["Data.Action"] = "empty"
elif not True: #TODO: replace True with check_config()
settings["Data.Warning"] = "NotInitialized"
settings["Data.Action"] = "form_init"
elif True: #TODO: replace True with check_init_running()
settings["Data.Warning"] = "InitNotFinished"
settings["Data.Action"] = "empty"
settings["Data.Redirect.Action"] = "form_config"
settings["Data.Redirect.Delay"] = "30"
elif not True: #TODO: replace True with check_mounted(device)
settings["Data.Warning"] = "NotMounted"
settings["Data.Action"] = "show_volume"
else: #unmount
#TODO: replace this line with umount_vol(device)
if True: #TODO: replace True with check_mounted(device)
settings["Data.Warning"] = "UmountFailed"
settings["Data.Action"] = "show_volume"
else:
settings["Data.Action"] = "show_volume"
################ mount_do ########################
elif action == "mount_do":
if device:
pass #TODO: is_encrypted = check_device_encryption(device)
else:
self.log.debug("invalid device chosen: %s" device
settings["Data.Warning"] = "InvalidDevice"
settings["Data.Action"] = "empty"
elif not True: #TODO: replace True with check_config()
settings["Data.Warning"] = "NotInitialized"
settings["Data.Action"] = "form_init"
#at cryptobox.pl line 568
'''
##################### input checker ##########################
def __setWebLang(self, value):
## 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 or \
not guess in availLangs or \
re.search(u'\W', guess):
guess = self.prefs["WebSettings"]["Language"]
## maybe the language is still not valid
if not guess in availLangs:
self.log.warn("the configured language is invalid: %s" % guess)
guess = availLangs[0]
self.dataset["Settings.Language"] = guess
self.dataset["Settings.DocLang"] = guess
self.dataset["Settings.LinkAttrs.weblang"] = guess
def __setDevice(self, device):
if device and re.match(u'[\w /\-]+$', device) and self.cbox.getContainer(device):
self.log.debug("select device: %s" % device)
self.dataset.setCurrentDiskState(device)
return True
else:
self.log.warn("invalid device: %s" % device)
self.dataset["Data.Warning"] = "InvalidDevice"
return False
def __checkVolumeName(self, name):
if name and re.match(u'[\w \-]+$', name):
return True
else:
return False
def __render(self, template):
'''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.
'''
import os
try:
import neo_cgi, neo_util, neo_cs
except ImportError:
errorMsg = "Could not import clearsilver modules. Try 'apt-get install python-clearsilver'."
self.log.error(errorMsg)
sys.stderr.write(errorMsg)
raise ImportError, errorMsg
self.dataset["Data.Action"] = template
self.log.info("rendering site: " + template)
cs_path = 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
# 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
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]))
cs = neo_cs.CS(hdf)
cs.parseFile(cs_path)
return cs.render()
############################################################################
## to make the sites visible through the webserver they must be exposed here
index.exposed = True
doc.exposed = True
logs.exposed = True
system.exposed = True
status.exposed = True
show_volume.exposed = True
volume_name_set.exposed = True
mount_do.exposed = True
volume_init_ask.exposed = True
init_do.exposed = True
umount_do.exposed = True
show_volumes.exposed = True
test.exposed = True
"""
## TODO: check this before anything else
if self.cbox.getAvailableDocLanguages():
self.dataset["Data.Error"] = "NoDocumentation"
return self.__render("show_status")
"""

View file

@ -59,7 +59,7 @@ Stylesheet = /cryptobox-misc/cryptobox.css
Language = de
# default language for documentation
DocLang = de
DocLanguage = de
[Programs]

View file

@ -14,6 +14,7 @@ Lang {
Log = Protokoll der CryptoBox
System = System
Status = Status der CryptoBox
Volume = Eigenschaften von
}
@ -40,6 +41,12 @@ Lang {
Configuration = Einstellungen
CryptoIsActive = Die Crypto-Daten sind verfügbar.
CryptoIsDown = Die Crypto-Daten sind vor jedem Zugriff geschützt.
ChoosePartition = Welchen Daten-Container möchtest du auswählen?
ChosenPartition = Der aktuelle Daten-Container ist
ActivePartitions = Die folgenden Daten-Container sind derzeit aktiv
PassivePartitions = Die folgenden Daten-Container sind derzeit inaktiv
ContainerName = Der Name des Daten-Containers
ContainerEncryption = Aktiviere Verschlüsselung
}
@ -56,6 +63,8 @@ Lang {
Documentation = Hilfe
Status = Status
System = System
ContainerNameSet = Setze den neuen Namen
InitContainer = Reinitialisiere den Container
}
@ -154,6 +163,36 @@ Lang {
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?
}
NoDiskAvailableForUmount {
Title = Kein Daten-Container verfügbar
Text = Kein Daten-Container ist aktiv. Vielleicht wurden alle Container deaktiviert.
}
InvalidDevice {
Title = Ungültiger Container
Text = Der angegebene Daten-Container ist nicht zulässig.
}
InvalidVolumeName {
Title = Umbenennung fehlgeschlagen
Text = Der gewählte neue Name des Containers ist ungültig. Versuche es erneut.
}
SetVolumeNameFailed {
Title = Umbenennung fehlgeschlagen
Text = Die Umbenennung des Containers schlug fehl. Details findest du in der Log-Datei.
}
VolumeMayNotBeMounted {
Title = Der Container ist derzeit aktiv
Text = Die gewünschte Aktion kann nicht durchgeführt werden, solange der Container aktiv ist.
}
}

View file

@ -45,7 +45,7 @@ Lang {
ChosenPartition = The chosen container is
ActivePartitions = The following containers are enabled
PassivePartitions = The following containers are disabled
ContainerName = Container's name:
ContainerName = Container's name
ContainerEncryption = Enable encryption
}

View file

@ -3,7 +3,7 @@
<div id="config">
<h1><?cs var:html_escape(Lang.Title.Config) ?></h1>
<?cs call:print_form_header() ?>
<?cs call:print_form_header("config_do") ?>
<?cs if:Data.Config.AdminPasswordIsSet ?>
<p><label for="current_admin_password"><?cs var:html_escape(Lang.Text.EnterCurrentAdminPassword) ?></label><br/>
<input type="password" id="current_admin_password" name="current_admin_password" size="20" maxlength="40" /> </p>
@ -26,7 +26,6 @@
<?cs /each ?>
</select></p>
<input type="hidden" name="action" value="config_do" />
<button type="submit"><?cs var:html_escape(Lang.Button.SaveConfig) ?></button>
</form>

View file

@ -3,14 +3,19 @@
<h1><?cs var:html_escape(Lang.Title.Init) ?></h1>
<div class="init">
<?cs call:print_form_header() ?>
<?cs call:print_form_header("init_do") ?>
<p class="note"><?cs var:html_escape(Lang.Text.InitWarning) ?></p>
<p><label for="confirm"><?cs var:html_escape(Lang.Text.ConfirmInitHint) ?><br/>
<span class="note" id="confirmtext"><?cs var:html_escape(Lang.Text.ConfirmInit)
?></span></label><br/>
<input type="text" id="confirm" name="confirm" size="30" maxlength="50" /></p>
<input type="hidden" name="action" value="init_do" />
<?cs if:Data.Init.isCrypto ?>
<p><label for="crypto_password"><?cs var:html_escape(Lang.Text.EnterNewCryptoPassword) ?></label> <input type="password" id="crypto_password" name="crypto_password" /></p>
<p><label for="crypto_password2"><?cs var:html_escape(Lang.Text.EnterSameCryptoPassword) ?></label> <input type="password" id="crypto_password2" name="crypto_password2" /></p>
<input type="hidden" name="encryption" value="1" />
<?cs /if ?>
<input type="hidden" name="device" value="<?cs var:Data.CurrentDisk.device ?>" />
<button type="submit"><?cs var:html_escape(Lang.Button.DoInit) ?></button>
</form>
</div>

View file

@ -2,7 +2,7 @@
<h1><?cs var:html_escape(Lang.Title.Init) ?></h1>
<?cs call:print_form_header() ?>
<?cs call:print_form_header("volume_init_do") ?>
<p class="note"><?cs var:html_escape(Lang.Text.InitWarning) ?></p>
<?cs if:Data.Config.AdminPasswordIsSet ?>
@ -27,7 +27,6 @@
<input type="text" id="confirm" name="confirm" size="30" maxlength="50" /></p>
<p><input type="hidden" name="device" value="<?cs var:html_escape(Data.CurrentDisk.device) ?>" />
<input type="hidden" name="action" value="volume_init_do" />
<button type="submit"><?cs var:html_escape(Lang.Button.InitContainer) ?></button></p>
</form>

View file

@ -10,7 +10,7 @@
<div align="center">
<?cs call:print_form_header() ?>
<?cs call:print_form_header("mount_do") ?>
<?cs if:subcount(Data.Disks.passive) > 1 ?>
<p><label for="device"><?cs var:html_escape(Lang.Text.ChoosePartition) ?></label>
@ -30,7 +30,6 @@
?></label>
<input type="password" id="crypto_password" name="crypto_password" size="20" maxlength="40" /></p>
<input type="hidden" name="action" value="mount_do" />
<button type="submit"><?cs var:html_escape(Lang.Button.Mount) ?></button>
</form>

View file

@ -1,6 +1,6 @@
<?cs # $Id$ ?>
<?cs if:subcount(Data.Disks.active) == 0 ?>
<?cs if:Data.activeDisksCount == 0 ?>
<?cs call:warning('NoDiskAvailableForUmount') ?>
@ -9,25 +9,28 @@
<h1><?cs var:html_escape(Lang.Title.Umount) ?></h1>
<div align="center">
<?cs call:print_form_header() ?>
<?cs call:print_form_header("umount_do") ?>
<?cs if:subcount(Data.Disks.active) > 1 ?>
<?cs if:Data.activeDisksCount > 1 ?>
<p><label for="device"><?cs var:html_escape(Lang.Text.ChoosePartition) ?></label>
<select name="device" id="device" size="0">
<?cs each:partition = Data.Disks.active ?><option value="<?cs
<?cs each:partition = Data.Disks
?><?cs if:partition.active ?><option value="<?cs
var:partition.device ?>"><?cs
var:partition.name ?></option>
var:partition.name ?></option><?cs /if ?>
<?cs /each ?>
</select></p>
<?cs else ?>
<?cs # the perl code should take care, that there is at least
one mounted disk - otherwise it should display a warning ?>
<?cs each:partition = Data.Disks ?><?cs
if:partition.active ?><?cs set:act_name = partition.name ?><?cs
act_device = partition.device ?><?cs /if ?><?cs /each ?>
<p><?cs var:html_escape(Lang.Text.ChosenPartition) ?>: <?cs
var:Data.Disks.active.0.name ?></p>
var:act_name ?></p>
<input type="hidden" name="device" value="<?cs
var:Data.Disks.active.0.device ?>"/>
var:act_device ?>"/>
<?cs /if ?>
<input type="hidden" name="action" value="umount_do" />
<button type="submit"><?cs var:html_escape(Lang.Button.Umount) ?></button>
</form>

View file

@ -16,7 +16,7 @@
</head>
<body>
<?cs if:subcount(Data.Disks.available) > 0 ?>
<?cs if:subcount(Data.Disks) > 0 ?>
<div id="volumes">
<?cs include:Settings.TemplateDir + '/show_volumes.cs' ?>
</div>
@ -24,14 +24,13 @@
<div id="lang">
<?cs each:item = Data.Languages ?>
<a href="<?cs call:link('weblang',name(item),'','','') ?><?cs
if:Data.QueryString ?>&<?cs var:Data.QueryString ?><?cs /if ?>"><?cs
<a href="<?cs call:link('','weblang',name(item),'','') ?>"><?cs
var:item ?></a><br/>
<?cs /each ?>
</div>
<div id="main">
<?cs if:subcount(Data.Disks.active) > 0 ?>
<?cs if:Data.activeDisksCount > 0 ?>
<div id="head_red">
<?cs else ?>
<div id="head_green">

View file

@ -75,8 +75,8 @@ def:link(path, attr1, value1, attr2, value2)
?><?cs /if ?><?cs
/def ?><?cs
def:print_form_header() ?><?cs #
def:print_form_header(action) ?><?cs #
# the header of a form - including Setting.LinkAttrs
?><form action="<?cs call:link("","","","","") ?>" method="post" enctype="application/x-www-from-urlencoded" accept-charset="utf-8"><?cs
?><form action="<?cs call:link(action,"","","","") ?>" method="post" enctype="application/x-www-from-urlencoded" accept-charset="utf-8"><?cs
/def ?>

View file

@ -6,14 +6,14 @@
<!-- TODO: remove the following lines, as soon as we completely switched to the volume-based user interface
<?cs if:subcount(Data.Disks.passive) > 0 ?>
<a href="<?cs call:link('mount_ask','','','','') ?>" title="<?cs var:html_escape(Lang.Text.DoMount) ?>"><?cs var:html_escape(Lang.Button.Mount) ?></a><?cs /if ?>
<?cs if:subcount(Data.Disks.active) > 0 ?>
<?cs if:Data.activeDisksCount > 0 ?>
<a href="<?cs call:link('umount_ask','','','','') ?>" title="<?cs var:html_escape(Lang.Text.DoUmount) ?>"><?cs var:html_escape(Lang.Button.Umount) ?></a><?cs /if ?>
-->
<a href="<?cs if:subcount(Data.Disks.available) > 1
<a href="<?cs if:subcount(Data.Disks) > 1
?><?cs call:link('show_status','','','','')
?><?cs else
?><?cs call:link('show_volume','device',Data.Disks.available.0.device,'','')
?><?cs call:link('show_volume','device',Data.Disks.0.device,'','')
?><?cs /if
?>" title="<?cs var:html_escape(Lang.Button.Status) ?>"><?cs var:html_escape(Lang.Button.Status) ?></a>
<?cs /if ?>

View file

@ -2,27 +2,27 @@
<h1><?cs var:html_escape(Lang.Title.Status) ?></h1>
<?cs if:subcount(Data.Disks.available) == 0 ?>
<?cs if:subcount(Data.Disks) == 0 ?>
<?cs # there are no partitions available ?>
<?cs # this case may never be true, as it should trigger a warning before ?>
<p>Sorry - you should have never seen this ...</p>
<?cs # elif:subcount(Data.Disks.active) == subcount(Data.Disks.available) ?>
<?cs # elif:Data.activeDisksCount == subcount(Data.Disks) ?>
<?cs # all available disks are mounted ?>
<?cs # we do not use this special condition now - or should we? ?>
<?cs # elif:subcount(Data.Disks.passive) == subcount(Data.Disks.available) ?>
<?cs # elif:subcount(Data.Disks.passive) == subcount(Data.Disks) ?>
<?cs # no available disk is mounted ?>
<?cs # we do not use this special condition now - or should we? ?>
<?cs else ?>
<?cs # some are mounted - and some are not ... ?>
<?cs if:subcount(Data.Disks.active) > 0 ?>
<?cs if:Data.activeDisksCount > 0 ?>
<p><?cs var:html_escape(Lang.Text.ActivePartitions) ?>:
<ul><?cs each:partition = Data.Disks.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 /each ?></ul><?cs /if ?>
<?cs if:subcount(Data.Disks.passive) > 0 ?>
?>"><?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.passive ?>
<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 /each ?></ul><?cs /if ?>
?>"><?cs var:partition.name ?></a></li><?cs /if ?><?cs /each ?></ul><?cs /if ?>
<?cs /if ?>

View file

@ -7,21 +7,19 @@
<?cs # is the disc active? ?>
<?cs if:!Data.CurrentDisk.active ?>
<h2>Mount container</h2>
<?cs call:print_form_header() ?>
<?cs call:print_form_header("mount_do") ?>
<p>
<?cs if:Data.CurrentDisk.encryption ?>
<label for="crypto_passwort"><?cs var:html_escape(Lang.Text.EnterCurrentCryptoPassword) ?></label>
<input type="password" id="crypto_password" name="crypto_password" size="20" maxlength="40" />
<