Changeset 1243
- Timestamp:
- 08/12/06 11:39:31
- Files:
-
- trunk/cherrypy/__init__.py (modified) (2 diffs)
- trunk/cherrypy/_cpengine.py (modified) (1 diff)
- trunk/cherrypy/_cperror.py (modified) (2 diffs)
- trunk/cherrypy/_cpmodpy.py (modified) (2 diffs)
- trunk/cherrypy/_cprequest.py (modified) (6 diffs)
- trunk/cherrypy/config.py (modified) (2 diffs)
- trunk/cherrypy/lib/__init__.py (modified) (1 diff)
- trunk/cherrypy/lib/caching.py (modified) (7 diffs)
- trunk/cherrypy/lib/cptools.py (modified) (2 diffs)
- trunk/cherrypy/lib/encoding.py (modified) (1 diff)
- trunk/cherrypy/lib/http.py (modified) (6 diffs)
- trunk/cherrypy/lib/static.py (modified) (3 diffs)
- trunk/cherrypy/lib/tidy.py (modified) (7 diffs)
- trunk/cherrypy/test/test_core.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1236 r1243 168 168 return newfunc 169 169 170 def decorate All(obj, decorator):170 def decorate_all(obj, decorator): 171 171 """ 172 172 Recursively decorate all exposed functions of obj and all of its children, … … 181 181 if callable(value) and getattr(value, "exposed", False): 182 182 setattr(obj, key, decorate(value, decorator)) 183 decorate All(value, decorator)183 decorate_all(value, decorator) 184 184 185 185 trunk/cherrypy/_cpengine.py
r1231 r1243 257 257 return cherrypy.response 258 258 259 260 def drop_privileges(new_user='nobody', new_group='nogroup'): 261 """Drop privileges. UNIX only.""" 262 # Special thanks to Gavin Baker: http://antonym.org/node/100. 263 264 import pwd, grp 265 266 def names(): 267 return pwd.getpwuid(os.getuid())[0], grp.getgrgid(os.getgid())[0] 268 name, group = names() 269 cherrypy.log('Started as %r/%r' % (name, group), "PRIV") 270 271 if os.getuid() != 0: 272 # We're not root so, like, whatever dude. 273 cherrypy.log("Already running as %r" % name, "PRIV") 274 return 275 276 # Try setting the new uid/gid (from new_user/new_group). 277 try: 278 os.setgid(grp.getgrnam(new_group)[2]) 279 except OSError, e: 280 cherrypy.log('Could not set effective group id: %r' % e, "PRIV") 281 282 try: 283 os.setuid(pwd.getpwnam(new_user)[2]) 284 except OSError, e: 285 cherrypy.log('Could not set effective user id: %r' % e, "PRIV") 286 287 # Ensure a very convervative umask 288 old_umask = os.umask(077) 289 cherrypy.log('Old umask: %o, new umask: 077' % old_umask, "PRIV") 290 cherrypy.log('Running as %r/%r' % names(), "PRIV") 291 trunk/cherrypy/_cperror.py
r1231 r1243 27 27 path, pm = path.split("?", 1) 28 28 request.query_string = pm 29 request.params = _http.parse QueryString(pm)29 request.params = _http.parse_query_string(pm) 30 30 31 31 # Note that urljoin will "do the right thing" whether url is: … … 246 246 247 247 try: 248 code, reason, message = _http.valid Status(status)248 code, reason, message = _http.valid_status(status) 249 249 except ValueError, x: 250 250 raise cherrypy.HTTPError(500, x.args[0]) trunk/cherrypy/_cpmodpy.py
r1225 r1243 92 92 req.protocol, headers, rfile) 93 93 94 send Response(req, response.status, response.header_list, response.body)94 send_response(req, response.status, response.header_list, response.body) 95 95 request.close() 96 96 except: … … 98 98 cherrypy.log(tb) 99 99 s, h, b = bare_error() 100 send Response(req, s, h, b)100 send_response(req, s, h, b) 101 101 return apache.OK 102 102 103 def send Response(req, status, headers, body):103 def send_response(req, status, headers, body): 104 104 # Set response status 105 105 req.status = int(status[:3]) trunk/cherrypy/_cprequest.py
r1234 r1243 250 250 251 251 def process_headers(self): 252 self.params = http.parse QueryString(self.query_string)252 self.params = http.parse_query_string(self.query_string) 253 253 254 254 # Process the headers into self.headers … … 367 367 self.body = forms.file 368 368 else: 369 self.params.update(http.params FromCGIForm(forms))369 self.params.update(http.params_from_CGI_form(forms)) 370 370 371 371 def handle_error(self, exc): … … 545 545 if path[-1:] != '/': 546 546 atoms = request.browser_url.split("?", 1) 547 new Url = atoms.pop(0) + '/'547 new_url = atoms.pop(0) + '/' 548 548 if atoms: 549 new Url += "?" + atoms[0]550 raise cherrypy.HTTPRedirect(new Url)549 new_url += "?" + atoms[0] 550 raise cherrypy.HTTPRedirect(new_url) 551 551 return candidate, names[i:-1] 552 552 … … 598 598 599 599 600 def file Generator(input, chunkSize=65536):600 def file_generator(input, chunkSize=65536): 601 601 """Yield the given input (a file object) in chunks (default 64k).""" 602 602 chunk = input.read(chunkSize) … … 622 622 # Convert the given value to an iterable object. 623 623 if isinstance(value, types.FileType): 624 value = file Generator(value)624 value = file_generator(value) 625 625 elif isinstance(value, types.GeneratorType): 626 626 value = flattener(value) … … 684 684 685 685 try: 686 code, reason, _ = http.valid Status(self.status)686 code, reason, _ = http.valid_status(self.status) 687 687 except ValueError, x: 688 688 raise cherrypy.HTTPError(500, x.args[0]) trunk/cherrypy/config.py
r1236 r1243 225 225 cherrypy.log("Server parameters:", 'CONFIG') 226 226 227 server Vars = [227 server_vars = [ 228 228 'environment', 229 229 'log_to_screen', … … 238 238 ] 239 239 240 for var in server Vars:240 for var in server_vars: 241 241 cherrypy.log(" %s: %s" % (var, get(var)), 'CONFIG') 242 242 trunk/cherrypy/lib/__init__.py
r1141 r1243 15 15 return mod 16 16 17 def attributes(full AttributeName):17 def attributes(full_attribute_name): 18 18 """Load a module and retrieve an attribute of that module.""" 19 19 20 20 # Parse out the path, module, and attribute 21 last Dot = fullAttributeName.rfind(u".")22 attr Name = fullAttributeName[lastDot + 1:]23 mod Path = fullAttributeName[:lastDot]21 last_dot = full_attribute_name.rfind(u".") 22 attr_name = full_attribute_name[last_dot + 1:] 23 mod_path = full_attribute_name[:last_dot] 24 24 25 aMod = modules(modPath)25 mod = modules(mod_path) 26 26 # Let an AttributeError propagate outward. 27 27 try: 28 attr = getattr( aMod, attrName)28 attr = getattr(mod, attr_name) 29 29 except AttributeError: 30 30 raise AttributeError("'%s' object has no attribute '%s'" 31 % (mod Path, attrName))31 % (mod_path, attr_name)) 32 32 33 33 # Return a reference to the attribute. trunk/cherrypy/lib/caching.py
r1224 r1243 11 11 def __init__(self): 12 12 self.clear() 13 t = threading.Thread(target=self.expire Cache, name='expireCache')14 self.expiration Thread = t13 t = threading.Thread(target=self.expire_cache, name='expire_cache') 14 self.expiration_thread = t 15 15 t.setDaemon(True) 16 16 t.start() … … 20 20 self.cache = {} 21 21 self.expirations = {} 22 self.tot Puts = 023 self.tot Gets = 024 self.tot Hits= 025 self.tot Expires = 026 self.tot NonModified = 022 self.tot_puts = 0 23 self.tot_gets = 0 24 self.tot_hist = 0 25 self.tot_expires = 0 26 self.tot_non_modified = 0 27 27 self.cursize = 0 28 28 … … 31 31 key = property(_key) 32 32 33 def expire Cache(self):34 # expire Cache runs in a separate thread which the servers are33 def expire_cache(self): 34 # expire_cache runs in a separate thread which the servers are 35 35 # not aware of. It's possible that "time" will be set to None 36 36 # arbitrarily, so we check "while time" to avoid exceptions. … … 38 38 while time: 39 39 now = time.time() 40 for expiration Time, objects in self.expirations.items():41 if expiration Time <= now:42 for obj Size, objKey in objects:40 for expiration_time, objects in self.expirations.items(): 41 if expiration_time <= now: 42 for obj_size, obj_key in objects: 43 43 try: 44 del self.cache[obj Key]45 self.tot Expires += 146 self.cursize -= obj Size44 del self.cache[obj_key] 45 self.tot_expires += 1 46 self.cursize -= obj_size 47 47 except KeyError: 48 48 # the key may have been deleted elsewhere 49 49 pass 50 del self.expirations[expiration Time]50 del self.expirations[expiration_time] 51 51 time.sleep(0.1) 52 52 53 53 def get(self): 54 54 """Return the object if in the cache, else None.""" 55 self.tot Gets += 156 cache Item = self.cache.get(self.key, None)57 if cache Item:58 self.tot Hits+= 159 return cache Item55 self.tot_gets += 1 56 cache_item = self.cache.get(self.key, None) 57 if cache_item: 58 self.tot_hist += 1 59 return cache_item 60 60 else: 61 61 return None … … 66 66 if len(self.cache) < conf("tools.caching.maxobjects", 1000): 67 67 # Size check no longer includes header length 68 obj Size = len(obj[2])69 maxobj size = conf("tools.caching.maxobjsize", 100000)68 obj_size = len(obj[2]) 69 maxobj_size = conf("tools.caching.maxobj_size", 100000) 70 70 71 total Size = self.cursize + objSize71 total_size = self.cursize + obj_size 72 72 maxsize = conf("tools.caching.maxsize", 10000000) 73 73 74 74 # checks if there's space for the object 75 if (obj Size < maxobjsize and totalSize < maxsize):75 if (obj_size < maxobj_size and total_size < maxsize): 76 76 # add to the expirations list and cache 77 expiration Time = time.time() + conf("tools.caching.delay", 600)78 obj Key = self.key79 bucket = self.expirations.setdefault(expiration Time, [])80 bucket.append((obj Size, objKey))81 self.cache[obj Key] = obj82 self.tot Puts += 183 self.cursize = total Size77 expiration_time = time.time() + conf("tools.caching.delay", 600) 78 obj_key = self.key 79 bucket = self.expirations.setdefault(expiration_time, []) 80 bucket.append((obj_size, obj_key)) 81 self.cache[obj_key] = obj 82 self.tot_puts += 1 83 self.cursize = total_size 84 84 85 85 … … 97 97 cherrypy.request.cached = c = False 98 98 else: 99 cache Data = cherrypy._cache.get()100 cherrypy.request.cached = c = bool(cache Data)99 cache_data = cherrypy._cache.get() 100 cherrypy.request.cached = c = bool(cache_data) 101 101 102 102 if c: 103 103 response = cherrypy.response 104 s, response.headers, b, create_time = cache Data104 s, response.headers, b, create_time = cache_data 105 105 106 106 # Add the required Age header … … 111 111 except cherrypy.HTTPError, x: 112 112 if x.status == 304: 113 cherrypy._cache.tot NonModified += 1113 cherrypy._cache.tot_non_modified += 1 114 114 raise 115 115 trunk/cherrypy/lib/cptools.py
r1233 r1243 23 23 cherrypy.response.ETag = etag 24 24 25 status, reason, msg = _http.valid Status(cherrypy.response.status)25 status, reason, msg = _http.valid_status(cherrypy.response.status) 26 26 27 27 conditions = cherrypy.request.headers.elements('If-Match') or [] … … 44 44 lastmod = cherrypy.response.headers.get('Last-Modified') 45 45 if lastmod: 46 status, reason, msg = _http.valid Status(cherrypy.response.status)46 status, reason, msg = _http.valid_status(cherrypy.response.status) 47 47 48 48 since = cherrypy.request.headers.get('If-Unmodified-Since') trunk/cherrypy/lib/encoding.py
r1233 r1243 33 33 34 34 def decode_params(encoding): 35 decoded Params = {}35 decoded_params = {} 36 36 for key, value in cherrypy.request.params.items(): 37 37 if hasattr(value, 'file'): 38 38 # This is a file being uploaded: skip it 39 decoded Params[key] = value39 decoded_params[key] = value 40 40 elif isinstance(value, list): 41 41 # value is a list: decode each element 42 decoded Params[key] = [v.decode(encoding) for v in value]42 decoded_params[key] = [v.decode(encoding) for v in value] 43 43 else: 44 44 # value is a regular string: decode it 45 decoded Params[key] = value.decode(encoding)45 decoded_params[key] = value.decode(encoding) 46 46 47 47 # Decode all or nothing, so we can try again on error. 48 cherrypy.request.params = decoded Params48 cherrypy.request.params = decoded_params 49 49 50 50 trunk/cherrypy/lib/http.py
r1225 r1243 8 8 9 9 from BaseHTTPServer import BaseHTTPRequestHandler 10 response Codes = BaseHTTPRequestHandler.responses.copy()10 response_codes = BaseHTTPRequestHandler.responses.copy() 11 11 12 12 # From http://www.cherrypy.org/ticket/361 13 response Codes[500] = ('Internal error',13 response_codes[500] = ('Internal error', 14 14 'The server encountered an unexpected condition ' 15 15 'which prevented it from fulfilling the request.') 16 response Codes[503] = ('Service Unavailable',16 response_codes[503] = ('Service Unavailable', 17 17 'The server is currently unable to handle the ' 18 18 'request due to a temporary overloading or ' … … 38 38 return int(protocol_str[5]), int(protocol_str[7]) 39 39 40 def get Ranges(headervalue, content_length):40 def get_ranges(headervalue, content_length): 41 41 """Return a list of (start, stop) indices from a Range header, or None. 42 42 … … 194 194 return decodedvalue 195 195 196 def valid Status(status):196 def valid_status(status): 197 197 """Return legal HTTP status Code, Reason-phrase and Message. 198 198 … … 226 226 "(%s is out of range)." % repr(code)) 227 227 228 if code not in response Codes:228 if code not in response_codes: 229 229 # code is unknown but not illegal 230 default Reason, message = "", ""230 default_reason, message = "", "" 231 231 else: 232 default Reason, message = responseCodes[code]232 default_reason, message = response_codes[code] 233 233 234 234 if reason is None: 235 reason = default Reason235 reason = default_reason 236 236 237 237 return code, reason, message … … 240 240 image_map_pattern = re.compile(r"[0-9]+,[0-9]+") 241 241 242 def parse QueryString(query_string, keep_blank_values=True):243 """Build a param Mapdictionary from a query_string."""242 def parse_query_string(query_string, keep_blank_values=True): 243 """Build a params dictionary from a query_string.""" 244 244 if image_map_pattern.match(query_string): 245 245 # Server-side image map. Map the coords to 'x' and 'y' … … 254 254 return pm 255 255 256 def params FromCGIForm(form):257 param Map= {}256 def params_from_CGI_form(form): 257 params = {} 258 258 for key in form.keys(): 259 value List = form[key]260 if isinstance(value List, list):261 param Map[key] = []262 for item in value List:259 value_list = form[key] 260 if isinstance(value_list, list): 261 params[key] = [] 262 for item in value_list: 263 263 if item.filename is not None: 264 264 value = item # It's a file upload 265 265 else: 266 266 value = item.value # It's a regular field 267 param Map[key].append(value)267 params[key].append(value) 268 268 else: 269 if value List.filename is not None:270 value = value List # It's a file upload269 if value_list.filename is not None: 270 value = value_list # It's a file upload 271 271 else: 272 value = value List.value # It's a regular field273 param Map[key] = value274 return param Map272 value = value_list.value # It's a regular field 273 params[key] = value 274 return params 275 275 276 276 trunk/cherrypy/lib/static.py
r1242 r1243 75 75 if cherrypy.request.protocol >= (1, 1): 76 76 response.headers["Accept-Ranges"] = "bytes" 77 r = http.get Ranges(cherrypy.request.headers.get('Range'), c_len)77 r = http.get_ranges(cherrypy.request.headers.get('Range'), c_len) 78 78 if r == []: 79 79 response.headers['Content-Range'] = "bytes */%s" % c_len … … 99 99 ## del response.headers['Content-Length'] 100 100 101 def file Ranges():101 def file_ranges(): 102 102 for start, stop in r: 103 103 yield "--" + boundary … … 110 110 # Final boundary 111 111 yield "--" + boundary 112 response.body = file Ranges()112 response.body = file_ranges() 113 113 else: 114 114 response.headers['Content-Length'] = c_len trunk/cherrypy/lib/tidy.py
r1190 r1243 17 17 # the tidy tool, by its very nature it's not generator friendly, 18 18 # so we just collapse the body and work with it. 19 orig inalBody = cherrypy.response.collapse_body()19 orig_body = cherrypy.response.collapse_body() 20 20 21 21 fct = cherrypy.response.headers.get('Content-Type', '') … … 27 27 28 28 if ct == 'text/html': 29 page File = os.path.join(temp_dir, 'page.html')30 open(page File, 'wb').write(originalBody)29 page_file = os.path.join(temp_dir, 'page.html') 30 open(page_file, 'wb').write(orig_body) 31 31 32 out File = os.path.join(temp_dir, 'tidy.out')33 err File = os.path.join(temp_dir, 'tidy.err')34 tidy Encoding= encoding.replace('-', '')35 if tidy Encoding:36 tidy Encoding = '-' + tidyEncoding32 out_file = os.path.join(temp_dir, 'tidy.out') 33 err_file = os.path.join(temp_dir, 'tidy.err') 34 tidy_enc = encoding.replace('-', '') 35 if tidy_enc: 36 tidy_enc = '-' + tidy_enc 37 37 38 38 strict_xml = (" -xml", "")[bool(strict_xml)] 39 39 os.system('"%s" %s%s -f %s -o %s %s' % 40 (tidy_path, tidy Encoding, strict_xml,41 err File, outFile, pageFile))42 errs = open(err File, 'rb').read()40 (tidy_path, tidy_enc, strict_xml, 41 err_file, out_file, page_file)) 42 errs = open(err_file, 'rb').read() 43 43 44 44 new_errs = [] … … 46 46 if (err.find('Warning') != -1 or err.find('Error') != -1): 47 47 ignore = 0 48 for err Ign in errors_to_ignore or []:49 if err.find(err Ign) != -1:48 for err_ign in errors_to_ignore or []: 49 if err.find(err_ign) != -1: 50 50 ignore = 1 51 51 break … … 55 55 if new_errs: 56 56 cherrypy.response.body = wrong_content('<br />'.join(new_errs), 57 orig inal_body)57 orig_body) 58 58 elif strict_xml: 59 59 # The HTML is OK, but is it valid XML? 60 60 # Use elementtree to parse XML 61 61 from elementtree.ElementTree import parse 62 tag List = ['nbsp', 'quot']63 for tag in tag List:64 orig inalBody = originalBody.replace('&' + tag + ';', tag.upper())62 tag_list = ['nbsp', 'quot'] 63 for tag in tag_list: 64 orig_body = orig_body.replace('&' + tag + ';', tag.upper()) 65 65 66 66 if encoding: 67 67 enctag = '<?xml version="1.0" encoding="%s"?>' % encoding 68 orig inalBody = enctag + originalBody68 orig_body = enctag + orig_body 69 69 70 f = StringIO.StringIO(orig inalBody)70 f = StringIO.StringIO(orig_body) 71 71 try: 72 72 tree = parse(f) 73 73 except: 74 74 # Wrong XML 75 body File = StringIO.StringIO()76 traceback.print_exc(file = body File)77 body File = '<br />'.join(bodyFile.getvalue())78 cherrypy.response.body = wrong_content(body File, originalbody, "XML")75 body_file = StringIO.StringIO() 76 traceback.print_exc(file = body_file) 77 body_file = '<br />'.join(body_file.getvalue()) 78 cherrypy.response.body = wrong_content(body_file, orig_body, "XML") 79 79 80 80 def html_space(text): … … 96 96 # the tidy tool, by its very nature it's not generator friendly, 97 97 # so we just collect the body and work with it. 98 orig inal_body = cherrypy.response.collapse_body()98 orig_body = cherrypy.response.collapse_body() 99 99 100 100 fct = cherrypy.response.headers.get('Content-Type', '') … … 109 109 # Javascript code nsgmls complains about it) 110 110 while True: 111 i = orig inal_body.find('<script')111 i = orig_body.find('<script') 112 112 if i == -1: 113 113 break 114 j = orig inal_body.find('</script>', i)114 j = orig_body.find('</script>', i) 115 115 if j == -1: 116 116 break 117 orig inal_body = original_body[:i] + original_body[j+9:]117 orig_body = orig_body[:i] + orig_body[j+9:] 118 118 119 119 page_file = os.path.join(temp_dir, 'page.html') 120 open(page_file, 'wb').write(orig inal_body)120 open(page_file, 'wb').write(orig_body) 121 121 122 122 err_file = os.path.join(temp_dir, 'nsgmls.err') … … 139 139 if new_errs: 140 140 cherrypy.response.body = wrong_content('<br />'.join(new_errs), 141 orig inal_body)141 orig_body) 142 142 trunk/cherrypy/test/test_core.py
r1225 r1243 243 243 def get_ranges(self): 244 244 h = cherrypy.request.headers.get('Range') 245 return repr(http.get Ranges(h, 8))245 return repr(http.get_ranges(h, 8)) 246 246 247 247 def slice_file(self):

