Merge branch 'master' of git://github.com/web2py/web2py
This commit is contained in:
@@ -545,7 +545,7 @@ regex_dd=re.compile(r'\$\$(?P<latex>.*?)\$\$')
|
||||
regex_code = re.compile('('+META+'|'+DISABLED_META+r'|````)|(``(?P<t>.+?)``(?::(?P<c>[a-zA-Z][_a-zA-Z\-\d]*)(?:\[(?P<p>[^\]]*)\])?)?)',re.S)
|
||||
regex_strong=re.compile(r'\*\*(?P<t>[^\s*]+( +[^\s*]+)*)\*\*')
|
||||
regex_del=re.compile(r'~~(?P<t>[^\s*]+( +[^\s*]+)*)~~')
|
||||
regex_em=re.compile(r"''(?P<t>[^\s']+(?: +[^\s']+)*)''")
|
||||
regex_em=re.compile(r"''(?P<t>([^\s']| |'(?!'))+)''")
|
||||
regex_num=re.compile(r"^\s*[+-]?((\d+(\.\d*)?)|\.\d+)([eE][+-]?[0-9]+)?\s*$")
|
||||
regex_list=re.compile('^(?:(?:(#{1,6})|(?:(\.+|\++|\-+)(\.)?))\s*)?(.*)$')
|
||||
regex_bq_headline=re.compile('^(?:(\.+|\++|\-+)(\.)?\s+)?(-{3}-*)$')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
|
||||
@@ -97,7 +97,7 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1):
|
||||
except ImportError, e3:
|
||||
raise ImportError, e1, import_tb # there an import error in the module
|
||||
except Exception, e2:
|
||||
raise e2 # there is an error in the module
|
||||
raise # there is an error in the module
|
||||
finally:
|
||||
if import_tb:
|
||||
import_tb = None
|
||||
|
||||
+25
-4
@@ -2843,6 +2843,8 @@ class PostgreSQLAdapter(BaseAdapter):
|
||||
self._after_connection = after_connection
|
||||
self.srid = srid
|
||||
self.find_or_make_work_folder()
|
||||
self._last_insert = None # for INSERT ... RETURNING ID
|
||||
|
||||
ruri = uri.split('://', 1)[1]
|
||||
m = self.REGEX_URI.match(ruri)
|
||||
if not m:
|
||||
@@ -2887,10 +2889,29 @@ class PostgreSQLAdapter(BaseAdapter):
|
||||
self.execute("SET standard_conforming_strings=on;")
|
||||
self.try_json()
|
||||
|
||||
def lastrowid(self, table=None):
|
||||
self.execute("select lastval()")
|
||||
return int(self.cursor.fetchone()[0])
|
||||
def _insert(self, table, fields):
|
||||
table_rname = table.sqlsafe
|
||||
if fields:
|
||||
keys = ','.join(f.sqlsafe_name for f, v in fields)
|
||||
values = ','.join(self.expand(v, f.type) for f, v in fields)
|
||||
if table._id:
|
||||
self._last_insert = (table._id, 1)
|
||||
return 'INSERT INTO %s(%s) VALUES (%s) RETURNING %s;' % (
|
||||
table_rname, keys, values, table._id.name)
|
||||
else:
|
||||
self._last_insert = None
|
||||
return 'INSERT INTO %s(%s) VALUES (%s);' % (table_rname, keys, values)
|
||||
else:
|
||||
self._last_insert
|
||||
return self._insert_empty(table)
|
||||
|
||||
def lastrowid(self, table=None):
|
||||
if self._last_insert:
|
||||
return int(self.cursor.fetchone()[0])
|
||||
else:
|
||||
self.execute("select lastval()")
|
||||
return int(self.cursor.fetchone()[0])
|
||||
|
||||
def try_json(self):
|
||||
# check JSON data type support
|
||||
# (to be added to after_connection)
|
||||
@@ -10101,7 +10122,7 @@ class Field(Expression):
|
||||
self.custom_qualifier = custom_qualifier
|
||||
self.label = (label if label is not None else
|
||||
fieldname.replace('_', ' ').title())
|
||||
self.requires = requires if requires is not None else []
|
||||
self.requires = requires if not requires in (None, DEFAULT) else []
|
||||
self.map_none = map_none
|
||||
self._rname = rname
|
||||
|
||||
|
||||
+8
-4
@@ -150,7 +150,7 @@ class HTTP(Exception):
|
||||
return self.message
|
||||
|
||||
|
||||
def redirect(location='', how=303, client_side=False):
|
||||
def redirect(location='', how=303, client_side=False, headers=None):
|
||||
"""Raises a redirect (303)
|
||||
|
||||
Args:
|
||||
@@ -159,16 +159,20 @@ def redirect(location='', how=303, client_side=False):
|
||||
client_side: if set to True, it triggers a reload of the entire page
|
||||
when the fragment has been loaded as a component
|
||||
"""
|
||||
headers = headers or {}
|
||||
if location:
|
||||
from gluon import current
|
||||
loc = location.replace('\r', '%0D').replace('\n', '%0A')
|
||||
if client_side and current.request.ajax:
|
||||
raise HTTP(200, **{'web2py-redirect-location': loc})
|
||||
headers['web2py-redirect-location'] = loc
|
||||
raise HTTP(200, **headers)
|
||||
else:
|
||||
headers['Location'] = loc
|
||||
raise HTTP(how,
|
||||
'You are being redirected <a href="%s">here</a>' % loc,
|
||||
Location=loc)
|
||||
**headers)
|
||||
else:
|
||||
from gluon import current
|
||||
if client_side and current.request.ajax:
|
||||
raise HTTP(200, **{'web2py-component-command': 'window.location.reload(true)'})
|
||||
headers['web2py-component-command'] = 'window.location.reload(true)'
|
||||
raise HTTP(200, **headers)
|
||||
|
||||
@@ -359,6 +359,7 @@ def wsgibase(environ, responder):
|
||||
local_hosts = global_settings.local_hosts
|
||||
client = get_client(env)
|
||||
x_req_with = str(env.http_x_requested_with).lower()
|
||||
cmd_opts = request.global_settings.cmd_options
|
||||
|
||||
request.update(
|
||||
client = client,
|
||||
@@ -366,6 +367,8 @@ def wsgibase(environ, responder):
|
||||
ajax = x_req_with == 'xmlhttprequest',
|
||||
cid = env.http_web2py_component_element,
|
||||
is_local = env.remote_addr in local_hosts,
|
||||
is_shell = cmd_opts and cmd_opts.shell,
|
||||
is_sheduler = cmd_opts and cmd_opts.scheduler,
|
||||
is_https = env.wsgi_url_scheme in HTTPS_SCHEMES or \
|
||||
request.env.http_x_forwarded_proto in HTTPS_SCHEMES \
|
||||
or env.https == 'on'
|
||||
|
||||
+50
-18
@@ -1016,6 +1016,7 @@ class SQLFORM(FORM):
|
||||
formstyle='table3cols',
|
||||
buttons=['submit'],
|
||||
separator=': ',
|
||||
extra_fields=None,
|
||||
**attributes
|
||||
):
|
||||
T = current.T
|
||||
@@ -1079,11 +1080,19 @@ class SQLFORM(FORM):
|
||||
|
||||
sep = separator or ''
|
||||
|
||||
extra_fields = extra_fields or []
|
||||
self.extra_fields = {}
|
||||
for extra_field in extra_fields:
|
||||
extra_field.tablename = '_extra'
|
||||
self.fields.append(extra_field.name)
|
||||
self.extra_fields[extra_field.name] = extra_field
|
||||
|
||||
for fieldname in self.fields:
|
||||
if fieldname.find('.') >= 0:
|
||||
continue
|
||||
|
||||
field = self.table[fieldname]
|
||||
field = (self.table[fieldname] if fieldname in self.table.fields
|
||||
else self.extra_fields[fieldname])
|
||||
comment = None
|
||||
|
||||
if comments:
|
||||
@@ -1383,7 +1392,8 @@ class SQLFORM(FORM):
|
||||
# ## THIS IS FOR UNIQUE RECORDS, read IS_NOT_IN_DB
|
||||
|
||||
for fieldname in self.fields:
|
||||
field = self.table[fieldname]
|
||||
field = (self.table[fieldname] if fieldname in self.table.fields
|
||||
else self.extra_fields[fieldname])
|
||||
requires = field.requires or []
|
||||
if not isinstance(requires, (list, tuple)):
|
||||
requires = [requires]
|
||||
@@ -1428,7 +1438,10 @@ class SQLFORM(FORM):
|
||||
# auch is true when user tries to delete a record
|
||||
# that does not pass validation, yet it should be deleted
|
||||
for fieldname in self.fields:
|
||||
field = self.table[fieldname]
|
||||
|
||||
field = (self.table[fieldname]
|
||||
if fieldname in self.table.fields
|
||||
else self.extra_fields[fieldname])
|
||||
### this is a workaround! widgets should always have default not None!
|
||||
if not field.widget and field.type.startswith('list:') and \
|
||||
not OptionsWidget.has_options(field):
|
||||
@@ -1439,7 +1452,7 @@ class SQLFORM(FORM):
|
||||
elif self.record:
|
||||
value = self.record[fieldname]
|
||||
else:
|
||||
value = self.table[fieldname].default
|
||||
value = field.default
|
||||
row_id = '%s_%s%s' % (
|
||||
self.table, fieldname, SQLFORM.ID_ROW_SUFFIX)
|
||||
widget = field.widget(field, value)
|
||||
@@ -1586,6 +1599,10 @@ class SQLFORM(FORM):
|
||||
fields[fieldname] = self.vars[fieldname]
|
||||
|
||||
if dbio:
|
||||
print fields
|
||||
for fieldname in fields:
|
||||
if fieldname in self.extra_fields:
|
||||
del fields[fieldname]
|
||||
if 'delete_this_record' in fields:
|
||||
# this should never happen but seems to happen to some
|
||||
del fields['delete_this_record']
|
||||
@@ -1754,35 +1771,37 @@ class SQLFORM(FORM):
|
||||
label = isinstance(
|
||||
field.label, str) and T(field.label) or field.label
|
||||
selectfields.append(OPTION(label, _value=str(field)))
|
||||
operators = SELECT(*[OPTION(T(option), _value=option) for option in options])
|
||||
operators = SELECT(*[OPTION(T(option), _value=option) for option in options],_class='form-control')
|
||||
_id = "%s_%s" % (value_id, name)
|
||||
if field.type == 'boolean':
|
||||
value_input = SQLFORM.widgets.boolean.widget(field, field.default, _id=_id)
|
||||
value_input = SQLFORM.widgets.boolean.widget(field, field.default, _id=_id,_class='form-control')
|
||||
elif field.type == 'double':
|
||||
value_input = SQLFORM.widgets.double.widget(field, field.default, _id=_id)
|
||||
value_input = SQLFORM.widgets.double.widget(field, field.default, _id=_id,_class='form-control')
|
||||
elif field.type == 'time':
|
||||
value_input = SQLFORM.widgets.time.widget(field, field.default, _id=_id)
|
||||
value_input = SQLFORM.widgets.time.widget(field, field.default, _id=_id,_class='form-control')
|
||||
elif field.type == 'date':
|
||||
iso_format = {'_data-w2p_date_format' : '%Y-%m-%d'}
|
||||
value_input = SQLFORM.widgets.date.widget(field, field.default, _id=_id, **iso_format)
|
||||
value_input = SQLFORM.widgets.date.widget(field, field.default, _id=_id,_class='form-control', **iso_format)
|
||||
elif field.type == 'datetime':
|
||||
iso_format = {'_data-w2p_datetime_format' : '%Y-%m-%d %H:%M:%S'}
|
||||
value_input = SQLFORM.widgets.datetime.widget(field, field.default, _id=_id, **iso_format)
|
||||
value_input = SQLFORM.widgets.datetime.widget(field, field.default, _id=_id,_class='form-control', **iso_format)
|
||||
elif (field.type.startswith('reference ') or
|
||||
field.type.startswith('list:reference ')) and \
|
||||
hasattr(field.requires, 'options'):
|
||||
value_input = SELECT(
|
||||
*[OPTION(v, _value=k)
|
||||
for k, v in field.requires.options()],
|
||||
_class='form-control',
|
||||
**dict(_id=_id))
|
||||
elif field.type == 'integer' or \
|
||||
field.type.startswith('reference ') or \
|
||||
field.type.startswith('list:integer') or \
|
||||
field.type.startswith('list:reference '):
|
||||
value_input = SQLFORM.widgets.integer.widget(field, field.default, _id=_id)
|
||||
value_input = SQLFORM.widgets.integer.widget(field, field.default, _id=_id,_class='form-control')
|
||||
else:
|
||||
value_input = INPUT(
|
||||
_type='text', _id=_id, _class=field.type)
|
||||
_type='text', _id=_id,
|
||||
_class=(field.type or '')+' form-control')
|
||||
|
||||
new_button = INPUT(
|
||||
_type="button", _value=T('New Search'), _class="btn btn-default", _title=T('Start building a new search'),
|
||||
@@ -1801,13 +1820,13 @@ class SQLFORM(FORM):
|
||||
operators, value_input, new_button,
|
||||
and_button, or_button, close_button,
|
||||
_id='%s_%s' % (field_id, name),
|
||||
_class='w2p_query_row hidden',
|
||||
_class='w2p_query_row',
|
||||
_style='display:inline'))
|
||||
|
||||
criteria.insert(0, SELECT(
|
||||
_id=fields_id,
|
||||
_onchange="jQuery('.w2p_query_row').hide();jQuery('#%s_'+jQuery('#%s').val().replace('.','-')).show();" % (field_id, fields_id),
|
||||
_style='float:left',
|
||||
_style='float:left',_class='form-control',
|
||||
*selectfields))
|
||||
|
||||
fadd = SCRIPT("""
|
||||
@@ -2297,7 +2316,7 @@ class SQLFORM(FORM):
|
||||
skeywords_id = '%s_keywords' % prefix
|
||||
search_widget = lambda sfield, url: CAT(FORM(
|
||||
INPUT(_name='keywords', _value=request.vars.keywords,
|
||||
_id=skeywords_id,
|
||||
_id=skeywords_id,_class='form-control',
|
||||
_onfocus="jQuery('#%s').change();jQuery('#%s').slideDown();" % (spanel_id, sfields_id) if advanced_search else ''
|
||||
),
|
||||
INPUT(_type='submit', _value=T('Search'), _class="btn btn-default"),
|
||||
@@ -2440,7 +2459,7 @@ class SQLFORM(FORM):
|
||||
message = T('at least %(nrows)s records found') % dict(nrows=nrows)
|
||||
else:
|
||||
message = T('%(nrows)s records found') % dict(nrows=nrows)
|
||||
console.append(DIV(message or T('None'), _class='web2py_counter'))
|
||||
console.append(DIV(message or '', _class='web2py_counter'))
|
||||
|
||||
paginator = UL()
|
||||
if paginate and dbset._db._adapter.dbengine == 'google:datastore':
|
||||
@@ -2670,7 +2689,7 @@ class SQLFORM(FORM):
|
||||
|
||||
@staticmethod
|
||||
def smartgrid(table, constraints=None, linked_tables=None,
|
||||
links=None, links_in_grid=True,
|
||||
links=None, links_in_grid=True, max_linked_inline=0,
|
||||
args=None, user_signature=True,
|
||||
divider='>', breadcrumbs_class='',
|
||||
**kwargs):
|
||||
@@ -2812,6 +2831,8 @@ class SQLFORM(FORM):
|
||||
linked_tables = linked_tables.get(table._tablename, [])
|
||||
if linked_tables:
|
||||
for item in linked_tables:
|
||||
opts = [OPTION(T('References')+':', _value='')]
|
||||
linked = []
|
||||
tb = None
|
||||
if isinstance(item, Table) and item._tablename in check:
|
||||
tablename = item._tablename
|
||||
@@ -2833,11 +2854,22 @@ class SQLFORM(FORM):
|
||||
t = T(tb._plural) if not multiple_links else \
|
||||
T(tb._plural + '(' + fieldname + ')')
|
||||
args0 = tablename + '.' + fieldname
|
||||
links.append(
|
||||
opts.append(OPTION(t,_value=args0))
|
||||
linked.append(
|
||||
lambda row, t=t, nargs=nargs, args0=args0:
|
||||
A(SPAN(t), cid=request.cid, _href=url(
|
||||
args=[args0, row[id_field_name]])))
|
||||
|
||||
if 0 < max_linked_inline < len(opts)-1:
|
||||
links.append(
|
||||
lambda row:
|
||||
SELECT(opts, cid=request.cid, _rowid=row[id_field_name],
|
||||
_onchange="javascript:document.location='"+url()+
|
||||
"/'+this.value+'/'+this.attributes['rowid'].value"
|
||||
)
|
||||
)
|
||||
else: links += linked
|
||||
|
||||
grid = SQLFORM.grid(query, args=request.args[:nargs], links=links,
|
||||
links_in_grid=links_in_grid,
|
||||
user_signature=user_signature, **kwargs)
|
||||
|
||||
+43
-73
@@ -15,6 +15,7 @@ import cPickle
|
||||
import datetime
|
||||
import thread
|
||||
import logging
|
||||
import copy
|
||||
import sys
|
||||
import glob
|
||||
import os
|
||||
@@ -948,7 +949,7 @@ class Recaptcha(DIV):
|
||||
captcha.append(DIV(self.errors['captcha'], _class='error'))
|
||||
return XML(captcha).xml()
|
||||
|
||||
|
||||
# this should only be used for catcha and perhaps not even for that
|
||||
def addrow(form, a, b, c, style, _id, position=-1):
|
||||
if style == "divs":
|
||||
form[0].insert(position, DIV(DIV(LABEL(a), _class='w2p_fl'),
|
||||
@@ -1360,7 +1361,7 @@ class Auth(object):
|
||||
|
||||
# for "remember me" option
|
||||
response = current.response
|
||||
if auth and auth.remember:
|
||||
if auth and auth.remember_me:
|
||||
# when user wants to be logged in for longer
|
||||
response.session_cookie_expires = auth.expiration
|
||||
if signature:
|
||||
@@ -2177,15 +2178,14 @@ class Auth(object):
|
||||
elif not fields.get(settings.userfield):
|
||||
raise ValueError("register_bare: " +
|
||||
"userfield not provided or invalid")
|
||||
fields[settings.passfield
|
||||
] = settings.table_user[settings.passfield].validate(
|
||||
fields[settings.passfield])[0]
|
||||
user = self.get_or_create_user(fields, login=False,
|
||||
get=False,
|
||||
update_fields=self.settings.update_fields)
|
||||
fields[settings.passfield] = \
|
||||
settings.table_user[settings.passfield].validate(
|
||||
fields[settings.passfield])[0]
|
||||
user = self.get_or_create_user(
|
||||
fields, login=False, get=False,
|
||||
update_fields=self.settings.update_fields)
|
||||
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 user
|
||||
|
||||
@@ -2401,6 +2401,14 @@ class Auth(object):
|
||||
# previous version of this file, other than for indentation inside
|
||||
# to put it inside the if-block
|
||||
if session.auth_two_factor_user is None:
|
||||
|
||||
if settings.remember_me_form:
|
||||
extra_fields = [
|
||||
Field('remember_me','boolean',default=False,
|
||||
label = self.messages.label_remember_me)]
|
||||
else:
|
||||
extra_fields = []
|
||||
|
||||
# do we use our own login form, or from a central source?
|
||||
if settings.login_form == self:
|
||||
form = SQLFORM(
|
||||
@@ -2411,38 +2419,10 @@ class Auth(object):
|
||||
submit_button=self.messages.login_button,
|
||||
delete_label=self.messages.delete_label,
|
||||
formstyle=settings.formstyle,
|
||||
separator=settings.label_separator
|
||||
separator=settings.label_separator,
|
||||
extra_fields = extra_fields,
|
||||
)
|
||||
|
||||
if settings.remember_me_form:
|
||||
## adds a new input checkbox "remember me for longer"
|
||||
if settings.formstyle != 'bootstrap':
|
||||
addrow(form, XML(" "),
|
||||
DIV(XML(" "),
|
||||
INPUT(_type='checkbox',
|
||||
_class='checkbox',
|
||||
_id="auth_user_remember",
|
||||
_name="remember",
|
||||
),
|
||||
XML(" "),
|
||||
LABEL(
|
||||
self.messages.label_remember_me,
|
||||
_for="auth_user_remember",
|
||||
)), "",
|
||||
settings.formstyle,
|
||||
'auth_user_remember__row')
|
||||
elif settings.formstyle == 'bootstrap':
|
||||
addrow(form,
|
||||
"",
|
||||
LABEL(
|
||||
INPUT(_type='checkbox',
|
||||
_id="auth_user_remember",
|
||||
_name="remember"),
|
||||
self.messages.label_remember_me,
|
||||
_class="checkbox"),
|
||||
"",
|
||||
settings.formstyle,
|
||||
'auth_user_remember__row')
|
||||
|
||||
captcha = settings.login_captcha or \
|
||||
(settings.login_captcha != False and settings.captcha)
|
||||
@@ -2616,10 +2596,10 @@ class Auth(object):
|
||||
# user wants to be logged in for longer
|
||||
self.login_user(user)
|
||||
session.auth.expiration = \
|
||||
request.vars.get('remember', False) and \
|
||||
request.post_vars.remember_me and \
|
||||
settings.long_expiration or \
|
||||
settings.expiration
|
||||
session.auth.remember = 'remember' in request.vars
|
||||
session.auth.remember_me = 'remember_me' in request.post_vars
|
||||
self.log_event(log, user)
|
||||
session.flash = self.messages.logged_in
|
||||
|
||||
@@ -2725,6 +2705,13 @@ class Auth(object):
|
||||
|
||||
passfield = self.settings.password_field
|
||||
formstyle = self.settings.formstyle
|
||||
if self.settings.register_verify_password:
|
||||
extra_fields = [
|
||||
Field("password_two", "password", requires=IS_EQUAL_TO(
|
||||
request.post_vars.get(passfield,None),
|
||||
error_message=self.messages.mismatched_password))]
|
||||
else:
|
||||
extra_fields = []
|
||||
form = SQLFORM(table_user,
|
||||
fields=self.settings.register_fields,
|
||||
hidden=dict(_next=next),
|
||||
@@ -2732,33 +2719,10 @@ class Auth(object):
|
||||
submit_button=self.messages.register_button,
|
||||
delete_label=self.messages.delete_label,
|
||||
formstyle=formstyle,
|
||||
separator=self.settings.label_separator
|
||||
separator=self.settings.label_separator,
|
||||
extra_fields = extra_fields
|
||||
)
|
||||
if self.settings.register_verify_password:
|
||||
for i, row in enumerate(form[0].components):
|
||||
item = row.element('input', _name=passfield)
|
||||
if item:
|
||||
form.custom.widget.password_two = \
|
||||
INPUT(_name="password_two", _type="password",
|
||||
_class="password",
|
||||
requires=IS_EXPR(
|
||||
'value==%s' %
|
||||
repr(request.vars.get(passfield, None)),
|
||||
error_message=self.messages.mismatched_password))
|
||||
|
||||
if formstyle == 'bootstrap':
|
||||
form.custom.widget.password_two[
|
||||
'_class'] = 'span4'
|
||||
|
||||
addrow(
|
||||
form, self.messages.verify_password +
|
||||
self.settings.label_separator,
|
||||
form.custom.widget.password_two,
|
||||
self.messages.verify_password_comment,
|
||||
formstyle,
|
||||
'%s_%s__row' % (table_user, 'password_two'),
|
||||
position=i + 1)
|
||||
break
|
||||
captcha = self.settings.register_captcha or self.settings.captcha
|
||||
if captcha:
|
||||
addrow(form, captcha.label, captcha,
|
||||
@@ -3221,10 +3185,12 @@ class Auth(object):
|
||||
if log is DEFAULT:
|
||||
log = self.messages['change_password_log']
|
||||
passfield = self.settings.password_field
|
||||
is_crypt = copy.copy([t for t in table_user[passfield].requires
|
||||
if isinstance(t,CRYPT)][0])
|
||||
is_crypt.min_length = 0
|
||||
form = SQLFORM.factory(
|
||||
Field('old_password', 'password',
|
||||
label=self.messages.old_password,
|
||||
requires=table_user[passfield].requires),
|
||||
Field('old_password', 'password', requires=[is_crypt],
|
||||
label=self.messages.old_password),
|
||||
Field('new_password', 'password',
|
||||
label=self.messages.new_password,
|
||||
requires=table_user[passfield].requires),
|
||||
@@ -3243,7 +3209,8 @@ class Auth(object):
|
||||
onvalidation=onvalidation,
|
||||
hideerror=self.settings.hideerror):
|
||||
|
||||
if not form.vars['old_password'] == s.select(limitby=(0,1), orderby_on_limitby=False).first()[passfield]:
|
||||
current_user = s.select(limitby=(0,1), orderby_on_limitby=False).first()
|
||||
if not form.vars['old_password'] == current_user[passfield]:
|
||||
form.errors['old_password'] = self.messages.invalid_password
|
||||
else:
|
||||
d = {passfield: str(form.vars.new_password)}
|
||||
@@ -5388,8 +5355,11 @@ class Expose(object):
|
||||
base = base or os.path.join(current.request.folder, 'static')
|
||||
basename = basename or current.request.function
|
||||
self.basename = basename
|
||||
self.args = current.request.raw_args and \
|
||||
[arg for arg in current.request.raw_args.split('/') if arg] or []
|
||||
|
||||
if current.request.raw_args:
|
||||
self.args = [arg for arg in current.request.raw_args.split('/') if arg]
|
||||
else:
|
||||
self.args = [arg for arg in current.request.args if args]
|
||||
filename = os.path.join(base, *self.args)
|
||||
if not os.path.exists(filename):
|
||||
raise HTTP(404, "FILE NOT FOUND")
|
||||
|
||||
+18
-9
@@ -34,6 +34,7 @@ if python_version == 2:
|
||||
else:
|
||||
import pickle
|
||||
|
||||
import hashlib
|
||||
from hashlib import md5, sha1, sha224, sha256, sha384, sha512
|
||||
|
||||
try:
|
||||
@@ -43,18 +44,26 @@ except ImportError:
|
||||
|
||||
import hmac
|
||||
|
||||
try:
|
||||
try:
|
||||
from gluon.contrib.pbkdf2_ctypes import pbkdf2_hex
|
||||
except (ImportError, AttributeError):
|
||||
from gluon.contrib.pbkdf2 import pbkdf2_hex
|
||||
if hasattr(hashlib, "pbkdf2_hmac"):
|
||||
def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):
|
||||
hashfunc = hashfunc or sha1
|
||||
return hashlib.pbkdf2_hmac(hashfunc().name,
|
||||
data, salt, iterations,
|
||||
keylen).encode("hex")
|
||||
HAVE_PBKDF2 = True
|
||||
except ImportError:
|
||||
else:
|
||||
try:
|
||||
from .pbkdf2 import pbkdf2_hex
|
||||
try:
|
||||
from gluon.contrib.pbkdf2_ctypes import pbkdf2_hex
|
||||
except (ImportError, AttributeError):
|
||||
from gluon.contrib.pbkdf2 import pbkdf2_hex
|
||||
HAVE_PBKDF2 = True
|
||||
except (ImportError, ValueError):
|
||||
HAVE_PBKDF2 = False
|
||||
except ImportError:
|
||||
try:
|
||||
from .pbkdf2 import pbkdf2_hex
|
||||
HAVE_PBKDF2 = True
|
||||
except (ImportError, ValueError):
|
||||
HAVE_PBKDF2 = False
|
||||
|
||||
logger = logging.getLogger("web2py")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user