forked from Kitware/tangelo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tangelo.py
108 lines (86 loc) · 3.6 KB
/
tangelo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import cherrypy
import os.path
import sys
import types
# This function defines the structure of a service response. Each service
# module should import this function from this package.
#
# The payload is contained in the 'result' field, while the 'error' field can
# indicate that something went wrong. Posibly more fields could be added in the
# future.
def empty_response():
return {'result' : None,
'error' : None}
def content_type(t=None):
r = cherrypy.response.headers['Content-type']
if t is not None:
cherrypy.response.headers['Content-type'] = t
return r
def log(*pargs, **kwargs):
cherrypy.log(*pargs, **kwargs)
def request_path():
return cherrypy.request.path_info
def legal_path(path):
#orig = path
if os.path.isabs(path):
return (False, "absolute")
# Extract the web root directory from the global config.
webroot = cherrypy.config.get("webroot")
if path[0] != "~":
path = os.path.abspath(webroot + os.path.sep + path)
if len(path) >= len(webroot) and path[:len(webroot)] == webroot:
return (True, "web root")
else:
home = os.path.expanduser("~").split(os.path.sep)[:-1]
path = os.path.abspath(os.path.expanduser(path))
comp = path.split(os.path.sep)
if len(comp) >= len(home) + 2 and comp[:len(home)] == home and comp[len(home)+1] == "tangelo_html":
return (True, "home directory")
return (False, "illegal")
def abspath(path):
if path[0] == "~":
comp = path.split(os.path.sep)
comp = [os.path.expanduser(comp[0])] + ["tangelo_html"] + comp[1:]
path = os.path.sep.join(comp)
else:
path = webroot + os.path.sep + path
return os.path.abspath(path)
def paths(runtimepaths):
# If a single string is passed in, wrap it into a singleton list (this is
# important because a string in Python is technically a list of lists, so
# without this check, this function will treat a single string as a list of
# single-letter strings - not at all what we expect to happen).
if type(runtimepaths) in types.StringTypes:
runtimepaths = [runtimepaths]
home = os.path.expanduser("~").split(os.path.sep)[:-1]
root = cherrypy.config.get("webroot")
# This function returns an absolute path if the path is allowed (i.e., in
# someone's tangelo_html directory, or under the web root directory), or
# logs a complaint and returns None otherwise.
def good(path):
orig = path
if os.path.isabs(path):
log("Illegal path (absolute): %s" % (orig), "SERVICE")
return None
path = os.path.abspath(cherrypy.thread_data.modulepath + os.path.sep + path)
if len(path) >= len(root) and path[:len(root)] == root:
return path
comp = path.split(os.path.sep)
if len(comp) >= len(home) + 2 and comp[:len(home)] == home and comp[len(home)+1] == "tangelo_html":
return path
log("Illegal path (outside of web space): %s" % (orig), "SERVICE")
return None
# Construct the list of new runtime paths by first mapping the checker over
# the list, then throwing away any Nones that showed up (the paths that led
# to Nones will have been logged).
newpaths = filter(lambda x: x is not None, map(good, runtimepaths))
# Finally, augment the path list.
sys.path = newpaths + sys.path
class HTTPStatusCode:
def __init__(self, code, msg=None):
self.code = code
self.msg = msg
# A decorator that exposes functions as being part of a service's RESTful API.
def restful(f):
f.restful = True
return f