Merge branch 'master' of github.com:web2py/web2py
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.00.0 (2012-07-19 16:56:40) dev
|
Version 2.00.0 (2012-07-20 17:37:48) dev
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ def peek():
|
|||||||
app = get_app(request.vars.app)
|
app = get_app(request.vars.app)
|
||||||
filename = '/'.join(request.args)
|
filename = '/'.join(request.args)
|
||||||
if request.vars.app:
|
if request.vars.app:
|
||||||
path = abspath(filename, gluon=False)
|
path = abspath(filename)
|
||||||
else:
|
else:
|
||||||
path = apath(filename, r=request)
|
path = apath(filename, r=request)
|
||||||
try:
|
try:
|
||||||
@@ -696,7 +696,7 @@ def edit_language():
|
|||||||
s = strings[key]
|
s = strings[key]
|
||||||
(prefix, sep, key) = key.partition('\x01')
|
(prefix, sep, key) = key.partition('\x01')
|
||||||
if sep:
|
if sep:
|
||||||
prefix = SPAN(prefix+': ', _style='color: blue;')
|
prefix = SPAN(prefix+': ', _class='tm_ftag')
|
||||||
k = key
|
k = key
|
||||||
else:
|
else:
|
||||||
(k, prefix) = (prefix, '')
|
(k, prefix) = (prefix, '')
|
||||||
@@ -1034,7 +1034,7 @@ def create_file():
|
|||||||
anchor='#'+request.vars.id if request.vars.id else ''
|
anchor='#'+request.vars.id if request.vars.id else ''
|
||||||
if request.vars.app:
|
if request.vars.app:
|
||||||
app = get_app(request.vars.app)
|
app = get_app(request.vars.app)
|
||||||
path = abspath(request.vars.location, gluon=False)
|
path = abspath(request.vars.location)
|
||||||
else:
|
else:
|
||||||
app = get_app(name=request.vars.location.split('/')[0])
|
app = get_app(name=request.vars.location.split('/')[0])
|
||||||
path = apath(request.vars.location, r=request)
|
path = apath(request.vars.location, r=request)
|
||||||
|
|||||||
@@ -1248,3 +1248,4 @@ color: #222;
|
|||||||
.error, .error a {color:red}
|
.error, .error a {color:red}
|
||||||
.pluralsform thead td {font-weight:bold; font-size:1.2em; padding-bottom:5px}
|
.pluralsform thead td {font-weight:bold; font-size:1.2em; padding-bottom:5px}
|
||||||
.pluralsform td {padding-left:5px}
|
.pluralsform td {padding-left:5px}
|
||||||
|
.tm_ftag {color:blue}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ def index():
|
|||||||
"""
|
"""
|
||||||
example action using the internationalization operator T and flash
|
example action using the internationalization operator T and flash
|
||||||
rendered by views/default/index.html or views/generic.html
|
rendered by views/default/index.html or views/generic.html
|
||||||
|
|
||||||
|
if you need a simple wiki simple replace the two lines below with:
|
||||||
|
return auth.wiki()
|
||||||
"""
|
"""
|
||||||
response.flash = T("Welcome to web2py!")
|
response.flash = T("Welcome to web2py!")
|
||||||
return dict(message=T('Hello World'))
|
return dict(message=T('Hello World'))
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ response.generic_patterns = ['*'] if request.is_local else []
|
|||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
|
from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
|
||||||
auth = Auth(db, hmac_key=Auth.get_or_create_key(), salt=True)
|
auth = Auth(db)
|
||||||
crud, service, plugins = Crud(db), Service(), PluginManager()
|
crud, service, plugins = Crud(db), Service(), PluginManager()
|
||||||
|
|
||||||
## create all tables needed by auth if not custom tables
|
## create all tables needed by auth if not custom tables
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -667,19 +667,19 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
'<p>[[probe]]</p>'
|
'<p>[[probe]]</p>'
|
||||||
|
|
||||||
>>> render(r"\\\\[[probe]]")
|
>>> render(r"\\\\[[probe]]")
|
||||||
'<p>\\\\<span id="probe"></span></p>'
|
'<p>\\\\<a name="markmin_probe"></a></p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\[[probe]]")
|
>>> render(r"\\\\\\[[probe]]")
|
||||||
'<p>\\\\[[probe]]</p>'
|
'<p>\\\\[[probe]]</p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\\\[[probe]]")
|
>>> render(r"\\\\\\\\[[probe]]")
|
||||||
'<p>\\\\\\\\<span id="probe"></span></p>'
|
'<p>\\\\\\\\<a name="markmin_probe"></a></p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\\\\[[probe]]")
|
>>> render(r"\\\\\\\\\[[probe]]")
|
||||||
'<p>\\\\\\\\[[probe]]</p>'
|
'<p>\\\\\\\\[[probe]]</p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\\\\\\[[probe]]")
|
>>> render(r"\\\\\\\\\\\[[probe]]")
|
||||||
'<p>\\\\\\\\\\\\<span id="probe"></span></p>'
|
'<p>\\\\\\\\\\\\<a name="markmin_probe"></a></p>'
|
||||||
|
|
||||||
>>> render("``[[ [\\[[probe\]\\]] URL\\[x\\]]]``:red[dummy_params]")
|
>>> render("``[[ [\\[[probe\]\\]] URL\\[x\\]]]``:red[dummy_params]")
|
||||||
'<span style="color: red"><a href="URL[x]" title="[[probe]]">URL[x]</a></span>'
|
'<span style="color: red"><a href="URL[x]" title="[[probe]]">URL[x]</a></span>'
|
||||||
@@ -725,6 +725,10 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
|
|
||||||
>>> render("**@{probe}**", environment=dict(probe="this is a test"))
|
>>> render("**@{probe}**", environment=dict(probe="this is a test"))
|
||||||
'<p><strong>this is a test</strong></p>'
|
'<p><strong>this is a test</strong></p>'
|
||||||
|
|
||||||
|
>>> render('[[id1 [span **messag** in ''markmin''] ]] ... [[**link** to id [link\\\'s title] #mark1]]')
|
||||||
|
'<p><a name="markmin_id1">span <strong>messag</strong> in markmin</a> ... <a href="#markmin_mark1" title="link\\\'s title"><strong>link</strong> to id</a></p>'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
text = str(text or '')
|
text = str(text or '')
|
||||||
text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text)
|
text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text)
|
||||||
@@ -855,7 +859,7 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
""" paragraphs in lists """
|
""" paragraphs in lists """
|
||||||
lent=len(t)
|
lent=len(t)
|
||||||
if lent>lev:
|
if lent>lev:
|
||||||
return parse_list(t, '.', s, 'ul', lev, mtag)
|
return parse_list(t, '.', s, 'ul', lev, mtag, lineno)
|
||||||
elif lent<lev:
|
elif lent<lev:
|
||||||
while ltags[-1]>lent:
|
while ltags[-1]>lent:
|
||||||
ltags.pop()
|
ltags.pop()
|
||||||
@@ -986,7 +990,9 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
URL,
|
URL,
|
||||||
environment,
|
environment,
|
||||||
latex,
|
latex,
|
||||||
auto)
|
auto,
|
||||||
|
class_prefix,
|
||||||
|
id_prefix)
|
||||||
)
|
)
|
||||||
mtag='q'
|
mtag='q'
|
||||||
else:
|
else:
|
||||||
@@ -1100,7 +1106,8 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
elif p in ('left','right'):
|
elif p in ('left','right'):
|
||||||
style = ' style="float:%s"' % p
|
style = ' style="float:%s"' % p
|
||||||
if p in ('video','audio'):
|
if p in ('video','audio'):
|
||||||
t = render(t, {}, {}, 'br', URL, environment, latex, auto)
|
t = render(t, {}, {}, 'br', URL, environment, latex,
|
||||||
|
auto, class_prefix, id_prefix)
|
||||||
return '<%(p)s controls="controls"%(title)s%(width)s><source src="%(k)s" />%(t)s</%(p)s>' \
|
return '<%(p)s controls="controls"%(title)s%(width)s><source src="%(k)s" />%(t)s</%(p)s>' \
|
||||||
% dict(p=p, title=title, width=width, k=k, t=t)
|
% dict(p=p, title=title, width=width, k=k, t=t)
|
||||||
alt = ' alt="%s"'%escape(t).replace(META, DISABLED_META) if t else ''
|
alt = ' alt="%s"'%escape(t).replace(META, DISABLED_META) if t else ''
|
||||||
@@ -1115,13 +1122,19 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
t = t or ''
|
t = t or ''
|
||||||
a = escape(a) if a else ''
|
a = escape(a) if a else ''
|
||||||
if k:
|
if k:
|
||||||
|
if k.startswith('#'):
|
||||||
|
k = '#'+id_prefix+k[1:]
|
||||||
k = escape(k)
|
k = escape(k)
|
||||||
title = ' title="%s"' % a.replace(META, DISABLED_META) if a else ''
|
title = ' title="%s"' % a.replace(META, DISABLED_META) if a else ''
|
||||||
target = ' target="_blank"' if p == 'popup' else ''
|
target = ' target="_blank"' if p == 'popup' else ''
|
||||||
t = render(t, {}, {}, 'br', URL, environment, latex, auto) if t else k
|
t = render(t, {}, {}, 'br', URL, environment, latex, auto,
|
||||||
|
class_prefix, id_prefix) if t else k
|
||||||
return '<a href="%(k)s"%(title)s%(target)s>%(t)s</a>' \
|
return '<a href="%(k)s"%(title)s%(target)s>%(t)s</a>' \
|
||||||
% dict(k=k, title=title, target=target, t=t)
|
% dict(k=k, title=title, target=target, t=t)
|
||||||
return '<span id="%s">%s</span>' % (escape(t),a)
|
return '<a name="%s">%s</a>' % (escape(id_prefix+t),
|
||||||
|
render(a, {},{},'br', URL,
|
||||||
|
environment, latex, auto,
|
||||||
|
class_prefix, id_prefix))
|
||||||
|
|
||||||
parts = text.split(LINK)
|
parts = text.split(LINK)
|
||||||
text = parts[0]
|
text = parts[0]
|
||||||
@@ -1183,21 +1196,36 @@ def markmin2html(text, extra={}, allowed={}, sep='p', auto=True):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
import doctest
|
import doctest
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
html=dedent("""
|
||||||
|
<!doctype html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
|
%(style)s
|
||||||
|
<title>%(title)s</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
%(body)s
|
||||||
|
</body>
|
||||||
|
</html>""")[1:]
|
||||||
|
|
||||||
if sys.argv[1:2] == ['-h']:
|
if sys.argv[1:2] == ['-h']:
|
||||||
print """<html><body>
|
style=dedent("""
|
||||||
<style>
|
<style>
|
||||||
blockquote { background-color: lime; }
|
blockquote { background-color: lime; }
|
||||||
thead { color: white; background-color: gray; text-align: center; }
|
thead { color: white; background-color: gray; text-align: center; }
|
||||||
tfoot { color: white; background-color: gray; }
|
tfoot { color: white; background-color: gray; }
|
||||||
|
.tableclass1 { background-color: yellow; }
|
||||||
|
.tableclass1 thead { color: yellow; background-color: green; }
|
||||||
|
.tableclass1 tfoot { color: yellow; background-color: green; }
|
||||||
|
|
||||||
.tableclass1 { background-color: yellow; }
|
td.num { text-align: right; }
|
||||||
.tableclass1 thead { color: yellow; background-color: green; }
|
pre { background-color: #E0E0E0; }
|
||||||
.tableclass1 tfoot { color: yellow; background-color: green; }
|
</style>""")[1:]
|
||||||
|
|
||||||
td.num { text-align: right; }
|
print html % dict(title="Markmin markup language", style=style, body=markmin2html(__doc__))
|
||||||
pre { background-color: #E0E0E0; }
|
|
||||||
</style>
|
|
||||||
"""+markmin2html(__doc__)+'</body></html>'
|
|
||||||
elif sys.argv[1:2] == ['-t']:
|
elif sys.argv[1:2] == ['-t']:
|
||||||
from timeit import Timer
|
from timeit import Timer
|
||||||
loops=1000
|
loops=1000
|
||||||
@@ -1208,7 +1236,7 @@ if __name__ == '__main__':
|
|||||||
elif len(sys.argv) > 1:
|
elif len(sys.argv) > 1:
|
||||||
fargv = open(sys.argv[1],'r')
|
fargv = open(sys.argv[1],'r')
|
||||||
try:
|
try:
|
||||||
print '<html><body>'+markmin2html(fargv.read())+'</body></html>'
|
print html % dict(title=sys.argv[1], style='', body=markmin2html(fargv.read()))
|
||||||
finally:
|
finally:
|
||||||
fargv.close()
|
fargv.close()
|
||||||
else:
|
else:
|
||||||
|
|||||||
+5
-1
@@ -1800,6 +1800,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
query = query & newquery
|
query = query & newquery
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
# List of all the available adapters; they all extend BaseAdapter.
|
# List of all the available adapters; they all extend BaseAdapter.
|
||||||
###################################################################################
|
###################################################################################
|
||||||
@@ -8593,7 +8594,10 @@ class Rows(object):
|
|||||||
"""
|
"""
|
||||||
returns a list of sorted elements (not sorted in place)
|
returns a list of sorted elements (not sorted in place)
|
||||||
"""
|
"""
|
||||||
return Rows(self.db,sorted(self,key=f,reverse=reverse),self.colnames)
|
rows = Rows(self.db,[],self.colnames,compact=False)
|
||||||
|
rows.records = sorted(self,key=f,reverse=reverse)
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
def group_by_value(self, field):
|
def group_by_value(self, field):
|
||||||
"""
|
"""
|
||||||
|
|||||||
+4
-4
@@ -880,7 +880,7 @@ class Auth(object):
|
|||||||
def here(self):
|
def here(self):
|
||||||
return URL(args=current.request.args,vars=current.request.vars)
|
return URL(args=current.request.args,vars=current.request.vars)
|
||||||
|
|
||||||
def __init__(self, environment=None, db=None, mailer=True, salt = False,
|
def __init__(self, environment=None, db=None, mailer=True,
|
||||||
hmac_key=None, controller='default', function='user', cas_provider=None):
|
hmac_key=None, controller='default', function='user', cas_provider=None):
|
||||||
"""
|
"""
|
||||||
auth=Auth(db)
|
auth=Auth(db)
|
||||||
@@ -922,7 +922,6 @@ class Auth(object):
|
|||||||
|
|
||||||
settings.hideerror = False
|
settings.hideerror = False
|
||||||
settings.password_min_length = 4
|
settings.password_min_length = 4
|
||||||
settings.salt = salt
|
|
||||||
settings.cas_domains = [request.env.http_host]
|
settings.cas_domains = [request.env.http_host]
|
||||||
settings.cas_provider = cas_provider
|
settings.cas_provider = cas_provider
|
||||||
settings.cas_actions = {'login':'login',
|
settings.cas_actions = {'login':'login',
|
||||||
@@ -1198,7 +1197,8 @@ class Auth(object):
|
|||||||
if URL() == action:
|
if URL() == action:
|
||||||
next = ''
|
next = ''
|
||||||
else:
|
else:
|
||||||
next = '?_next=' + urllib.quote(URL(args=request.args, vars=request.get_vars))
|
next = '?_next=' + urllib.quote(URL(args=request.args,
|
||||||
|
vars=request.get_vars))
|
||||||
|
|
||||||
href = lambda function: '%s/%s%s' % (action, function,
|
href = lambda function: '%s/%s%s' % (action, function,
|
||||||
next if referrer_actions is DEFAULT or function in referrer_actions else '')
|
next if referrer_actions is DEFAULT or function in referrer_actions else '')
|
||||||
@@ -1409,7 +1409,7 @@ class Auth(object):
|
|||||||
table.last_name.requires = \
|
table.last_name.requires = \
|
||||||
IS_NOT_EMPTY(error_message=self.messages.is_empty)
|
IS_NOT_EMPTY(error_message=self.messages.is_empty)
|
||||||
table[passfield].requires = [
|
table[passfield].requires = [
|
||||||
CRYPT(key=settings.hmac_key,salt=settings.salt,
|
CRYPT(key=settings.hmac_key,
|
||||||
min_length=settings.password_min_length)]
|
min_length=settings.password_min_length)]
|
||||||
table.email.requires = \
|
table.email.requires = \
|
||||||
[IS_EMAIL(error_message=self.messages.invalid_email),
|
[IS_EMAIL(error_message=self.messages.invalid_email),
|
||||||
|
|||||||
+24
-23
@@ -15,7 +15,7 @@ import __builtin__
|
|||||||
__all__ = ['Utf8']
|
__all__ = ['Utf8']
|
||||||
|
|
||||||
repr_escape_tab={}
|
repr_escape_tab={}
|
||||||
for i in xrange(1,32): repr_escape_tab[i]=ur'\x%02i'%i
|
for i in range(1,32): repr_escape_tab[i]=ur'\x%02x'%i
|
||||||
repr_escape_tab[7]=u'\\a'
|
repr_escape_tab[7]=u'\\a'
|
||||||
repr_escape_tab[8]=u'\\b'
|
repr_escape_tab[8]=u'\\b'
|
||||||
repr_escape_tab[9]=u'\\t'
|
repr_escape_tab[9]=u'\\t'
|
||||||
@@ -71,6 +71,24 @@ def size(string):
|
|||||||
"""
|
"""
|
||||||
return Utf8(string).__size__()
|
return Utf8(string).__size__()
|
||||||
|
|
||||||
|
def truncate(string, length, dots='...'):
|
||||||
|
""" returns string of length < *length* or truncate
|
||||||
|
string with adding *dots* suffix to the string's end
|
||||||
|
|
||||||
|
args:
|
||||||
|
length (int): max length of string
|
||||||
|
dots (str or unicode): string suffix, when string is cutted
|
||||||
|
|
||||||
|
returns:
|
||||||
|
(utf8-str): original or cutted string
|
||||||
|
"""
|
||||||
|
text = unicode(string, 'utf-8')
|
||||||
|
dots = unicode(dots, 'utf-8') if isinstance(dots, str) else dots
|
||||||
|
if len(text) > length:
|
||||||
|
text = text[:length-len(dots)] + dots
|
||||||
|
return str.__new__(Utf8, text.encode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
class Utf8(str):
|
class Utf8(str):
|
||||||
"""
|
"""
|
||||||
Class for utf8 string storing and manipulations
|
Class for utf8 string storing and manipulations
|
||||||
@@ -131,23 +149,6 @@ class Utf8(str):
|
|||||||
else:
|
else:
|
||||||
return "'"+unicode(self, 'utf-8').translate(repr_escape_tab2).encode('utf-8')+"'"
|
return "'"+unicode(self, 'utf-8').translate(repr_escape_tab2).encode('utf-8')+"'"
|
||||||
|
|
||||||
def truncate(self, length, dots='...'):
|
|
||||||
""" returns string of length < *length* or truncate
|
|
||||||
string with adding *dots* suffix to the string's end
|
|
||||||
|
|
||||||
args:
|
|
||||||
length (int): max length of string
|
|
||||||
dots (str or unicode): string suffix, when string is cutted
|
|
||||||
|
|
||||||
returns:
|
|
||||||
(utf8-str): original or cutted string
|
|
||||||
"""
|
|
||||||
text = unicode(self, 'utf-8')
|
|
||||||
dots = unicode(dots, 'utf-8') if isinstance(dots, str) else dots
|
|
||||||
if len(text) > length:
|
|
||||||
text = text[:length-len(dots)] + dots
|
|
||||||
return str.__new__(Utf8, text.encode('utf-8'))
|
|
||||||
|
|
||||||
def __size__(self):
|
def __size__(self):
|
||||||
""" length of utf-8 string in bytes """
|
""" length of utf-8 string in bytes """
|
||||||
return str.__len__(self)
|
return str.__len__(self)
|
||||||
@@ -419,15 +420,15 @@ if __name__ == '__main__':
|
|||||||
'прОБА є prOBE'
|
'прОБА є prOBE'
|
||||||
>>> type(s.swapcase())
|
>>> type(s.swapcase())
|
||||||
<class '__main__.Utf8'>
|
<class '__main__.Utf8'>
|
||||||
>>> s.truncate(10)
|
>>> truncate(s, 10)
|
||||||
'ПРоба Є...'
|
'ПРоба Є...'
|
||||||
>>> s.truncate(20)
|
>>> truncate(s, 20)
|
||||||
'ПРоба Є PRobe'
|
'ПРоба Є PRobe'
|
||||||
>>> s.truncate(10, '•••') # utf-8 string as *dots*
|
>>> truncate(s, 10, '•••') # utf-8 string as *dots*
|
||||||
'ПРоба Є•••'
|
'ПРоба Є•••'
|
||||||
>>> s.truncate(10, u'®') # you can use unicode string as *dots*
|
>>> truncate(s, 10, u'®') # you can use unicode string as *dots*
|
||||||
'ПРоба Є P®'
|
'ПРоба Є P®'
|
||||||
>>> type(s.truncate(10))
|
>>> type(truncate(s, 10))
|
||||||
<class '__main__.Utf8'>
|
<class '__main__.Utf8'>
|
||||||
>>> Utf8(s.encode('koi8-u'), 'koi8-u')
|
>>> Utf8(s.encode('koi8-u'), 'koi8-u')
|
||||||
'ПРоба Є PRobe'
|
'ПРоба Є PRobe'
|
||||||
|
|||||||
+8
-8
@@ -16,7 +16,7 @@ import random
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
from gluon.contrib.pbkdf2 import pbkdf2_hex
|
from contrib.pbkdf2 import pbkdf2_hex
|
||||||
|
|
||||||
logger = logging.getLogger("web2py")
|
logger = logging.getLogger("web2py")
|
||||||
|
|
||||||
@@ -69,15 +69,15 @@ def get_digest(value):
|
|||||||
elif value == "sha512":
|
elif value == "sha512":
|
||||||
return hashlib.sha512
|
return hashlib.sha512
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid digest algorithm")
|
raise ValueError("Invalid digest algorithm: %s" % value)
|
||||||
|
|
||||||
DIGEST_ALG_BY_SIZE = {
|
DIGEST_ALG_BY_SIZE = {
|
||||||
128/16: 'md5',
|
128/4: 'md5',
|
||||||
160/16: 'sha1',
|
160/4: 'sha1',
|
||||||
224/16: 'sha224',
|
224/4: 'sha224',
|
||||||
256/16: 'sha256',
|
256/4: 'sha256',
|
||||||
384/16: 'sha384',
|
384/4: 'sha384',
|
||||||
512/16: 'sha512',
|
512/4: 'sha512',
|
||||||
}
|
}
|
||||||
|
|
||||||
def hmac_hash(value, salt, digest_alg='md5'):
|
def hmac_hash(value, salt, digest_alg='md5'):
|
||||||
|
|||||||
+56
-7
@@ -130,7 +130,7 @@ class IS_MATCH(Validator):
|
|||||||
('hello', None)
|
('hello', None)
|
||||||
|
|
||||||
>>> IS_MATCH('hell')('hello')
|
>>> IS_MATCH('hell')('hello')
|
||||||
('hello', 'invalid expression')
|
('hello', None)
|
||||||
|
|
||||||
>>> IS_MATCH('hell.*', strict=False)('hello')
|
>>> IS_MATCH('hell.*', strict=False)('hello')
|
||||||
('hello', None)
|
('hello', None)
|
||||||
@@ -139,10 +139,10 @@ class IS_MATCH(Validator):
|
|||||||
('shello', 'invalid expression')
|
('shello', 'invalid expression')
|
||||||
|
|
||||||
>>> IS_MATCH('hello', search=True)('shello')
|
>>> IS_MATCH('hello', search=True)('shello')
|
||||||
('hello', None)
|
('shello', None)
|
||||||
|
|
||||||
>>> IS_MATCH('hello', search=True, strict=False)('shellox')
|
>>> IS_MATCH('hello', search=True, strict=False)('shellox')
|
||||||
('hello', None)
|
('shellox', None)
|
||||||
|
|
||||||
>>> IS_MATCH('.*hello.*', search=True, strict=False)('shellox')
|
>>> IS_MATCH('.*hello.*', search=True, strict=False)('shellox')
|
||||||
('shellox', None)
|
('shellox', None)
|
||||||
@@ -2579,7 +2579,13 @@ class LazyCrypt(object):
|
|||||||
"""
|
"""
|
||||||
compares the current lazy crypted password with a stored password
|
compares the current lazy crypted password with a stored password
|
||||||
"""
|
"""
|
||||||
key = self.crypt.key.split(':')[1] if ':' in self.crypt.key else ''
|
if self.crypt.key:
|
||||||
|
if ':' in self.crypt.key:
|
||||||
|
key = self.crypt.key.split(':')[1]
|
||||||
|
else:
|
||||||
|
key = self.crypt.key
|
||||||
|
else:
|
||||||
|
key = ''
|
||||||
if stored_password.count('$')==2:
|
if stored_password.count('$')==2:
|
||||||
(digest_alg, salt, hash) = stored_password.split('$')
|
(digest_alg, salt, hash) = stored_password.split('$')
|
||||||
masterkey = key+salt
|
masterkey = key+salt
|
||||||
@@ -2629,13 +2635,55 @@ class CRYPT(object):
|
|||||||
Important: hashed password is returned as a LazyCrypt object and computed only if needed.
|
Important: hashed password is returned as a LazyCrypt object and computed only if needed.
|
||||||
The LasyCrypt object also knows how to compare itself with an existing salted password
|
The LasyCrypt object also knows how to compare itself with an existing salted password
|
||||||
|
|
||||||
|
Supports standard algorithms
|
||||||
|
|
||||||
|
>>> for alg in ('md5','sha1','sha256','sha384','sha512'):
|
||||||
|
... print str(CRYPT(digest_alg=alg,salt=True)('test')[0])
|
||||||
|
md5$...$...
|
||||||
|
sha1$...$...
|
||||||
|
sha256$...$...
|
||||||
|
sha384$...$...
|
||||||
|
sha512$...$...
|
||||||
|
|
||||||
|
The syntax is always alg$salt$hash
|
||||||
|
|
||||||
|
Supports for pbkdf2
|
||||||
|
|
||||||
|
>>> alg = 'pbkdf2(1000,20,sha512)'
|
||||||
|
>>> print str(CRYPT(digest_alg=alg,salt=True)('test')[0])
|
||||||
|
pbkdf2(1000,20,sha512)$...$...
|
||||||
|
|
||||||
|
An optional hmac_key can be specified and it is used as salt prefix
|
||||||
|
|
||||||
|
>>> a = str(CRYPT(digest_alg='md5',key='mykey',salt=True)('test')[0])
|
||||||
|
>>> print a
|
||||||
|
md5$...$...
|
||||||
|
|
||||||
|
Even if the algorithm changes the hash can still be validated
|
||||||
|
|
||||||
|
>>> CRYPT(digest_alg='sha1',key='mykey',salt=True)('test')[0] == a
|
||||||
|
True
|
||||||
|
|
||||||
|
If no salt is specified CRYPT can guess the algorithms from length:
|
||||||
|
|
||||||
|
>>> a = str(CRYPT(digest_alg='sha1',salt=False)('test')[0])
|
||||||
|
>>> a
|
||||||
|
'sha1$$a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
|
||||||
|
>>> CRYPT(digest_alg='sha1',salt=False)('test')[0] == a
|
||||||
|
True
|
||||||
|
>>> CRYPT(digest_alg='sha1',salt=False)('test')[0] == a[6:]
|
||||||
|
True
|
||||||
|
>>> CRYPT(digest_alg='md5',salt=False)('test')[0] == a
|
||||||
|
True
|
||||||
|
>>> CRYPT(digest_alg='md5',salt=False)('test')[0] == a[6:]
|
||||||
|
True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
key=None,
|
key=None,
|
||||||
digest_alg='md5',
|
digest_alg='pbkdf2(1000,20,sha512)',
|
||||||
min_length=0,
|
min_length=0,
|
||||||
error_message='too short', salt=None):
|
error_message='too short', salt=True):
|
||||||
"""
|
"""
|
||||||
important, digest_alg='md5' is not the default hashing algorithm for
|
important, digest_alg='md5' is not the default hashing algorithm for
|
||||||
web2py. This is only an example of usage of this function.
|
web2py. This is only an example of usage of this function.
|
||||||
@@ -3093,7 +3141,8 @@ class IS_IPV4(Validator):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@ License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
|
|||||||
The widget is called from web2py.
|
The widget is called from web2py.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
import cStringIO
|
import cStringIO
|
||||||
import time
|
import time
|
||||||
@@ -41,7 +42,7 @@ except NameError:
|
|||||||
BaseException = Exception
|
BaseException = Exception
|
||||||
|
|
||||||
ProgramName = 'web2py Web Framework'
|
ProgramName = 'web2py Web Framework'
|
||||||
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-2011'
|
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-' + str(datetime.datetime.now().year)
|
||||||
ProgramVersion = read_file('VERSION').strip()
|
ProgramVersion = read_file('VERSION').strip()
|
||||||
|
|
||||||
ProgramInfo = '''%s
|
ProgramInfo = '''%s
|
||||||
|
|||||||
Reference in New Issue
Block a user