Merge branch 'master' of github.com:web2py/web2py

This commit is contained in:
mdipierro committed 2015-03-31 14:45:59 -05:00
commit 1b39736561
4 files changed
+192 -211

No files matched your search

+128 -160
View File
@@ -287,29 +287,28 @@ class Mail(object):
self.result = {} self.result = {}
self.error = None self.error = None
def send( def send(self,
self,
to, to,
subject = '[no subject]', subject='[no subject]',
message = '[no message]', message='[no message]',
attachments = None, attachments=None,
cc = None, cc=None,
bcc = None, bcc=None,
reply_to = None, reply_to=None,
sender = None, sender=None,
encoding = 'utf-8', encoding='utf-8',
raw = False, raw=False,
headers = {}, headers={},
from_address = None, from_address=None,
cipher_type = None, cipher_type=None,
sign = None, sign=None,
sign_passphrase = None, sign_passphrase=None,
encrypt = None, encrypt=None,
x509_sign_keyfile = None, x509_sign_keyfile=None,
x509_sign_chainfile = None, x509_sign_chainfile=None,
x509_sign_certfile = None, x509_sign_certfile=None,
x509_crypt_certfiles = None, x509_crypt_certfiles=None,
x509_nocerts = None x509_nocerts=None
): ):
""" """
Sends an email using data specified in constructor Sends an email using data specified in constructor
@@ -664,7 +663,7 @@ class Mail(object):
# SIGN # SIGN
if sign: if sign:
#key for signing # key for signing
try: try:
keyfile_bio = BIO.openfile(x509_sign_keyfile)\ keyfile_bio = BIO.openfile(x509_sign_keyfile)\
if os.path.isfile(x509_sign_keyfile)\ if os.path.isfile(x509_sign_keyfile)\
@@ -796,7 +795,7 @@ class Mail(object):
subject=subject, body=text, **xcc) subject=subject, body=text, **xcc)
else: else:
smtp_args = self.settings.server.split(':') smtp_args = self.settings.server.split(':')
kwargs = dict(timeout = self.settings.timeout) kwargs = dict(timeout=self.settings.timeout)
if self.settings.ssl: if self.settings.ssl:
server = smtplib.SMTP_SSL(*smtp_args, **kwargs) server = smtplib.SMTP_SSL(*smtp_args, **kwargs)
else: else:
@@ -839,8 +838,7 @@ class Recaptcha(DIV):
API_SERVER = 'http://www.google.com/recaptcha/api' API_SERVER = 'http://www.google.com/recaptcha/api'
VERIFY_SERVER = 'http://www.google.com/recaptcha/api/verify' VERIFY_SERVER = 'http://www.google.com/recaptcha/api/verify'
def __init__( def __init__(self,
self,
request=None, request=None,
public_key='', public_key='',
private_key='', private_key='',
@@ -849,7 +847,7 @@ class Recaptcha(DIV):
error_message='invalid', error_message='invalid',
label='Verify:', label='Verify:',
options='', options='',
comment = '', comment='',
ajax=False ajax=False
): ):
request = request or current.request request = request or current.request
@@ -942,7 +940,7 @@ class Recaptcha(DIV):
jQuery.getScript('%(url)s',function() { jQuery.getScript('%(url)s',function() {
Recaptcha.create('%(public_key)s', Recaptcha.create('%(public_key)s',
'recaptcha',jQuery.extend(RecaptchaOptions,{'callback':Recaptcha.focus_response_field})) 'recaptcha',jQuery.extend(RecaptchaOptions,{'callback':Recaptcha.focus_response_field}))
}) """ % ({'options':RecaptchaOptions,'url':url_recaptcha_js,'public_key':public_key}) }) """ % ({'options': RecaptchaOptions, 'url': url_recaptcha_js, 'public_key': public_key})
captcha = DIV( captcha = DIV(
SCRIPT( SCRIPT(
script, script,
@@ -963,6 +961,7 @@ class Recaptcha(DIV):
captcha.append(DIV(self.errors['captcha'], _class='error')) captcha.append(DIV(self.errors['captcha'], _class='error'))
return XML(captcha).xml() return XML(captcha).xml()
# this should only be used for catcha and perhaps not even for that # this should only be used for catcha and perhaps not even for that
def addrow(form, a, b, c, style, _id, position=-1): def addrow(form, a, b, c, style, _id, position=-1):
if style == "divs": if style == "divs":
@@ -1050,14 +1049,14 @@ class Auth(object):
profile_fields=None, profile_fields=None,
email_case_sensitive=True, email_case_sensitive=True,
username_case_sensitive=True, username_case_sensitive=True,
update_fields = ['email'], update_fields=['email'],
ondelete="CASCADE", ondelete="CASCADE",
client_side = True, client_side=True,
renew_session_onlogin=True, renew_session_onlogin=True,
renew_session_onlogout=True, renew_session_onlogout=True,
keep_session_onlogin=True, keep_session_onlogin=True,
keep_session_onlogout=False, keep_session_onlogout=False,
wiki = Settings(), wiki=Settings(),
) )
# ## these are messages that can be customized # ## these are messages that can be customized
default_messages = dict( default_messages = dict(
@@ -1099,8 +1098,7 @@ class Auth(object):
retrieve_username_subject='Username retrieve', retrieve_username_subject='Username retrieve',
retrieve_password='Your password is: %(password)s', retrieve_password='Your password is: %(password)s',
retrieve_password_subject='Password retrieve', retrieve_password_subject='Password retrieve',
reset_password= reset_password='Click on the link %(link)s to reset your password',
'Click on the link %(link)s to reset your password',
reset_password_subject='Password reset', reset_password_subject='Password reset',
invalid_reset_password='Invalid reset password', invalid_reset_password='Invalid reset password',
profile_updated='Profile updated', profile_updated='Profile updated',
@@ -1263,7 +1261,7 @@ class Auth(object):
f=f, args=args, vars=vars, scheme=scheme) f=f, args=args, vars=vars, scheme=scheme)
def here(self): def here(self):
return URL(args=current.request.args,vars=current.request.get_vars) return URL(args=current.request.args, vars=current.request.get_vars)
def __init__(self, environment=None, db=None, mailer=True, def __init__(self, environment=None, db=None, mailer=True,
hmac_key=None, controller='default', function='user', hmac_key=None, controller='default', function='user',
@@ -1365,7 +1363,8 @@ class Auth(object):
# ## these are messages that can be customized # ## these are messages that can be customized
messages = self.messages = Messages(current.T) messages = self.messages = Messages(current.T)
messages.update(Auth.default_messages) messages.update(Auth.default_messages)
messages.update(ajax_failed_authentication=DIV(H4('NOT AUTHORIZED'), messages.update(ajax_failed_authentication=
DIV(H4('NOT AUTHORIZED'),
'Please ', 'Please ',
A('login', A('login',
_href=self.settings.login_url + _href=self.settings.login_url +
@@ -1392,7 +1391,7 @@ class Auth(object):
return next return next
def _get_user_id(self): def _get_user_id(self):
"accessor for auth.user_id" """accessor for auth.user_id"""
return self.user and self.user.id or None return self.user and self.user.id or None
user_id = property(_get_user_id, doc="user.id or None") user_id = property(_get_user_id, doc="user.id or None")
@@ -1545,10 +1544,10 @@ class Auth(object):
self.bar[0][3].append((item['name'], False, item['href'])) self.bar[0][3].append((item['name'], False, item['href']))
def bootstrap3(): # Default web2py scaffolding def bootstrap3(): # Default web2py scaffolding
def rename(icon): return icon+' '+icon.replace('icon','glyphicon') def rename(icon): return icon+' '+icon.replace('icon', 'glyphicon')
self.bar = UL(LI(Anr(I(_class=rename('icon '+items[0]['icon'])), self.bar = UL(LI(Anr(I(_class=rename('icon '+items[0]['icon'])),
' ' + items[0]['name'], ' ' + items[0]['name'],
_href=items[0]['href'])),_class='dropdown-menu') _href=items[0]['href'])), _class='dropdown-menu')
del items[0] del items[0]
for item in items: for item in items:
self.bar.insert(-1, LI(Anr(I(_class=rename('icon '+item['icon'])), self.bar.insert(-1, LI(Anr(I(_class=rename('icon '+item['icon'])),
@@ -1557,13 +1556,13 @@ class Auth(object):
self.bar.insert(-1, LI('', _class='divider')) self.bar.insert(-1, LI('', _class='divider'))
if self.user_id: if self.user_id:
self.bar = LI(Anr(prefix, user_identifier, self.bar = LI(Anr(prefix, user_identifier,
_href='#',_class="dropdown-toggle", _href='#', _class="dropdown-toggle",
data={'toggle':'dropdown'}), data={'toggle': 'dropdown'}),
self.bar,_class='dropdown') self.bar, _class='dropdown')
else: else:
self.bar = LI(Anr(T('Log In'), self.bar = LI(Anr(T('Log In'),
_href='#',_class="dropdown-toggle", _href='#', _class="dropdown-toggle",
data={'toggle':'dropdown'}), self.bar, data={'toggle': 'dropdown'}), self.bar,
_class='dropdown') _class='dropdown')
def bare(): def bare():
@@ -1714,7 +1713,7 @@ class Auth(object):
""" """
current_record_label = current_record_label or current.T( current_record_label = current_record_label or current.T(
current_record.replace('_',' ').title()) current_record.replace('_', ' ').title())
for table in tables: for table in tables:
fieldnames = table.fields() fieldnames = table.fields()
if ('id' in fieldnames and if ('id' in fieldnames and
@@ -1787,8 +1786,10 @@ class Auth(object):
""" """
db = self.db db = self.db
if migrate is None: migrate = db._migrate if migrate is None:
if fake_migrate is None: fake_migrate = db._fake_migrate migrate = db._migrate
if fake_migrate is None:
fake_migrate = db._fake_migrate
settings = self.settings settings = self.settings
if username is None: if username is None:
username = settings.use_username username = settings.use_username
@@ -1895,8 +1896,7 @@ class Auth(object):
settings.table_group_name, settings.table_group_name,
Field('role', length=512, default='', Field('role', length=512, default='',
label=self.messages.label_role, label=self.messages.label_role,
requires=IS_NOT_IN_DB( requires=IS_NOT_IN_DB(db, '%s.role' % settings.table_group_name)),
db, '%s.role' % settings.table_group_name)),
Field('description', 'text', Field('description', 'text',
label=self.messages.label_description), label=self.messages.label_description),
*extra_fields, *extra_fields,
@@ -2116,8 +2116,7 @@ class Auth(object):
basic_realm = unicode(basic_auth_realm) basic_realm = unicode(basic_auth_realm)
elif basic_auth_realm is True: elif basic_auth_realm is True:
basic_realm = u'' + current.request.application basic_realm = u'' + current.request.application
http_401 = HTTP(401, u'Not Authorized', http_401 = HTTP(401, u'Not Authorized', **{'WWW-Authenticate': u'Basic realm="' + basic_realm + '"'})
**{'WWW-Authenticate': u'Basic realm="' + basic_realm + '"'})
if not basic or not basic[:6].lower() == 'basic ': if not basic or not basic[:6].lower() == 'basic ':
if basic_auth_realm: if basic_auth_realm:
raise http_401 raise http_401
@@ -2135,16 +2134,15 @@ class Auth(object):
from gluon.settings import global_settings from gluon.settings import global_settings
if global_settings.web2py_runtime_gae: if global_settings.web2py_runtime_gae:
user = Row(self.table_user()._filter_fields(user, id=True)) user = Row(self.table_user()._filter_fields(user, id=True))
delattr(user,'password') delattr(user, 'password')
else: else:
user = Row(user) user = Row(user)
for key, value in user.items(): for key, value in user.items():
if callable(value) or key=='password': if callable(value) or key == 'password':
delattr(user,key) delattr(user, key)
if self.settings.renew_session_onlogin: if self.settings.renew_session_onlogin:
current.session.renew(clear_session=not self.settings.keep_session_onlogin) current.session.renew(clear_session=not self.settings.keep_session_onlogin)
current.session.auth = Storage( current.session.auth = Storage(user=user,
user = user,
last_visit=current.request.now, last_visit=current.request.now,
expiration=self.settings.expiration, expiration=self.settings.expiration,
hmac_key=web2py_uuid()) hmac_key=web2py_uuid())
@@ -2178,8 +2176,7 @@ class Auth(object):
else: else:
# user not in database try other login methods # user not in database try other login methods
for login_method in self.settings.login_methods: for login_method in self.settings.login_methods:
if login_method != self and \ if login_method != self and login_method(username, password):
login_method(username, password):
self.user = username self.user = username
return username return username
return False return False
@@ -2196,20 +2193,14 @@ class Auth(object):
elif not fields.get(settings.userfield): elif not fields.get(settings.userfield):
raise ValueError("register_bare: " + raise ValueError("register_bare: " +
"userfield not provided or invalid") "userfield not provided or invalid")
fields[settings.passfield] = \ fields[settings.passfield] = settings.table_user[settings.passfield].validate(fields[settings.passfield])[0]
settings.table_user[settings.passfield].validate( user = self.get_or_create_user(fields, login=False, get=False, update_fields=self.settings.update_fields)
fields[settings.passfield])[0]
user = self.get_or_create_user(
fields, login=False, get=False,
update_fields=self.settings.update_fields)
if not user: if not user:
# get or create did not create a user (it ignores duplicate records) # get or create did not create a user (it ignores duplicate records)
return False return False
return user return user
def cas_login(self,
def cas_login(
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -2303,18 +2294,17 @@ class Auth(object):
raise HTTP(200, message) raise HTTP(200, message)
def _reset_two_factor_auth(self, session): def _reset_two_factor_auth(self, session):
'''When two-step authentication is enabled, this function is used to """When two-step authentication is enabled, this function is used to
clear the session after successfully completing second challenge clear the session after successfully completing second challenge
or when the maximum number of tries allowed has expired. or when the maximum number of tries allowed has expired.
''' """
session.auth_two_factor_user = None session.auth_two_factor_user = None
session.auth_two_factor = None session.auth_two_factor = None
session.auth_two_factor_enabled = False session.auth_two_factor_enabled = False
# Allow up to 4 attempts (the 1st one plus 3 more) # Allow up to 4 attempts (the 1st one plus 3 more)
session.auth_two_factor_tries_left = 3 session.auth_two_factor_tries_left = 3
def login( def login(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -2424,7 +2414,7 @@ class Auth(object):
if settings.remember_me_form: if settings.remember_me_form:
extra_fields = [ extra_fields = [
Field('remember_me','boolean',default=False, Field('remember_me', 'boolean', default=False,
label = self.messages.label_remember_me)] label = self.messages.label_remember_me)]
else: else:
extra_fields = [] extra_fields = []
@@ -2549,7 +2539,7 @@ class Auth(object):
# auth.settings.two_factor_authentication_group # auth.settings.two_factor_authentication_group
if user and self.settings.two_factor_authentication_group: if user and self.settings.two_factor_authentication_group:
role = self.settings.two_factor_authentication_group role = self.settings.two_factor_authentication_group
session.auth_two_factor_enabled = self.has_membership(user_id=user.id,role=role) session.auth_two_factor_enabled = self.has_membership(user_id=user.id, role=role)
# challenge # challenge
if session.auth_two_factor_enabled: if session.auth_two_factor_enabled:
form = SQLFORM.factory( form = SQLFORM.factory(
@@ -2673,8 +2663,7 @@ class Auth(object):
if not next is None: if not next is None:
redirect(next) redirect(next)
def register( def register(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -2728,7 +2717,7 @@ class Auth(object):
if self.settings.register_verify_password: if self.settings.register_verify_password:
extra_fields = [ extra_fields = [
Field("password_two", "password", requires=IS_EQUAL_TO( Field("password_two", "password", requires=IS_EQUAL_TO(
request.post_vars.get(passfield,None), request.post_vars.get(passfield, None),
error_message=self.messages.mismatched_password), error_message=self.messages.mismatched_password),
label=current.T("Confirm Password"))] label=current.T("Confirm Password"))]
else: else:
@@ -2772,7 +2761,7 @@ class Auth(object):
link = self.url( link = self.url(
self.settings.function, args=('verify_email', key), scheme=True) self.settings.function, args=('verify_email', key), scheme=True)
d = dict(form.vars) d = dict(form.vars)
d.update(dict(key=key, link=link,username=form.vars[username])) d.update(dict(key=key, link=link, username=form.vars[username]))
if not (self.settings.mailer and self.settings.mailer.send( if not (self.settings.mailer and self.settings.mailer.send(
to=form.vars.email, to=form.vars.email,
subject=self.messages.verify_email_subject, subject=self.messages.verify_email_subject,
@@ -2813,8 +2802,7 @@ class Auth(object):
return True return True
return False return False
def verify_email( def verify_email(self,
self,
next=DEFAULT, next=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
log=DEFAULT, log=DEFAULT,
@@ -2847,8 +2835,7 @@ class Auth(object):
callback(onaccept, user) callback(onaccept, user)
redirect(next) redirect(next)
def retrieve_username( def retrieve_username(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -2905,8 +2892,7 @@ class Auth(object):
username = ', '.join(u.username for u in users) username = ', '.join(u.username for u in users)
self.settings.mailer.send(to=form.vars.email, self.settings.mailer.send(to=form.vars.email,
subject=self.messages.retrieve_username_subject, subject=self.messages.retrieve_username_subject,
message=self.messages.retrieve_username message=self.messages.retrieve_username % dict(username=username))
% dict(username=username))
session.flash = self.messages.email_sent session.flash = self.messages.email_sent
for user in users: for user in users:
self.log_event(log, user) self.log_event(log, user)
@@ -2931,8 +2917,7 @@ class Auth(object):
password += random.choice(specials) password += random.choice(specials)
return ''.join(random.sample(password, len(password))) return ''.join(random.sample(password, len(password)))
def reset_password_deprecated( def reset_password_deprecated(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -2991,8 +2976,7 @@ class Auth(object):
if self.settings.mailer and \ if self.settings.mailer and \
self.settings.mailer.send(to=form.vars.email, self.settings.mailer.send(to=form.vars.email,
subject=self.messages.retrieve_password_subject, subject=self.messages.retrieve_password_subject,
message=self.messages.retrieve_password message=self.messages.retrieve_password % dict(password=password)):
% dict(password=password)):
session.flash = self.messages.email_sent session.flash = self.messages.email_sent
else: else:
session.flash = self.messages.unable_to_send_email session.flash = self.messages.unable_to_send_email
@@ -3006,8 +2990,7 @@ class Auth(object):
table_user.email.requires = old_requires table_user.email.requires = old_requires
return form return form
def reset_password( def reset_password(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -3071,8 +3054,7 @@ class Auth(object):
redirect(next, client_side=self.settings.client_side) redirect(next, client_side=self.settings.client_side)
return form return form
def request_reset_password( def request_reset_password(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -3101,7 +3083,7 @@ class Auth(object):
log = self.messages['reset_password_log'] log = self.messages['reset_password_log']
userfield = self.settings.login_userfield or 'username' \ userfield = self.settings.login_userfield or 'username' \
if 'username' in table_user.fields else 'email' if 'username' in table_user.fields else 'email'
if userfield=='email': if userfield == 'email':
table_user.email.requires = [ table_user.email.requires = [
IS_EMAIL(error_message=self.messages.invalid_email), IS_EMAIL(error_message=self.messages.invalid_email),
IS_IN_DB(self.db, table_user.email, IS_IN_DB(self.db, table_user.email,
@@ -3169,8 +3151,7 @@ class Auth(object):
return True return True
return False return False
def retrieve_password( def retrieve_password(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -3181,8 +3162,7 @@ class Auth(object):
else: else:
return self.reset_password_deprecated(next, onvalidation, onaccept, log) return self.reset_password_deprecated(next, onvalidation, onaccept, log)
def change_password( def change_password(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -3211,9 +3191,9 @@ class Auth(object):
log = self.messages['change_password_log'] log = self.messages['change_password_log']
passfield = self.settings.password_field passfield = self.settings.password_field
requires = table_user[passfield].requires requires = table_user[passfield].requires
if not isinstance(requires,(list, tuple)): if not isinstance(requires, (list, tuple)):
requires = [requires] requires = [requires]
requires = filter(lambda t:isinstance(t,CRYPT), requires) requires = filter(lambda t: isinstance(t, CRYPT), requires)
if requires: if requires:
requires[0].min_length = 0 requires[0].min_length = 0
form = SQLFORM.factory( form = SQLFORM.factory(
@@ -3237,7 +3217,7 @@ class Auth(object):
onvalidation=onvalidation, onvalidation=onvalidation,
hideerror=self.settings.hideerror): hideerror=self.settings.hideerror):
current_user = s.select(limitby=(0,1), orderby_on_limitby=False).first() current_user = s.select(limitby=(0, 1), orderby_on_limitby=False).first()
if not form.vars['old_password'] == current_user[passfield]: if not form.vars['old_password'] == current_user[passfield]:
form.errors['old_password'] = self.messages.invalid_password form.errors['old_password'] = self.messages.invalid_password
else: else:
@@ -3253,8 +3233,7 @@ class Auth(object):
redirect(next, client_side=self.settings.client_side) redirect(next, client_side=self.settings.client_side)
return form return form
def profile( def profile(self,
self,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
onaccept=DEFAULT, onaccept=DEFAULT,
@@ -3314,7 +3293,7 @@ class Auth(object):
onaccept = self.settings.login_onaccept onaccept = self.settings.login_onaccept
if onaccept: if onaccept:
form = Storage(dict(vars=self.user)) form = Storage(dict(vars=self.user))
if not isinstance(onaccept,(list, tuple)): if not isinstance(onaccept, (list, tuple)):
onaccept = [onaccept] onaccept = [onaccept]
for callback in onaccept: for callback in onaccept:
callback(form) callback(form)
@@ -3615,8 +3594,7 @@ class Auth(object):
if group_id in self.user_groups: del self.user_groups[group_id] if group_id in self.user_groups: del self.user_groups[group_id]
return ret return ret
def has_permission( def has_permission(self,
self,
name='any', name='any',
table_name='', table_name='',
record_id=0, record_id=0,
@@ -3668,8 +3646,7 @@ class Auth(object):
table_name=table_name, record_id=record_id)) table_name=table_name, record_id=record_id))
return r return r
def add_permission( def add_permission(self,
self,
group_id, group_id,
name='any', name='any',
table_name='', table_name='',
@@ -3683,7 +3660,7 @@ class Auth(object):
if group_id == 0: if group_id == 0:
group_id = self.user_group() group_id = self.user_group()
record = self.db(permission.group_id == group_id)(permission.name == name)(permission.table_name == str(table_name))( record = self.db(permission.group_id == group_id)(permission.name == name)(permission.table_name == str(table_name))(
permission.record_id == long(record_id)).select(limitby=(0,1), orderby_on_limitby=False).first() permission.record_id == long(record_id)).select(limitby=(0, 1), orderby_on_limitby=False).first()
if record: if record:
id = record.id id = record.id
else: else:
@@ -3696,8 +3673,7 @@ class Auth(object):
record_id=record_id)) record_id=record_id))
return id return id
def del_permission( def del_permission(self,
self,
group_id, group_id,
name='any', name='any',
table_name='', table_name='',
@@ -3862,7 +3838,8 @@ class Auth(object):
force_render=False, force_render=False,
groups=None): groups=None):
if controller and function: resolve = False if controller and function:
resolve = False
if not hasattr(self, '_wiki'): if not hasattr(self, '_wiki'):
self._wiki = Wiki(self, render=render, self._wiki = Wiki(self, render=render,
@@ -3885,7 +3862,7 @@ class Auth(object):
if resolve: if resolve:
if slug: if slug:
wiki = self._wiki.read(slug, force_render) wiki = self._wiki.read(slug, force_render)
if isinstance(wiki, dict) and wiki.has_key('content'): if isinstance(wiki, dict) and wiki.has_key('content'): # FIXME: .has_key() is deprecated
# We don't want to return a dict object, just the wiki # We don't want to return a dict object, just the wiki
wiki = wiki['content'] wiki = wiki['content']
else: else:
@@ -4013,8 +3990,7 @@ class Crud(object):
return Auth.archive(form, archive_table=archive_table, return Auth.archive(form, archive_table=archive_table,
current_record=current_record) current_record=current_record)
def update( def update(self,
self,
table, table,
record, record,
next=DEFAULT, next=DEFAULT,
@@ -4125,8 +4101,7 @@ class Crud(object):
raise HTTP(401, serializers.json(dict(errors=form.errors))) raise HTTP(401, serializers.json(dict(errors=form.errors)))
return form return form
def create( def create(self,
self,
table, table,
next=DEFAULT, next=DEFAULT,
onvalidation=DEFAULT, onvalidation=DEFAULT,
@@ -4182,8 +4157,7 @@ class Crud(object):
return table._filter_fields(form.record, id=True) return table._filter_fields(form.record, id=True)
return form return form
def delete( def delete(self,
self,
table, table,
record_id, record_id,
next=DEFAULT, next=DEFAULT,
@@ -4237,8 +4211,7 @@ class Crud(object):
limitby=limitby)) limitby=limitby))
return rows return rows
def select( def select(self,
self,
table, table,
query=None, query=None,
fields=None, fields=None,
@@ -4329,7 +4302,7 @@ class Crud(object):
""" """
table = tables[0] table = tables[0]
fields = args.get('fields', table.fields) fields = args.get('fields', table.fields)
validate = args.get('validate',True) validate = args.get('validate', True)
request = current.request request = current.request
db = self.db db = self.db
if not (isinstance(table, Table) or table in db.tables): if not (isinstance(table, Table) or table in db.tables):
@@ -4382,8 +4355,7 @@ class Crud(object):
if request.post_vars and (chkval or field.type == 'id'): if request.post_vars and (chkval or field.type == 'id'):
if txtval and opval != '': if txtval and opval != '':
if field.type[0:10] == 'reference ': if field.type[0:10] == 'reference ':
refsearch.append(self.get_query(field, refsearch.append(self.get_query(field, opval, txtval, refsearch=True))
opval, txtval, refsearch=True))
elif validate: elif validate:
value, error = field.validate(txtval) value, error = field.validate(txtval)
if not error: if not error:
@@ -4477,8 +4449,7 @@ def universal_caller(f, *a, **b):
# Fill the arg_dict with name and value for the submitted, positional values # Fill the arg_dict with name and value for the submitted, positional values
for pos_index, pos_val in enumerate(a[:c]): for pos_index, pos_val in enumerate(a[:c]):
arg_dict[n[pos_index] arg_dict[n[pos_index]] = pos_val # n[pos_index] is the name of the argument
] = pos_val # n[pos_index] is the name of the argument
# There might be pos_args left, that are sent as named_values. Gather them as well. # There might be pos_args left, that are sent as named_values. Gather them as well.
# If a argument already is populated with values we simply replaces them. # If a argument already is populated with values we simply replaces them.
@@ -4856,7 +4827,6 @@ class Service(object):
-32603: ("Internal error", "Internal JSON-RPC error."), -32603: ("Internal error", "Internal JSON-RPC error."),
-32099: ("Server error", "Reserved for implementation-defined server-errors.")} -32099: ("Server error", "Reserved for implementation-defined server-errors.")}
def serve_jsonrpc(self): def serve_jsonrpc(self):
def return_response(id, result): def return_response(id, result):
return serializers.json({'version': '1.1', return serializers.json({'version': '1.1',
@@ -4886,7 +4856,7 @@ class Service(object):
if not method in methods: if not method in methods:
return return_error(id, 100, 'method "%s" does not exist' % method) return return_error(id, 100, 'method "%s" does not exist' % method)
try: try:
if isinstance(params,dict): if isinstance(params, dict):
s = methods[method](**params) s = methods[method](**params)
else: else:
s = methods[method](*params) s = methods[method](*params)
@@ -4952,8 +4922,6 @@ class Service(object):
return True return True
request = current.request request = current.request
response = current.response response = current.response
if not data: if not data:
@@ -4986,7 +4954,7 @@ class Service(object):
if not method in methods: if not method in methods:
return return_error(id, -32601, data='Method "%s" does not exist' % method) return return_error(id, -32601, data='Method "%s" does not exist' % method)
try: try:
if isinstance(params,dict): if isinstance(params, dict):
s = methods[method](**params) s = methods[method](**params)
else: else:
s = methods[method](*params) s = methods[method](*params)
@@ -5006,7 +4974,6 @@ class Service(object):
logger.warning('%s: %s\n%s' % (etype.__name__, eval, traceback.format_tb(etb))) logger.warning('%s: %s\n%s' % (etype.__name__, eval, traceback.format_tb(etb)))
return return_error(id, -32099, data=data) return return_error(id, -32099, data=data)
def serve_xmlrpc(self): def serve_xmlrpc(self):
request = current.request request = current.request
response = current.response response = current.response
@@ -5407,7 +5374,7 @@ class Expose(object):
self.filenames = [f[len(path) - 1:] for f in sorted(glob.glob(path)) self.filenames = [f[len(path) - 1:] for f in sorted(glob.glob(path))
if not os.path.isdir(f) and not self.isprivate(f)] if not os.path.isdir(f) and not self.isprivate(f)]
if 'README' in self.filenames: if 'README' in self.filenames:
readme = open(os.path.join(filename,'README')).read() readme = open(os.path.join(filename, 'README')).read()
self.paragraph = MARKMIN(readme) self.paragraph = MARKMIN(readme)
else: else:
self.paragraph = None self.paragraph = None
@@ -5464,7 +5431,8 @@ class Expose(object):
class Wiki(object): class Wiki(object):
everybody = 'everybody' everybody = 'everybody'
rows_page = 25 rows_page = 25
def markmin_base(self,body):
def markmin_base(self, body):
return MARKMIN(body, extra=self.settings.extra, return MARKMIN(body, extra=self.settings.extra,
url=True, environment=self.env, url=True, environment=self.env,
autolinks=lambda link: expand_one(link, {})).xml() autolinks=lambda link: expand_one(link, {})).xml()
@@ -5576,7 +5544,7 @@ class Wiki(object):
table_definitions = [ table_definitions = [
('wiki_page', { ('wiki_page', {
'args':[ 'args': [
Field('slug', Field('slug',
requires=[IS_SLUG(), requires=[IS_SLUG(),
IS_NOT_IN_DB(db, 'wiki_page.slug')], IS_NOT_IN_DB(db, 'wiki_page.slug')],
@@ -5601,20 +5569,20 @@ class Wiki(object):
requires=IS_EMPTY_OR( requires=IS_EMPTY_OR(
IS_IN_SET(engines))), IS_IN_SET(engines))),
auth.signature], auth.signature],
'vars':{'format':'%(title)s', 'migrate':migrate}}), 'vars': {'format': '%(title)s', 'migrate': migrate}}),
('wiki_tag', { ('wiki_tag', {
'args':[ 'args': [
Field('name'), Field('name'),
Field('wiki_page', 'reference wiki_page'), Field('wiki_page', 'reference wiki_page'),
auth.signature], auth.signature],
'vars':{'format':'%(title)s', 'migrate':migrate}}), 'vars':{'format': '%(title)s', 'migrate': migrate}}),
('wiki_media', { ('wiki_media', {
'args':[ 'args': [
Field('wiki_page', 'reference wiki_page'), Field('wiki_page', 'reference wiki_page'),
Field('title', required=True), Field('title', required=True),
Field('filename', 'upload', required=True), Field('filename', 'upload', required=True),
auth.signature], auth.signature],
'vars':{'format':'%(title)s', 'migrate':migrate}}), 'vars': {'format': '%(title)s', 'migrate': migrate}}),
] ]
# define only non-existent tables # define only non-existent tables
@@ -5633,7 +5601,7 @@ class Wiki(object):
if self.settings.templates is None and not \ if self.settings.templates is None and not \
self.settings.manage_permissions: self.settings.manage_permissions:
self.settings.templates = db.wiki_page.tags.contains('template')&\ self.settings.templates = db.wiki_page.tags.contains('template') & \
db.wiki_page.can_read.contains('everybody') db.wiki_page.can_read.contains('everybody')
def update_tags_insert(page, id, db=db): def update_tags_insert(page, id, db=db):
@@ -5643,7 +5611,7 @@ class Wiki(object):
db.wiki_tag.insert(name=tag, wiki_page=id) db.wiki_tag.insert(name=tag, wiki_page=id)
def update_tags_update(dbset, page, db=db): def update_tags_update(dbset, page, db=db):
page = dbset.select(limitby=(0,1)).first() page = dbset.select(limitby=(0, 1)).first()
db(db.wiki_tag.wiki_page == page.id).delete() db(db.wiki_tag.wiki_page == page.id).delete()
for tag in page.tags or []: for tag in page.tags or []:
tag = tag.strip().lower() tag = tag.strip().lower()
@@ -5733,7 +5701,7 @@ class Wiki(object):
elif not zero or not zero.startswith('_'): elif not zero or not zero.startswith('_'):
return self.read(zero) return self.read(zero)
elif zero == '_edit': elif zero == '_edit':
return self.edit(request.args(1) or 'index',request.args(2) or 0) return self.edit(request.args(1) or 'index', request.args(2) or 0)
elif zero == '_editmedia': elif zero == '_editmedia':
return self.editmedia(request.args(1) or 'index') return self.editmedia(request.args(1) or 'index')
elif zero == '_create': elif zero == '_create':
@@ -5804,7 +5772,7 @@ class Wiki(object):
created_on=page.created_on, created_on=page.created_on,
modified_on=page.modified_on) modified_on=page.modified_on)
def edit(self,slug,from_template=0): def edit(self, slug, from_template=0):
auth = self.auth auth = self.auth
db = auth.db db = auth.db
page = db.wiki_page(slug=slug) page = db.wiki_page(slug=slug)
@@ -5825,7 +5793,8 @@ class Wiki(object):
db.wiki_page.body.default = \ db.wiki_page.body.default = \
'- Menu Item > @////index\n- - Submenu > http://web2py.com' '- Menu Item > @////index\n- - Submenu > http://web2py.com'
else: else:
db.wiki_page.body.default = db(db.wiki_page.id==from_template).select(db.wiki_page.body)[0].body if int(from_template) > 0 else '## %s\n\npage content' % title_guess db.wiki_page.body.default = db(db.wiki_page.id == from_template).select(db.wiki_page.body)[0].body \
if int(from_template) > 0 else '## %s\n\npage content' % title_guess
vars = current.request.post_vars vars = current.request.post_vars
if vars.body: if vars.body:
vars.body = vars.body.replace('://%s' % self.host, '://HOSTNAME') vars.body = vars.body.replace('://%s' % self.host, '://HOSTNAME')
@@ -5880,9 +5849,9 @@ class Wiki(object):
} }
}) })
}) })
""" % dict(url=URL(args=('_preview', slug)),link_media=('true' if page else 'false'), """ % dict(url=URL(args=('_preview', slug)), link_media=('true' if page else 'false'),
urlmedia=URL(extension='load', urlmedia=URL(extension='load',
args=('_editmedia',slug), args=('_editmedia', slug),
vars=dict(embedded=1))) vars=dict(embedded=1)))
return dict(content=TAG[''](form, SCRIPT(script))) return dict(content=TAG[''](form, SCRIPT(script)))
@@ -5894,9 +5863,7 @@ class Wiki(object):
return self.not_authorized(page) return self.not_authorized(page)
self.auth.db.wiki_media.id.represent = lambda id, row: \ self.auth.db.wiki_media.id.represent = lambda id, row: \
id if not row.filename else \ id if not row.filename else \
SPAN('@////%i/%s.%s' % SPAN('@////%i/%s.%s' % (id, IS_SLUG.urlify(row.title.split('.')[0]), row.filename.split('.')[-1]))
(id, IS_SLUG.urlify(row.title.split('.')[0]),
row.filename.split('.')[-1]))
self.auth.db.wiki_media.wiki_page.default = page.id self.auth.db.wiki_media.wiki_page.default = page.id
self.auth.db.wiki_media.wiki_page.writable = False self.auth.db.wiki_media.wiki_page.writable = False
links = [] links = []
@@ -5907,16 +5874,16 @@ class Wiki(object):
fragment = self.auth.db.wiki_media.id.represent fragment = self.auth.db.wiki_media.id.represent
csv = False csv = False
create = False create = False
links=[ links= [
lambda row: lambda row:
A('copy into source', _href='#', _onclick=script % (fragment(row.id, row))) A('copy into source', _href='#', _onclick=script % (fragment(row.id, row)))
] ]
content = SQLFORM.grid( content = SQLFORM.grid(
self.auth.db.wiki_media.wiki_page == page.id, self.auth.db.wiki_media.wiki_page == page.id,
orderby=self.auth.db.wiki_media.title, orderby=self.auth.db.wiki_media.title,
links = links, links=links,
csv = csv, csv=csv,
create = create, create=create,
args=['_editmedia', slug], args=['_editmedia', slug],
user_signature=False) user_signature=False)
return dict(content=content) return dict(content=content)
@@ -5925,12 +5892,12 @@ class Wiki(object):
if not self.can_edit(): if not self.can_edit():
return self.not_authorized() return self.not_authorized()
db = self.auth.db db = self.auth.db
slugs=db(db.wiki_page.id>0).select(db.wiki_page.id,db.wiki_page.slug) slugs = db(db.wiki_page.id > 0).select(db.wiki_page.id, db.wiki_page.slug)
options=[OPTION(row.slug,_value=row.id) for row in slugs] options = [OPTION(row.slug, _value=row.id) for row in slugs]
options.insert(0, OPTION('',_value='')) options.insert(0, OPTION('', _value=''))
fields = [Field("slug", default=current.request.args(1) or fields = [Field("slug", default=current.request.args(1) or
self.settings.force_prefix, self.settings.force_prefix,
requires=(IS_SLUG(), IS_NOT_IN_DB(db,db.wiki_page.slug))),] requires=(IS_SLUG(), IS_NOT_IN_DB(db, db.wiki_page.slug))),]
if self.settings.templates: if self.settings.templates:
fields.append( fields.append(
Field("from_template", "reference wiki_page", Field("from_template", "reference wiki_page",
@@ -5947,7 +5914,7 @@ class Wiki(object):
if form.process().accepted: if form.process().accepted:
form.vars.from_template = 0 if not form.vars.from_template \ form.vars.from_template = 0 if not form.vars.from_template \
else form.vars.from_template else form.vars.from_template
redirect(URL(args=('_edit', form.vars.slug,form.vars.from_template or 0))) # added param redirect(URL(args=('_edit', form.vars.slug, form.vars.from_template or 0))) # added param
return dict(content=form) return dict(content=form)
def pages(self): def pages(self):
@@ -5960,14 +5927,14 @@ class Wiki(object):
wiki_table = self.auth.db.wiki_page wiki_table = self.auth.db.wiki_page
content = SQLFORM.grid( content = SQLFORM.grid(
wiki_table, wiki_table,
fields = [wiki_table.slug, fields=[wiki_table.slug,
wiki_table.title, wiki_table.tags, wiki_table.title, wiki_table.tags,
wiki_table.can_read, wiki_table.can_edit], wiki_table.can_read, wiki_table.can_edit],
links=[ links=[
lambda row: lambda row:
A('edit', _href=URL(args=('_edit', row.slug)),_class='btn'), A('edit', _href=URL(args=('_edit', row.slug)), _class='btn'),
lambda row: lambda row:
A('media', _href=URL(args=('_editmedia', row.slug)),_class='btn')], A('media', _href=URL(args=('_editmedia', row.slug)), _class='btn')],
details=False, editable=False, deletable=False, create=False, details=False, editable=False, deletable=False, create=False,
orderby=self.auth.db.wiki_page.title, orderby=self.auth.db.wiki_page.title,
args=['_pages'], args=['_pages'],
@@ -6151,6 +6118,7 @@ class Wiki(object):
request.post_vars.render = None request.post_vars.render = None
return render(request.post_vars) return render(request.post_vars)
class Config(object): class Config(object):
def __init__( def __init__(
self, self,
@@ -6166,7 +6134,7 @@ class Config(object):
self.filename = filename self.filename = filename
def read(self): def read(self):
if not( isinstance(current.session['settings_%s' % self.section], dict) ): if not(isinstance(current.session['settings_%s' % self.section], dict)):
settings = dict(self.config.items(self.section)) settings = dict(self.config.items(self.section))
else: else:
settings = current.session['settings_%s' % self.section] settings = current.session['settings_%s' % self.section]
+2
View File
@@ -66,6 +66,7 @@ else:
logger = logging.getLogger("web2py") logger = logging.getLogger("web2py")
def AES_new(key, IV=None): def AES_new(key, IV=None):
""" Returns an AES cipher object and random IV if None specified """ """ Returns an AES cipher object and random IV if None specified """
if IV is None: if IV is None:
@@ -88,6 +89,7 @@ def md5_hash(text):
""" Generates a md5 hash with the given text """ """ Generates a md5 hash with the given text """
return md5(text).hexdigest() return md5(text).hexdigest()
def simple_hash(text, key='', salt='', digest_alg='md5'): def simple_hash(text, key='', salt='', digest_alg='md5'):
""" """
Generates hash with the given text using the specified Generates hash with the given text using the specified
+49 -39
View File
@@ -190,9 +190,9 @@ class IS_MATCH(Validator):
if not expression.endswith('$'): if not expression.endswith('$'):
expression = '(%s)$' % expression expression = '(%s)$' % expression
if is_unicode: if is_unicode:
if not isinstance(expression,unicode): if not isinstance(expression, unicode):
expression = expression.decode('utf8') expression = expression.decode('utf8')
self.regex = re.compile(expression,re.UNICODE) self.regex = re.compile(expression, re.UNICODE)
else: else:
self.regex = re.compile(expression) self.regex = re.compile(expression)
self.error_message = error_message self.error_message = error_message
@@ -200,7 +200,7 @@ class IS_MATCH(Validator):
self.is_unicode = is_unicode self.is_unicode = is_unicode
def __call__(self, value): def __call__(self, value):
if self.is_unicode and not isinstance(value,unicode): if self.is_unicode and not isinstance(value, unicode):
match = self.regex.search(str(value).decode('utf8')) match = self.regex.search(str(value).decode('utf8'))
else: else:
match = self.regex.search(str(value)) match = self.regex.search(str(value))
@@ -348,6 +348,7 @@ class IS_LENGTH(Validator):
return (value, translate(self.error_message) return (value, translate(self.error_message)
% dict(min=self.minsize, max=self.maxsize)) % dict(min=self.minsize, max=self.maxsize))
class IS_JSON(Validator): class IS_JSON(Validator):
""" """
Example: Example:
@@ -377,7 +378,7 @@ class IS_JSON(Validator):
except JSONErrors: except JSONErrors:
return (value, translate(self.error_message)) return (value, translate(self.error_message))
def formatter(self,value): def formatter(self, value):
if value is None: if value is None:
return None return None
if self.native_json: if self.native_json:
@@ -669,7 +670,7 @@ class IS_NOT_IN_DB(Validator):
self.record_id = id self.record_id = id
def __call__(self, value): def __call__(self, value):
if isinstance(value,unicode): if isinstance(value, unicode):
value = value.encode('utf8') value = value.encode('utf8')
else: else:
value = str(value) value = str(value)
@@ -696,7 +697,7 @@ class IS_NOT_IN_DB(Validator):
def range_error_message(error_message, what_to_enter, minimum, maximum): def range_error_message(error_message, what_to_enter, minimum, maximum):
"build the error message for the number range validators" """build the error message for the number range validators"""
if error_message is None: if error_message is None:
error_message = 'Enter ' + what_to_enter error_message = 'Enter ' + what_to_enter
if minimum is not None and maximum is not None: if minimum is not None and maximum is not None:
@@ -938,7 +939,7 @@ class IS_DECIMAL_IN_RANGE(Validator):
def is_empty(value, empty_regex=None): def is_empty(value, empty_regex=None):
"test empty field" """test empty field"""
if isinstance(value, (str, unicode)): if isinstance(value, (str, unicode)):
value = value.strip() value = value.strip()
if empty_regex is not None and empty_regex.match(value): if empty_regex is not None and empty_regex.match(value):
@@ -1153,6 +1154,7 @@ class IS_EMAIL(Validator):
return (value, None) return (value, None)
return (value, translate(self.error_message)) return (value, translate(self.error_message))
class IS_LIST_OF_EMAILS(object): class IS_LIST_OF_EMAILS(object):
""" """
Example: Example:
@@ -1166,7 +1168,8 @@ class IS_LIST_OF_EMAILS(object):
) )
""" """
split_emails = re.compile('[^,;\s]+') split_emails = re.compile('[^,;\s]+')
def __init__(self, error_message = 'Invalid emails: %s'):
def __init__(self, error_message='Invalid emails: %s'):
self.error_message = error_message self.error_message = error_message
def __call__(self, value): def __call__(self, value):
@@ -1182,7 +1185,7 @@ class IS_LIST_OF_EMAILS(object):
return (value, return (value,
translate(self.error_message) % ', '.join(bad_emails)) translate(self.error_message) % ', '.join(bad_emails))
def formatter(self,value,row=None): def formatter(self, value, row=None):
return ', '.join(value or []) return ', '.join(value or [])
@@ -1334,7 +1337,7 @@ label_split_regex = re.compile(u'[\u002e\u3002\uff0e\uff61]')
def escape_unicode(string): def escape_unicode(string):
''' """
Converts a unicode string into US-ASCII, using a simple conversion scheme. Converts a unicode string into US-ASCII, using a simple conversion scheme.
Each unicode character that does not have a US-ASCII equivalent is Each unicode character that does not have a US-ASCII equivalent is
converted into a URL escaped form based on its hexadecimal value. converted into a URL escaped form based on its hexadecimal value.
@@ -1348,7 +1351,7 @@ def escape_unicode(string):
string: the US-ASCII escaped form of the inputted string string: the US-ASCII escaped form of the inputted string
@author: Jonathan Benn @author: Jonathan Benn
''' """
returnValue = StringIO() returnValue = StringIO()
for character in string: for character in string:
@@ -1363,7 +1366,7 @@ def escape_unicode(string):
def unicode_to_ascii_authority(authority): def unicode_to_ascii_authority(authority):
''' """
Follows the steps in RFC 3490, Section 4 to convert a unicode authority Follows the steps in RFC 3490, Section 4 to convert a unicode authority
string into its ASCII equivalent. string into its ASCII equivalent.
For example, u'www.Alliancefran\xe7aise.nu' will be converted into For example, u'www.Alliancefran\xe7aise.nu' will be converted into
@@ -1382,19 +1385,19 @@ def unicode_to_ascii_authority(authority):
authority authority
@author: Jonathan Benn @author: Jonathan Benn
''' """
#RFC 3490, Section 4, Step 1 # RFC 3490, Section 4, Step 1
#The encodings.idna Python module assumes that AllowUnassigned == True # The encodings.idna Python module assumes that AllowUnassigned == True
#RFC 3490, Section 4, Step 2 # RFC 3490, Section 4, Step 2
labels = label_split_regex.split(authority) labels = label_split_regex.split(authority)
#RFC 3490, Section 4, Step 3 # RFC 3490, Section 4, Step 3
#The encodings.idna Python module assumes that UseSTD3ASCIIRules == False # The encodings.idna Python module assumes that UseSTD3ASCIIRules == False
#RFC 3490, Section 4, Step 4 # RFC 3490, Section 4, Step 4
#We use the ToASCII operation because we are about to put the authority # We use the ToASCII operation because we are about to put the authority
#into an IDN-unaware slot # into an IDN-unaware slot
asciiLabels = [] asciiLabels = []
try: try:
import encodings.idna import encodings.idna
@@ -1402,18 +1405,18 @@ def unicode_to_ascii_authority(authority):
if label: if label:
asciiLabels.append(encodings.idna.ToASCII(label)) asciiLabels.append(encodings.idna.ToASCII(label))
else: else:
#encodings.idna.ToASCII does not accept an empty string, but # encodings.idna.ToASCII does not accept an empty string, but
#it is necessary for us to allow for empty labels so that we # it is necessary for us to allow for empty labels so that we
#don't modify the URL # don't modify the URL
asciiLabels.append('') asciiLabels.append('')
except: except:
asciiLabels = [str(label) for label in labels] asciiLabels = [str(label) for label in labels]
#RFC 3490, Section 4, Step 5 # RFC 3490, Section 4, Step 5
return str(reduce(lambda x, y: x + unichr(0x002E) + y, asciiLabels)) return str(reduce(lambda x, y: x + unichr(0x002E) + y, asciiLabels))
def unicode_to_ascii_url(url, prepend_scheme): def unicode_to_ascii_url(url, prepend_scheme):
''' """
Converts the inputed unicode url into a US-ASCII equivalent. This function Converts the inputed unicode url into a US-ASCII equivalent. This function
goes a little beyond RFC 3490, which is limited in scope to the domain name goes a little beyond RFC 3490, which is limited in scope to the domain name
(authority) only. Here, the functionality is expanded to what was observed (authority) only. Here, the functionality is expanded to what was observed
@@ -1443,23 +1446,23 @@ def unicode_to_ascii_url(url, prepend_scheme):
string: a US-ASCII equivalent of the inputed url string: a US-ASCII equivalent of the inputed url
@author: Jonathan Benn @author: Jonathan Benn
''' """
#convert the authority component of the URL into an ASCII punycode string, # convert the authority component of the URL into an ASCII punycode string,
#but encode the rest using the regular URI character encoding # but encode the rest using the regular URI character encoding
groups = url_split_regex.match(url).groups() groups = url_split_regex.match(url).groups()
#If no authority was found # If no authority was found
if not groups[3]: if not groups[3]:
#Try appending a scheme to see if that fixes the problem # Try appending a scheme to see if that fixes the problem
scheme_to_prepend = prepend_scheme or 'http' scheme_to_prepend = prepend_scheme or 'http'
groups = url_split_regex.match( groups = url_split_regex.match(
unicode(scheme_to_prepend) + u'://' + url).groups() unicode(scheme_to_prepend) + u'://' + url).groups()
#if we still can't find the authority # if we still can't find the authority
if not groups[3]: if not groups[3]:
raise Exception('No authority component found, ' + raise Exception('No authority component found, ' +
'could not decode unicode to US-ASCII') 'could not decode unicode to US-ASCII')
#We're here if we found an authority, let's rebuild the URL # We're here if we found an authority, let's rebuild the URL
scheme = groups[1] scheme = groups[1]
authority = groups[3] authority = groups[3]
path = groups[4] or '' path = groups[4] or ''
@@ -2047,12 +2050,12 @@ class IS_URL(Validator):
try: try:
asciiValue = unicode_to_ascii_url(value, self.prepend_scheme) asciiValue = unicode_to_ascii_url(value, self.prepend_scheme)
except Exception: except Exception:
#If we are not able to convert the unicode url into a # If we are not able to convert the unicode url into a
# US-ASCII URL, then the URL is not valid # US-ASCII URL, then the URL is not valid
return (value, translate(self.error_message)) return (value, translate(self.error_message))
methodResult = subMethod(asciiValue) methodResult = subMethod(asciiValue)
#if the validation of the US-ASCII version of the value failed # if the validation of the US-ASCII version of the value failed
if not methodResult[1] is None: if not methodResult[1] is None:
# then return the original input value, not the US-ASCII version # then return the original input value, not the US-ASCII version
return (value, methodResult[1]) return (value, methodResult[1])
@@ -2120,7 +2123,7 @@ class IS_TIME(Validator):
if not value.group('s') is None: if not value.group('s') is None:
s = int(value.group('s')) s = int(value.group('s'))
if value.group('d') == 'pm' and 0 < h < 12: if value.group('d') == 'pm' and 0 < h < 12:
h = h + 12 h += 12
if value.group('d') == 'am' and h == 12: if value.group('d') == 'am' and h == 12:
h = 0 h = 0
if not (h in range(24) and m in range(60) and s if not (h in range(24) and m in range(60) and s
@@ -2134,18 +2137,23 @@ class IS_TIME(Validator):
pass pass
return (ivalue, translate(self.error_message)) return (ivalue, translate(self.error_message))
# A UTC class. # A UTC class.
class UTC(datetime.tzinfo): class UTC(datetime.tzinfo):
"""UTC""" """UTC"""
ZERO = datetime.timedelta(0) ZERO = datetime.timedelta(0)
def utcoffset(self, dt): def utcoffset(self, dt):
return UTC.ZERO return UTC.ZERO
def tzname(self, dt): def tzname(self, dt):
return "UTC" return "UTC"
def dst(self, dt): def dst(self, dt):
return UTC.ZERO return UTC.ZERO
utc = UTC() utc = UTC()
class IS_DATE(Validator): class IS_DATE(Validator):
""" """
Examples: Examples:
@@ -2159,7 +2167,7 @@ class IS_DATE(Validator):
def __init__(self, format='%Y-%m-%d', def __init__(self, format='%Y-%m-%d',
error_message='Enter date as %(format)s', error_message='Enter date as %(format)s',
timezone = None): timezone=None):
self.format = translate(format) self.format = translate(format)
self.error_message = str(error_message) self.error_message = str(error_message)
self.timezone = timezone self.timezone = timezone
@@ -2402,7 +2410,7 @@ class IS_LIST_OF(Validator):
new_value = [] new_value = []
other = self.other other = self.other
if self.other: if self.other:
if not isinstance(other, (list,tuple)): if not isinstance(other, (list, tuple)):
other = [other] other = [other]
for item in ivalue: for item in ivalue:
v = item v = item
@@ -2735,6 +2743,7 @@ class LazyCrypt(object):
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)
class CRYPT(object): class CRYPT(object):
""" """
Examples: Examples:
@@ -2852,7 +2861,7 @@ otherset = frozenset(
def calc_entropy(string): def calc_entropy(string):
" calculates a simple entropy for a given string " """ calculates a simple entropy for a given string """
import math import math
alphabet = 0 # alphabet size alphabet = 0 # alphabet size
other = set() other = set()
@@ -3374,6 +3383,7 @@ class IS_IPV4(Validator):
return (value, None) return (value, None)
return (value, translate(self.error_message)) return (value, translate(self.error_message))
class IS_IPV6(Validator): class IS_IPV6(Validator):
""" """
Checks if field's value is an IP version 6 address. First attempts to Checks if field's value is an IP version 6 address. First attempts to
+13 -12
View File
@@ -143,7 +143,7 @@ class web2pyDialog(object):
root.withdraw() root.withdraw()
self.root = Tkinter.Toplevel(root, bg=bg_color) self.root = Tkinter.Toplevel(root, bg=bg_color)
self.root.resizable(0,0) self.root.resizable(0, 0)
self.root.title(ProgramName) self.root.title(ProgramName)
self.options = options self.options = options
@@ -151,7 +151,7 @@ class web2pyDialog(object):
self.menu = Tkinter.Menu(self.root) self.menu = Tkinter.Menu(self.root)
servermenu = Tkinter.Menu(self.menu, tearoff=0) servermenu = Tkinter.Menu(self.menu, tearoff=0)
httplog = os.path.join(self.options.folder, 'httpserver.log') httplog = os.path.join(self.options.folder, 'httpserver.log')
iconphoto = os.path.join('extras','icons','web2py.gif') iconphoto = os.path.join('extras', 'icons', 'web2py.gif')
if os.path.exists(iconphoto): if os.path.exists(iconphoto):
img = Tkinter.PhotoImage(file=iconphoto) img = Tkinter.PhotoImage(file=iconphoto)
self.root.tk.call('wm', 'iconphoto', self.root._w, img) self.root.tk.call('wm', 'iconphoto', self.root._w, img)
@@ -206,7 +206,7 @@ class web2pyDialog(object):
self.logoarea.grid(row=0, column=0, columnspan=4, sticky=sticky) self.logoarea.grid(row=0, column=0, columnspan=4, sticky=sticky)
self.logoarea.after(1000, self.update_canvas) self.logoarea.after(1000, self.update_canvas)
logo = os.path.join('extras','icons','splashlogo.gif') logo = os.path.join('extras', 'icons', 'splashlogo.gif')
if os.path.exists(logo): if os.path.exists(logo):
img = Tkinter.PhotoImage(file=logo) img = Tkinter.PhotoImage(file=logo)
pnl = Tkinter.Label(self.logoarea, image=img, background=bg_color, bd=0) pnl = Tkinter.Label(self.logoarea, image=img, background=bg_color, bd=0)
@@ -328,7 +328,7 @@ class web2pyDialog(object):
if os.path.exists( if os.path.exists(
'applications/%s/models/scheduler.py' % arq)] 'applications/%s/models/scheduler.py' % arq)]
if start: if start:
#the widget takes care of starting the scheduler # the widget takes care of starting the scheduler
if self.options.scheduler and self.options.with_scheduler: if self.options.scheduler and self.options.with_scheduler:
apps = [app.strip() for app apps = [app.strip() for app
in self.options.scheduler.split(',') in self.options.scheduler.split(',')
@@ -336,7 +336,7 @@ class web2pyDialog(object):
for app in apps: for app in apps:
self.try_start_scheduler(app) self.try_start_scheduler(app)
#reset the menu # reset the menu
self.schedmenu.delete(0, len(available_apps)) self.schedmenu.delete(0, len(available_apps))
for arq in available_apps: for arq in available_apps:
if arq not in self.scheduler_processes: if arq not in self.scheduler_processes:
@@ -413,7 +413,7 @@ class web2pyDialog(object):
def connect_pages(self): def connect_pages(self):
""" Connects pages """ """ Connects pages """
#reset the menu # reset the menu
available_apps = [arq for arq in os.listdir('applications/') available_apps = [arq for arq in os.listdir('applications/')
if os.path.exists( if os.path.exists(
'applications/%s/__init__.py' % arq)] 'applications/%s/__init__.py' % arq)]
@@ -939,13 +939,13 @@ def console():
if options.gae: if options.gae:
if not os.path.exists('app.yaml'): if not os.path.exists('app.yaml'):
name = raw_input("Your GAE app name: ") name = raw_input("Your GAE app name: ")
content = open(os.path.join('examples','app.example.yaml'),'rb').read() content = open(os.path.join('examples', 'app.example.yaml'), 'rb').read()
open('app.yaml','wb').write(content.replace("yourappname",name)) open('app.yaml', 'wb').write(content.replace("yourappname", name))
else: else:
print "app.yaml alreday exists in the web2py folder" print "app.yaml alreday exists in the web2py folder"
if not os.path.exists('gaehandler.py'): if not os.path.exists('gaehandler.py'):
content = open(os.path.join('handlers','gaehandler.py'),'rb').read() content = open(os.path.join('handlers', 'gaehandler.py'), 'rb').read()
open('gaehandler.py','wb').write(content) open('gaehandler.py', 'wb').write(content)
else: else:
print "gaehandler.py alreday exists in the web2py folder" print "gaehandler.py alreday exists in the web2py folder"
sys.exit(0) sys.exit(0)
@@ -1112,7 +1112,7 @@ def start(cron=True):
if hasattr(options, key): if hasattr(options, key):
setattr(options, key, getattr(options2, key)) setattr(options, key, getattr(options2, key))
logfile0 = os.path.join('extras','examples','logging.example.conf') logfile0 = os.path.join('extras', 'examples', 'logging.example.conf')
if not os.path.exists('logging.conf') and os.path.exists(logfile0): if not os.path.exists('logging.conf') and os.path.exists(logfile0):
import shutil import shutil
sys.stdout.write("Copying logging.conf.example to logging.conf ... ") sys.stdout.write("Copying logging.conf.example to logging.conf ... ")
@@ -1183,7 +1183,7 @@ def start(cron=True):
root = None root = None
if not options.nogui and options.password=='<ask>': if not options.nogui and options.password == '<ask>':
try: try:
import Tkinter import Tkinter
havetk = True havetk = True
@@ -1263,6 +1263,7 @@ end tell
# if the line was not found (under py2exe & when file was modified) # if the line was not found (under py2exe & when file was modified)
import linecache import linecache
py2exe_getline = linecache.getline py2exe_getline = linecache.getline
def getline(filename, lineno, *args, **kwargs): def getline(filename, lineno, *args, **kwargs):
line = py2exe_getline(filename, lineno, *args, **kwargs) line = py2exe_getline(filename, lineno, *args, **kwargs)
if not line: if not line: