Initial Commit

master
Harald Wolff 2018-03-01 23:37:52 +01:00
commit b821c1da4a
70 changed files with 4306 additions and 0 deletions

8
.gitignore vendored 100644
View File

@ -0,0 +1,8 @@
.DS_Store
**/*.pyc
#hServer/packages/*
!hServer/packages/hcore
#hServer/DiskSync/*
#hServer/objects/*

211
hServer.project 100644
View File

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Project Name="hServer" InternalType="">
<Reconciliation>
<Regexes/>
<Excludepaths/>
<Ignorefiles/>
<Extensions>
<![CDATA[cpp;c;h;hpp;xrc;wxcp;fbp;py;]]>
</Extensions>
<Topleveldir>../hserver</Topleveldir>
</Reconciliation>
<Description/>
<Dependencies/>
<Settings Type="Executable">
<GlobalSettings>
<Compiler Options="" C_Options="" Assembler="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
<ResourceCompiler Options=""/>
</GlobalSettings>
<Configuration Name="Debug" CompilerType="GCC" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-g -Wall" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
<IncludePath Value="."/>
</Compiler>
<Linker Options="-O0" Required="yes">
<LibraryPath Value="."/>
<LibraryPath Value="Debug"/>
</Linker>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="./Debug" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
<Environment EnvVarSetName="&lt;Use Workspace Settings&gt;" DbgSetName="&lt;Use Global Settings&gt;">
<![CDATA[]]>
</Environment>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
<DebuggerSearchPaths/>
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName/>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
<Completion EnableCpp11="no" EnableCpp14="no">
<ClangCmpFlagsC/>
<ClangCmpFlags/>
<ClangPP/>
<SearchPaths/>
</Completion>
</Configuration>
</Settings>
<VirtualDirectory Name="hServer">
<VirtualDirectory Name="hserver">
<File Name="hServer/hserver/__init__.py"/>
<File Name="hServer/hserver/request.py"/>
<File Name="hServer/hserver/server.py"/>
<File Name="hServer/hserver/headers.py"/>
<File Name="hServer/hserver/systemplates.py"/>
<File Name="hServer/hserver/utils.py"/>
<File Name="hServer/hserver/mime.py"/>
<File Name="hServer/hserver/mimeheaders.py"/>
<File Name="hServer/hserver/formdata.py"/>
<File Name="hServer/hserver/templates.py"/>
<VirtualDirectory Name="packages">
<File Name="hServer/hserver/packages/__init__.py"/>
<File Name="hServer/hserver/packages/package.py"/>
</VirtualDirectory>
<File Name="hServer/hserver/templatemod.py"/>
<VirtualDirectory Name="configuration"/>
<VirtualDirectory Name="ostore"/>
<VirtualDirectory Name="api">
<File Name="hServer/hserver/api/__init__.py"/>
<File Name="hServer/hserver/api/fileobject.py"/>
<File Name="hServer/hserver/api/simpleobject.py"/>
<File Name="hServer/hserver/api/webobject.py"/>
</VirtualDirectory>
<File Name="hServer/hserver/run.py"/>
<VirtualDirectory Name="templates.src">
<File Name="hServer/hserver/templates.src/so_updates.html"/>
</VirtualDirectory>
<File Name="hServer/hserver/exceptions.py"/>
</VirtualDirectory>
<VirtualDirectory Name="doc">
<File Name="hServer/doc/templates.txt"/>
</VirtualDirectory>
<VirtualDirectory Name="packages">
<VirtualDirectory Name="hserver-h_wo_image">
<VirtualDirectory Name="templates"/>
</VirtualDirectory>
<VirtualDirectory Name="h_asterisk">
<VirtualDirectory Name="asterisk">
<File Name="hServer/packages/h_asterisk/asterisk/__init__.py"/>
<File Name="hServer/packages/h_asterisk/asterisk/exceptions.py"/>
<File Name="hServer/packages/h_asterisk/asterisk/connection.py"/>
<File Name="hServer/packages/h_asterisk/asterisk/asterisk.py"/>
</VirtualDirectory>
<File Name="hServer/packages/h_asterisk/h_asterisk.py"/>
</VirtualDirectory>
<VirtualDirectory Name="h_astfax">
<VirtualDirectory Name="templates">
<File Name="hServer/packages/h_astfax/templates/status.html"/>
<File Name="hServer/packages/h_astfax/templates/view.html"/>
<File Name="hServer/packages/h_astfax/templates/page.html"/>
<File Name="hServer/packages/h_astfax/templates/child.html"/>
<File Name="hServer/packages/h_astfax/templates/view-row-page.html"/>
<File Name="hServer/packages/h_astfax/templates/queues.html"/>
</VirtualDirectory>
<File Name="hServer/packages/h_astfax/tifftools.py"/>
<File Name="hServer/packages/h_astfax/FaxJob.py"/>
<File Name="hServer/packages/h_astfax/package.conf"/>
<File Name="hServer/packages/h_astfax/WebFaxJob.py"/>
</VirtualDirectory>
<VirtualDirectory Name="hcore">
<VirtualDirectory Name="templates">
<File Name="hServer/packages/hcore/templates/404.html"/>
<File Name="hServer/packages/hcore/templates/overview.html"/>
<File Name="hServer/packages/hcore/templates/frame.html"/>
<File Name="hServer/packages/hcore/templates/packages.html"/>
<File Name="hServer/packages/hcore/templates/style.css"/>
<File Name="hServer/packages/hcore/templates/stat.html"/>
<File Name="hServer/packages/hcore/templates/control.html"/>
<File Name="hServer/packages/hcore/templates/tree.html"/>
<File Name="hServer/packages/hcore/templates/treelevel.html"/>
<File Name="hServer/packages/hcore/templates/api.js"/>
<File Name="hServer/packages/hcore/templates/list_wo.html"/>
<File Name="hServer/packages/hcore/templates/browse.html"/>
<File Name="hServer/packages/hcore/templates/browse.css"/>
</VirtualDirectory>
<File Name="hServer/packages/hcore/core.py"/>
<VirtualDirectory Name="coremod">
<File Name="hServer/packages/hcore/coremod/__init__.py"/>
<File Name="hServer/packages/hcore/coremod/exceptions.py"/>
</VirtualDirectory>
<File Name="hServer/packages/hcore/webmanager.py"/>
<File Name="hServer/packages/hcore/package.conf"/>
<File Name="hServer/packages/hcore/browser.py"/>
</VirtualDirectory>
<VirtualDirectory Name="h_endkontrolle">
<File Name="hServer/packages/h_endkontrolle/endkontrolle.py"/>
<VirtualDirectory Name="templates">
<File Name="hServer/packages/h_endkontrolle/templates/frame.html"/>
<File Name="hServer/packages/h_endkontrolle/templates/index.html"/>
<File Name="hServer/packages/h_endkontrolle/templates/style.css"/>
<File Name="hServer/packages/h_endkontrolle/templates/parts.html"/>
<File Name="hServer/packages/h_endkontrolle/templates/partdetail.html"/>
<File Name="hServer/packages/h_endkontrolle/templates/packaging.html"/>
<File Name="hServer/packages/h_endkontrolle/templates/partprint.html"/>
</VirtualDirectory>
<File Name="hServer/packages/h_endkontrolle/package.conf"/>
</VirtualDirectory>
<VirtualDirectory Name="WebAlbum"/>
<VirtualDirectory Name="h_wo_image">
<File Name="hServer/packages/h_wo_image/package.conf"/>
<File Name="hServer/packages/h_wo_image/h_wo_image.py"/>
</VirtualDirectory>
<VirtualDirectory Name="derkleinebasar">
<VirtualDirectory Name="templates">
<File Name="hServer/packages/derkleinebasar/templates/layout.html"/>
<File Name="hServer/packages/derkleinebasar/templates/layout.css"/>
<File Name="hServer/packages/derkleinebasar/templates/index.html"/>
<File Name="hServer/packages/derkleinebasar/templates/list_verk.html"/>
<File Name="hServer/packages/derkleinebasar/templates/print_tags.html"/>
<File Name="hServer/packages/derkleinebasar/templates/search.html"/>
<File Name="hServer/packages/derkleinebasar/templates/list_artikel.html"/>
<File Name="hServer/packages/derkleinebasar/templates/verk_prov.html"/>
<File Name="hServer/packages/derkleinebasar/templates/artikel_display.html"/>
<File Name="hServer/packages/derkleinebasar/templates/verk_display.html"/>
<File Name="hServer/packages/derkleinebasar/templates/artikel_tag.html"/>
<File Name="hServer/packages/derkleinebasar/templates/print.css"/>
<File Name="hServer/packages/derkleinebasar/templates/verkauf.html"/>
<File Name="hServer/packages/derkleinebasar/templates/quittung.html"/>
<File Name="hServer/packages/derkleinebasar/templates/common.css"/>
</VirtualDirectory>
<File Name="hServer/packages/derkleinebasar/basar.py"/>
<File Name="hServer/packages/derkleinebasar/artikel.py"/>
<File Name="hServer/packages/derkleinebasar/verkaeufer.py"/>
<File Name="hServer/packages/derkleinebasar/package.conf"/>
<File Name="hServer/packages/derkleinebasar/verkauf.py"/>
</VirtualDirectory>
</VirtualDirectory>
<VirtualDirectory Name="hwo">
<File Name="hServer/hwo/Proxy.py"/>
<File Name="hServer/hwo/__init__.py"/>
<File Name="hServer/hwo/Logging.py"/>
<File Name="hServer/hwo/objectbroker.py"/>
<File Name="hServer/hwo/objectstore.py"/>
<File Name="hServer/hwo/persistence.py"/>
<File Name="hServer/hwo/aquisition.py"/>
</VirtualDirectory>
<File Name="hServer/HServer.py"/>
<VirtualDirectory Name="DiskSync">
<File Name="hServer/DiskSync/ROOT"/>
</VirtualDirectory>
<VirtualDirectory Name="objects"/>
</VirtualDirectory>
<Dependencies Name="Debug"/>
</CodeLite_Project>

39
hServer/HServer.py 100755
View File

@ -0,0 +1,39 @@
#!/usr/bin/python3
import hserver
import os
import sys
newDefault = None
listen = ['localhost',8080]
opts = list( sys.argv[1:] )
while (len(opts)>0):
o = opts.pop(0)
if (o == '-b'):
listen[0] = opts.pop(0)
elif (o == '-p'):
listen[1] = int(opts.pop(0))
elif (o == '--default'):
newDefault = opts.pop(0)
server = hserver.HServer(listen)
if not newDefault is None:
server.getRoot().setDefault(newDefault)
server.run()

View File

@ -0,0 +1,25 @@
Simple Python Template Engine
-----------------------------
<WS> HEX: 0x0D,0x0A,0x20
<%[action]<WS>[expr]%>
[action] Aktion
"" [expr] als Python Code Interpretieren
= Rückgabewert von [expr] in Dokument einsetzen
include Weiteres Template einfügen [expr] ist entweder eine Liste der Form ('template-name',<self-ref>) oder 'template-name'
Zukünftig:
----------
iterate [expr] = <iterator> <iteration>
end Markiert Ende eines Blocks (z.B. iterate)
Globale Funktionen:
include(<templatename>,<selfref>) Fügt das Template <templatename> mit der "self" referenz <selfref> an der aktuellen Position ein
print(<text>) Gibt <text> an der aktuellen Position aus

View File

@ -0,0 +1,20 @@
from hserver.exceptions import HServerException,FinishRequestException,HttpException
import hserver.api
from hserver.request import Request
from hserver.headers import Headers
from hserver.templates import Template
from hserver.templatemod import TemplateModule
import hserver.run
import hserver.systemplates
from hserver.server import HServer

View File

@ -0,0 +1,6 @@
from hwo import Persistence,NoPersistence,Aquisition
from hserver.api.webobject import WebObject,WebFolder,WebCallable
from hserver.api.fileobject import FileObject
from hserver.api.simpleobject import SimpleObject

View File

@ -0,0 +1,32 @@
from hserver.api import WebObject
from hwo import Persistence,NoPersistence
import os
class FileObject(WebObject):
def __init__(self,file=None,path=None,contenttype="application/octet-stream"):
self._file = file
self._path = path
self._content = None
self._contenttype = contenttype
def __call__(self,request,o=None):
if self._content is None:
if self._file is None:
self._file = open( self._path, "rb" )
self._content = self._file.read()
request.setResponseHeader("Content-Type",self._contenttype)
request.getBinaryContentFile().write(self._content)
class DiskFolder(WebObject,Persistence):
def __init__(self,path):
self._path = path
def __dir__(self):
return os.listdir( self._path)

View File

@ -0,0 +1,16 @@
from hserver.api.webobject import WebObject,Persistence
import hserver
class SimpleObject(WebObject,Persistence):
def __init__(self,accepts=["*/*"],contenttype="application/octetstream",content=b""):
self.setDefault("update")
self.accepts = accepts
self.contenttype = contenttype
self.content = content
def __call__(self,request,o=None):
request.setResponseHeader("Content-Type",self.contenttype)
request.getBinaryContentFile().write( bytes(self.content) )

View File

@ -0,0 +1,108 @@
from hwo import Persistence,NoPersistence,Aquisition,AquisitionProxy
import hserver
class WebCallable:
def __init__(self, method=None, instance=None):
self._method = method
self._instance = instance
def __call__(self,request, o=None):
if (hasattr(self,"_method")):
m = getattr( self, "_method")
i = getattr( self, "_instance", o)
if i is None:
i = o
m(i,request, o=o)
else:
request.getContentFile().write("<html><head><title>No Content</title></head><body>Sorry, no content here!</body></html>")
class WebObject(WebCallable,Aquisition):
def __init__(self):
self.__default = None
def __getitem__(self,name):
try:
return getattr( self, name )
except:
raise IndexError("%s not found in %s" % (name,self))
def __setitem__(self,name,value):
setattr( self, name, value )
def __delitem__(self,name):
delattr( self, name )
def setDefault(self,default):
self.__default = default
def setChild(self,name,child):
setattr( self, name, child )
def children(self):
ls = []
for an in dir(self):
if isinstance( self[an], WebObject ):
ls.append( an )
return ls
def walk(self,request):
next, stack = request.pathwalker().walk()
no = getattr(self, next, None)
if no is None:
raise hserver.HttpException(404,"%s in /%s" % (next,request.pathwalker().walked(-1)))
if (len(stack)==0) or (not isinstance(no,WebObject)):
if (isinstance(no,WebCallable)):
no(request, o=self)
else:
raise hserver.HttpException(404,"%s in /%s" % (next,request.pathwalker().walked(-1)))
else:
no.walk(request)
def __call__(self,request,o = None):
if not self.__default is None:
request.redirect( request.pathwalker().walked() + "/" + self.__default )
request.getContentFile().write("<html><head><title>No Content</title></head><body>Sorry, no content here!</body></html>")
def attribute(self,name,default):
if not hasattr(self,name):
setattr( self, name, default )
return getattr( self, name )
def __public_types(self):
if hasattr(self,"_public_types"):
return self._public_types
return {}
def __public_names(self):
if hasattr(self,"_public_names"):
return self._public_names
return {}
def update(self,request):
if not request is None:
f = request.getForm()
else:
f = None
for n in self.__public_names():
if n in self.__public_types():
t = self.__public_types()[n]
else:
t = str
if (not f is None) and (n in f):
setattr(self, n, t(f[n].value()))
elif not hasattr(self, n):
setattr( self, n, t() )
class WebFolder(WebObject, Persistence):
pass

View File

@ -0,0 +1,13 @@
class HServerException(Exception):
pass
class FinishRequestException(HServerException):
pass
class HttpException(HServerException):
def __init__(self,status,message):
HServerException.__init__(self)
self.status = status
self.message = message

View File

@ -0,0 +1,85 @@
from urllib.parse import unquote_plus
class FormValue:
def __init__(self,name,value = None,headers = {}):
self.__name = name
self.__value = value
self.__headers = headers
def name(self):
return self.__name
def value(self):
return self.__value
def headers(self):
return self.__headers
def filename(self):
pp = self.__headers.parameters("CONTENT-DISPOSITION")
if (not pp is None) and ("filename" in pp.keys()):
return pp["filename"]
return None
class FormData:
def __init__(self,request):
self.__request = request
self.__values = {}
self.__append_query()
self.__append_mime()
def __getitem__(self,name):
return self.__values[name][0]
def __contains__(self,name):
return name in self.__values
def get(self,name):
try:
return self[name][0]
except:
return None
def keys(self):
return self.__values.keys()
def list(self,name):
if name in self.__values:
return list(self.__values[name])
return []
def __append_var(self,var):
if not var.name() in self.__values.keys():
self.__values[var.name()] = []
self.__values[var.name()].append( var )
def __append_mime(self):
mime = self.__request.mime()
if (mime.multipart()):
for p in mime.parts():
n = p.name()
if not n is None:
self.__append_var(FormValue(n,p.body(),p.headers()))
def __append_query(self):
qs = self.__request.QUERY_STRING
pairs = qs.split("&")
for pair in pairs:
sp = pair.split("=")
if (len(sp)>0):
name = sp[0]
if (len(sp)>1):
value = sp[1]
else:
value= ""
self.__append_var(FormValue( unquote_plus(name), unquote_plus(value)))

View File

@ -0,0 +1,68 @@
import io
import string
import hserver.utils
class Headers:
def __init__(self, fp=None, src=None):
self.__items = {}
self.__parameters = {}
if not fp is None:
self.__read(fp)
def get(self,name,default = None):
if not name in self.__items.keys():
return default
return self.__items[name]
def __getitem__(self,name):
if name in self.__items.keys():
return self.__items[name]
raise KeyError()
def __read(self,fp):
cont = True
lines = []
while (cont):
l = str(fp.readline(),"iso-8859-1").strip()
if (l.strip() == ""):
cont = False
else:
if (l[0] in string.whitespace ):
lines[-1] = lines[-1] + " " + l.lstrip()
else:
lines.append(l)
for line in lines:
self.__parseline(line)
def __parseline(self,line):
i = line.find(":")
if (i > 0):
name = line[:i]
value = line[ i+1 : ].strip()
i = value.find(";")
if (i>0):
parameters = value[ i+1 : ]
value = value[ :i ]
else:
parameters = None
self.__items[name] = value
print("Headers: %s: %s" % (name,value))
# if (not parameters is None):
# p = hserver.utils.StreamTokenizer(io.StringIO(parameters))

View File

@ -0,0 +1,109 @@
import io
import traceback
from hserver.mimeheaders import MIMEHeaders
class MIMEException(Exception):
pass
class ContentSizeLimitException(MIMEException):
pass
class MIME:
def __init__(self,fp=None,source=None,limit=10485760,defaultlength=-1,parent=None):
if (not fp is None):
self.__fp = fp
elif (not source is None):
self.__fp = io.BytesIO(source)
self.__parent = parent
self.__limit = limit
self.__defaultlength = defaultlength
self.__body = None
self.__headers = None
self.__multipart = False
self.__parts = []
self.__parse()
def __getitem__(self,name):
if self.__multipart:
for p in self.__parts:
if not p.name() is None:
return p.name()
raise KeyError()
def headers(self):
return self.__headers
def multipart(self):
return self.__multipart
def parts(self):
return self.__parts
def name(self):
pp = self.__headers.parameters("CONTENT-DISPOSITION")
if (not pp is None) and ("name" in pp.keys()):
return pp["name"]
return None
def body(self):
return self.__body
def __parse(self):
self.__headers = MIMEHeaders( fp=self.__fp )
l = int(self.__headers.value("CONTENT-LENGTH",self.__defaultlength))
if (l > self.__limit):
raise ContentSizeLimitException(size=l,limit=self.__limit)
self.__body = self.__fp.read(l)
if (not "filename" in self.__headers.parameters("CONTENT-DISPOSITION")) and (self.__headers.value("CONTENT-TYPE").upper() == "TEXT/PLAIN"):
if ("charset" in self.__headers.parameters("CONTENT-TYPE")):
charset = self.__headers.parameters("CONTENT-TYPE")["charset"]
else:
# charset = "us-ascii"
charset = "utf-8"
self.__body = str(self.__body,charset)
type = self.__headers.value("CONTENT-TYPE","/").split("/")[0].upper()
if (type == "MULTIPART"):
try:
self.__parsemultipart()
except Exception as ex:
traceback.print_exception(type(ex),ex,ex.__traceback__)
def __parsemultipart(self):
"""
p = start of preceeding boundary
c = end of preceeding boundary
e = start of following boundary
"""
self.__multipart = True
boundary = b'--' + bytes(self.__headers.get("CONTENT-TYPE").parameters()["boundary"],"iso-8859-1")
p = self.__body.find(boundary)
c = p + len(boundary) + 2
boundary = b'\r\n' + boundary
while (True):
e = self.__body.find(boundary,c)
if (e < 0):
return
else:
self.__parts.append(MIME(source=self.__body[c : e],parent=self))
p = e
c = p + len(boundary) + 2
if (self.__body[c - 2 : c] == b"--"):
return

View File

@ -0,0 +1,136 @@
import io
import string
import hserver.utils
class MIMEHeader:
def __init__(self,line):
self.__line = line
self.__parameters ={}
self.__parseline()
def name(self):
return self.__name
def rawvalue(self):
return self.__rawvalue
def value(self):
return self.__value
def parameters(self):
return self.__parameters
def __parseparameters(self,parameters):
p = 0
while (p < len(parameters)):
pe = parameters.find("=",p)
if (pe < 0):
return
name = parameters[p:pe].strip()
pe = pe + 1
if (parameters[pe] == '"'):
pe = pe + 1
pq = parameters.find('"',pe)
pr = parameters.find(';',pq)
value = parameters[ pe : pq]
else:
pq = parameters.find(";",pe)
if (pq < 0):
pq = len(parameters)
pr = pq
value = parameters[ pe : pq].strip()
self.__parameters[name] = value
if (pr < 0):
return
p = pr + 1
def __parseline(self):
i = self.__line.find(":")
if (i > 0):
self.__name = self.__line[:i].upper()
self.__rawvalue = self.__line[ i+1 : ].strip()
i = self.__rawvalue.find(";")
if (i>0):
self.__parseparameters(self.__rawvalue[ i+1 : ])
self.__value = self.__rawvalue[ :i ]
else:
self.__value = self.__rawvalue
# print("MIMEHeader: %s: %s %s" % (self.__name,self.__value,self.__parameters))
class MIMEHeaders:
def __init__(self, fp=None, src=None):
self.__items = {}
self.__parameters = {}
if not fp is None:
self.__read(fp)
def get(self,name):
name = name.upper()
if not name in self.__items.keys():
return None
return self.__items[name]
def __getitem__(self,name):
name = name.upper()
if name in self.__items.keys():
return self.__items[name].rawvalue()
raise KeyError()
def value(self,name,default=None):
h = self.get(name)
if h is None:
return default
return h.value()
def rawvalue(self,name,default=None):
h = self.get(name)
if h is None:
return default
return h.rawvalue()
def parameters(self,name):
h = self.get(name)
if h is None:
return {}
return h.parameters()
def __read(self,fp):
cont = True
lines = []
while (cont):
l = str(fp.readline(),"iso-8859-1").strip()
if (l.strip() == ""):
cont = False
else:
if (l[0] in string.whitespace ):
lines[-1] = lines[-1] + " " + l.lstrip()
else:
lines.append(l)
for line in lines:
h = MIMEHeader(line)
self.__items[ h.name() ] = h
if self.get("CONTENT-TYPE") is None:
self.__items[ "CONTENT-TYPE" ] = MIMEHeader("Content-Type: text/plain")

View File

@ -0,0 +1,3 @@
from hserver.packages.package import Package,PackageManager

View File

@ -0,0 +1,242 @@
import os
import os.path
import sys
import gc
import importlib
import types
import hserver.api
def new_module(modname, path = None, file = None):
mod = types.ModuleType( modname )
if not path is None:
mod.__path__ = path
if not file is None:
mod.__file__ = file
sys.modules[ modname ] = mod
return mod
class Package:
def __init__(self, pm, path, pname):
self.__pm = pm
self.__path = path
self.__modpath = "packages.%s" % (pname,)
self.__mod = new_module( self.__modpath )
self.__allowed_modules = [ "hserver", "hserver.api" ]
self.__modules = {}
self.__builtins = dict(__builtins__)
self.__builtins["__import__"] = self.__mod_import
self.__builtins["export"] = self.__export
self.__exports = {}
self.__load()
def module(self):
return self.__mod
def __load(self):
print("Package.__load(): Path=%s" % (self.__path,))
setattr( self.__mod, "Templates", hserver.TemplateModule("%s/templates" % (self.__path,)) )
self.__modules["%s.Templates" % (self.__modpath,)] = self.__mod.Templates
if os.path.exists("%s/package.conf" % (self.__path,)):
pcn = "%s/package.conf" % (self.__path,)
self.__config = new_module( "package.conf", file=pcn )
self.__mod_refresh( self.__config )
if (hasattr(self.__config,"modules")):
for mname in self.__config.modules:
self.__allowed_modules.append( mname )
files = os.listdir( self.__path )
for fn in files:
if (fn.endswith(".py")):
self.__mod_create( fn[:-3] )
print("Package: Modules: %s" % (self.__modules,))
def __mod_create(self, localname):
"Erstelle/Lade ein Modul aus diesem Package"
modname = "%s.%s" % (self.__modpath,localname)
if modname in self.__modules:
return self.__modules[ modname ]
modpath = localname.split(".")
localfile = modpath[-1]
del modpath[-1]
if len(modpath)==0 :
modparent = self.__mod
else:
modparent = self.__mod_create( ".".join(modpath) )
mfile = ("%s/%s/%s.py" % (self.__path,"/".join(modpath),localfile)).replace("//","/")
mpath = ("%s/%s" % (self.__path,"/".join(modpath))).replace("//","/")
print("__mod_create( %s ): Check: F=%s , P=%s" % (localname, mfile, mpath))
if not (os.path.exists(mfile)):
mfile = ("%s/%s/%s/__init__.py" % (self.__path,"/".join(modpath),localfile)).replace("//","/")
mpath = ("%s/%s/%s" % (self.__path,"/".join(modpath), localfile)).replace("//","/")
print("__mod_create( %s ): Check: F=%s , P=%s" % (localname, mfile, mpath))
if os.path.exists(mpath):
if not (os.path.exists(mfile)):
mfile = None
else:
raise Exception("Package: module '%s'not found" % (localname,))
print("__mod_create( %s ): Result: F=%s , P=%s" % (localname, mfile, mpath))
mod = new_module( modname, path=mpath, file=mfile )
self.__modules[ modname ] = mod
setattr( modparent, localfile, mod)
mod.__builtins__ = self.__builtins
self.__mod_refresh( mod )
return mod
def exports(self):
return dict(self.__exports)
def modules(self):
return dict(self.__modules)
def reload(self):
for modname in list(self.__modules.keys()):
mod = self.__modules[ modname ]
self.__mod_refresh( mod )
self.__update_classes( modname )
files = os.listdir( self.__path )
for fn in files:
if (fn.endswith(".py")):
if not fn[:-3] in self.__modules:
self.__mod_create( fn[:-3] )
def __update_classes(self, modname):
for o in gc.get_objects():
if (isinstance( o, object )):
if o.__class__.__module__ == modname:
c = getattr( self.__modules[modname], o.__class__.__name__, None )
if not c is None:
try:
o.__class__ = c
except Exception as ex:
print("__update_classes(): Exception: %s" % (ex,))
def __mod_import(self,name,globals=None,locals=None,fromlist=(),level=0):
print("import(%s,%s,%s,%s,%s)" % (name,"...","...",fromlist,level))
bname = name.split(".")[0]
if (name in self.__allowed_modules):
mod = importlib.import_module( name )
self.__modules[ name ] = mod
bmod = sys.modules[ bname ]
else:
mod = self.__mod_create( name )
if bname == name:
bmod = mod
else:
bmod = self.__modules[ "%s.%s" % (self.__modpath,bname) ]
if (not fromlist is None) and (len(fromlist) > 0):
return mod
return bmod
def __mod_refresh(self, mod):
if not hasattr(mod, "__file__"):
return
print("__mod_refresh: %s [%s]" % (mod.__name__,mod.__file__))
if not os.path.exists( mod.__file__ ):
del self.__modules[ mod.__name__ ]
return
f = open(mod.__file__, "r")
src = f.read()
f.close()
co = compile( src, mod.__file__, "exec" )
exec( co, mod.__dict__ )
def __export(self, name, o, glob=False):
self.__exports[ name ] = o
if glob:
self.__pm.export( name, o )
def __getattr__(self, name):
if name in self.__modules:
return self.__modules[ name ]
if name in self.__exports:
return self.__exports[ name ]
raise AttributeError("%s not found in %s" % (name,self))
class PackageManager:
def __init__(self, path ):
self.__path = os.path.abspath( path )
self.__packagesmod = new_module( "packages" )
self.__packages = {}
self.__exports = {}
print("PackageManager loads from %s" % (self.__path,))
self.__load()
def __load(self):
plist = os.listdir( self.__path )
for pname in plist:
ppath = "%s/%s" % (self.__path,pname)
if (os.path.isdir(ppath)):
print("PackageManager loads %s" % (pname,))
p = Package( self, ppath, pname )
self.__packages[ pname ] = p
setattr( self.__packagesmod, pname, p.module() )
def export(self, name, o):
self.__exports[ name ] = o
def imp(self, modname):
if modname in self.__exports:
return self.__exports[ modname ]
return None
def list_exports(self):
return list( self.__exports.keys() )
def exports(self):
return self.__exports
def packages(self):
return self.__packages
def __getattr__(self, name):
if name in self.__packages:
return self.__packages[ name ]
raise AttributeError("%s not found in %s" % (name,self))

View File

@ -0,0 +1,179 @@
import http.server
import hserver
from hserver.formdata import FormData
import io
class PathWalker:
def __init__(self,path_info):
self.__walk = path_info
self.__walked = []
def len(self):
return len(self.__walk)
def next(self):
return self.__walk[0]
def walk(self):
n = self.__walk[0]
del self.__walk[0]
self.__walked.append(n)
return (n,self.__walk)
def walked(self, limit=None):
if limit is None:
return "%s" % ("/".join(self.__walked),)
return "%s" % ("/".join(self.__walked[:limit]),)
def stack(self):
return self.__walk
def wstack(self,ind = None):
if ind is None:
return self.__walked
return self.__walked[ind]
class Request:
def __init__(self, MIME=None, URI = None, vars = {}, method = "", read = None):
self.reset()
self.__mime = MIME
self.__headers = self.__mime.headers()
self.__vars = vars
self.__form = None
self.__read = read
self.set("REQUEST_URI", URI)
self.set("REQUEST_METHOD", method)
self.__initialize()
def __resetContent(self):
self.__bcontent = io.BytesIO()
self.__content = io.TextIOWrapper(self.__bcontent,write_through=True)
def reset(self):
self.__resetContent()
self.__status = 200
self.__rheaders = { "Content-Type": "text/html" }
def mime(self):
return self.__mime
def getContentFile(self):
return self.__content
def getBinaryContentFile(self):
return self.__bcontent
def getContent(self):
return self.__bcontent.getvalue()
def __getattr__(self,name):
if name in self.__vars.keys():
return self.__vars[name]
raise AttributeError()
def set(self,name,value):
self.__vars[name] = value
def keys(self):
return self.__vars.keys()
def __getitem__(self,name):
if name in self.__vars.keys():
return self.__vars[ name ]
def getForm(self):
return self.__form
def getResponseHeaders(self):
return self.__rheaders
def setResponseHeader(self,name,value):
self.__rheaders[ name ] = value
def setStatus(self,status):
self.__status = status
def getStatus(self):
return self.__status
def self(self,limit = None,trail=False):
p = self.SCRIPT_NAME + "/" + self.__pathwalker.walked( limit )
if trail and (p!="/"):
p = p + "/"
return p
def pathwalker(self):
return self.__pathwalker
def __initvar(self,name):
if not name in self.__vars.keys():
self.__vars[name] = ""
def __initialize(self):
self.__initvar("SCRIPT_NAME")
self.__vars["CLIMBPATH"] = []
ind = self.REQUEST_URI.find("?")
if (ind >= 0):
self.set("QUERY_STRING", self.REQUEST_URI[ ind + 1 :])
else:
self.set("QUERY_STRING", "")
ind = len(self.REQUEST_URI)
self.set("PATH_INFO", self.REQUEST_URI[:ind])
l = int( self.__headers.value("Content-Length",0) )
print("Request: Content-Length: %s" % (l,))
self.set("CONTENT_TYPE", self.__headers.value("Content-Type", ""))
self.set("REFERER", self.__headers.value("Referer", ""))
self.__construct_path_info()
self.__form = FormData(self)
self.__pathwalker = PathWalker(self.__path_info)
def __construct_path_info(self):
path_info = self.PATH_INFO.split("/")
del path_info[0]
if (len(path_info)>0) and (path_info[0] == ""):
del path_info[0]
if (len(path_info)>0) and (path_info[-1] == ""):
del path_info[-1]
self.__path_info = path_info
def redirect(self,uri = "",append = None):
if (len(uri)>0 and uri[0]!="/"):
uri = "/" + uri
if not append is None:
uri = "%s/%s" % (uri,append)
self.__status = 307
self.setResponseHeader("Location", "%s%s" % (self.SCRIPT_NAME,uri))
raise hserver.FinishRequestException()
def __str__(self):
b = io.StringIO()
b.write("<Request(M:%s U:%s)>" % (self.REQUEST_METHOD,self.REQUEST_URI))
return b.getvalue()

View File

@ -0,0 +1,4 @@
import hserver
import os.path
templates = hserver.TemplateModule(path="%s/templates.src" % (os.path.dirname(__file__),))

View File

@ -0,0 +1,172 @@
import socketserver
import traceback
import io
import hserver
import hserver.systemplates
import threading
import socket
from hserver.mime import MIME
from hserver.packages import PackageManager
import hwo
from hwo import AquisitionProxy
class HServerRequestHandler(socketserver.StreamRequestHandler):
""
def handle(self):
self.__keepalive = False
print("handle():")
try:
self.handle_request()
while (self.__keepalive):
self.handle_request()
except:
print("handle(): Exception:")
traceback.print_exc()
# self.rfile.close()
# self.wfile.close()
self.request.close()
print("handle(): finished.")
def handle_request(self):
print("handle_request():")
l = self.rfile.readline()
rline = str(l,"iso-8859-1")
toks = rline.split()
print("handle_request: requestline: %s" % (toks,))
if (len(toks)!=3):
return
method,uri,version = toks
if (not version.startswith("HTTP/")):
print("handle_request: Version String: %s" % (version,))
return
#self.rbfile = self.rfile
#self.rfile = io.TextIOWrapper(self.rbfile, "iso-8859-1")
print("MIMEing...")
mime = MIME(self.rfile, defaultlength=0)
r = hserver.Request( URI=uri, MIME=mime, method=method, read=self.rfile )
try:
self.server.hserver.handle(r)
except hserver.FinishRequestException:
pass
except hserver.HttpException as ex:
r.reset()
r.setResponseHeader("Content-Type","text/html")
t = self.server.hserver.packagemanager().hcore.Templates.provide("%s.html" % (ex.status,))
t.run( ex, outfile=r.getContentFile() )
except Exception as ex:
traceback.print_exception(type(ex),ex,ex.__traceback__)
r.reset()
r.setResponseHeader("Content-Type","text/html")
self.templ_exception = hserver.Template(source=hserver.systemplates.tmpl_exception, disable_sandbox=True)
self.templ_exception.run( ex, globals(), outfile=r.getContentFile() )
print("handle_request(): reply")
r.setResponseHeader("Connection","close")
w = io.TextIOWrapper(self.wfile)
w.write("%s %s %s\r\n" % (version,r.getStatus(),r.getStatus()))
c = r.getContent()
r.getResponseHeaders()['Content-Length'] = str(len(c))
for k in r.getResponseHeaders().keys():
w.write("%s: %s\r\n" % (k, r.getResponseHeaders()[k]))
w.write("\r\n")
w.flush()
print("handle_request(): sending content... (%s Bytes)" % (len(c),))
self.wfile.write( c )
#self.wfile.write( b"\r\n" );
print("handle_request(): finished.")
class HServer:
def __init__(self,listen = ('localhost',8080)):
self.__listen = (listen[0],listen[1])
self.__disksync = hwo.DiscObjectStore("./DiskSync")
self.__broker = hwo.ObjectBroker( self.__disksync )
self.__packages = PackageManager("./packages")
if "ROOT" in self.__disksync:
self.__root = self.__broker.load( self.__disksync["ROOT"].decode("UTF-8") )
else:
self.__root = hserver.api.WebFolder()
persistence_id = self.__broker.save( self.__root )
self.__disksync["ROOT"] = persistence_id.encode("UTF-8")
self.__packages.hcore.module().core.init(self)
def _shutdown(self):
self.__http.shutdown()
def shutdown(self):
t = threading.Thread(target=HServer._shutdown,args=(self,))
t.start()
def packagemanager(self):
return self.__packages
def getRoot(self):
return self.__root
def aq_root(self):
return AquisitionProxy( self.__root )
def run(self):
socketserver.TCPServer.allow_reuse_address = True
self.__http = socketserver.TCPServer(self.__listen,HServerRequestHandler)
self.__http.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.__http.hserver = self
self.__http.serve_forever()
def handle(self,request):
print("Hserver.handle(%s)" % (request,))
root = self.aq_root()
if (request.pathwalker().len()==0):
root( request )
else:
root.walk( request )
self.__broker.save( self.__root )

View File

@ -0,0 +1,31 @@
import hserver
tmpl_exception = """
<html>
<head>
<title>HServer Exception</title>
<style>
body,p,div {
font-family: "DejaVu Sans","Helvetica", "Arial", "Sans";
}
</style>
</head>
<body>
<h1>HServer Exception</h1>
<p>There was an exception raised, while handling your request!</p>
<p>Eine Ausnahme trat auf, w&auml;hrend die Anfrage bearbeitet wurde!</p>
<div>
<%
tracelist = traceback.extract_tb( self.__traceback__ )
%>
<%iterate trace tracelist%>
<div>
<b><%=trace[0]%>:<%=trace[1]%></b> in <i><%=trace[2]%></i><br/>
<%=trace[3]%><br/><br/>
</div>
<%end%>
</div>
</body>
</html>"""

View File

@ -0,0 +1,73 @@
import os
import os.path
import hserver
class TemplateModule:
def __init__(self,path,parent=None):
self.__path = path
self.__parent = parent
self.__children = {}
self.__altchildren = {}
self.__load()
def __load(self):
if not os.path.exists( self.__path ):
return
l = os.listdir( self.__path )
for fn in l:
p = "%s/%s" % (self.__path, fn)
o = None
if os.path.isdir( p ):
o = TemplateModule( p, self)
elif (os.path.isfile( p )):
o = hserver.Template( template=fn, base=self.__path, provider=self)
if not o is None:
self.__children[ fn ] = o
self.__altchildren[ self.transform(fn) ] = o
def transform(self,name):
if not name[0].isalpha():
name = "_%s" % (name,)
return name.replace(".","_")
def __getattr__(self,name):
if not ((name in self.__children) or (name in self.__altchildren)):
self.__load()
if name in self.__children:
return self.__children[name]
if name in self.__altchildren:
return self.__altchildren[name]
raise AttributeError("%s not found in %s" % (name,self))
def __getitem__(self,name):
if not ((name in self.__children) or (name in self.__altchildren)):
self.__load()
if name in self.__children:
return self.__children[name]
if name in self.__altchildren:
return self.__altchildren[name]
raise IndexError("%s not found in %s" % (name,self))
def provide(self,name):
s = name.split("/")
if len(s) > 1:
return self[s[0]].provide("/".join(s[1:]))
return self[s[0]]
def __str__(self):
cl = []
for c in self.__children:
cl.append( c )
return "<TemplateModule (%s)>" % (", ".join(cl))

View File

@ -0,0 +1,369 @@
import io
import re
import sys
import os
import hserver.api
import html
import builtins
def text2html(text):
lines = text.splitlines()
html = ""
for l in lines:
html = "{0}<p>{1}</p>".format(html,l)
return html
class SandboxPrinter:
def __init__(self,stream):
self.stream = stream
def __call__(self,te = ""):
self.stream.write(str(te))
class SandboxInclude:
def __init__(self,template):
self.__template = template
def __call__(self,template,selfref = None):
if (selfref is None):
self.__template.include( template )
else:
self.__template.include( [template, selfref] )
class TemplateSegment:
def __init__(self,template,parent = None):
self.__template = template
self.__parent = parent
def setParent(self,parent):
self.__parent = parent
def getParent(self):
return self.__parent
def getTemplate(self):
return self.__template
def run(self,env,priv = {}):
"""Run this Segement of the Template"""
pass
def __repr__(self):
return "<TemplateSegment>"
class TemplateGroupSegment(TemplateSegment):
def __init__(self,template,parent = None):
TemplateSegment.__init__(self,template,parent)
self.__children = []
def appendChild(self,segment):
self.__children.append(segment)
def getChildren(self):
return self.__children
def run(self,env,priv={}):
for child in self.__children:
child.run(env,priv)
def __repr__(self):
return "<TemplateGroupSegment( %s )>" % (str(self.getChildren()),)
class TemplateTextSegment(TemplateSegment):
def __init__(self,template,parent = None,text = ""):
TemplateSegment.__init__(self,template,parent)
self.__text = text
def run(self,env,priv={}):
self.getTemplate().getContentFile().write(self.__text)
def __repr__(self):
return "<TemplateTextSegment>"
class TemplateCodeSegment(TemplateSegment):
def __init__(self,template,parent = None,code = ""):
TemplateSegment.__init__(self,template,parent)
self.__code = code
def run(self,env,priv={}):
exec( self.__code, env )
def __repr__(self):
return "<TemplateCodeSegment(%s)>" %(self.__code,)
class TemplateValueSegment(TemplateSegment):
def __init__(self,template,parent = None,code = ""):
TemplateSegment.__init__(self,template,parent)
self.__code = code
def run(self,env,priv={}):
code = self.__code
v = eval( code, env )
self.getTemplate().getContentFile().write(str(v))
class TemplateIterateSegment(TemplateGroupSegment):
def __init__(self,template,parent = None,code = ""):
TemplateGroupSegment.__init__(self,template,parent)
(self.__iterator, self.__iteration) = code.split(" ",1)
def run(self,env,priv={}):
iter = eval( self.__iteration, env )
for v in iter:
env[self.__iterator] = v
TemplateGroupSegment.run(self,env,priv)
def __repr__(self):
return "<TemplateIterateSegment( %s=%s : %s )>" % (self.__iterator,self.__iteration,self.getChildren(),)
class TemplateIfSegment(TemplateGroupSegment):
def __init__(self,template,parent = None,code = ""):
TemplateGroupSegment.__init__(self,template,parent)
self.__code = code
def run(self,env,priv={}):
v = eval( self.__code, env )
if (v):
TemplateGroupSegment.run(self,env,priv)
def __repr__(self):
return "<TemplateIfSegment( %s )>" % (str(self.__children),)
class TemplateIncludeSegment(TemplateSegment):
def __init__(self,template,parent = None,code = ""):
TemplateSegment.__init__(self,template,parent)
self.__code = code
def run(self,env,priv={}):
v = eval( self.__code, env )
self.getTemplate().include(v,priv={})
def __repr__(self):
return "<TemplateIncludeSegment(%s)>" % (str(self.__code),)
class TemplateContentSegment(TemplateSegment):
def __init__(self,template,parent = None):
TemplateSegment.__init__(self,template,parent)
def run(self,env,priv={}):
priv["framed"].framed(env,priv)
def __repr__(self):
return "<TemplateContentSegment(%s)>" % (str(self.__code),)
class Template(hserver.api.WebCallable):
def __init__(self,template=None,base = ".",source = None,disable_sandbox=False,frame=None,provider=None):
self.template = template
self.base = base
self.__content = None
self.__frame = frame
self.__source = source
self.__root = None
self.__current = self.__root
self.__disable_sandbox = disable_sandbox
self.__timestamp = None
self.__provider = provider
def getContent(self):
return self.__content.getvalue()
def getContentFile(self):
return self.__content
def setFrame(self,frame):
self.__frame = frame
def provider(self):
return self.__provider
def __appendSegment(self,segment):
self.__current.appendChild(segment)
def __appendGroup(self,segment):
self.__appendSegment(segment)
self.__current = segment
def __leaveGroup(self):
if (self.__current != self.__root) and (self.__current.getParent() is not None):
self.__current = self.__current.getParent()
def indexWS(self,te):
p = 0
while (p < len(te)):
if (ord(te[p]) <= 0x20):
return p
p = p + 1
return p
def __splittag(self,tag):
"Split <tag> to a list of [ <action>, <expr> ]"
if (ord(tag[0]) <= 0x20):
return ["",tag[1:]]
elif (tag[0]=="="):
return ["=",tag[1:]]
else:
i = self.indexWS(tag)
if (i == len(tag)):
return [ tag , "" ]
else:
return [ tag[:i], tag[ i+1: ] ]
def __parsetag(self,tag):
(action,expr) = self.__splittag(tag)
if (action == ""):
self.__appendSegment( TemplateCodeSegment(self,self.__current,expr) )
elif (action == "="):
self.__appendSegment( TemplateValueSegment(self,self.__current,expr) )
elif (action == "include"):
self.__appendSegment( TemplateIncludeSegment(self,self.__current,expr) )
elif (action == "iterate"):
s = TemplateIterateSegment(self,self.__current,expr)
self.__appendGroup( s )
elif (action == "if"):
s = TemplateIfSegment(self,self.__current,expr)
self.__appendGroup( s )
elif (action == "end"):
self.__leaveGroup()
elif (action == "content"):
self.__appendSegment( TemplateContentSegment( self, self.__current ))
elif (action == "frame"):
self.__frame = self.__provider.provide( expr )
else:
pass
def __parse(self,source):
if self.__root is None:
self.__root = TemplateGroupSegment(self)
self.__current = self.__root
pos = 0;
while (len(source) > pos):
iopen = None
iclose = None
try:
iopen = source.index( "<%", pos )
iclose = source.index( "%>", iopen )
except ValueError as ve:
self.debugException(ve)
if (iopen is None):
iopen = len(source)
iclose = len(source)
else:
raise ve
if (iopen > pos):
self.__appendSegment( TemplateTextSegment(self, self.__current, source[pos : iopen]) )
if (iopen < len(source)):
self.__parsetag( source[ iopen + 2 : iclose ] )
pos = iclose + 2
def debugException(self,ex):
pass
def __load_source(self):
if not self.template is None:
tfilename = "%s/%s" % (self.base,self.template)
st = os.stat( tfilename )
print("Template.__load_source(): Check %s > %s" % (st.st_mtime, self.__timestamp))
if (self.__timestamp is None) or (st.st_mtime > self.__timestamp):
self.__timestamp = st.st_mtime
tfile = open(tfilename,"r")
self.__source = tfile.read()
tfile.close()
self.__root = None
__allowed_builtins = ["getattr","setattr","hasattr","range","abs","dict","hex","int","float","bytes","bool","chr","ord","pow","str","map","round","len"]
def run(self,o = None,env = {},outfile=None,framed=None):
save_content = self.__content
if (not outfile is None):
self.__content = outfile
else:
self.__content = io.StringIO()
priv = {}
priv["framed"] = framed
self.__load_source()
self.__parse(self.__source)
if o is not None:
env['self'] = o
if not self.__disable_sandbox:
env['__builtins__'] = {
getattr: getattr
}
env['print'] = SandboxPrinter(self.__content)
env['include'] = SandboxInclude(self)
env['escape'] = html.escape
env['text2html'] = text2html
for an in self.__allowed_builtins:
if hasattr(globals(),an):
env[an] = getattr(globals(),an)
if hasattr(builtins,an):
env[an] = getattr(builtins,an)
print("Template.run(): my frame is: %s" % (self.__frame,))
self.env = env
if self.__frame is not None:
self.frame(env)
else:
self.__root.run(env,priv)
if (isinstance( self.__content, io.StringIO) ):
c = self.__content.getvalue()
else:
c = None
self.__content = save_content
return c
def frame(self,env):
print("Template: Framing with %s" % (self.__frame,))
self.__frame.run(env=env,outfile=self.__content,framed=self)
def framed(self,env,priv):
print("Frame %s called %s" % (self.__frame,self))
self.__root.run(env,priv)
def include(self,expr,priv):
print("<!--INCLUDE: %s" % (expr,))
child = self.__provider.provide( expr[0] )
cenv = dict( self.env )
self.__content.write( child.run( expr[1], cenv) )
def escape(self,t):
return t.replace("\\","\\\\").replace("\"","\\\"")
def __call__(self,request, o = None, output=None):
if output is None:
output = request.getContentFile()
self.run( o=o, env = { "request": request },outfile=output)

View File

@ -0,0 +1,3 @@
<form action="">
<div>so_updates</div>
</form>

View File

@ -0,0 +1,21 @@
class StreamTokenizer:
WHITESPACE = [' ','\n','\r','\t','\d']
def __init__(self,stream):
self.__stream = stream
def read(self,len = 1):
self.__stream.read(len)
def readToSeparator(self,separator = WHITESPACE):
token = bytearray()
c = self.__stream.read(1)
while (not c is None) and (len(c) != 0) and (not c in separator):
token.append(c)
c = self.__stream.read(1)
return token

View File

@ -0,0 +1,31 @@
import sys
import datetime
LLERROR = 0
LLINFO = 1
LLDETAIL = 2
LLDEBUGCALL = 5
LLDEBUG = 10
class Logger:
def __init__(self,target = sys.stderr,maxlevel = 1):
self.__target = target
def log(self,msg,level = 0,o = None):
dt = datetime.datetime.today()
self.__target.write("%s: [%s] %s\n" % (dt,level,msg))
self.__target.flush()
default_logging = Logger()
def log(msg,level = 0):
default_logging.log(msg,level)

View File

@ -0,0 +1,62 @@
def getter(attrib):
return lambda self, *args, **kwargs: getattr(object.__getattribute__( self, "_o"), attrib)(*args, **kwargs)
class InterceptedProxy:
_special_names=[
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__',
'__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
'__idiv__', '__idivmod__', '__ifloordiv__', '__ilshift__', '__imod__',
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__',
'__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__',
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
'__neg__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__',
'__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rfloorfiv__', '__rlshift__', '__rmod__',
'__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
'__rtruediv__', '__rxor__', '__setitem__', '__setslice__', '__sub__',
'__truediv__', '__xor__', 'next',
]
def _get_proxy_cls(cls,obj):
ocls = obj.__class__
ns = {}
for n in InterceptedProxy._special_names:
if (hasattr(ocls, n)):
ns[n] = getter(n)
return type( "InterceptedProxy(%s)" % (ocls.__name__,), (cls,), ns )
def __new__(cls,obj,listener):
pcls = InterceptedProxy._get_proxy_cls(cls,obj)
inst = object.__new__( pcls )
object.__setattr__( inst, "_o", obj)
object.__setattr__( inst, "_l", listener)
return inst
def __getattribute__(self,name):
v = getattr( object.__getattribute__( self, "_o"), name )
return v
def __setattr__(self,name,value):
o = object.__getattribute__( self, "_o")
setattr( o, name, value )
object.__getattribute__( self, "_l").notify("__setattr__",o,name,value)
def __delattr__(self,name):
delattr( object.__getattribute__( self, "_o"), name )
def __nonzero__(self):
return bool(object.__getattribute__(self, "_o"))
def __str__(self):
return str(object.__getattribute__(self, "_o"))
def __repr__(self):
return repr(object.__getattribute__(self, "_o"))
def __dir__(self):
return dir( object.__getattribute__(self, "_o") )

View File

@ -0,0 +1,10 @@
import hwo.Logging
from hwo.persistence import Persistence,NoPersistence
from hwo.objectstore import DiscObjectStore
from hwo.objectbroker import ObjectBroker
from hwo.aquisition import Aquisition,AquisitionProxy
import hwo.Proxy

View File

@ -0,0 +1,161 @@
import collections
__doc__ = """Einfache Objekt Aquisition für Python."""
class Aquisition:
"""Markiert ein Objekt als Ziel von Aquisition durch AquisitionProxy"""
pass
def caller(inst,a):
return lambda *args,**kwargs: a.__func__(inst,*args,**kwargs)
def call(self,method,*args,**kwargs):
m = getattr(object.__getattribute__( self, "_o"), method)
if hasattr(m,"__func__"):
return m.__func__(self,*args,**kwargs)
else:
return m(*args,**kwargs)
def getter(attrib):
return lambda self, *args, **kwargs: call(self,attrib,*args, **kwargs)
if hasattr(m, "__func__"):
return lambda self, *args, **kwargs: m.__func__(self, *args, **kwargs)
else:
return lambda self, *args, **kwargs: m(*args, **kwargs)
class AquisitionProxy:
"""Basisobjekt für Aquisition."""
_special_names=[
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__',
'__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
'__idiv__', '__idivmod__', '__ifloordiv__', '__ilshift__', '__imod__',
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__',
'__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__',
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
'__neg__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__',
'__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rfloorfiv__', '__rlshift__', '__rmod__',
'__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
'__rtruediv__', '__rxor__', '__setitem__', '__setslice__', '__sub__',
'__truediv__', '__xor__', 'next',
]
def _get_proxy_cls(cls,obj):
ocls = obj.__class__
ns = {}
_methods = {}
for n in AquisitionProxy._special_names:
if (hasattr(ocls, n)):
ns[n] = getter(n)
return type( "AProxy(%s)" % (ocls.__name__,), (cls,), ns )
def __new__(cls,obj,p = None,aq_name=None,aq_root=None):
pcls = AquisitionProxy._get_proxy_cls(cls,obj)
inst = object.__new__( pcls )
_methods = {}
for n in dir(obj):
# print("AQ_ATTR: %s" % (n,))
a = getattr(obj,n)
if isinstance( a, collections.Callable ) and hasattr( a, "__func__" ): # and not hasattr( AquisitionProxy, n ):
# print("AQ_METHOD: %s = %s" % (n,a))
_methods[n] = caller(inst,a)
object.__setattr__( inst, "_methods", _methods )
object.__setattr__( inst, "_o", obj)
object.__setattr__( inst, "_p", p)
object.__setattr__( inst, "_aq_name", aq_name)
if (aq_root is None):
aq_root = inst
object.__setattr__( inst, "_aq_root", aq_root)
return inst
def __getattribute__(self,name):
v = None
# print("AQN: %s" % (name,))
if name.startswith("_aq_"):
if (name == "_aq_parent"):
return object.__getattribute__( self, "_p")
# return AquisitionProxy( p, self, aq_name=p._aq_name, aq_root=self._aq_root )
if (name == "_aq_name"):
n = object.__getattribute__( self, "_aq_name")
if n is None:
return "/"
return n
if (name == "_aq_object"):
return object.__getattribute__( self, "_o")
return object.__getattribute__( self, name )
_methods = object.__getattribute__(self,"_methods")
if name in _methods:
return _methods[name]
try:
v = getattr( object.__getattribute__( self, "_o"), name )
except AttributeError as ae:
try:
print("AQN_PARENT: %s %s" % (object.__getattribute__( self, "_p"), name))
v = getattr( object.__getattribute__( self, "_p"), name)
if (isinstance(v, AquisitionProxy)):
v = object.__getattribute__( v, "_o" )
except AttributeError as ae2:
raise ae2
if isinstance( v, Aquisition ):
v = AquisitionProxy( v, self, aq_name=name, aq_root=self._aq_root )
return v
def __setattr__(self,name,value):
setattr( object.__getattribute__( self, "_o"), name, value )
def __delattr__(self,name):
delattr( object.__getattribute__( self, "_o"), name )
def __nonzero__(self):
return bool(object.__getattribute__(self, "_o"))
def __str__(self):
return str(object.__getattribute__(self, "_o"))
def __repr__(self):
return repr(object.__getattribute__(self, "_o"))
def __dir__(self):
return dir( object.__getattribute__(self, "_o") )
def dir(self,cls):
realcls = object.__getattribute__( self, "__class__" )
ls = []
for an in dir(self):
if issubclass( getattr( self, an ).__class__, cls):
ls.append(an)
if issubclass(realcls,AquisitionProxy):
p = object.__getattribute__( self, "_p")
if not p is None:
for an in AquisitionProxy.dir(p, cls):
if not an in ls:
ls.append( an )
return ls
def _aq_path(self):
if (self._aq_name is None) or (self._aq_parent is None):
return ""
return "%s/%s" % (self._aq_parent._aq_path(),self._aq_name)

View File

@ -0,0 +1,115 @@
import weakref
import hwo
import collections
import pickle
from hwo.Logging import log,LLDEBUGCALL,LLDEBUG,LLINFO,LLERROR
def dump_state(state):
print("Persistent ID: %s" % (state["pid"],))
print("Type: %s.%s" % (state["module"],state["class"]))
print("Non-Persistent:")
for n in state["fields"].keys():
print("K: %s = %s" % (n,state["fields"][n]))
print("Persistent:")
for n in state["pfields"].keys():
print("K: %s = %s" % (n,state["pfields"][n]))
print("")
def obj_getstate(o):
if not isinstance(o, hwo.Persistence):
raise TypeError("obj_getstate() needs Persistence object")
state = {}
state["pid"] = hwo.Persistence._persistence_id( o )
state["module"] = o.__class__.__module__
state["class"] = o.__class__.__name__
state["fields"] = {}
state["pfields"] = {}
state["pvalues"] = {}
d = object.__getattribute__(o, "__dict__")
for n in d.keys():
a = getattr( o, n )
if (not isinstance( a, collections.Callable)) or isinstance( a, object ):
if (isinstance( a, hwo.NoPersistence)):
state["fields"][n] = None
elif (isinstance( a, hwo.Persistence)):
state["pvalues"][n] = a
state["pfields"][n] = hwo.Persistence._persistence_id( a )
else:
state["fields"][n] = a
return state
class ObjectBroker:
"""ObjectBroker """
def __init__(self, store={}):
self.__store = store
self.__cache = weakref.WeakValueDictionary()
self.__unsaved = {}
log("ObjectBroker instantiated", LLDEBUGCALL)
def save(self,o,recursed=False):
if (o in self.__unsaved):
return
state = obj_getstate(o)
# dump_state( state )
self.__cache[ state["pid"] ] = o
self.__unsaved[o] = state
for pn in state["pvalues"]:
self.save( state["pvalues"][pn], recursed=True )
# dump_state(state)
if not recursed:
for n in list( self.__unsaved.keys() ):
s = self.__unsaved[n]
s["pvalues"] = None
self.__store[ s["pid"] ] = pickle.dumps(s)
del self.__unsaved[n]
return state["pid"]
def load(self,persistence_id):
if (persistence_id in self.__cache):
o = self.__cache[persistence_id]
if not o is None:
return o
state = pickle.loads(self.__store[ persistence_id ])
# dump_state(state)
m = __import__(state["module"],fromlist=[state["class"]])
cls = getattr(m, state["class"] )
o = cls.__new__(cls)
self.__cache[ persistence_id ] = o
for n in state["fields"]:
setattr( o, n, state["fields"][n] )
for n in state["pfields"]:
print("SS: %s = %s" % (n,state["pfields"][n]))
setattr( o, n, self.load( state["pfields"][n] ))
return o
def remove(self,o=None,persistence_id=None):
pass

View File

@ -0,0 +1,25 @@
import os
class DiscObjectStore:
"""DiscObjectStore ist ein Mapping Objekt, welches ein Verzeichnis im Dateisystem als Speicher nutzt und somit persistent zwischen Programmstarts arbeitet"""
def __init__(self,path = "./objects"):
self._path = path
self.check()
def check(self):
if not os.path.exists( self._path ):
os.makedirs( self._path )
def __contains__(self, name):
return os.path.exists( "%s/%s" % (self._path, name))
def __getitem__(self, name):
f = open("%s/%s" % (self._path, name), "rb")
v = f.read()
f.close()
return v
def __setitem__(self, name, value):
f = open("%s/%s" % (self._path, name), "wb")
v = f.write(value)
f.close()

View File

@ -0,0 +1,11 @@
import uuid
class Persistence:
def _persistence_id(self):
if not hasattr(self, "__persistence_id__"):
setattr( self, "__persistence_id__", uuid.uuid4().hex )
return getattr( self, "__persistence_id__" )
class NoPersistence:
pass

View File

@ -0,0 +1,91 @@
from hserver.api import WebObject,Persistence,WebFolder,WebCallable
import hserver
import Templates
import uuid
import os
import io
import time
class Artikel(WebObject,Persistence):
_public_names = {
"bezeichnung": "",
"bezeichnung2": "",
"preis": 0.00,
"beschreibung": "",
"seriennummer": "",
"bemerkungen": "",
"verkauft": False,
"bezahlt": False,
"erloes": 0.00
}
_public_types = {
"preis": float,
"verkauft": bool,
"bezahlt": bool,
"erloes": float
}
#tag = Templates.artikel_tag_html
def __init__(self,vid):
WebObject.__init__(self)
self.id = uuid.uuid4().hex
self.vid = vid
self.update(None)
def __call__(self,request,o=None):
Templates.artikel_display_html(request,self)
def verkaeufer(self):
vl = self._aq_parent._aq_parent.verkaeufer
v = getattr( vl, self.vid, None)
return v
def _tag(self,request,o=None):
_io = io.StringIO()
Templates.artikel_tag_html(request,o,output=_io)
if "printer" in request.getForm():
prn = request.getForm()["printer"].value()
else:
prn = None
pcmd = None
if prn in self.printers:
pcmd = self.printers[prn]
print("TAG Print: {0} / {1}".format(prn,pcmd))
tmphtml = "/tmp/print.{0}.html".format(time.time())
tmppdf = tmphtml + ".pdf"
tmp = open(tmphtml,"w")
tmp.write(_io.getvalue())
tmp.close()
os.system("wkhtmltopdf -T 0 -B 0 -L 0 -R 0 --dpi 400 --print-media-type --page-width 96mm --page-height 48mm {0} {1}".format(tmphtml,tmppdf))
#os.system("lpr -P SII_SLP440 {0}".format(tmppdf))
if pcmd is None:
request.reset()
tp = open(tmppdf,"rb")
pdf = tp.read()
tp.close()
request.getBinaryContentFile().write(pdf)
request.setResponseHeader("content-type","application/pdf")
else:
os.system(pcmd.format(tmppdf))
request.redirect(request.self(-1))
tag = WebCallable(method=_tag)
def __str__(self):
return self.bezeichnung

View File

@ -0,0 +1,131 @@
from hserver.api import WebObject,Persistence,WebFolder,WebCallable
import hserver
import Templates
import uuid
from verkaeufer import Verkaeufer
from artikel import Artikel
from verkauf import Verkauf
import qrcode
import qrcode.image.svg
import io
class KleinerBasar(WebObject,Persistence):
layout_css = Templates.layout_css
index = Templates.index_html
list_verk = Templates.list_verk_html
list_artikel = Templates.list_artikel_html
print_tags = Templates.print_tags_html
print_css = Templates.print_css
printers = {
"SLP440": "lpr -P SII_SLP440 {0}",
"SLP200": "lpr -P SII_SLP200 {0}",
"PDF": None,
"PDF (Server)": "open {0}"
}
def __init__(self):
self.setDefault("index")
self.artikel = WebFolder()
self.verkaeufer = WebFolder()
self.verkauf = WebFolder()
self.tags = WebFolder()
def walk(self,request):
if not hasattr(self,"verkauf"):
self.verkauf = WebFolder()
request.app = request.self()
WebObject.walk(self,request)
def _tags(self):
l = []
for n in range(128):
l.append(uuid.uuid4())
return l
def _addverk(self,request,o=None):
v = Verkaeufer()
v.update(request)
setattr( self.verkaeufer, v.id, v )
request.redirect( request.app + "/verkaeufer/" + v.id )
addverk = WebCallable(method=_addverk)
def _addartikel(self,request,o=None):
a = Artikel(request.getForm()["vid"].value())
a.update(request)
setattr( self.artikel, a.id, a )
request.redirect( request.app + "/artikel/" + a.id )
addartikel = WebCallable(method=_addartikel)
def _search(self,request,o=None):
q = request.getForm()["q"].value()
if hasattr(self.verkaeufer, q):
request.redirect(request.app + "/verkaeufer/" + q)
if hasattr(self.artikel, q):
request.redirect(request.app + "/artikel/" + q)
if hasattr(self.verkauf, q):
request.redirect(request.app + "/verkauf/" + q)
r = []
for n in self.artikel.children():
a = getattr(self.artikel, n)
for n in dir(a):
if (str(getattr(a,n)).lower().find(q.lower())>=0):
r.append( {
"link": request.app + "/artikel/" + a.id,
"text": "Artikel: %s" % (a.bezeichnung,)
})
break
for n in self.verkaeufer.children():
v = getattr(self.verkaeufer, n)
for n in dir(v):
if (str(getattr(v,n)).lower().find(q.lower())>=0):
r.append( {
"link": request.app + "/verkaeufer/" + v.id,
"text": "Verk&auml;ufer: %s, %s" % (v.lastname,v.firstname)
})
break
request.results = r
Templates.search_html(request,self)
search = WebCallable(method=_search)
def svgqrcode(self,c):
qr = qrcode.make(c, image_factory=qrcode.image.svg.SvgPathImage, box_size=8)
b = io.BytesIO()
qr.save(b)
return str(b.getvalue(),"utf-8").split("\n")[1]
def _qrcode(self,request,o=None):
img = qrcode.make(request.getForm()["c"].value())
img.save( request.getBinaryContentFile(), format="png" )
request.setResponseHeader("Content-Type","image/png")
qrcode = WebCallable(method=_qrcode)
def _verkaufen(self,request,o=None):
v = Verkauf()
setattr(self.verkauf, v._persistence_id(), v)
request.redirect(request.self(-1)+"/verkauf/"+v._persistence_id())
verkaufen = WebCallable(method=_verkaufen)
hserver.api.KleinerBasar = KleinerBasar

View File

@ -0,0 +1 @@
modules=["uuid","datetime","qrcode","qrcode.image.svg","io","os","time"]

View File

@ -0,0 +1,111 @@
<%frame layout_html%>
<%
self.update(request)
%>
<script type="text/javascript">
storage = window.localStorage;
function $(name){
return document.getElementById(name);
}
function setDefaultLabelPrinter(){
var selp = $("printers")
var prn = selp.options[selp.selectedIndex].value
storage.setItem("def_label_printer",prn);
}
function loadDefaultLabelPrinter(){
var selp = $("printers")
var defprn = storage.getItem("def_label_printer");
var n;
for (n=0;n<selp.options.length;n++){
if (selp.options[n].value == defprn){
selp.selectedIndex = n;
}
}
}
</script>
<h1>Artikel Details</h1>
<br/>
Artikel# <%=self.id%><br/>
Verk&auml;ufer: <a href="<%=request.app%>/verkaeufer/<%=self.vid%>"><%=self.verkaeufer().lastname%>, <%=self.verkaeufer().firstname%></a>
<br/>
<br/>
<div>
<form action="<%=request.self()%>/tag" method="GET" __enctype="multipart/form-data" onsubmit="setDefaultLabelPrinter();">
<select size="1" name="printer" id="printers">
<%iterate printer self.printers%><option value="<%=printer%>"><%=printer%></option>
<%end%></select>
<input type="submit" value="LABEL DRUCKEN"/>
</form>
</div>
<br/>
<form action="<%=request.self()%>" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>Bezeichnung (kurz):</td>
<td><input type="text" name="bezeichnung" value="<%=self.bezeichnung%>"/></td>
<td>Preis</td>
<td><input type="number" name="preis" min="0" max="999999" step="0.01" value="<%=self.preis%>"/></td>
</tr>
<tr>
<td>Bezeichnung (lang):</td>
<td colspan="3"><input type="text" name="bezeichnung2" value="<%=self.bezeichnung2%>"/></td>
</tr>
<tr>
<td>Seriennummer:</td>
<td colspan="3">
<input type="text" name="seriennummer" value="<%=self.seriennummer%>"/>
</td>
</tr>
<tr>
<td>Verkauft:</td>
<td colspan="3">
<select name="verkauft">
<option value=""<%if not self.verkauft%> selected<%end%>>Nein</option>
<option value="True"<%if self.verkauft%> selected<%end%>>Ja</option>
</select>
für
<input type="number" name="erloes" min="0" max="999999" step="0.01" value="<%=self.erloes%>"/>
<%if hasattr(self,"quittung")%>
<a href="<%=request.app%>/verkauf/<%=self.quittung%>" target="_blank">Quittung</a>
<%end%>
</td>
<!-- <td>Bezahlt:</td>
<td>
<select name="bezahlt">
<option value=""<%if not self.bezahlt%> selected<%end%>>Nein</option>
<option value="True"<%if self.bezahlt%> selected<%end%>>Ja</option>
</select>
</td>-->
</tr>
<tr>
<td colspan="4">
Beschreibung:<br/>
<textarea name="beschreibung"><%=self.beschreibung%></textarea>
</td>
</tr>
<tr>
<td colspan="4">
Bemerkungen:<br/>
<textarea name="bemerkungen"><%=self.bemerkungen%></textarea>
</td>
</tr>
<tr>
<td><input type="submit" value="aktualisieren"/></td>
</tr>
</table>
</form>
<script type="text/javascript">
loadDefaultLabelPrinter();
</script>

View File

@ -0,0 +1,38 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<!--link rel="stylesheet" href="<%=request.app%>/print_css"/-->
<style>
<%include ("print.css",None)%>
</style>
</head>
<body class="SRL">
<div id="page">
<div>
<div id="scancode">
<%=self.svgqrcode(self.id)%>
</div>
<div class="title">Fahrradbörse 2018</div>
<section id="content">
<div class="title sub">
<div><%=self.bezeichnung%></div><br/>
<%=self.bezeichnung2%>
</div>
<div id="description"><%=text2html(self.beschreibung)%></div>
<div id="price" class="title ul">
<div><%="%0.2f &euro;" % (self.preis,)%></div>
</div>
<div id="tagid" class="small">
<%=self.id%>
</div>
</section>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
.right {
position: absolute;
right: 0px;
text-align: right;
}
.hr {
border-bottom: 1px dotted gray;
}
.indent {
margin-left: 1cm;
}
.box {
display: block;
}

View File

@ -0,0 +1 @@
<%frame layout_html%>

View File

@ -0,0 +1,181 @@
<%
request.setResponseHeader("Content-Type","text/css")
%>
<%include ("common_css",self)%>
body,div,section {
font-family: DejaVu Sans, Sans;
font-size: 14px;
}
table {
border-collapse: collapse;
border-spacing: 0px;
}
td {
padding: 4px;
padding-right: 10px;
height: auto;
overflow: scroll;
vertical-align: top;
border-bottom: 1px dotted gray;
}
td textarea {
width: 95%;
height: 80px;
}
input[type="number"] {
text-align: right;
}
#header {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
height: 40px;
border-bottom: 2px solid black;
background-color: #60FF80;
}
#header > div {
position: absolute;
top: 5px;
right: 15px;
font-size: 24px;
font-style: italic;
}
#search {
border-radius: 8px;
border: 1px solid black;
margin-top: 5px;
padding: 8px;
width: 90%;
font-size: 12px;
font-style: italic;
background-color: #60FF80;
}
#search input[type=text] {
border-radius: 5px;
padding: 2px;
width: 160px;
margin-top: 4px;
margin-bottom: 4px;
}
#menu {
float: left;
position: absolute;
top: 50px;
left: 0px;
padding-left: 20px;
padding-right: 10px;
border-right: 2px solid #60FF80;
min-height: 400px;
min-width: 180px;
}
#menu > a {
display: block;
padding: 10px;
margin: 5px;
border: 2px solid #60FF80;
border-radius: 8px;
font-size: 24px;
text-align: center;
}
#menu > a:link {
font-style: normal;
text-decoration: none;
color: blue;
background-color: #A0FFD0;
}
#menu > a:visited {
font-style: normal;
text-decoration: none;
color: blue;
}
#menu > a:hover {
background-color: #40DF60;
font-style: italic;
}
#page {
display: block;
margin-left: 240px;
margin-top: 50px;
}
thead > tr {
padding-bottom: 2px;
border-bottom: 1px solid black;
font-style: italic;
font-weight: bold;
}
thead > tr > td {
padding-right: 40px;
}
a {
font-style: italic;
}
td > input {
width: 95%;
min-width: 60px;
}
.big {
font-size: 150%;
}
.wide {
width: 240px;
}
.space {
padding-top: 8px;
padding-bottom: 8px;
}
.pre {
white-space: pre;
}
.indent {
margin-left: 1cm;
}
.stroke {
text-decoration: line-through;
}
.gray {
color: gray;
}
@media print {
#menu, #search {
visibility: hidden;
display: none;
}
#page {
margin-left: 0px;
}
}

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset="UTF-8"/>
<html>
<head>
<title>Der kleine Basar</title>
<link rel="stylesheet" href="layout_css"/>
</head>
<body onLoad="document.getElementById('query').focus();">
<div id="body">
<section id="header">
<div>Der kleine Basar</div>
</section>
<section id="menu">
<form action="<%=request.app%>/search">
<div id="search">
Direktsuche:<br/>
<input type="text" id="query" name="q" value=""/><br/>
<input type="submit" value="suchen..."/>
</div>
</form>
<a href="<%=request.app%>/list_verk">Verk&auml;ufer</a>
<a href="<%=request.app%>/list_artikel">Artikel</a>
<a href="<%=request.app%>/verkaufen" target="_blank">Verkauf</a>
</section>
<section id="page"><%content%></section>
<section id="footer">
</section>
</div>
</body>
</html>

View File

@ -0,0 +1,65 @@
<%frame layout_html%>
<h1>Artikelliste</h1>
<br/>
<table>
<thead>
<tr>
<td>Artikel#</td>
<td>Bezeichnung</td>
<td>Verkauft</td>
<td>Verk&auml;ufer</td>
</tr>
</thead>
<tbody>
<%
n_artikel = 0
s_verkauft = 0.0
n_verkauft = 0
s_preis = 0.0
s_preisverkauf = 0.0
def akey(p):
return getattr(self.artikel, p).bezeichnung
al = self.artikel.children()
al.sort(key=akey)
for n in range(al.__len__()):
al[n] = getattr(self.artikel, al[n])
s_preis = s_preis + al[n].preis
%>
<%iterate a al%>
<tr>
<td><a href="<%=request.app%>/artikel/<%=a.id%>"><%=a.id%></a></td>
<td><%=a.bezeichnung%></td>
<td>
<%if not a.verkauft%>NEIN<%end%>
<%if a.verkauft%>Verkauft (<%="%0.2f" % (a.erloes,)%>&euro;)<%
s_verkauft = s_verkauft + a.erloes
n_verkauft = n_verkauft + 1
s_preisverkauf = s_preisverkauf + a.preis
%><%end%>
</td>
<td>
<a href="<%=request.app%>/verkaeufer/<%=a.vid%>">
<%=a.verkaeufer().lastname%>, <%=a.verkaeufer().firstname%>
</a>
</td>
</tr>
<%end%>
</tbody>
</table>
<br/>
<br/>
<div>
Statistik: <%=len(al)%> Artikel,
davon <%=n_verkauft%> verkauft für insgesamt <%="%0.2f" % (s_verkauft,)%>&euro;
(Provisionen: <%="%0.2f" % (s_verkauft*0.1,)%>&euro;)
<br/>
Bepreiste Verkaufssumme wäre gewesen: <%="%0.2f" % (s_preisverkauf,)%>&euro;, dies w&auml;ren <%="%0.2f" % (s_preisverkauf*0.1,)%>&euro; Provision gewesen.<br/>
Bepreiste Gesamtsumme war: <%="%0.2f" % (s_preis,)%>&euro;, dies w&auml;ren <%="%0.2f" % (s_preis*0.1,)%>&euro; Provision gewesen.<br/>
</div>

View File

@ -0,0 +1,71 @@
<%frame layout_html%>
<h1>Verk&auml;uferliste</h1>
<br/>
<a href="<%=request.self()%>?away=yes">[ +AUSGECHECKTE ]</a><br/>
<br/>
<table>
<thead>
<tr>
<td>Verk.#</td>
<td>Nachname</td>
<td>Vornamen</td>
<td>Angebotene Artikel</td>
</tr>
</thead>
<tbody>
<form action="<%=request.app%>/addverk">
<tr style="background-color: #E0E0E0;">
<td>neu:</td>
<td><input type="text" name="lastname" value=""/></td>
<td><input type="text" name="firstname" value=""/></td>
<td></td>
<td><input type="submit" value="erstellen..."/></td>
</tr>
</form>
<%
def vkey(p):
return getattr(self.verkaeufer, p).lastname
vl = self.verkaeufer.children()
vl.sort(key=vkey)
for n in range(vl.__len__()):
vl[n] = getattr(self.verkaeufer, vl[n])
if "away" in request.getForm():
away = True
else:
away = False
l = []
for v in vl:
if (not v.checkedout) or away:
l.append(v)
vl = l
%>
<%iterate v vl%>
<tr>
<td><a href="<%=request.app%>/verkaeufer/<%=v.id%>"><%=v.id%></a></td>
<td><%=v.lastname%></td>
<td><%=v.firstname%></td>
<td style="max-width: 250px;">
<div style="display: inline-block; vertical-align: top;">
<%=v.artikel().__len__()%></div>
<div style="display: inline-block; margin-left: 5px;">
<%iterate a v.artikel()%>
<div><a <%if a.verkauft%>class="stroke gray" <%end%>href="<%=request.app%>/artikel/<%=a.id%>"><%=a.bezeichnung%></a></div>
<%end%>
</div>
</td>
</tr>
<%end%>
</tbody>
</table>
<br/>
<br/>
<div>
Auf dieser Liste sind <%=len(vl)%> Verk&auml;ufer gelistet.
</div>

View File

@ -0,0 +1,163 @@
<%
request.setResponseHeader("Content-Type","text/css")
%>
* {
font-family: DejaVu Sans,Sans,Helvetica,Arial;
font-size: 4mm;
border: none;
margin: 0;
padding: 0;
}
<%include ("common_css",self)%>
body {
}
.title {
display: block;
font-size: 4mm;
font-style: italic;
}
.title div {
font-size: 150%;
font-weight: bold;
}
.sub {
font-size: 5mm;
}
.big {
font-size: 200%;
}
.ul {
text-decoration: underline;
}
.b {
font-weight: bold;
}
.i {
font-style: italic;
}
.pre {
white-space: pre;
}
.small {
font-size: 3mm;
}
.borderless {
border: none;
}
#price {
position: absolute;
right: 0.5cm;
top: 0.8cm;
font-size: 5mm;
-webkit-transform: rotate(-90deg);
-webkit-transform-origin: right top;
}
#tagid {
position: absolute;
right: 0.1cm;
top: 0.1cm;
}
#description {
margin-top: 0.4cm;
width: 7cm;
white-space: pre-wrap;
}
#description > p {
margin-bottom: 0.2cm;
}
@page {
margin: 0cm;
}
#scancode {
position: absolute;
right: 4mm;
top: 4mm;
}
#scancode > svg {
width: 25mm;
height: 25mm;
}
#page > div {
position: absolute;
top: 2mm;
left: 2mm;
bottom: 2mm;
right: 2mm;
display: block;
}
@media print {
.RLE {
width: 86mm;
height: 32mm;
}
body, .SRL {
width: 95mm;
height: 47mm;
}
body {
margin: 0px;
padding: 0px;
}
#page {
position: absolute;
left: 0cm;
top: 0cm;
right: 0cm;
bottom: 0cm;
border: 0px;
}
.noprint {
visibility: hidden;
}
}
@media screen {
body {
background-color: #404040;
}
#page {
position: relative;
top: 30px;
left: 30px;
background-color: white;
width: 210mm;
height: 297mm;
border: 2px solid black;
}
.RLE #page {
width: 86mm;
height: 32mm;
}
}
div {
display: inline-block;
}

View File

@ -0,0 +1,58 @@
<%
tags = self._tags()
%>
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="<%=request.app%>/print_css"/>
<style>
#page > div {
position: absolute:
top: 13.23mm;
left: 8mm;
right: 8mm;
bottom: 13.23mm;
padding: 0cm;
margin: 0cm;
}
.tag {
position: relative;
display: inline-block;
width: 48.5mm;
height: 16.9mm;
padding: 0px;
margin: 0px;
box-sizing: border-box;
border: 1px solid black;
}
.tagrow {
display: block;
box-sizing: border-box;
}
</style>
</head>
<body>
<div id="page">
<div>
<%iterate y range(16)%>
<div class="tagrow">
<%iterate x range(4)%><%
t = tags.pop()
%><div class="tag">
<img src="<%=request.app%>/qrcode?c=<%=t%>" style="width: 10mm; height: 10mm;"/>
</div><%end%><br/>
</div>
<%end%>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,71 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="<%=request.app%>/print_css"/>
<style>
#page > div {
position: absolute;
top: 15mm;
left: 15mm;
bottom: 15mm;
right: 15mm;
display: block;
}
</style>
</head>
<body>
<div id="page">
<div>
<%
summe = 0.0
%>
<div class="right">
<%=self.svgqrcode(self._aq_name)%>
</div>
<div class="title">Fahrradb&ouml;rse von<br/>
<div>Bündnis90 / Die Grünen (2016)</div>
</div>
<br/>
<br/>
<div class="big">Quittung / Mitnahmeschein</div><br/>
<div class="small"><%=self._aq_name%></div><br/>
<div class="small"><%=self.zeit%></div>
<br/>
<br/>
<%iterate artikel self.artikel.keys()%>
<div class="hr box">
<%=artikel.bezeichnung%>
<div class="right"><%="%0.2f" % (self.artikel[artikel],)%>&euro;</div><br/>
<div class="small pre indent"><%=artikel.beschreibung%></div>
</div>
<%
summe = summe + self.artikel[artikel]
%>
<%end%>
<br/>
<br/>
<div class="right">Summe: <%="%0.2f" % (summe,)%>&euro;</div>
<br/>
<div class="small"><span class="ul">Grunds&auml;tze:</span><br/>
Veranstalter der Fahrradb&ouml;rse ist Bündnis90 / die Gr&uuml;nen OV Vaihingen.<br/>
Der Veranstalter tritt in der Fahrradb&ouml;rse als Vermittler auf, die Vermittlerprovision betr&auml;gt 10% des erzielten Preises.<br/>
<br/>
Der Veranstalter &uuml;bernimmt keine Gewährleistung und Garantie für die Ware!<br/>
Bitte prüfen Sie den Zustand und die Funktionsfähigkeit der Ware genau!<br/>
<br/>
Der Veranstalter überwacht die Fahrradbörse, er übernimmt keine Haftung bei Diebstahl.<br/>
Am Abend nicht abgeholte Ware geht in den Besitz des Veranstalters über und wird gespendet bzw. entsorgt.
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<%frame layout_html%>
<h1>Direktsuche</h1>
<br/>
Suche nach: <%=request.getForm()["q"].value()%><br/>
<hr/>
<%if len(request.results)==0%>
<div>Keine Treffer!</div>
<%end%>
<%if len(request.results)!=0%>
<%iterate r request.results%>
<a href="<%=r["link"]%>"><%=r["text"]%></a><br/>
<%end%>
<%end%>

View File

@ -0,0 +1,82 @@
<%frame layout_html%>
<%
self.update(request)
%>
<h1>Verk&auml;ufer Details</h1>
<a href="<%=request.self()%>/prov" target="_blank">Abrechnungsliste</a><br/>
<br/>
<%if self.checkedout%>
<h1>!!! AUSGECHECKT !!!</h1>
<%end%>
<form action="<%=request.self()%>" method="POST" enctype="multipart/form-data">
<table>
<tr>
<td>Nachname:</td>
<td><input type="text" name="lastname" value="<%=self.lastname%>"/></td>
<td>Vorname:</td>
<td><input type="text" name="firstname" value="<%=self.firstname%>"/></td>
</tr>
<tr>
<td>Firma:</td>
<td colspan="3"><input type="text" name="company" value="<%=self.company%>"/></td>
</tr>
<tr>
<td>Telefon:</td>
<td colspan="3"><input type="text" name="telefon" value="<%=self.telefon%>"/></td>
</tr>
<tr>
<td>Ausgecheckt:</td>
<td colspan="3">
<select name="checkedout">
<option value=""<%if not self.checkedout%> selected<%end%>>NEIN</option>
<option value="True"<%if self.checkedout%> selected<%end%>>JA</option>
</select>
</td>
</tr>
<tr>
<td colspan="4">Anschrift:<br/>
<textarea name="anschrift"><%=self.anschrift%></textarea></td>
</tr>
<tr>
<td colspan="4">Bemerkungen:<br/>
<textarea name="bemerkungen"><%=self.bemerkungen%></textarea></td>
</tr>
<tr>
<td><input type="submit" value="aktualisieren"/></td>
</tr>
</table>
</form>
<br/>
<h2>Angebotene Artikel</h2>
<table>
<thead>
<tr>
<td>Artikel#</td>
<td>Bezeichnung (kurz)</td>
<td>Bezeichnung (lang)</td>
<td>Preis</td>
<td></td>
</tr>
</thead>
<tbody>
<form action="<%=request.app%>/addartikel?vid=<%=self.id%>" method="POST" enctype="multipart/form-data">
<tr style="background-color: #E0E0E0;">
<td>neu:</td>
<td><input type="text" name="bezeichnung" value=""/></td>
<td><input type="text" name="bezeichnung2" value=""/></td>
<td><input type="number" name="preis" min="0" max="999999" step="0.01" value="1"/></td>
<td></td>
<td><input type="submit" value="erstellen..."/></td>
</tr>
<%iterate artikel self.artikel()%>
<tr>
<td><a href="<%=request.app%>/artikel/<%=artikel.id%>"><%=artikel.id%></a></td>
<td><%=artikel.bezeichnung%></td>
<td><%=artikel.bezeichnung2%></td>
<td><%=artikel.preis%></td>
</tr>
<%end%>
</tbody>
</table>

View File

@ -0,0 +1,164 @@
<%
def akey(p):
return getattr(self._aq_parent.artikel, p).bezeichnung
al = self._aq_parent.artikel.children()
al.sort(key=akey)
for n in range(al.__len__()):
al[n] = getattr(self._aq_parent.artikel, al[n])
l = []
for a in al:
if a.vid==self.id:
l.append(a)
al = l
summe = 0.00
sum_erloes = 0.00
%><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Verk&auml;uferabrechnung</title>
<link rel="stylesheet" href="<%=request.app%>/print_css"/>
<style>
td {
border-bottom: 1px dotted black;
border-collapse: collapse;
}
#scancode {
position: absolute;
right: 1cm;
top: 0cm;
}
#scancode > img {
width: 3cm;
height: 3cm;
}
#page > div {
position: absolute;
top: 15mm;
left: 15mm;
bottom: 15mm;
right: 15mm;
display: block;
}
</style>
</head>
<body>
<div id="page">
<div>
<div id="scancode"><img src="<%=request.app%>/qrcode?c=<%=self.id%>"/></div>
<%if not self.checkedout%>
<div class="noprint">
<a href="<%=request.self(-1)%>/checkout">[ VERK&Auml;UFER AUSCHECKEN ]</a>
</div>
<%end%>
<div class="title">Fahrradb&ouml;rse von<br/>
<div>Bündnis90 / Die Grünen (2018)</div>
</div>
<br/>
<%if self.checkedout%>
<span class="ul b i big">CHECKOUT</span><br/><br/>
<%end%>
<div class="title">
Abrechnungsliste Verk&auml;ufer<br/>
<div><%=self.lastname%>, <%=self.firstname%></div><br/>
Verk&auml;ufer-ID: <%=self.id%>
</div>
<br/>
<table style="width: 18cm;">
<thead>
<tr>
<td class="i small">Artikel</td>
<td class="i small">Bepreisung</td>
<td class="i small">Erlös</td>
</tr>
</thead>
<tbody>
<%iterate a al%>
<tr>
<td>
<%=a.bezeichnung%><br/>
<div class="sub"><%=a.id%></div><br/>
</td>
<td style="text-align: right;">
<%="%03.2f" % (a.preis,)%>&euro;
</td>
<td style="text-align: right;">
<%
summe = summe + a.preis
%><%if a.verkauft%>
<%="%03.2f" % (a.erloes,)%>&euro;
<%
sum_erloes = sum_erloes + a.erloes
%>
<%end%>
<%if not (a.verkauft)%>
N. Verkauft
<%end%>
</td>
</tr>
<%end%>
</tbody>
<tfoot>
<tr>
<td class="borderless"></td>
<td class="borderless"></td>
<td class="borderless"></td>
</tr>
<tr>
<td class="borderless" style="text-align: right;">Summe:</td>
<td style="text-align: right;">( <%="%03.2f" % (round(summe,2),)%>&euro; )</td>
<td style="text-align: right;"><%="%03.2f" % (round(sum_erloes,2),)%>&euro;</td>
</tr>
<tr>
<td class="borderless" style="text-align: right;">Provision:</td>
<td style="text-align: right;">( <%="%03.2f" % (round(summe * 0.1,2),)%>&euro; )</td>
<td style="text-align: right;"><%="%03.2f" % (round(sum_erloes * 0.1,2),)%>&euro;</td>
</tr>
<tr>
<td class="borderless" style="text-align: right;">Auszahlung:</td>
<td class="borderless" style="font-weight: normal; text-align: right;">( <%="%03.2f" % (round(summe * 0.9,2),)%>&euro; )</td>
<td class="borderless" style="font-weight: bold; font-size: 8mm; text-decoration: underline; text-align: right;"><%="%03.2f" % (round(sum_erloes * 0.9,2),)%>&euro;</td>
</tr>
</tfoot>
</table>
<%if self.checkedout%>
<div>
<br/>
<br/>
Betrag erhalten: <div style="width: 8cm; border-bottom: 0.1cm dotted black;">&nbsp;</div>
</div>
<br/><br/>
<%end%>
<div class="small"><span class="ul">Grunds&auml;tze:</span><br/>
Veranstalter der Fahrradb&ouml;rse ist Bündnis90 / die Gr&uuml;nen OV Vaihingen.<br/>
Der Veranstalter tritt in der Fahrradb&ouml;rse als Vermittler auf, die Vermittlerprovision betr&auml;gt 10% des erzielten Preises.<br/>
<br/>
Der Veranstalter &uuml;bernimmt keine Gewährleistung und Garantie für die Ware!<br/>
Bitte prüfen Sie den Zustand und die Funktionsfähigkeit der Ware genau!<br/>
<br/>
Der Veranstalter überwacht die Fahrradbörse, er übernimmt keine Haftung bei Diebstahl.<br/>
Am Abend nicht abgeholte Ware geht in den Besitz des Veranstalters über und wird gespendet bzw. entsorgt.
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,46 @@
<%frame layout_html%>
<%
summe = 0.0
%>
<br/>
<div class="big">Verkauf</div>
<br/>
<form action="" method="post" enctype="multipart/form-data">
<%if hasattr(request,"message")%>
<div class="message"><%=request.message%></div>
<br/>
<%end%>
<div>
Artikel hinzufügen: <input class="wide" type="text" id="artikelid" name="artikelid" value=""/>
</div>
<br/>
<%iterate artikel self.artikel.keys()%>
<div class="space hr">
<a href="<%=request.self(-3)%>/artikel/<%=artikel.id%>" target="_blank"><%=artikel.bezeichnung%></a>
<input class="right" type="number" name="erloes_<%=artikel.id%>" min="0" max="999999" step="1.0" value="<%=self.artikel[artikel]%>"/><br/>
<div class="small pre indent"><%=artikel.beschreibung%></div>
</div>
<%
summe = summe + self.artikel[artikel]
%>
<%end%>
<br/>
<br/>
<div style="position: relative; right: 0px; text-align: right;">Summe: <%="%0.2f" % (summe,)%>&euro;</div>
<br/>
<br/>
<input class="big" type="submit" name="action" value="AKTUALISIEREN"/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input class="big" type="submit" name="action" value="BEZAHLT"/>
</form>
<script>
window.setTimeout( function(){document.getElementById('artikelid').focus();}, 250 );
</script>

View File

@ -0,0 +1,53 @@
from hserver.api import WebObject,Persistence,WebFolder,WebCallable
import hserver
import Templates
import uuid
import qrcode
class Verkaeufer(WebObject,Persistence):
_public_names = {
"lastname": "",
"firstname": "",
"anschrift": "",
"bemerkungen": "",
"company": "",
"telefon": "",
"checkedout": False
};
_public_types = {
"checkedout": bool
}
prov = Templates.verk_prov_html
def __init__(self):
WebObject.__init__(self)
self.id = uuid.uuid4().hex
self.lastname = "";
self.firstname = "";
self.company = "";
self.anschrift = "";
self.bemerkungen = "";
self.telefon = ""
self.checkedout = False
def __call__(self,request,o=None):
Templates.verk_display_html(request,self)
def artikel(self):
r = []
artikel = self._aq_parent._aq_parent.artikel
for n in artikel.children():
a = getattr(artikel, n)
if a.vid == self.id:
r.append(a)
return r
def _checkout(self,request,o=None):
self.checkedout = True
request.redirect(request.self(-1) + "/prov")
checkout = WebCallable(method=_checkout)

View File

@ -0,0 +1,61 @@
from hserver.api import WebObject,Persistence,WebFolder,WebCallable
import hserver
import Templates
import uuid
import qrcode
import datetime
class Verkauf(WebObject,Persistence):
def __init__(self):
WebObject.__init__(self)
self.setDefault("verkauf")
self.artikel = {}
self.bezahlt = False
def _verkauf(self,request,o=None):
if not self.bezahlt:
if ("artikelid" in request.getForm()) and not (request.getForm()["artikelid"].value()==""):
try:
a = getattr( self._aq_parent._aq_parent.artikel, request.getForm()["artikelid"].value())._aq_object
if a is not None:
if a in self.artikel:
request.message = "Artikel bereits gescannt!"
else:
if a.verkauft:
request.message = "Artikel wurde bereits verkauft!"
else:
self.artikel[ a ] = a.preis;
except Exception as e:
request.message = "Artikel nicht gefunden!"
print(e)
for a in self.artikel:
ea = "erloes_%s" % (a.id,)
if ea in request.getForm():
self.artikel[a] = float(request.getForm()[ea].value())
if ("action" in request.getForm()):
ac = request.getForm()["action"].value()
if ac=="BEZAHLT":
for a in self.artikel:
a.verkauft = True
a.erloes = self.artikel[a]
a.quittung = self._aq_name
self.bezahlt = True
self.zeit = str(datetime.datetime.now())
if self.bezahlt:
Templates.quittung_html(request,o)
else:
Templates.verkauf_html(request,o)
verkauf = WebCallable(method=_verkauf)

View File

@ -0,0 +1,48 @@
from hserver.api import WebObject,NoPersistence,WebCallable
import Templates
import hserver
class TreeBrowser(WebObject,NoPersistence):
def __init__(self):
WebObject.__init__(self)
self.setDefault("browse")
_browse = Templates.browse_html;
def __call__(self,request,o=None):
return self._browse(request,o)
def _addObject(self, request, o):
f = request.getForm()
if ("oname" in f) and ("oclass" in f):
oclass = getattr( hserver.api , f["oclass"].value() )
i = oclass()
print(">>>%s" % (o._aq_parent._aq_name,))
setattr( self._aq_parent, f["oname"].value(), i )
request.redirect( request.pathwalker().walked(-2) + "/_browse" )
add = WebCallable(method=_addObject)
def _delObject(self, request, o):
print(">>>%s" % (o._aq_parent._aq_name,))
delattr(o._aq_parent._aq_parent, o._aq_parent._aq_name)
request.redirect( request.pathwalker().walked(-3) + "/_browse" )
remove = WebCallable(method=_delObject)
def wo_types(self):
r = []
exp = hserver.api.__dict__
for t in exp.values():
try:
if (issubclass(t,hserver.api.WebObject)):
r.append(t. __name__)
except:
pass
r.sort()
return r

View File

@ -0,0 +1,19 @@
import coremod.exceptions
from webmanager import WebManager
from browser import TreeBrowser
_hserver = None
def init(hserver):
_hserver = hserver
root = hserver.getRoot()
manager = WebManager( hserver )
root.setChild( "manage", manager)
root.setDefault("manage")
root.setChild("_browse", TreeBrowser())

View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1 @@
modules=("hwo",)

View File

@ -0,0 +1,15 @@
<html>
<head>
<title>404 Not Found</title>
<style>
body,p,div {
font-family: "DejaVu Sans","Helvetica", "Arial", "Sans";
}
</style>
</head>
<body>
<h1>Die angeforderte Resource konnte nicht gefunden werden</h1>
<h1>The requested resource was not found</h1>
<div><%=self.message%></div>
</body>
</html>

View File

@ -0,0 +1,17 @@
function byID(id){
return document.getElementById(id);
}
function addObject( path ){
oname = byID("oname").value;
oclass = byID("oclass").value;
if (oname == ""){
alert("Bitte einen Objektnamen vergeben!");
byID("oname").focus();
} else {
url = "<%=request.self(-1)%>/addObject?path=" + path + "&oclass=" + oclass + "&oname=" + oname;
window.location.href = url
}
}

View File

@ -0,0 +1,40 @@
#display {
white-space: nowrap;
vertical-align: top;
position: absolute;
}
#path{
margin-bottom: 20px;
}
#tree, #details {
display: inline-block;
}
.treenode {
display: block;
position: relative;
border-top: 1px solid gray;
font-size: 14px;
padding-top: 5px;
padding-bottom: 5px;
white-space: nowrap;
}
.treenode > div {
display: inline-block;
text-align: right;
float: right;
padding-left: 10px;
position: relative;
top: -14px;
}
#tree {
padding-right: 10px;
margin-right: 10px;
border-right: 1px solid black;
float: left;
}

View File

@ -0,0 +1,40 @@
<%frame frame_html%>
<div id="path">Pfad: <%=request.self(-1,trail=True)%></div>
<div id="display">
<div id="tree">
<%if not self._aq_parent is None%>
<div><a href="<%=request.self(-2,trail=True)%>_browse">..</a></div>
<%end%>
<%if self._aq_parent is None%>
<div>&nbsp;</div>
<%end%>
<form action="<%=request.self()%>/add">
<div class="treenode">
<input type="text" name="oname"/><br/>
<select size="1" name="oclass">
<%iterate wo_cls getattr(self,"_browse").wo_types()%><option value="<%=wo_cls%>"><%=wo_cls%></option><%end%>
</select><br/>
<input type="submit" value="erstellen"/>
</div>
</form>
<%iterate node self.children()%>
<div class="treenode"><a href="<%=request.self(-1,trail=True)%><%=node%>/_browse"><%=node%></a><div><%=getattr(self,node).__class__.__name__%></div></div>
<%end%>
</div>
<div id="details">
<%=self._aq_name%> (<%=self.__class__.__name__%>)<br/>
<div id="actions">
<a href="<%=request.self(-1)%>">[ ANZEIGEN ]</a>
<%if not self._aq_name=="/"%>
<a href="<%=request.self()%>/remove">[ ENTFERNEN ]</a>
<%end%>
</div>
<br/>
<%if hasattr(self,"_wo_manage")%>
<% self._wo_manage(request,self) %>
<%end%>
</div>
</div>

View File

@ -0,0 +1,14 @@
<%frame frame_html%>
<%
if "shutdown" in request.getForm() and request.getForm()["shutdown"].value()=="yes":
self.server().shutdown()
%>
<%if "shutdown" in request.getForm() and request.getForm()["shutdown"].value()=="yes" %>
<div id="message">Server will shutdown after this request.</div>
<%end%>
<a href="<%=request.self()%>?shutdown=yes"><div class="button">Shutdown</div></a>

View File

@ -0,0 +1,22 @@
<html>
<head>
<title>HServer Management</title>
<style>
<%include ("style_css",self)%>
<%include ("browse.css",self)%>
</style>
</head>
<body>
<section id="menu">
<a href="/manage/control"><div>Control</div></a>
<a href="/manage/packages"><div>Packages</div></a>
<a href="/_browse"><div>Tree Browser</div></a>
</section>
<div id="content">
<%content%>
</div>
</body>
</html>

View File

@ -0,0 +1,11 @@
<div class="wo_frame">
<div class="wo_name"><%=self._aq_name%></div>
<div class="wo_class">[<%=escape(self.__class__.__name__)%>]</div>
<div class="wo_actions">
<a href="" onClick="addObject( '<%=self._aq_path()%>' )">[ ADD HERE ]</a>
</div>
<%iterate wobj self.children()%>
<%include ("list_wo.html",getattr(self,wobj))%>
<%end%>
</div>

View File

@ -0,0 +1,3 @@
<%frame frame_html%>

View File

@ -0,0 +1,38 @@
<%frame frame_html%>
<%
if ("reload" in request.getForm().keys()):
which = request.getForm()["reload"].value()
if (which == "_all"):
l = self.server().packagemanager().packages().keys()
else:
l = (which,)
for p in l:
self.server().packagemanager().packages()[ p ].reload()
request.redirect(request.self())
%>
<div>Loaded Packages: (<a href="<%=request.self()%>?reload=_all">reload</a>) <br/>
<%iterate _p self.server().packagemanager().packages().keys()%>
<% p = self.server().packagemanager().packages()[_p] %>
<div class="block">
<div class="headline"><%=_p%> (<a href="<%=request.self()%>?reload=<%=escape(_p)%>">reload</a>)</div>
<div>Exports:<br/>
<%iterate e p.exports()%>
<% exp = p.exports()[e] %>
<div class="listitem"><%=e%>: <%=escape("%s" % (exp,))%></div>
<%end%>
</div>
<div>Contents:<br/>
<%iterate e p.modules()%>
<% exp = p.modules()[e] %>
<div class="listitem"><%=e%>: <%=escape("%s" % (exp,))%></div>
<%end%>
</div>
</div>
<%end%>
</div>

View File

@ -0,0 +1,80 @@
body,p,div {
font-family: "DejaVu Sans","Helvetica", "Arial", "Sans";
}
#menu {
width: 90%;
border-bottom: 1px solid black;
margin-bottom: 40px;
}
#menu>a {
display: inline;
}
#menu>a>div {
padding: 10px;
display: inline-block;
}
.block {
display: block;
border: 1px solid black;
background-color: #C0C0C0;
margin-bottom: 10px;
}
.headline {
width: 100%;
border-bottom: 1px solid #404040;
background-color: #4040FF;
margin-bottom: 5px;
}
.listitem {
padding-left: 5px;
}
.button {
background-color: #00D0D0;
padding: 20px;
display: inline-block;
border: 1px solid #008080;
}
#treeitem {
x-border-left: 1px solid blue;
border-top: 1px solid blue;
padding-left: 5px;
}
.cell {
display: inline-block;
width: 140px;
}
#icon {
width: 24px;
height: 24px;
}
.wo_frame {
position: relative;
left: 10px;
display: block;
margin-top: 5px;
border-top: 1px solid gray;
}
.wo_name {
display: inline-block;
position: relative;
}
.wo_class,.wo_actions {
display: inline-block;
position: relative;
left: 50px;
}

View File

@ -0,0 +1,30 @@
<%frame frame_html%>
<script src="api"></script>
<div>Tree Setup</div><br/>
<br/>
<%
path = ()
objs = self.list_webobjects()
%>
<div>
<div>Neues Objekt:
<input type="text" id="oname" value=""/>
<select id="oclass" size="1">
<%iterate t objs%>
<option value="<%=t.__name__%>"><%=t.__name__%></option>
<%end%>
</select>
</div>
<br/>
<%include ("list_wo.html",self.server().aq_root())%>
</div>

View File

@ -0,0 +1,15 @@
<div id="treeitem">
<div class="cell"><%=self[0]%></div>
<div class="cell"><%=self[1].__class__.__name__%></div>
<div class="cell" style="width: auto;">
<img src="<%=request.self(-1)%>/gfx_plus.png" class="icon" onClick="addObject( '<%=self[0]%>' )"/>
</div>
<%iterate n self[2]%>
<%include ('treelevel_html', n)%>
<%end%>
</div>

View File

@ -0,0 +1,67 @@
import Templates
import hserver.api
from hwo import NoPersistence
import browser
class WebManager(hserver.api.WebObject,NoPersistence):
def __init__(self,server):
hserver.api.WebObject.__init__(self)
self.__server = server
self.setDefault("overview")
def server(self):
return self.__server
def list_webobjects(self):
r = []
#exp = self.__server.exports()
exp = hserver.api.__dict__
for t in exp.values():
try:
if (issubclass(t,hserver.api.WebObject)):
r.append(t)
except:
pass
return r
def list_paths(self,folder = None, path = "", recurse = 100):
if recurse <= 0:
return []
if folder is None:
folder = self.__server.getRoot()
path = ""
return [ "/", folder, self.list_paths( folder, "", 100), "" ]
ls = []
for c in folder.children():
co = folder[c]
cpath = "%s/%s" % (path,c)
ls.append( [ cpath, co, self.list_paths( co, cpath, recurse - 1), c ] )
return ls
def _addObject(self, request, o):
f = request.getForm()
if ("oname" in f) and ("oclass" in f):
oclass = getattr( hserver.api , f["oclass"].value() )
i = oclass()
setattr( self.server().getRoot(), f["oname"].value(), i )
request.redirect( request.pathwalker().walked(-1) + "/tree" )
addObject = hserver.api.WebCallable(method=_addObject)
overview = Templates.overview_html
packages = Templates.packages_html
control = Templates.control_html
tree = Templates.tree_html
api = Templates.api_js