Merge github.com:web2py/web2py

This commit is contained in:
Michele Comitini
2012-10-27 21:26:31 +02:00
22 changed files with 477 additions and 396 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.2.1 (2012-10-22 15:07:32) stable Version 2.2.1 (2012-10-26 15:51:12) stable
+3 -3
View File
@@ -998,11 +998,11 @@ def design():
statics.sort() statics.sort()
# Get all languages # Get all languages
langpath = os.path.join(apath(app, r=request),'languages')
languages = dict([(lang, info) for lang, info languages = dict([(lang, info) for lang, info
in read_possible_languages( in read_possible_languages(langpath).iteritems()
apath(app, r=request)).iteritems()
if info[2] != 0]) # info[2] is langfile_mtime: if info[2] != 0]) # info[2] is langfile_mtime:
# get only existed files # get only existed files
#Get crontab #Get crontab
cronfolder = apath('%s/cron' % app, r=request) cronfolder = apath('%s/cron' % app, r=request)
+2 -1
View File
@@ -396,7 +396,8 @@ def build_environment(request, response, session, store_current=True):
response.models_to_run = [r'^\w+\.py$', r'^%s/\w+\.py$' % request.controller, response.models_to_run = [r'^\w+\.py$', r'^%s/\w+\.py$' % request.controller,
r'^%s/%s/\w+\.py$' % (request.controller, request.function)] r'^%s/%s/\w+\.py$' % (request.controller, request.function)]
t = environment['T'] = translator(request) t = environment['T'] = translator(os.path.join(request.folder,'languages'),
request.env.http_accept_language)
c = environment['cache'] = Cache(request) c = environment['cache'] = Cache(request)
if store_current: if store_current:
+5 -5
View File
@@ -64,7 +64,7 @@ def new(key, mode=MODE_CBC, IV=None):
return ECBMode(AES(key)) return ECBMode(AES(key))
elif mode == MODE_CBC: elif mode == MODE_CBC:
if IV is None: if IV is None:
raise ValueError, "CBC mode needs an IV value!" raise ValueError("CBC mode needs an IV value!")
return CBCMode(AES(key), IV) return CBCMode(AES(key), IV)
else: else:
@@ -91,7 +91,7 @@ class AES(object):
elif self.key_size == 32: elif self.key_size == 32:
self.rounds = 14 self.rounds = 14
else: else:
raise ValueError, "Key length must be 16, 24 or 32 bytes" raise ValueError("Key length must be 16, 24 or 32 bytes")
self.expand_key() self.expand_key()
@@ -313,7 +313,7 @@ class ECBMode(object):
"""Perform ECB mode with the given function""" """Perform ECB mode with the given function"""
if len(data) % self.block_size != 0: if len(data) % self.block_size != 0:
raise ValueError, "Plaintext length must be multiple of 16" raise ValueError("Plaintext length must be multiple of 16")
block_size = self.block_size block_size = self.block_size
data = array('B', data) data = array('B', data)
@@ -357,7 +357,7 @@ class CBCMode(object):
block_size = self.block_size block_size = self.block_size
if len(data) % block_size != 0: if len(data) % block_size != 0:
raise ValueError, "Plaintext length must be multiple of 16" raise ValueError("Plaintext length must be multiple of 16")
data = array('B', data) data = array('B', data)
IV = self.IV IV = self.IV
@@ -381,7 +381,7 @@ class CBCMode(object):
block_size = self.block_size block_size = self.block_size
if len(data) % block_size != 0: if len(data) % block_size != 0:
raise ValueError, "Ciphertext length must be multiple of 16" raise ValueError("Ciphertext length must be multiple of 16")
data = array('B', data) data = array('B', data)
IV = self.IV IV = self.IV
+29 -16
View File
@@ -222,7 +222,8 @@ def ldap_auth(server='ldap', port=None,
con.set_option(ldap.OPT_PROTOCOL_VERSION, 3) con.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# In cases where ForestDnsZones and DomainDnsZones are found, # In cases where ForestDnsZones and DomainDnsZones are found,
# result will look like the following: # result will look like the following:
# ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,DC=domain,DC=com'] # ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,
# DC=domain,DC=com']
if ldap_binddn: if ldap_binddn:
# need to search directory with an admin account 1st # need to search directory with an admin account 1st
con.simple_bind_s(ldap_binddn, ldap_bindpw) con.simple_bind_s(ldap_binddn, ldap_bindpw)
@@ -238,8 +239,9 @@ def ldap_auth(server='ldap', port=None,
user_mail_attrib]) user_mail_attrib])
result = con.search_ext_s( result = con.search_ext_s(
ldap_basedn, ldap.SCOPE_SUBTREE, ldap_basedn, ldap.SCOPE_SUBTREE,
"(&(sAMAccountName=%s)(%s))" % (ldap.filter.escape_filter_chars(username_bare), "(&(sAMAccountName=%s)(%s))" % (
filterstr), ldap.filter.escape_filter_chars(username_bare),
filterstr),
requested_attrs)[0][1] requested_attrs)[0][1]
if not isinstance(result, dict): if not isinstance(result, dict):
# result should be a dict in the form # result should be a dict in the form
@@ -292,8 +294,9 @@ def ldap_auth(server='ldap', port=None,
# bind anonymously # bind anonymously
con.simple_bind_s(dn, pw) con.simple_bind_s(dn, pw)
# search by e-mail address # search by e-mail address
filter = '(&(mail=%s)(%s))' % (ldap.filter.escape_filter_chars(username), filter = '(&(mail=%s)(%s))' % (
filterstr) ldap.filter.escape_filter_chars(username),
filterstr)
# find the uid # find the uid
attrs = ['uid'] attrs = ['uid']
if manage_user: if manage_user:
@@ -330,8 +333,10 @@ def ldap_auth(server='ldap', port=None,
break break
except ldap.LDAPError, detail: except ldap.LDAPError, detail:
(exc_type, exc_value) = sys.exc_info()[:2] (exc_type, exc_value) = sys.exc_info()[:2]
logger.warning("ldap_auth: searching %s for %s resulted in %s: %s\n" % logger.warning(
(basedn, filter, exc_type, exc_value)) "ldap_auth: searching %s for %s resulted in %s: %s\n" %
(basedn, filter, exc_type, exc_value)
)
if not found: if not found:
logger.warning('User [%s] not found!' % username) logger.warning('User [%s] not found!' % username)
return False return False
@@ -365,8 +370,10 @@ def ldap_auth(server='ldap', port=None,
break break
except ldap.LDAPError, detail: except ldap.LDAPError, detail:
(exc_type, exc_value) = sys.exc_info()[:2] (exc_type, exc_value) = sys.exc_info()[:2]
logger.warning("ldap_auth: searching %s for %s resulted in %s: %s\n" % logger.warning(
(basedn, filter, exc_type, exc_value)) "ldap_auth: searching %s for %s resulted in %s: %s\n" %
(basedn, filter, exc_type, exc_value)
)
if not found: if not found:
logger.warning('User [%s] not found!' % username) logger.warning('User [%s] not found!' % username)
return False return False
@@ -502,8 +509,8 @@ def ldap_auth(server='ldap', port=None,
'There is no username or email for %s!' % username) 'There is no username or email for %s!' % username)
raise raise
db_group_search = db((db.auth_membership.user_id == db_user_id) & db_group_search = db((db.auth_membership.user_id == db_user_id) &
(db.auth_user.id == db.auth_membership.user_id) & (db.auth_user.id == db.auth_membership.user_id) &
(db.auth_group.id == db.auth_membership.group_id)) (db.auth_group.id == db.auth_membership.group_id))
db_groups_of_the_user = list() db_groups_of_the_user = list()
db_group_id = dict() db_group_id = dict()
@@ -522,7 +529,8 @@ def ldap_auth(server='ldap', port=None,
for group_to_del in db_groups_of_the_user: for group_to_del in db_groups_of_the_user:
if ldap_groups_of_the_user.count(group_to_del) == 0: if ldap_groups_of_the_user.count(group_to_del) == 0:
db((db.auth_membership.user_id == db_user_id) & db((db.auth_membership.user_id == db_user_id) &
(db.auth_membership.group_id == db_group_id[group_to_del])).delete() (db.auth_membership.group_id == \
db_group_id[group_to_del])).delete()
# #
# Create user membership in groups where user is not in already # Create user membership in groups where user is not in already
@@ -531,7 +539,7 @@ def ldap_auth(server='ldap', port=None,
if db_groups_of_the_user.count(group_to_add) == 0: if db_groups_of_the_user.count(group_to_add) == 0:
if db(db.auth_group.role == group_to_add).count() == 0: if db(db.auth_group.role == group_to_add).count() == 0:
gid = db.auth_group.insert(role=group_to_add, gid = db.auth_group.insert(role=group_to_add,
description='Generated from LDAP') description='Generated from LDAP')
else: else:
gid = db(db.auth_group.role == group_to_add).select( gid = db(db.auth_group.role == group_to_add).select(
db.auth_group.id).first().id db.auth_group.id).first().id
@@ -608,7 +616,8 @@ def ldap_auth(server='ldap', port=None,
con.set_option(ldap.OPT_PROTOCOL_VERSION, 3) con.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# In cases where ForestDnsZones and DomainDnsZones are found, # In cases where ForestDnsZones and DomainDnsZones are found,
# result will look like the following: # result will look like the following:
# ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,DC=domain,DC=com'] # ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,
# DC=domain,DC=com']
if ldap_binddn: if ldap_binddn:
# need to search directory with an admin account 1st # need to search directory with an admin account 1st
con.simple_bind_s(ldap_binddn, ldap_bindpw) con.simple_bind_s(ldap_binddn, ldap_bindpw)
@@ -620,7 +629,8 @@ def ldap_auth(server='ldap', port=None,
# We have to use the full string # We have to use the full string
username = con.search_ext_s(base_dn, ldap.SCOPE_SUBTREE, username = con.search_ext_s(base_dn, ldap.SCOPE_SUBTREE,
"(&(sAMAccountName=%s)(%s))" % "(&(sAMAccountName=%s)(%s))" %
(ldap.filter.escape_filter_chars(username_bare), filterstr), ["cn"])[0][0] (ldap.filter.escape_filter_chars(username_bare),
filterstr), ["cn"])[0][0]
else: else:
if ldap_binddn: if ldap_binddn:
# need to search directory with an bind_dn account 1st # need to search directory with an bind_dn account 1st
@@ -630,7 +640,9 @@ def ldap_auth(server='ldap', port=None,
con.simple_bind_s('', '') con.simple_bind_s('', '')
# search for groups where user is in # search for groups where user is in
filter = '(&(%s=%s)(%s))' % (ldap.filter.escape_filter_chars(group_member_attrib), filter = '(&(%s=%s)(%s))' % (ldap.filter.escape_filter_chars(
group_member_attrib
),
ldap.filter.escape_filter_chars(username), ldap.filter.escape_filter_chars(username),
group_filterstr) group_filterstr)
group_search_result = con.search_s(group_dn, group_search_result = con.search_s(group_dn,
@@ -648,3 +660,4 @@ def ldap_auth(server='ldap', port=None,
if filterstr[0] == '(' and filterstr[-1] == ')': # rfc4515 syntax if filterstr[0] == '(' and filterstr[-1] == ')': # rfc4515 syntax
filterstr = filterstr[1:-1] # parens added again where used filterstr = filterstr[1:-1] # parens added again where used
return ldap_auth_aux return ldap_auth_aux
+3 -2
View File
@@ -1262,8 +1262,9 @@ def render(text,
t = t or '' t = t or ''
a = escape(a) if a else '' a = escape(a) if a else ''
if k: if k:
if k.startswith('#'): if '#' in k and not ':' in k.split('#')[0]:
k = '#'+id_prefix+k[1:] # wikipage, not external url
k=k.replace('#','#'+id_prefix)
k = escape(k) k = escape(k)
title = ' title="%s"' % a.replace(META, DISABLED_META) if a else '' title = ' title="%s"' % a.replace(META, DISABLED_META) if a else ''
target = ' target="_blank"' if p == 'popup' else '' target = ' target="_blank"' if p == 'popup' else ''
+297 -266
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -388,7 +388,10 @@ class Response(Storage):
if not items: if not items:
raise HTTP(404) raise HTTP(404)
(t, f) = (items.group('table'), items.group('field')) (t, f) = (items.group('table'), items.group('field'))
field = db[t][f] try:
field = db[t][f]
except AttributeError:
raise HTTP(404)
try: try:
(filename, stream) = field.retrieve(name) (filename, stream) = field.retrieve(name)
except IOError: except IOError:
+3 -2
View File
@@ -1482,8 +1482,9 @@ class A(DIV):
(self['callback'], self['target'] or '', d) (self['callback'], self['target'] or '', d)
self['_href'] = self['_href'] or '#null' self['_href'] = self['_href'] or '#null'
elif self['cid']: elif self['cid']:
self['_onclick'] = 'web2py_component("%s","%s");%sreturn false;' % \ pre = self['pre_call'] + ';' if self['pre_call'] else ''
(self['_href'], self['cid'], d) self['_onclick'] = '%sweb2py_component("%s","%s");%sreturn false;' % \
(pre,self['_href'], self['cid'], d)
return DIV.xml(self) return DIV.xml(self)
+38 -30
View File
@@ -12,17 +12,24 @@ Plural subsystem is created by Vladyslav Kozlovskyy (Ukraine)
import os import os
import re import re
import sys
import pkgutil import pkgutil
from utf8 import Utf8
from cgi import escape
import portalocker
import logging import logging
import marshal import marshal
import copy_reg from cgi import escape
from threading import RLock
try:
import copyreg as copy_reg # python 3
except ImportError:
import copy_reg # python 2
from portalocker import read_locked, LockedFile
from utf8 import Utf8
from fileutils import listdir from fileutils import listdir
import settings import settings
from cfs import getcfs from cfs import getcfs
from thread import allocate_lock
from html import XML, xmlescape from html import XML, xmlescape
from contrib.markmin.markmin2html import render, markmin_escape from contrib.markmin.markmin2html import render, markmin_escape
from string import maketrans from string import maketrans
@@ -35,7 +42,7 @@ pjoin = os.path.join
pexists = os.path.exists pexists = os.path.exists
pdirname = os.path.dirname pdirname = os.path.dirname
isdir = os.path.isdir isdir = os.path.isdir
is_gae = settings.global_settings.web2py_runtime_gae is_gae = False # settings.global_settings.web2py_runtime_gae
DEFAULT_LANGUAGE = 'en' DEFAULT_LANGUAGE = 'en'
DEFAULT_LANGUAGE_NAME = 'English' DEFAULT_LANGUAGE_NAME = 'English'
@@ -137,7 +144,7 @@ def get_from_cache(cache, val, fun):
def clear_cache(filename): def clear_cache(filename):
cache = global_language_cache.setdefault( cache = global_language_cache.setdefault(
filename, ({}, allocate_lock())) filename, ({}, RLock()))
lang_dict, lock = cache lang_dict, lock = cache
lock.acquire() lock.acquire()
try: try:
@@ -147,11 +154,12 @@ def clear_cache(filename):
def read_dict_aux(filename): def read_dict_aux(filename):
lang_text = portalocker.read_locked(filename).replace('\r\n', '\n') lang_text = read_locked(filename).replace('\r\n', '\n')
clear_cache(filename) clear_cache(filename)
try: try:
return safe_eval(lang_text) or {} return safe_eval(lang_text) or {}
except Exception, e: except Exception:
e = sys.exc_info()[1]
status = 'Syntax error in %s (%s)' % (filename, e) status = 'Syntax error in %s (%s)' % (filename, e)
logging.error(status) logging.error(status)
return {'__corrupted__': status} return {'__corrupted__': status}
@@ -187,7 +195,8 @@ def read_possible_plural_rules():
DEFAULT_CONSTRUCT_PLURAL_FORM) DEFAULT_CONSTRUCT_PLURAL_FORM)
plurals[lang] = (lang, nplurals, get_plural_id, plurals[lang] = (lang, nplurals, get_plural_id,
construct_plural_form) construct_plural_form)
except ImportError, e: except ImportError:
e = sys.exc_info()[1]
logging.warn('Unable to import plural rules: %s' % e) logging.warn('Unable to import plural rules: %s' % e)
return plurals return plurals
@@ -261,17 +270,17 @@ def read_possible_languages_aux(langdir):
return langs return langs
def read_possible_languages(appdir): def read_possible_languages(langpath):
langdir = pjoin(appdir, 'languages') return getcfs('langs:' + langpath, langpath,
return getcfs('langs:' + langdir, langdir, lambda: read_possible_languages_aux(langpath))
lambda: read_possible_languages_aux(langdir))
def read_plural_dict_aux(filename): def read_plural_dict_aux(filename):
lang_text = portalocker.read_locked(filename).replace('\r\n', '\n') lang_text = read_locked(filename).replace('\r\n', '\n')
try: try:
return eval(lang_text) or {} return eval(lang_text) or {}
except Exception, e: except Exception:
e = sys.exc_info()[1]
status = 'Syntax error in %s (%s)' % (filename, e) status = 'Syntax error in %s (%s)' % (filename, e)
logging.error(status) logging.error(status)
return {'__corrupted__': status} return {'__corrupted__': status}
@@ -286,7 +295,7 @@ def write_plural_dict(filename, contents):
if '__corrupted__' in contents: if '__corrupted__' in contents:
return return
try: try:
fp = portalocker.LockedFile(filename, 'w') fp = LockedFile(filename, 'w')
fp.write('#!/usr/bin/env python\n{\n# "singular form (0)": ["first plural form (1)", "second plural form (2)", ...],\n') fp.write('#!/usr/bin/env python\n{\n# "singular form (0)": ["first plural form (1)", "second plural form (2)", ...],\n')
# coding: utf8\n{\n') # coding: utf8\n{\n')
for key in sorted(contents, lambda x, y: cmp(unicode(x, 'utf-8').lower(), unicode(y, 'utf-8').lower())): for key in sorted(contents, lambda x, y: cmp(unicode(x, 'utf-8').lower(), unicode(y, 'utf-8').lower())):
@@ -306,7 +315,7 @@ def write_dict(filename, contents):
if '__corrupted__' in contents: if '__corrupted__' in contents:
return return
try: try:
fp = portalocker.LockedFile(filename, 'w') fp = LockedFile(filename, 'w')
except (IOError, OSError): except (IOError, OSError):
if not settings.global_settings.web2py_runtime_gae: if not settings.global_settings.web2py_runtime_gae:
logging.warning('Unable to write to file %s' % filename) logging.warning('Unable to write to file %s' % filename)
@@ -434,11 +443,9 @@ class translator(object):
xx-yy.py -> xx.py -> xx-yy*.py -> xx*.py xx-yy.py -> xx.py -> xx-yy*.py -> xx*.py
""" """
def __init__(self, request): def __init__(self, langpath, http_accept_language):
self.request = request self.langpath = langpath
self.folder = request.folder self.http_accept_language = http_accept_language
self.langpath = pjoin(self.folder, 'languages')
self.http_accept_language = request.env.http_accept_language
self.is_writable = not is_gae self.is_writable = not is_gae
# filled in self.force(): # filled in self.force():
#------------------------ #------------------------
@@ -493,7 +500,7 @@ class translator(object):
construct_plural_form) # construct_plural_form() for current language construct_plural_form) # construct_plural_form() for current language
} }
""" """
info = read_possible_languages(self.folder) info = read_possible_languages(self.langpath)
if lang: if lang:
info = info.get(lang) info = info.get(lang)
return info return info
@@ -501,7 +508,7 @@ class translator(object):
def get_possible_languages(self): def get_possible_languages(self):
""" get list of all possible languages for current applications """ """ get list of all possible languages for current applications """
return list(set(self.current_languages + return list(set(self.current_languages +
[lang for lang in read_possible_languages(self.folder).iterkeys() [lang for lang in read_possible_languages(self.langpath).iterkeys()
if lang != 'default'])) if lang != 'default']))
def set_current_languages(self, *languages): def set_current_languages(self, *languages):
@@ -581,7 +588,7 @@ class translator(object):
default language will be selected if none default language will be selected if none
of them matches possible_languages. of them matches possible_languages.
""" """
pl_info = read_possible_languages(self.folder) pl_info = read_possible_languages(self.langpath)
def set_plural(language): def set_plural(language):
""" """
@@ -642,14 +649,14 @@ class translator(object):
self.t = read_dict(self.language_file) self.t = read_dict(self.language_file)
self.cache = global_language_cache.setdefault( self.cache = global_language_cache.setdefault(
self.language_file, self.language_file,
({}, allocate_lock())) ({}, RLock()))
set_plural(language) set_plural(language)
self.accepted_language = language self.accepted_language = language
return languages return languages
self.accepted_language = language or self.current_languages[0] self.accepted_language = language or self.current_languages[0]
self.language_file = self.default_language_file self.language_file = self.default_language_file
self.cache = global_language_cache.setdefault(self.language_file, self.cache = global_language_cache.setdefault(self.language_file,
({}, allocate_lock())) ({}, RLock()))
self.t = self.default_t self.t = self.default_t
set_plural(self.accepted_language) set_plural(self.accepted_language)
return languages return languages
@@ -670,7 +677,8 @@ class translator(object):
try: try:
otherT = self.otherTs[language] otherT = self.otherTs[language]
except KeyError: except KeyError:
otherT = self.otherTs[language] = translator(self.request) otherT = self.otherTs[language] = translator(
self.langpath, self.http_accept_language)
otherT.force(language) otherT.force(language)
return otherT(message, symbols, lazy=lazy) return otherT(message, symbols, lazy=lazy)
@@ -892,7 +900,7 @@ def findT(path, language=DEFAULT_LANGUAGE):
for filename in \ for filename in \
listdir(mp, '^.+\.py$', 0) + listdir(cp, '^.+\.py$', 0)\ listdir(mp, '^.+\.py$', 0) + listdir(cp, '^.+\.py$', 0)\
+ listdir(vp, '^.+\.html$', 0) + listdir(mop, '^.+\.py$', 0): + listdir(vp, '^.+\.html$', 0) + listdir(mop, '^.+\.py$', 0):
data = portalocker.read_locked(filename) data = read_locked(filename)
items = regex_translate.findall(data) items = regex_translate.findall(data)
for item in items: for item in items:
try: try:
+1 -1
View File
@@ -460,7 +460,7 @@ def wsgibase(environ, responder):
is_https=env.wsgi_url_scheme in HTTPS_SCHEMES is_https=env.wsgi_url_scheme in HTTPS_SCHEMES
or request.env.http_x_forwarded_proto in HTTPS_SCHEMES or request.env.http_x_forwarded_proto in HTTPS_SCHEMES
or env.https == 'on') or env.https == 'on')
request.uuid = request.compute_uuid() # requires client request.compute_uuid() # requires client
request.url = environ['PATH_INFO'] request.url = environ['PATH_INFO']
# ################################################## # ##################################################
+1 -1
View File
@@ -167,5 +167,5 @@ if __name__ == '__main__':
f.write('test ok') f.write('test ok')
f.close() f.close()
f = LockedFile('test.txt', mode='rb') f = LockedFile('test.txt', mode='rb')
print f.read() sys.stdout.write(f.read()+'\n')
f.close() f.close()
+3 -3
View File
@@ -1192,7 +1192,7 @@ re_REQUEST_LINE = re.compile(r"""^
(?P<host>[^/]+) # Host (?P<host>[^/]+) # Host
)? # )? #
(?P<path>(\*|/[^ \?]*)) # Path (?P<path>(\*|/[^ \?]*)) # Path
(\? (?P<query_string>[^ ]+))? # Query String (\? (?P<query_string>[^ ]*))? # Query String
\ # (single space) \ # (single space)
(?P<protocol>HTTPS?/1\.[01]) # Protocol (?P<protocol>HTTPS?/1\.[01]) # Protocol
$ $
@@ -1670,8 +1670,8 @@ class WSGIWorker(Worker):
peercert = conn.socket.getpeercert(binary_form=True) peercert = conn.socket.getpeercert(binary_form=True)
environ['SSL_CLIENT_RAW_CERT'] = \ environ['SSL_CLIENT_RAW_CERT'] = \
peercert and ssl.DER_cert_to_PEM_cert(peercert) peercert and ssl.DER_cert_to_PEM_cert(peercert)
except Exception, e: except Exception:
print e print sys.exc_info()[1]
if environ.get('HTTP_TRANSFER_ENCODING', '') == 'chunked': if environ.get('HTTP_TRANSFER_ENCODING', '') == 'chunked':
environ['wsgi.input'] = ChunkedReader(sock_file) environ['wsgi.input'] = ChunkedReader(sock_file)
+6 -6
View File
@@ -63,7 +63,6 @@ import os
import time import time
import multiprocessing import multiprocessing
import sys import sys
import cStringIO
import threading import threading
import traceback import traceback
import signal import signal
@@ -206,7 +205,6 @@ def executor(queue, task, out):
if task.app: if task.app:
os.chdir(os.environ['WEB2PY_PATH']) os.chdir(os.environ['WEB2PY_PATH'])
from gluon.shell import env, parse_path_info from gluon.shell import env, parse_path_info
from gluon.dal import BaseAdapter
from gluon import current from gluon import current
level = logging.getLogger().getEffectiveLevel() level = logging.getLogger().getEffectiveLevel()
logging.getLogger().setLevel(logging.WARN) logging.getLogger().setLevel(logging.WARN)
@@ -788,9 +786,9 @@ class Scheduler(MetaScheduler):
#the scheduler): then it wasn't expired, but now it is #the scheduler): then it wasn't expired, but now it is
db(st.status.belongs( db(st.status.belongs(
(QUEUED, ASSIGNED)))(st.stop_time < now).update(status=EXPIRED) (QUEUED, ASSIGNED)))(st.stop_time < now).update(status=EXPIRED)
all_available = db(st.status.belongs((QUEUED, ASSIGNED)))((st.times_run < st.repeats) | (st.repeats == 0))(st.start_time <= now)((st.stop_time == None) | (st.stop_time > now))(st.next_run_time <= now)(st.enabled == True) all_available = db(st.status.belongs((QUEUED, ASSIGNED)))((st.times_run < st.repeats) | (st.repeats == 0))(st.start_time <= now)((st.stop_time == None) | (st.stop_time > now))(st.next_run_time <= now)(st.enabled == True)
limit = len(all_workers) * (50 / len(wkgroups)) limit = len(all_workers) * (50 / (len(wkgroups) or 1))
#if there are a moltitude of tasks, let's figure out a maximum of tasks per worker. #if there are a moltitude of tasks, let's figure out a maximum of tasks per worker.
#this can be adjusted with some added intelligence (like esteeming how many tasks will #this can be adjusted with some added intelligence (like esteeming how many tasks will
#a worker complete before the ticker reassign them around, but the gain is quite small #a worker complete before the ticker reassign them around, but the gain is quite small
@@ -804,11 +802,13 @@ class Scheduler(MetaScheduler):
#let's freeze it up #let's freeze it up
db.commit() db.commit()
x = 0
for group in wkgroups.keys(): for group in wkgroups.keys():
tasks = all_available(st.group_name==group).select( tasks = all_available(st.group_name==group).select(
limitby=(0, limit), orderby=st.next_run_time) limitby=(0, limit), orderby=st.next_run_time)
#let's break up the queue evenly among workers #let's break up the queue evenly among workers
for task in tasks: for task in tasks:
x += 1
gname = task.group_name gname = task.group_name
ws = wkgroups.get(gname) ws = wkgroups.get(gname)
if ws: if ws:
@@ -827,10 +827,10 @@ class Scheduler(MetaScheduler):
db.commit() db.commit()
#I didn't report tasks but I'm working nonetheless!!!! #I didn't report tasks but I'm working nonetheless!!!!
if len(tasks) > 0: if x > 0:
self.empty_runs = 0 self.empty_runs = 0
logger.info('TICKER: workers are %s' % len(all_workers)) logger.info('TICKER: workers are %s' % len(all_workers))
logger.info('TICKER: tasks are %s' % len(tasks)) logger.info('TICKER: tasks are %s' % x)
def sleep(self): def sleep(self):
time.sleep(self.heartbeat * self.worker_status[1]) time.sleep(self.heartbeat * self.worker_status[1])
+1 -1
View File
@@ -1581,7 +1581,7 @@ class SQLFORM(FORM):
label = isinstance( label = isinstance(
field.label, str) and T(field.label) or field.label field.label, str) and T(field.label) or field.label
selectfields.append(OPTION(label, _value=str(field))) selectfields.append(OPTION(label, _value=str(field)))
operators = SELECT(*[T(option) for option in options]) operators = SELECT(*[OPTION(T(option), _value=option) for option in options])
if field.type == 'boolean': if field.type == 'boolean':
value_input = SELECT( value_input = SELECT(
OPTION(T("True"), _value="T"), OPTION(T("True"), _value="T"),
+10 -6
View File
@@ -16,9 +16,13 @@ Contributors:
import os import os
import cgi import cgi
import cStringIO
import logging import logging
from re import compile, sub, escape, DOTALL from re import compile, sub, escape, DOTALL
try:
import cStringIO as StringIO
except:
from io import StringIO
try: try:
# have web2py # have web2py
from restricted import RestrictedError from restricted import RestrictedError
@@ -791,13 +795,13 @@ def get_parsed(text):
class DummyResponse(): class DummyResponse():
def __init__(self): def __init__(self):
self.body = cStringIO.StringIO() self.body = StringIO.StringIO()
def write(self, data, escape=True): def write(self, data, escape=True):
if not escape: if not escape:
self.body.write(str(data)) self.body.write(str(data))
elif hasattr(data, 'xml') and callable(data.xml): elif hasattr(data, 'as_html') and callable(data.as_html):
self.body.write(data.xml()) self.body.write(data.as_html())
else: else:
# make it a string # make it a string
if not isinstance(data, (str, unicode)): if not isinstance(data, (str, unicode)):
@@ -870,7 +874,7 @@ def render(content="hello world",
# save current response class # save current response class
if context and 'response' in context: if context and 'response' in context:
old_response_body = context['response'].body old_response_body = context['response'].body
context['response'].body = cStringIO.StringIO() context['response'].body = StringIO.StringIO()
else: else:
old_response_body = None old_response_body = None
context['response'] = Response() context['response'] = Response()
@@ -887,7 +891,7 @@ def render(content="hello world",
stream = open(filename, 'rb') stream = open(filename, 'rb')
close_stream = True close_stream = True
elif content: elif content:
stream = cStringIO.StringIO(content) stream = StringIO.StringIO(content)
# Execute the template. # Execute the template.
code = str(TemplateParser(stream.read( code = str(TemplateParser(stream.read(
+8 -5
View File
@@ -13,7 +13,10 @@ else:
import unittest import unittest
import datetime import datetime
import cStringIO try:
import cStringIO as StringIO
except:
from io import StringIO
from dal import DAL, Field, Table, SQLALL from dal import DAL, Field, Table, SQLALL
ALLOWED_DATATYPES = [ ALLOWED_DATATYPES = [
@@ -555,11 +558,11 @@ class TestImportExportFields(unittest.TestCase):
id = db.person.insert(name=str(k)) id = db.person.insert(name=str(k))
db.pet.insert(friend=id,name=str(k)) db.pet.insert(friend=id,name=str(k))
db.commit() db.commit()
stream = cStringIO.StringIO() stream = StringIO.StringIO()
db.export_to_csv_file(stream) db.export_to_csv_file(stream)
db(db.pet).delete() db(db.pet).delete()
db(db.person).delete() db(db.person).delete()
stream = cStringIO.StringIO(stream.getvalue()) stream = StringIO.StringIO(stream.getvalue())
db.import_from_csv_file(stream) db.import_from_csv_file(stream)
assert db(db.person.id==db.pet.friend)(db.person.name==db.pet.name).count()==10 assert db(db.person.id==db.pet.friend)(db.person.name==db.pet.name).count()==10
db.pet.drop() db.pet.drop()
@@ -579,9 +582,9 @@ class TestImportExportUuidFields(unittest.TestCase):
id = db.person.insert(name=str(k),uuid=str(k)) id = db.person.insert(name=str(k),uuid=str(k))
db.pet.insert(friend=id,name=str(k)) db.pet.insert(friend=id,name=str(k))
db.commit() db.commit()
stream = cStringIO.StringIO() stream = StringIO.StringIO()
db.export_to_csv_file(stream) db.export_to_csv_file(stream)
stream = cStringIO.StringIO(stream.getvalue()) stream = StringIO.StringIO(stream.getvalue())
db.import_from_csv_file(stream) db.import_from_csv_file(stream)
assert db(db.person).count()==10 assert db(db.person).count()==10
assert db(db.person.id==db.pet.friend)(db.person.name==db.pet.name).count()==20 assert db(db.person.id==db.pet.friend)(db.person.name==db.pet.name).count()==20
+5 -7
View File
@@ -57,20 +57,18 @@ try:
class TestTranslations(unittest.TestCase): class TestTranslations(unittest.TestCase):
def setUp(self): def setUp(self):
self.request = Storage()
if os.path.isdir('gluon'): if os.path.isdir('gluon'):
self.request.folder = 'applications/welcome' self.langpath = 'applications/welcome/languages'
else: else:
self.request.folder = os.path.realpath( self.langpath = os.path.realpath(
'../../applications/welcome') '../../applications/welcome/languages')
self.request.env = Storage() self.http_accept_language = 'en'
self.request.env.http_accept_language = 'en'
def tearDown(self): def tearDown(self):
pass pass
def test_plain(self): def test_plain(self):
T = languages.translator(self.request) T = languages.translator(self.langpath, self.http_accept_language)
self.assertEqual(str(T('Hello World')), self.assertEqual(str(T('Hello World')),
'Hello World') 'Hello World')
self.assertEqual(str(T('Hello World## comment')), self.assertEqual(str(T('Hello World## comment')),
+24 -23
View File
@@ -5035,30 +5035,31 @@ class Wiki(object):
if True: if True:
submenu = [] submenu = []
menu.append((current.T('[Wiki]'), None, None, submenu)) menu.append((current.T('[Wiki]'), None, None, submenu))
if URL() == URL(controller, function): if self.auth.user:
if not str(request.args(0)).startswith('_'): if URL() == URL(controller, function):
slug = request.args(0) or 'index' if not str(request.args(0)).startswith('_'):
mode = 1 slug = request.args(0) or 'index'
elif request.args(0) == '_edit': mode = 1
slug = request.args(1) or 'index' elif request.args(0) == '_edit':
mode = 2 slug = request.args(1) or 'index'
elif request.args(0) == '_editmedia': mode = 2
slug = request.args(1) or 'index' elif request.args(0) == '_editmedia':
mode = 3 slug = request.args(1) or 'index'
else: mode = 3
mode = 0 else:
if mode in (2, 3): mode = 0
submenu.append((current.T('View Page'), None, if mode in (2, 3):
URL(controller, function, args=slug))) submenu.append((current.T('View Page'), None,
if mode in (1, 3): URL(controller, function, args=slug)))
submenu.append((current.T('Edit Page'), None, if mode in (1, 3):
URL(controller, function, args=('_edit', slug)))) submenu.append((current.T('Edit Page'), None,
if mode in (1, 2): URL(controller, function, args=('_edit', slug))))
submenu.append((current.T('Edit Page Media'), None, if mode in (1, 2):
URL(controller, function, args=('_editmedia', slug)))) submenu.append((current.T('Edit Page Media'), None,
URL(controller, function, args=('_editmedia', slug))))
submenu.append((current.T('Create New Page'), None, submenu.append((current.T('Create New Page'), None,
URL(controller, function, args=('_create')))) URL(controller, function, args=('_create'))))
if self.can_manage(): if self.can_manage():
submenu.append((current.T('Manage Pages'), None, submenu.append((current.T('Manage Pages'), None,
URL(controller, function, args=('_pages')))) URL(controller, function, args=('_pages'))))
+30 -9
View File
@@ -19,22 +19,37 @@ import random
import time import time
import os import os
import re import re
import sys
import logging import logging
import socket import socket
import cPickle
import base64 import base64
import zlib import zlib
python_version = sys.version_info[0]
if python_version == 2:
import cPickle as pickle
else:
import pickle
try: try:
from Crypto.Cipher import AES from Crypto.Cipher import AES
except ImportError: except ImportError:
from contrib import aes as AES try:
from .aes import AES
except (ImportError, ValueError):
from contrib.aes import AES
try: try:
from contrib.pbkdf2 import pbkdf2_hex from contrib.pbkdf2 import pbkdf2_hex
HAVE_PBKDF2 = True HAVE_PBKDF2 = True
except ImportError: except ImportError:
HAVE_PBKDF2 = False try:
from .pbkdf2 import pbkdf2_hex
HAVE_PBKDF2 = True
except (ImportError, ValueError):
HAVE_PBKDF2 = False
logger = logging.getLogger("web2py") logger = logging.getLogger("web2py")
@@ -115,7 +130,7 @@ def pad(s, n=32, padchar='.'):
def secure_dumps(data, encryption_key, hash_key=None, compression_level=None): def secure_dumps(data, encryption_key, hash_key=None, compression_level=None):
if not hash_key: if not hash_key:
hash_key = hashlib.sha1(encryption_key).hexdigest() hash_key = hashlib.sha1(encryption_key).hexdigest()
dump = cPickle.dumps(data) dump = pickle.dumps(data)
if compression_level: if compression_level:
dump = zlib.compress(dump, compression_level) dump = zlib.compress(dump, compression_level)
key = pad(encryption_key[:32]) key = pad(encryption_key[:32])
@@ -141,8 +156,8 @@ def secure_loads(data, encryption_key, hash_key=None, compression_level=None):
data = data.rstrip(' ') data = data.rstrip(' ')
if compression_level: if compression_level:
data = zlib.decompress(data) data = zlib.decompress(data)
return cPickle.loads(data) return pickle.loads(data)
except (TypeError, cPickle.UnpicklingError): except (TypeError, pickle.UnpicklingError):
return None return None
### compute constant CTOKENS ### compute constant CTOKENS
@@ -173,7 +188,10 @@ def initialize_urandom():
# try to add process-specific entropy # try to add process-specific entropy
frandom = open('/dev/urandom', 'wb') frandom = open('/dev/urandom', 'wb')
try: try:
frandom.write(''.join(chr(t) for t in ctokens)) if python_version == 2:
frandom.write(''.join(chr(t) for t in ctokens)) # python 2
else:
frandom.write(bytes([]).join(bytes([t]) for t in ctokens)) # python 3
finally: finally:
frandom.close() frandom.close()
except IOError: except IOError:
@@ -185,8 +203,11 @@ def initialize_urandom():
"""Cryptographically secure session management is not possible on your system because """Cryptographically secure session management is not possible on your system because
your system does not provide a cryptographically secure entropy source. your system does not provide a cryptographically secure entropy source.
This is not specific to web2py; consider deploying on a different operating system.""") This is not specific to web2py; consider deploying on a different operating system.""")
unpacked_ctokens = struct.unpack('=QQ', string.join( if python_version == 2:
(chr(x) for x in ctokens), '')) packed = ''.join(chr(x) for x in ctokens) # python 2
else:
packed = bytes([]).join(bytes([x]) for x in ctokens) # python 3
unpacked_ctokens = struct.unpack('=QQ', packed)
return unpacked_ctokens, have_urandom return unpacked_ctokens, have_urandom
UNPACKED_CTOKENS, HAVE_URANDOM = initialize_urandom() UNPACKED_CTOKENS, HAVE_URANDOM = initialize_urandom()
+3 -7
View File
@@ -23,6 +23,7 @@ Typical usage:
""" """
from __future__ import with_statement from __future__ import with_statement
from gluon import current
from gluon.storage import Storage from gluon.storage import Storage
from optparse import OptionParser from optparse import OptionParser
import cPickle import cPickle
@@ -93,10 +94,7 @@ class SessionSetDb(SessionSet):
def get(self): def get(self):
"""Return list of SessionDb instances for existing sessions.""" """Return list of SessionDb instances for existing sessions."""
sessions = [] sessions = []
tablename = 'web2py_session' table = current.response.session_db_table
from gluon import current
(record_id_name, table, record_id, unique_key) = \
current.response._dbtable_and_field
for row in table._db(table.id > 0).select(): for row in table._db(table.id > 0).select():
sessions.append(SessionDb(row)) sessions.append(SessionDb(row))
return sessions return sessions
@@ -121,9 +119,7 @@ class SessionDb(object):
self.row = row self.row = row
def delete(self): def delete(self):
from gluon import current table = current.response.session_db_table
(record_id_name, table, record_id, unique_key) = \
current.response._dbtable_and_field
self.row.delete_record() self.row.delete_record()
table._db.commit() table._db.commit()