R-2.9.12
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ Web2Py framework modules
|
||||
"""
|
||||
|
||||
__all__ = ['A', 'B', 'BEAUTIFY', 'BODY', 'BR', 'CAT', 'CENTER', 'CLEANUP', 'CODE', 'CRYPT', 'DAL', 'DIV', 'EM', 'EMBED', 'FIELDSET', 'FORM', 'Field', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEAD', 'HR', 'HTML', 'HTTP', 'I', 'IFRAME', 'IMG', 'INPUT', 'IS_ALPHANUMERIC', 'IS_DATE', 'IS_DATETIME', 'IS_DATETIME_IN_RANGE', 'IS_DATE_IN_RANGE', 'IS_DECIMAL_IN_RANGE', 'IS_EMAIL', 'IS_LIST_OF_EMAILS', 'IS_EMPTY_OR', 'IS_EQUAL_TO', 'IS_EXPR', 'IS_FLOAT_IN_RANGE', 'IS_IMAGE', 'IS_JSON', 'IS_INT_IN_RANGE', 'IS_IN_DB', 'IS_IN_SET', 'IS_IPV4', 'IS_LENGTH', 'IS_LIST_OF', 'IS_LOWER', 'IS_MATCH', 'IS_NOT_EMPTY', 'IS_NOT_IN_DB', 'IS_NULL_OR', 'IS_SLUG', 'IS_STRONG', 'IS_TIME', 'IS_UPLOAD_FILENAME', 'IS_UPPER', 'IS_URL', 'LABEL', 'LEGEND', 'LI', 'LINK', 'LOAD', 'MARKMIN', 'MENU', 'META', 'OBJECT', 'OL', 'ON', 'OPTGROUP', 'OPTION', 'P', 'PRE', 'SCRIPT', 'SELECT', 'SPAN', 'SQLFORM', 'SQLTABLE', 'STRONG', 'STYLE', 'TABLE', 'TAG', 'TBODY', 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TITLE', 'TR', 'TT', 'UL', 'URL', 'XHTML', 'XML', 'redirect', 'current', 'embed64']
|
||||
|
||||
|
||||
from globals import current
|
||||
from html import *
|
||||
from validators import *
|
||||
|
||||
+693
-693
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -407,7 +407,7 @@ def build_environment(request, response, session, store_current=True):
|
||||
# Enable standard conditional models (i.e., /*.py, /[controller]/*.py, and
|
||||
# /[controller]/[function]/*.py)
|
||||
response.models_to_run = [
|
||||
r'^\w+\.py$',
|
||||
r'^\w+\.py$',
|
||||
r'^%s/\w+\.py$' % request.controller,
|
||||
r'^%s/%s/\w+\.py$' % (request.controller, request.function)
|
||||
]
|
||||
@@ -514,7 +514,7 @@ def compile_controllers(folder):
|
||||
for function in exposed:
|
||||
command = data + "\nresponse._vars=response._caller(%s)\n" % \
|
||||
function
|
||||
filename = pjoin(folder, 'compiled',
|
||||
filename = pjoin(folder, 'compiled',
|
||||
'controllers.%s.%s.py' % (fname[:-3],function))
|
||||
write_file(filename, command)
|
||||
save_pyc(filename)
|
||||
|
||||
+10
-11
@@ -47,7 +47,7 @@ class Collection(object):
|
||||
if self.compact:
|
||||
for fieldname in (self.table_policy.get('fields',table.fields)):
|
||||
field = table[fieldname]
|
||||
if not ((field.type=='text' and text==False) or
|
||||
if not ((field.type=='text' and text==False) or
|
||||
field.type=='blob' or
|
||||
field.type.startswith('reference ') or
|
||||
field.type.startswith('list:reference ')) and field.name in row:
|
||||
@@ -56,7 +56,7 @@ class Collection(object):
|
||||
for fieldname in (self.table_policy.get('fields',table.fields)):
|
||||
field = table[fieldname]
|
||||
if not ((field.type=='text' and text==False) or
|
||||
field.type=='blob' or
|
||||
field.type=='blob' or
|
||||
field.type.startswith('reference ') or
|
||||
field.type.startswith('list:reference ')) and field.name in row:
|
||||
data.append({'name':field.name,'value':row[field.name],
|
||||
@@ -128,10 +128,10 @@ class Collection(object):
|
||||
for key,value in vars.items():
|
||||
if key=='_offset':
|
||||
limitby[0] = int(value) # MAY FAIL
|
||||
elif key == '_limit':
|
||||
elif key == '_limit':
|
||||
limitby[1] = int(value)+1 # MAY FAIL
|
||||
elif key=='_orderby':
|
||||
orderby = value
|
||||
orderby = value
|
||||
elif key in fieldnames:
|
||||
queries.append(table[key] == value)
|
||||
elif key.endswith('.eq') and key[:-3] in fieldnames: # for completeness (useless)
|
||||
@@ -156,14 +156,14 @@ class Collection(object):
|
||||
if filter_query:
|
||||
queries.append(filter_query)
|
||||
query = reduce(lambda a,b:a&b,queries[1:]) if len(queries)>1 else queries[0]
|
||||
orderby = [table[f] if f[0]!='~' else ~table[f[1:]] for f in orderby.split(',')]
|
||||
orderby = [table[f] if f[0]!='~' else ~table[f[1:]] for f in orderby.split(',')]
|
||||
return (query, limitby, orderby)
|
||||
|
||||
def table2queries(self,table, href):
|
||||
""" generates a set of collection.queries examples for the table """
|
||||
data = []
|
||||
for fieldname in (self.table_policy.get('fields', table.fields)):
|
||||
data.append({'name':fieldname,'value':''})
|
||||
data.append({'name':fieldname,'value':''})
|
||||
if self.extensions:
|
||||
data.append({'name':fieldname+'.ne','value':''}) # NEW !!!
|
||||
data.append({'name':fieldname+'.lt','value':''})
|
||||
@@ -192,7 +192,7 @@ class Collection(object):
|
||||
if not tablename:
|
||||
r['href'] = URL(scheme=True),
|
||||
# https://github.com/collection-json/extensions/blob/master/model.md
|
||||
r['links'] = [{'rel' : t, 'href' : URL(args=t,scheme=True), 'model':t}
|
||||
r['links'] = [{'rel' : t, 'href' : URL(args=t,scheme=True), 'model':t}
|
||||
for t in tablenames]
|
||||
response.headers['Content-Type'] = 'application/vnd.collection+json'
|
||||
return response.json({'collection':r})
|
||||
@@ -207,7 +207,7 @@ class Collection(object):
|
||||
# process GET
|
||||
if request.env.request_method=='GET':
|
||||
table = db[tablename]
|
||||
r['href'] = URL(args=tablename)
|
||||
r['href'] = URL(args=tablename)
|
||||
r['items'] = items = []
|
||||
try:
|
||||
(query, limitby, orderby) = self.request2query(table,request.get_vars)
|
||||
@@ -258,7 +258,7 @@ class Collection(object):
|
||||
return response.json({'collection':r})
|
||||
# process DELETE
|
||||
elif request.env.request_method=='DELETE':
|
||||
table = db[tablename]
|
||||
table = db[tablename]
|
||||
if not request.get_vars:
|
||||
return self.error(400, "BAD REQUEST", "Nothing to delete")
|
||||
else:
|
||||
@@ -312,7 +312,7 @@ class Collection(object):
|
||||
request, response = self.request, self.response
|
||||
r = OrderedDict({
|
||||
"version" : self.VERSION,
|
||||
"href" : URL(args=request.args,vars=request.vars),
|
||||
"href" : URL(args=request.args,vars=request.vars),
|
||||
"error" : {
|
||||
"title" : title,
|
||||
"code" : code,
|
||||
@@ -340,4 +340,3 @@ example_policies = {
|
||||
'DELETE':{'query':None},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -254,12 +254,12 @@ class Table(DALStorage):
|
||||
self._db(self.id > 0).delete()
|
||||
|
||||
|
||||
def insert(self, **fields):
|
||||
# Checks 3 times that the id is new. 3 times is enough!
|
||||
for i in range(3):
|
||||
id = self._create_id()
|
||||
if self.get(id) is None and self.update(id, **fields):
|
||||
return long(id)
|
||||
def insert(self, **fields):
|
||||
# Checks 3 times that the id is new. 3 times is enough!
|
||||
for i in range(3):
|
||||
id = self._create_id()
|
||||
if self.get(id) is None and self.update(id, **fields):
|
||||
return long(id)
|
||||
else:
|
||||
raise RuntimeError("Too many ID conflicts")
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ class Connection(object):
|
||||
parts = "complete"
|
||||
|
||||
return ("OK", (("%s " % message_id, message[parts]), message["flags"]))
|
||||
|
||||
|
||||
def _get_messages(self, query):
|
||||
if query.strip().isdigit():
|
||||
return [self.spam[self._mailbox][int(query.strip()) - 1],]
|
||||
@@ -151,7 +151,7 @@ class Connection(object):
|
||||
for item in self.spam[self._mailbox]:
|
||||
if item["uid"] == query[1:-1].replace("UID", "").strip():
|
||||
return [item,]
|
||||
messages = []
|
||||
messages = []
|
||||
try:
|
||||
for m in self.results[self._mailbox][query]:
|
||||
try:
|
||||
@@ -169,7 +169,7 @@ class Connection(object):
|
||||
return messages
|
||||
except KeyError:
|
||||
raise ValueError("The client issued an unexpected query: %s" % query)
|
||||
|
||||
|
||||
def setup(self, spam={}, results={}):
|
||||
"""adds custom message and query databases or sets
|
||||
the values to the module defaults.
|
||||
@@ -252,4 +252,3 @@ class IMAP4(object):
|
||||
return Connection()
|
||||
|
||||
IMAP4_SSL = IMAP4
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
Note: This module is intended as a plugin replacement of pbkdf2.py
|
||||
by Armin Ronacher.
|
||||
|
||||
Git repository:
|
||||
Git repository:
|
||||
$ git clone https://github.com/michele-comitini/pbkdf2_ctypes.git
|
||||
|
||||
:copyright: Copyright (c) 2013: Michele Comitini <mcm@glisco.it>
|
||||
@@ -86,7 +86,7 @@ def _openssl_hashlib_to_crypto_map_get(hashfunc):
|
||||
crypto_hashfunc.restype = ctypes.c_void_p
|
||||
return crypto_hashfunc()
|
||||
|
||||
|
||||
|
||||
def _openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
||||
"""OpenSSL compatibile wrapper
|
||||
"""
|
||||
@@ -99,7 +99,7 @@ def _openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
||||
c_iter = ctypes.c_int(iterations)
|
||||
c_keylen = ctypes.c_int(keylen)
|
||||
c_buff = ctypes.create_string_buffer(keylen)
|
||||
|
||||
|
||||
# PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
|
||||
# const unsigned char *salt, int saltlen, int iter,
|
||||
# const EVP_MD *digest,
|
||||
@@ -109,7 +109,7 @@ def _openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
||||
ctypes.c_char_p, ctypes.c_int,
|
||||
ctypes.c_int, ctypes.c_void_p,
|
||||
ctypes.c_int, ctypes.c_char_p]
|
||||
|
||||
|
||||
crypto.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int
|
||||
err = crypto.PKCS5_PBKDF2_HMAC(c_pass, c_passlen,
|
||||
c_salt, c_saltlen,
|
||||
|
||||
+408
-408
File diff suppressed because it is too large
Load Diff
+22
-22
@@ -37,7 +37,7 @@ def pay():
|
||||
elif form.errors:
|
||||
redirect(URL('pay_error'))
|
||||
return dict(form=form)
|
||||
|
||||
|
||||
"""
|
||||
|
||||
URL_CHARGE = 'https://%s:@api.stripe.com/v1/charges'
|
||||
@@ -114,7 +114,7 @@ class StripeForm(object):
|
||||
|
||||
def process(self):
|
||||
from gluon import current
|
||||
request = current.request
|
||||
request = current.request
|
||||
if request.post_vars:
|
||||
if self.signature == request.post_vars.signature:
|
||||
self.response = Stripe(self.sk).charge(
|
||||
@@ -127,7 +127,7 @@ class StripeForm(object):
|
||||
return self
|
||||
self.errors = True
|
||||
return self
|
||||
|
||||
|
||||
def xml(self):
|
||||
from gluon.template import render
|
||||
if self.accepted:
|
||||
@@ -135,8 +135,8 @@ class StripeForm(object):
|
||||
elif self.errors:
|
||||
return "There was an processing error"
|
||||
else:
|
||||
context = dict(amount=self.amount,
|
||||
signature=self.signature, pk=self.pk,
|
||||
context = dict(amount=self.amount,
|
||||
signature=self.signature, pk=self.pk,
|
||||
currency_symbol=self.currency_symbol,
|
||||
security_notice=self.security_notice,
|
||||
disclosure_notice=self.disclosure_notice)
|
||||
@@ -145,14 +145,14 @@ class StripeForm(object):
|
||||
|
||||
TEMPLATE = """
|
||||
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
|
||||
<script>
|
||||
<script>
|
||||
jQuery(function(){
|
||||
// This identifies your website in the createToken call below
|
||||
Stripe.setPublishableKey('{{=pk}}');
|
||||
|
||||
|
||||
var stripeResponseHandler = function(status, response) {
|
||||
var jQueryform = jQuery('#payment-form');
|
||||
|
||||
|
||||
if (response.error) {
|
||||
// Show the errors on the form
|
||||
jQuery('.payment-errors').text(response.error.message).show();
|
||||
@@ -167,17 +167,17 @@ jQuery(function(){
|
||||
jQueryform.get(0).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
jQuery(function(jQuery) {
|
||||
jQuery('#payment-form').submit(function(e) {
|
||||
|
||||
var jQueryform = jQuery(this);
|
||||
|
||||
|
||||
// Disable the submit button to prevent repeated clicks
|
||||
jQueryform.find('button').prop('disabled', true);
|
||||
|
||||
|
||||
Stripe.createToken(jQueryform, stripeResponseHandler);
|
||||
|
||||
|
||||
// Prevent the form from submitting with the default action
|
||||
return false;
|
||||
});
|
||||
@@ -189,33 +189,33 @@ jQuery(function(){
|
||||
<form action="" method="POST" id="payment-form" class="form-horizontal">
|
||||
|
||||
<div class="form-row control-group">
|
||||
<label class="control-label">Card Number</label>
|
||||
<label class="control-label">Card Number</label>
|
||||
<div class="controls">
|
||||
<input type="text" size="20" data-stripe="number"
|
||||
placeholder="4242424242424242"/>
|
||||
placeholder="4242424242424242"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row control-group">
|
||||
<label class="control-label">CVC</label>
|
||||
<label class="control-label">CVC</label>
|
||||
<div class="controls">
|
||||
<input type="text" size="4" style="width:80px" data-stripe="cvc"
|
||||
placeholder="XXX"/>
|
||||
placeholder="XXX"/>
|
||||
<a href="http://en.wikipedia.org/wiki/Card_Verification_Code" target="_blank">What is this?</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row control-group">
|
||||
<label class="control-label">Expiration</label>
|
||||
<label class="control-label">Expiration</label>
|
||||
<div class="controls">
|
||||
<input type="text" size="2" style="width:40px" data-stripe="exp-month"
|
||||
placeholder="MM"/>
|
||||
placeholder="MM"/>
|
||||
/
|
||||
<input type="text" size="4" style="width:80px" data-stripe="exp-year"
|
||||
placeholder="YYYY"/>
|
||||
placeholder="YYYY"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
"""
|
||||
Developed by Massimo Di Pierro
|
||||
Released under the web2py license (LGPL)
|
||||
|
||||
@@ -74,9 +74,9 @@ https is possible too using 'https://127.0.0.1:8888' instead of 'http://127.0.0.
|
||||
be started with
|
||||
|
||||
python gluon/contrib/websocket_messaging.py -k mykey -p 8888 -s keyfile.pem -c certfile.pem
|
||||
|
||||
|
||||
for secure websocket do:
|
||||
|
||||
|
||||
web2py_websocket('wss://127.0.0.1:8888/realtime/mygroup',callback)
|
||||
|
||||
Acknowledgements:
|
||||
|
||||
@@ -41,7 +41,7 @@ class CustomImportException(ImportError):
|
||||
|
||||
def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1):
|
||||
"""
|
||||
web2py's custom importer. It behaves like the standard Python importer but
|
||||
web2py's custom importer. It behaves like the standard Python importer but
|
||||
it tries to transform import statements as something like
|
||||
"import applications.app_name.modules.x".
|
||||
If the import fails, it falls back on naive_importer
|
||||
|
||||
+2
-2
@@ -228,7 +228,7 @@ if not 'google' in DRIVERS:
|
||||
DRIVERS.append('imaplib')
|
||||
except:
|
||||
LOGGER.debug('no IMAP driver imaplib')
|
||||
|
||||
|
||||
GAEDecimalProperty = None
|
||||
NDBDecimalProperty = None
|
||||
else:
|
||||
@@ -302,7 +302,7 @@ else:
|
||||
return decimal.Decimal(value)
|
||||
raise TypeError("Property %s must be a Decimal or string."\
|
||||
% self._name)
|
||||
|
||||
|
||||
psycopg2_adapt = None
|
||||
cx_Oracle = None
|
||||
pyodbc = None
|
||||
|
||||
@@ -427,7 +427,7 @@ class Table(object):
|
||||
for tn in db._adapter.tables(query)
|
||||
if tn == name or getattr(db[tn],'_ot',None)==name])
|
||||
query = self._common_filter
|
||||
if query:
|
||||
if query:
|
||||
self._common_filter = \
|
||||
lambda q: reduce(AND, [query(q), newquery(q)])
|
||||
else:
|
||||
@@ -692,7 +692,7 @@ class Table(object):
|
||||
if not (value is None or isinstance(value, str)):
|
||||
if hasattr(value, 'file') and hasattr(value, 'filename'):
|
||||
new_name = field.store(value.file, filename=value.filename)
|
||||
elif isinstance(value,dict):
|
||||
elif isinstance(value,dict):
|
||||
if 'data' in value and 'filename' in value:
|
||||
stream = StringIO.StringIO(value['data'])
|
||||
new_name = field.store(stream, filename=value['filename'])
|
||||
@@ -2569,7 +2569,7 @@ class Rows(object):
|
||||
:param render: whether we will render the fields using their represent
|
||||
(default False) can be a list of fields to render or
|
||||
True to render all.
|
||||
"""
|
||||
"""
|
||||
roots = []
|
||||
drows = {}
|
||||
rows = list(self.render(fields=None if render is True else render)) if render else self
|
||||
@@ -2703,4 +2703,3 @@ class Rows(object):
|
||||
# for consistent naming yet backwards compatible
|
||||
as_csv = __str__
|
||||
json = as_json
|
||||
|
||||
|
||||
+4
-4
@@ -94,7 +94,7 @@ def parse_version(version):
|
||||
return version_tuple
|
||||
|
||||
def read_file(filename, mode='r'):
|
||||
"""Returns content from filename, making sure to close the file explicitly
|
||||
"""Returns content from filename, making sure to close the file explicitly
|
||||
on exit.
|
||||
"""
|
||||
f = open(filename, mode)
|
||||
@@ -105,7 +105,7 @@ def read_file(filename, mode='r'):
|
||||
|
||||
|
||||
def write_file(filename, value, mode='w'):
|
||||
"""Writes <value> to filename, making sure to close the file
|
||||
"""Writes <value> to filename, making sure to close the file
|
||||
explicitly on exit.
|
||||
"""
|
||||
f = open(filename, mode)
|
||||
@@ -346,7 +346,7 @@ def get_session(request, other_application='admin'):
|
||||
session_filename = os.path.join(
|
||||
up(request.folder), other_application, 'sessions', session_id)
|
||||
if not os.path.exists(session_filename):
|
||||
session_filename = generate(session_filename)
|
||||
session_filename = generate(session_filename)
|
||||
osession = storage.load_storage(session_filename)
|
||||
except Exception, e:
|
||||
osession = storage.Storage()
|
||||
@@ -438,7 +438,7 @@ from settings import global_settings # we need to import settings here because
|
||||
|
||||
|
||||
def abspath(*relpath, **base):
|
||||
"""Converts relative path to absolute path based (by default) on
|
||||
"""Converts relative path to absolute path based (by default) on
|
||||
applications_parent
|
||||
"""
|
||||
path = os.path.join(*relpath)
|
||||
|
||||
+1
-1
@@ -1864,7 +1864,7 @@ class INPUT(DIV):
|
||||
break
|
||||
if not name in self.errors:
|
||||
self.vars[name] = value
|
||||
return True
|
||||
return True
|
||||
return False
|
||||
|
||||
def _postprocessing(self):
|
||||
|
||||
+2
-2
@@ -365,8 +365,8 @@ def wsgibase(environ, responder):
|
||||
client = client,
|
||||
folder = abspath('applications', app) + os.sep,
|
||||
ajax = x_req_with == 'xmlhttprequest',
|
||||
cid = env.http_web2py_component_element,
|
||||
is_local = (env.remote_addr in local_hosts and
|
||||
cid = env.http_web2py_component_element,
|
||||
is_local = (env.remote_addr in local_hosts and
|
||||
client == env.remote_addr),
|
||||
is_shell = cmd_opts and cmd_opts.shell,
|
||||
is_sheduler = cmd_opts and cmd_opts.scheduler,
|
||||
|
||||
+63
-63
@@ -1,63 +1,63 @@
|
||||
import os, uuid
|
||||
|
||||
def generate(filename, depth=2, base=512):
|
||||
if os.path.sep in filename:
|
||||
path, filename = os.path.split(filename)
|
||||
else:
|
||||
path = None
|
||||
dummyhash = sum(ord(c)*256**(i % 4) for i,c in enumerate(filename)) % base**depth
|
||||
folders = []
|
||||
for level in range(depth-1,-1,-1):
|
||||
code, dummyhash = divmod(dummyhash, base**level)
|
||||
folders.append("%03x" % code)
|
||||
folders.append(filename)
|
||||
if path:
|
||||
folders.insert(0,path)
|
||||
return os.path.join(*folders)
|
||||
|
||||
def exists(filename, path=None):
|
||||
if os.path.exists(filename):
|
||||
return True
|
||||
if path is None:
|
||||
path, filename = os.path.split(filename)
|
||||
fullfilename = os.path.join(path, generate(filename))
|
||||
if os.path.exists(fullfilename):
|
||||
return True
|
||||
return False
|
||||
|
||||
def remove(filename, path=None):
|
||||
if os.path.exists(filename):
|
||||
return os.unlink(filename)
|
||||
if path is None:
|
||||
path, filename = os.path.split(filename)
|
||||
fullfilename = os.path.join(path, generate(filename))
|
||||
if os.path.exists(fullfilename):
|
||||
return os.unlink(fullfilename)
|
||||
raise IOError
|
||||
|
||||
def open(filename, mode="r", path=None):
|
||||
if not path:
|
||||
path, filename = os.path.split(filename)
|
||||
fullfilename = None
|
||||
if not mode.startswith('w'):
|
||||
fullfilename = os.path.join(path, filename)
|
||||
if not os.path.exists(fullfilename):
|
||||
fullfilename = None
|
||||
if not fullfilename:
|
||||
fullfilename = os.path.join(path, generate(filename))
|
||||
if mode.startswith('w') and not os.path.exists(os.path.dirname(fullfilename)):
|
||||
os.makedirs(os.path.dirname(fullfilename))
|
||||
return file(fullfilename, mode)
|
||||
|
||||
def test():
|
||||
if not os.path.exists('tests'):
|
||||
os.mkdir('tests')
|
||||
for k in range(20):
|
||||
filename = os.path.join('tests',str(uuid.uuid4())+'.test')
|
||||
open(filename, "w").write('test')
|
||||
assert open(filename, "r").read()=='test'
|
||||
if exists(filename):
|
||||
remove(filename)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
import os, uuid
|
||||
|
||||
def generate(filename, depth=2, base=512):
|
||||
if os.path.sep in filename:
|
||||
path, filename = os.path.split(filename)
|
||||
else:
|
||||
path = None
|
||||
dummyhash = sum(ord(c)*256**(i % 4) for i,c in enumerate(filename)) % base**depth
|
||||
folders = []
|
||||
for level in range(depth-1,-1,-1):
|
||||
code, dummyhash = divmod(dummyhash, base**level)
|
||||
folders.append("%03x" % code)
|
||||
folders.append(filename)
|
||||
if path:
|
||||
folders.insert(0,path)
|
||||
return os.path.join(*folders)
|
||||
|
||||
def exists(filename, path=None):
|
||||
if os.path.exists(filename):
|
||||
return True
|
||||
if path is None:
|
||||
path, filename = os.path.split(filename)
|
||||
fullfilename = os.path.join(path, generate(filename))
|
||||
if os.path.exists(fullfilename):
|
||||
return True
|
||||
return False
|
||||
|
||||
def remove(filename, path=None):
|
||||
if os.path.exists(filename):
|
||||
return os.unlink(filename)
|
||||
if path is None:
|
||||
path, filename = os.path.split(filename)
|
||||
fullfilename = os.path.join(path, generate(filename))
|
||||
if os.path.exists(fullfilename):
|
||||
return os.unlink(fullfilename)
|
||||
raise IOError
|
||||
|
||||
def open(filename, mode="r", path=None):
|
||||
if not path:
|
||||
path, filename = os.path.split(filename)
|
||||
fullfilename = None
|
||||
if not mode.startswith('w'):
|
||||
fullfilename = os.path.join(path, filename)
|
||||
if not os.path.exists(fullfilename):
|
||||
fullfilename = None
|
||||
if not fullfilename:
|
||||
fullfilename = os.path.join(path, generate(filename))
|
||||
if mode.startswith('w') and not os.path.exists(os.path.dirname(fullfilename)):
|
||||
os.makedirs(os.path.dirname(fullfilename))
|
||||
return file(fullfilename, mode)
|
||||
|
||||
def test():
|
||||
if not os.path.exists('tests'):
|
||||
os.mkdir('tests')
|
||||
for k in range(20):
|
||||
filename = os.path.join('tests',str(uuid.uuid4())+'.test')
|
||||
open(filename, "w").write('test')
|
||||
assert open(filename, "r").read()=='test'
|
||||
if exists(filename):
|
||||
remove(filename)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ def env(
|
||||
request.function)
|
||||
if global_settings.cmd_options:
|
||||
ip = global_settings.cmd_options.ip
|
||||
port = global_settings.cmd_options.port
|
||||
port = global_settings.cmd_options.port
|
||||
else:
|
||||
ip, port = '127.0.0.1', '8000'
|
||||
request.env.http_host = '%s:%s' % (ip,port)
|
||||
|
||||
+1
-1
@@ -279,7 +279,7 @@ class TemplateParser(object):
|
||||
self.context = context
|
||||
|
||||
# allow optional alternative delimiters
|
||||
|
||||
|
||||
if delimiters != self.default_delimiters:
|
||||
escaped_delimiters = (escape(delimiters[0]),
|
||||
escape(delimiters[1]))
|
||||
|
||||
@@ -27,4 +27,4 @@ def fix_sys_path(current_path):
|
||||
os.path.abspath(os.path.join(path, 'site-packages')),
|
||||
os.path.abspath(os.path.join(path, 'gluon')),
|
||||
'']
|
||||
[add_path_first(path) for path in paths]
|
||||
[add_path_first(path) for path in paths]
|
||||
|
||||
@@ -65,7 +65,7 @@ class TestContribs(unittest.TestCase):
|
||||
self.assertEqual(myappconfig.take('config3.key1', cast=int), '1')
|
||||
|
||||
self.assertEqual(myappconfig.take('config3.key2'), 2)
|
||||
|
||||
|
||||
current.request = {}
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1388,7 +1388,7 @@ class TestQuoting(unittest.TestCase):
|
||||
|
||||
class TestTableAndFieldCase(unittest.TestCase):
|
||||
"""
|
||||
at the Python level we should not allow db.C and db.c because of .table conflicts on windows
|
||||
at the Python level we should not allow db.C and db.c because of .table conflicts on windows
|
||||
but it should be possible to map two different names into distinct tables "c" and "C" at the Python level
|
||||
By default Python models names should be mapped into lower case table names and assume case insensitivity.
|
||||
"""
|
||||
@@ -1406,4 +1406,3 @@ class TestQuotesByDefault(unittest.TestCase):
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
tearDownModule()
|
||||
|
||||
|
||||
+22
-22
@@ -131,7 +131,7 @@ class TestRouter(unittest.TestCase):
|
||||
'http://domain.com/abc/def'), "/init/default/abc ['def']")
|
||||
self.assertEqual(filter_url(
|
||||
'http://domain.com/index/a%20bc'), "/init/default/index ['a bc']")
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/static" % root))
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to/st~tic')
|
||||
try:
|
||||
@@ -195,7 +195,7 @@ class TestRouter(unittest.TestCase):
|
||||
norm_root('%s/applications/welcome/static/favicon.ico' % root))
|
||||
self.assertEqual(filter_url('http://domain.com/static/abc'),
|
||||
norm_root('%s/applications/welcome/static/abc' % root))
|
||||
self.assertEqual(filter_url('http://domain.com/static/path/to/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/static/path/to/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/static" % root))
|
||||
# outgoing
|
||||
self.assertEqual(filter_url(
|
||||
@@ -1086,13 +1086,13 @@ class TestRouter(unittest.TestCase):
|
||||
norm_root("%s/applications/admin/static/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/en/static/file'),
|
||||
norm_root("%s/applications/admin/static/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/en/static/file'),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/en/static/file'),
|
||||
norm_root("%s/applications/examples/static/en/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/file'),
|
||||
norm_root("%s/applications/examples/static/en/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it/static/file'),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it/static/file'),
|
||||
norm_root("%s/applications/examples/static/it/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it-it/static/file'),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it-it/static/file'),
|
||||
norm_root("%s/applications/examples/static/file" % root))
|
||||
|
||||
self.assertEqual(filter_url('https://domain.com/admin/ctr/fcn',
|
||||
@@ -1188,19 +1188,19 @@ class TestRouter(unittest.TestCase):
|
||||
norm_root("%s/applications/admin/static/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/en/static/file'),
|
||||
norm_root("%s/applications/admin/static/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/en/static/file'),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/en/static/file'),
|
||||
norm_root("%s/applications/examples/static/en/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/file'),
|
||||
norm_root("%s/applications/examples/static/en/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it/static/file'),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it/static/file'),
|
||||
norm_root("%s/applications/examples/static/it/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it-it/static/file'),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/it-it/static/file'),
|
||||
norm_root("%s/applications/examples/static/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/en/file').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/en/file').replace('/', os.sep),
|
||||
norm_root("%s/applications/examples/static/en/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/it/file').replace('/', os.sep),
|
||||
norm_root("%s/applications/examples/static/it/file" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/it-it/file').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/examples/static/it-it/file').replace('/', os.sep),
|
||||
norm_root("%s/applications/examples/static/it-it/file" % root))
|
||||
|
||||
def test_router_get_effective(self):
|
||||
@@ -1267,14 +1267,14 @@ class TestRouter(unittest.TestCase):
|
||||
|
||||
'''
|
||||
load(rdict=dict())
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/static" % root))
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to/st~tic')
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to--/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to--/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to--/static" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/==to--/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/==to--/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/==to--/static" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/-+=@$%/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/-+=@$%/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/-+=@$%%/static" % root))
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to/.static')
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to/s..tatic')
|
||||
@@ -1287,7 +1287,7 @@ class TestRouter(unittest.TestCase):
|
||||
),
|
||||
)
|
||||
load(rdict=router_static)
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/#static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/#static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/#static" % root))
|
||||
|
||||
router_static = dict(
|
||||
@@ -1296,23 +1296,23 @@ class TestRouter(unittest.TestCase):
|
||||
),
|
||||
)
|
||||
load(rdict=router_static)
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/static" % root))
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to/st~tic')
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to--/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to--/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to--/static" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/==to--/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/==to--/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/==to--/static" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/-+=@$%/static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/-+=@$%/static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/-+=@$%%/static" % root))
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/to//static')
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/#static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/#static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/#static" % root))
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/./static')
|
||||
self.assertRaises(HTTP, filter_url, 'http://domain.com/welcome/static/bad/path/../static')
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/.../static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/.../static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/.../static" % root))
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/.static').replace('/', os.sep),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/.static').replace('/', os.sep),
|
||||
norm_root("%s/applications/welcome/static/path/to/.static" % root))
|
||||
|
||||
def test_router_args(self):
|
||||
|
||||
@@ -108,7 +108,7 @@ class TestRoutes(unittest.TestCase):
|
||||
'http://domain.com/abc/def/ghi/jkl'), "/abc/def/ghi ['jkl']")
|
||||
self.assertEqual(filter_url(
|
||||
'http://domain.com/abc/def/ghi/j%20kl'), "/abc/def/ghi ['j_kl']")
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static'),
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/path/to/static'),
|
||||
norm_root("%s/applications/welcome/static/path/to/static" % root))
|
||||
# no more necessary since explcit check for directory traversal attacks
|
||||
"""
|
||||
@@ -174,7 +174,7 @@ default_application = 'defapp'
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/default/index/abc'), "/welcome/default/index ['abc']")
|
||||
self.assertEqual(filter_url('http://domain.com/welcome/static/abc'),
|
||||
norm_root('%s/applications/welcome/static/abc' % root))
|
||||
self.assertEqual(filter_url('http://domain.com/defapp/static/path/to/static'),
|
||||
self.assertEqual(filter_url('http://domain.com/defapp/static/path/to/static'),
|
||||
norm_root("%s/applications/defapp/static/path/to/static" % root))
|
||||
|
||||
def test_routes_raise(self):
|
||||
|
||||
+31
-32
@@ -173,7 +173,7 @@ class Mail(object):
|
||||
chain of email certificate. It can be a
|
||||
string containing the certs to. (PEM format)
|
||||
x509_nocerts : if True then no attached certificate in mail
|
||||
x509_crypt_certfiles: the certificates file or strings to encrypt
|
||||
x509_crypt_certfiles: the certificates file or strings to encrypt
|
||||
the messages with can be a file name /
|
||||
string or a list of file names /
|
||||
strings (PEM format)
|
||||
@@ -342,7 +342,7 @@ class Mail(object):
|
||||
from_address: address to appear in the 'From:' header, this is not
|
||||
the envelope sender. If not specified the sender will be used
|
||||
|
||||
cipher_type :
|
||||
cipher_type :
|
||||
gpg - need a python-pyme package and gpgme lib
|
||||
x509 - smime
|
||||
gpg_home : you can set a GNUPGHOME environment variable
|
||||
@@ -361,8 +361,8 @@ class Mail(object):
|
||||
chain of email certificate. It can be a
|
||||
string containing the certs to. (PEM format)
|
||||
x509_nocerts : if True then no attached certificate in mail
|
||||
x509_crypt_certfiles: the certificates file or strings to encrypt
|
||||
the messages with can be a file name / string or
|
||||
x509_crypt_certfiles: the certificates file or strings to encrypt
|
||||
the messages with can be a file name / string or
|
||||
a list of file names / strings (PEM format)
|
||||
Examples:
|
||||
Send plain text message to single address::
|
||||
@@ -1351,7 +1351,7 @@ class Auth(object):
|
||||
reset_password_onvalidation = [],
|
||||
reset_password_onaccept = [],
|
||||
hmac_key = hmac_key,
|
||||
formstyle = current.response.formstyle,
|
||||
formstyle = current.response.formstyle,
|
||||
)
|
||||
settings.lock_keys = True
|
||||
|
||||
@@ -2345,7 +2345,7 @@ class Auth(object):
|
||||
items = snext.split('/')
|
||||
if '//' in snext and items[2] != request.env.http_host:
|
||||
snext = None
|
||||
|
||||
|
||||
if snext:
|
||||
session._auth_next = snext
|
||||
elif session._auth_next:
|
||||
@@ -2433,20 +2433,20 @@ class Auth(object):
|
||||
separator=settings.label_separator,
|
||||
extra_fields = extra_fields,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
captcha = settings.login_captcha or \
|
||||
(settings.login_captcha != False and settings.captcha)
|
||||
if captcha:
|
||||
addrow(form, captcha.label, captcha, captcha.comment,
|
||||
settings.formstyle, 'captcha__row')
|
||||
accepted_form = False
|
||||
|
||||
|
||||
if form.accepts(request, session if self.csrf_prevention else None,
|
||||
formname='login', dbio=False,
|
||||
onvalidation=onvalidation,
|
||||
hideerror=settings.hideerror):
|
||||
|
||||
|
||||
accepted_form = True
|
||||
# check for username in db
|
||||
entered_username = form.vars[username]
|
||||
@@ -2464,7 +2464,7 @@ class Auth(object):
|
||||
elif temp_user.registration_key in ('disabled', 'blocked'):
|
||||
response.flash = self.messages.login_disabled
|
||||
return form
|
||||
elif (not temp_user.registration_key is None
|
||||
elif (not temp_user.registration_key is None
|
||||
and temp_user.registration_key.strip()):
|
||||
response.flash = \
|
||||
self.messages.registration_verifying
|
||||
@@ -2512,11 +2512,11 @@ class Auth(object):
|
||||
redirect(
|
||||
self.url(args=request.args, vars=request.get_vars),
|
||||
client_side=settings.client_side)
|
||||
|
||||
|
||||
else: # use a central authentication server
|
||||
cas = settings.login_form
|
||||
cas_user = cas.get_user()
|
||||
|
||||
|
||||
if cas_user:
|
||||
cas_user[passfield] = None
|
||||
user = self.get_or_create_user(
|
||||
@@ -2532,7 +2532,7 @@ class Auth(object):
|
||||
|
||||
# Extra login logic for two-factor authentication
|
||||
#################################################
|
||||
# If the 'user' variable has a value, this means that the first
|
||||
# If the 'user' variable has a value, this means that the first
|
||||
# authentication step was successful (i.e. user provided correct
|
||||
# username and password at the first challenge).
|
||||
# Check if this user is signed up for two-factor authentication
|
||||
@@ -2545,7 +2545,7 @@ class Auth(object):
|
||||
if session.auth_two_factor_enabled:
|
||||
form = SQLFORM.factory(
|
||||
Field('authentication_code',
|
||||
required=True,
|
||||
required=True,
|
||||
comment='This code was emailed to you and is required for login.'),
|
||||
hidden=dict(_next=next),
|
||||
formstyle=settings.formstyle,
|
||||
@@ -2564,8 +2564,8 @@ class Auth(object):
|
||||
session.auth_two_factor_tries_left = 3 # Allow user to try up to 4 times
|
||||
# TODO: Add some error checking to handle cases where email cannot be sent
|
||||
self.settings.mailer.send(
|
||||
to=user.email,
|
||||
subject="Two-step Login Authentication Code",
|
||||
to=user.email,
|
||||
subject="Two-step Login Authentication Code",
|
||||
message="Your temporary login code is {0}".format(session.auth_two_factor))
|
||||
if form.accepts(request, session if self.csrf_prevention else None,
|
||||
formname='login', dbio=False,
|
||||
@@ -2580,15 +2580,15 @@ class Auth(object):
|
||||
# normal.
|
||||
if user is None or user == session.auth_two_factor_user:
|
||||
user = session.auth_two_factor_user
|
||||
# For security, because the username stored in the
|
||||
# For security, because the username stored in the
|
||||
# session somehow does not match the just validated
|
||||
# user. Should not be possible without session stealing
|
||||
# which is hard with SSL.
|
||||
elif user != session.auth_two_factor_user:
|
||||
user = None
|
||||
# Either way, the user and code associated with this session should
|
||||
# be removed. This handles cases where the session login may have
|
||||
# expired but browser window is open, so the old session key and
|
||||
# be removed. This handles cases where the session login may have
|
||||
# expired but browser window is open, so the old session key and
|
||||
# session usernamem will still exist
|
||||
self._reset_two_factor_auth(session)
|
||||
else:
|
||||
@@ -2636,11 +2636,11 @@ class Auth(object):
|
||||
"""
|
||||
Logouts and redirects to login
|
||||
"""
|
||||
|
||||
|
||||
# Clear out 2-step authentication information if user logs
|
||||
# out. This information is also cleared on successful login.
|
||||
self._reset_two_factor_auth(current.session)
|
||||
|
||||
|
||||
if next is DEFAULT:
|
||||
next = self.get_vars_next() or self.settings.logout_next
|
||||
if onlogout is DEFAULT:
|
||||
@@ -2791,7 +2791,7 @@ class Auth(object):
|
||||
else:
|
||||
next = replace_id(next, form)
|
||||
redirect(next, client_side=self.settings.client_side)
|
||||
|
||||
|
||||
return form
|
||||
|
||||
def is_logged_in(self):
|
||||
@@ -3091,7 +3091,7 @@ class Auth(object):
|
||||
if log is DEFAULT:
|
||||
log = self.messages['reset_password_log']
|
||||
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':
|
||||
table_user.email.requires = [
|
||||
IS_EMAIL(error_message=self.messages.invalid_email),
|
||||
@@ -3197,11 +3197,11 @@ class Auth(object):
|
||||
log = self.messages['change_password_log']
|
||||
passfield = self.settings.password_field
|
||||
requires = table_user[passfield].requires
|
||||
if not isinstance(requires,(list, tuple)):
|
||||
if not isinstance(requires,(list, tuple)):
|
||||
requires = [requires]
|
||||
requires = filter(lambda t:isinstance(t,CRYPT), requires)
|
||||
if requires:
|
||||
requires[0].min_length = 0
|
||||
requires[0].min_length = 0
|
||||
form = SQLFORM.factory(
|
||||
Field('old_password', 'password', requires=requires,
|
||||
label=self.messages.old_password),
|
||||
@@ -3753,7 +3753,7 @@ class Auth(object):
|
||||
archive_current=False,
|
||||
fields=None):
|
||||
"""
|
||||
If you have a table (db.mytable) that needs full revision history you
|
||||
If you have a table (db.mytable) that needs full revision history you
|
||||
can just do::
|
||||
|
||||
form=crud.update(db.mytable,myrecord,onaccept=auth.archive)
|
||||
@@ -5371,8 +5371,8 @@ class Expose(object):
|
||||
base = base or os.path.join(current.request.folder, 'static')
|
||||
basename = basename or current.request.function
|
||||
self.basename = basename
|
||||
|
||||
if current.request.raw_args:
|
||||
|
||||
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]
|
||||
@@ -5696,8 +5696,8 @@ class Wiki(object):
|
||||
|
||||
def automenu(self):
|
||||
"""adds the menu if not present"""
|
||||
if (not self.wiki_menu_items and
|
||||
self.settings.controller and
|
||||
if (not self.wiki_menu_items and
|
||||
self.settings.controller and
|
||||
self.settings.function):
|
||||
self.wiki_menu_items = self.menu(self.settings.controller,
|
||||
self.settings.function)
|
||||
@@ -6169,4 +6169,3 @@ class Config(object):
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
@@ -350,4 +350,3 @@ def getipaddrinfo(host):
|
||||
and isinstance(addrinfo[4][0], basestring)]
|
||||
except socket.error:
|
||||
return []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user