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